# Overview

## What is Infinite Ajax Scroll?

Infinite Ajax Scroll is a javascript infinite scrolling plugin. It works by reading the next (and previous) links of your existing server-side pagination and load these pages via AJAX when the visitor scrolls to the end of the page.

This approach, also known as progressive enhancement, is SEO-friendly and offers your users a better user-experience, resulting in longer visitor times and more page views.

### Key features

* **Progressive enhancement**: Infinite Ajax Scroll progressively enhances your server-side pagination with AJAX. When a client doesn't support JavaScript it will fall back on your server-side pagination.
* **Back-button proof**: The browser url is automatically updated when you scroll between pages. Users can reload or bookmark the page and always return to the right page.
* **Highly customizable**: With it's flexible API and event based architecture you can adapt it to your needs.

## Commercial licensing

Infinite Ajax Scroll is an open-source project and can be used in projects under the AGPL license. The AGPL license requires that your project(s) should also be licensed (and open sourced) under AGPL. For closed-source/proprietary projects you can [buy a Commercial License](https://infiniteajaxscroll.com/pricing) to remove this limitation.

After purchase you will receive a Commercial License PDF which grants the right to use Infinite Ajax Scroll in your commercial projects.

## Source code

The source code of Infinite Ajax Scroll is made available at [github.com/webcreate/infinite-ajax-scroll](https://github.com/webcreate/infinite-ajax-scroll).


# Installation

## Use Infinite Ajax Scroll via CDN

Get up and running in no time by linking directly to Infinite Ajax Scroll on [unpkg](https://unpkg.com).

```markup
<script src="https://unpkg.com/@webcreate/infinite-ajax-scroll/dist/infinite-ajax-scroll.min.js"></script>
```

Place this code right before the `</body>` tag on each template or page that you want to use infinite scroll on.

You can also use the [jsDelivr](https://cdn.jsdelivr.net/npm/@webcreate/infinite-ajax-scroll/) CDN.

## Manage as a package

Are you using NPM in your projects? You can install and update our package easily.

```bash
$ npm install --save @webcreate/infinite-ajax-scroll
```


# Getting started

First make sure that Infinite Ajax Scroll is [installed](/installation) and included on every page where you need infinite scrolling functionality.

## Definitions/concepts

Infinite Ajax Scroll works with a few concepts:

**Container**: This is an element in which child elements (items) will be appended. This is usually a `div`, `ul` or `table` tag, but can be anything.

**Items**: These are elements that live inside the container. This can be `div`'s, `li`'s, `article`, table rows (`tr`) or anything else. Important is that the elements are a direct child of the container. Items for the next page will be inserted after the last item inside the container.

**Pagination**: This is the element that contains your pagination links, like next and previous page. Infinite Ajax Scroll will automatically hide this element.

**Next**: this element (`a` tag) is the link to the next page. The href is used to load the next page in the background and append the items.

## Markup

Given the above definitions, our minimal markup would be similar to this:

```html
<div class="container">
    <div class="item">...</div>
    <div class="item">...</div>
    <div class="item">...</div>
</div>

<div class="pagination">
    <a href="page2.html" class="next">Next</a>
</div>
```

> Important to notice: every next page has to follow the same markup.

## Javascript

Given the above markup, we need to instruct Infinite Ajax Scroll which element is what.

```javascript
// import if you use the NPM package (not needed if you use CDN)
import InfiniteAjaxScroll from '@webcreate/infinite-ajax-scroll';

let ias = new InfiniteAjaxScroll('.container', {
  item: '.item',
  next: '.next',
  pagination: '.pagination'
});
```

This will enable infinite scroll in it's most basic form. When you scroll down, the next page is loaded through an ajax request and new items are appended to the container.

Check the reference for all available [options](/reference/options), [methods](/reference/methods) and [events](/reference/events).


# License

Read about our licensing options.

## Open source license

This license is designed for open-source and non-commercial websites and applications. The Infinite Ajax Scroll open source license is [Affero General Public License (AGPL)](https://www.gnu.org/licenses/agpl-3.0.en.html). The most important part of the license is:

> The key point of the GPL is that it's "sticky." If you use GPL-licensed software in a modified form or incorporate it into your product, you have to make it available under the same terms. You can sell the software, but you also have to make its source code freely available.

> The AGPL is even stickier than the GPL. Its stickiness extends to code which runs on servers, even if it's never published.

source: <https://www.kwork.me/open-source-free-software-licenses/>

## Commercial license

The commercial license is designed to use Infinite Ajax Scroll in closed-source/proprietary websites and applications. This license removes the "sticky" requirements as described above.

After purchase you will receive a Commercial License PDF which grants the right to use Infinite Ajax Scroll in your commercial projects.

[Buy a commercial license](https://infiniteajaxscroll.com/pricing)

## OEM license

If you develop a commercial SDK, plugin, theme, or an other kind of wrapper around Infinite Ajax Scroll we offer an Commercial OEM License. This license is customized and pricing depends on the expected sales volume and pricing. Please contact us at <hello@webcreate.nl> for more details.


# Support

## Report a bug

If you think you have found a bug, please post an issue on our [issue tracker](https://github.com/webcreate/infinite-ajax-scroll/issues).

Before posting, please consider the following:

1. Are you using the latest version of Infinite Ajax Scroll?
2. Have you searched for existing issues, before creating a new one?

## Have a question?

Despite our efforts to provide you with the best possible documentation on implementing Infinite Ajax Scroll into your project, you may still have a question.

Unfortunately we don't provide dedicated personal support, as we are spending all our time on improving Infinite Ajax Scroll and it's documentation.

But what you can do is:

1. Ask your question on [StackOverflow](https://stackoverflow.com/questions/tagged/jquery-ias)
2. Ask [our community of Infinite Ajax Scroll users](https://spectrum.chat/infiniteajaxscroll)


# Options

## item

**Type:** `string|Element`\
**Default:** `undefined`\
**Required:** yes

Selector of the item elements that should be appended to the container.

{% hint style="info" %}
The item elements should live **inside** the container element.
{% endhint %}

```html
<div class="container">
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    ...
</div>
```

```javascript
let ias = new InfiniteAjaxScroll('.container', {
  item: '.item'
})
```

## next

**Type:** `string`\
**Default:** `undefined`\
**Required:** yes

Selector of the next link. The `href` attribute will be used for the url of the next page. Only a single element should match this selector.

```html
<a href="/page/2" class="pager__next">Next</a>
```

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  next: '.pager__next'
})
```

## prev

*Introduced in Infinite Ajax Scroll 3.1.0*

**Type:** `string`\
**Default:** `undefined`\
**Required:** no

Selector of the previous link. The `href` attribute will be used for the url of the previous page. Only a single element should match this selector.

```html
<a href="/page/1" class="pager__prev">Prev</a>
<span class="pager__current">2</span>
<a href="/page/3" class="pager__next">Next</a>
```

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  next: '.pager__next',
  prev: '.pager__prev'
})
```

## pagination

**Type:** `boolean|string|Element`\
**Default:** `false`\
**Required:** no

Selector of the elements that contain the pagination. The elements that match the selector will be hidden (`element.style.display` -> none) when Infinite Ajax Scroll binds.

The pagination elements will be restored (`element.style.display` -> original value) when [`unbind`](/reference/methods#unbind) is called.

```html
<div class="pager" id="pager1">
    <span class="pager__current">1</span>
    <a href="/page/2" class="pager__page">2</a>
    <a href="/page/3" class="pager__page">3</a>
    <a href="/page/2" class="pager__next">Next</a>
</div>
```

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  // pass pagination as selector:
  pagination: '.pager',

  // or pass pagination as Element:
  pagination: document.getElementById('pager1'),

  // or pass false explicitly to disable automatic hiding:
  pagination: false,
})
```

## responseType

**Type:** `string`\
**Default:** `"document"`\
**Required:** no

Type of response. Can be set to "json".

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  responseType: 'json'
})
```

See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) for available values.

## bind

**Type:** `boolean`\
**Default:** `true`\
**Required:** no

By default Infinite Ajax Scroll binds to the scroll and resize events on document ready. If you want to have manual control over this behaviour you can set this option to `false`. To bind manually you can call the [`bind`](/reference/methods#bind) method.

## scrollContainer

**Type:** `string|Element|window`\
**Default:** `window`\
**Required:** no

Set a selector of the element you want to use as a scroll container. Use this if you want infinite scroll inside an overflow element.

Note: Only a single element should match the selector.

```html
<div id="scroller">
    <div class="container">
        <div class="item">Item 1</div>
        <div class="item">Item 2</div>
    </div>
</div>
```

```javascript
let ias = new InfiniteAjaxScroll('.container', {
  scrollContainer: '#scroller'
})
```

[Read more about scrolling inside an element](/advanced/overflow)

## negativeMargin

**Type:** `int` (pixels)\
**Default:** `0`\
**Required:** no

By default Infinite Ajax Scroll starts loading new items when the user scrolls to the bottom of the last item. The negativeMargin (in pixels) will be subtracted from the items' offset, allowing you to load new pages sooner.

{% hint style="info" %}
This value is always transformed to a positive integer (a value of `-100` will behave the same as `100`)
{% endhint %}

{% hint style="warning" %}
User experience can degrade when new pages are loaded too quickly without visual feedback. Use with caution.
{% endhint %}

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  // start loading the next page when the user scrolls to (or passed) 400px before the end of the last item
  negativeMargin: 400
})
```

## spinner

**Type:** `string|Element|Object|boolean`\
**Default:** `false`\
**Required:** no

Configures a spinner/loader. By default no spinner is configured.

You can set a selector to an element you want to display when Infinite Ajax Scroll is loading the next page.

```html
<div id="spinner1" class="spinner">Loading...</div>
```

```js
let ias = new InfiniteAjaxScroll(/*..*/, {
  spinner: '.spinner',

  // alternatively we can pass an Element
  spinner: document.getElementById('spinner1'),
})
```

You can also set advanced spinner options.

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  spinner: {
    // element to show as spinner
    element: '.spinner',

    // delay in milliseconds
    // this is the minimal time the loader should be displayed. If loading takes longer, the spinner
    // will be shown for the duration of the loading. If the loading takes less then this duration,
    // say 300ms, then the spinner is still shown for 600ms.
    delay: 600,

    // this function is called when the button has to be shown
    show: function(element) {
      element.style.opacity = '1'; // default behaviour
    },

    // this function is called when the button has to be hidden
    hide: function(element) {
      element.style.opacity = '0'; // default behaviour
    }
  }
})
```

[View the use of a spinner in a live demo](https://infiniteajaxscroll.com/examples/articles/)

## trigger

**Type:** `string|Element|Object|boolean`\
**Default:** `false`\
**Required:** no

Configures a trigger. By default no trigger is configured.

You can use the selector of an element you want to use as a trigger.

```html
<button id="trigger1" class="trigger">Load more</button>
```

```js
let ias = new InfiniteAjaxScroll(/*..*/, {
  trigger: '.trigger',

  // alternatively we can pass an Element
  trigger: document.getElementById('trigger1'),

  // we can also pass a factory function to create an Element
  trigger: function() {
    let el = document.createElement('button');
    el.innerText = 'Load More...';
    document.querySelector('.some_parent_class').appendChild(el);

    // we have to return the element so IAS can add the necessary event listeners
    return el;
  },
})
```

We can also set advanced trigger options.

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  trigger: {
    // element to show as trigger
    element: '.trigger',

    // pass a function which returns true which determines if the load more button should be shown
    when: function(pageIndex) {
      return true;  // default behaviour (always show a trigger)
    },

    // this function is called when the button has to be shown
    show: function(element) {
      element.style.opacity = '1'; // default behaviour
    },

    // this function is called when the button has to be hidden
    hide: function(element) {
      element.style.opacity = '0'; // default behaviour
    }
  }
})
```

[View the use of a button in a live demo](https://infiniteajaxscroll.com/examples/button/)

## logger

**Type:** `Object|boolean`\
**Default:** `Object` (see [src/logger.js](https://github.com/webcreate/infinite-ajax-scroll/blob/master/src/logger.js))\
**Required:** no

Configure an event logger.

On default events are logged to console (see [src/logger.js](https://github.com/webcreate/infinite-ajax-scroll/blob/master/src/logger.js)):

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  logger: true
})
```

To disable the logger you can pass `false`:

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  logger: false
})
```

To create your own logger, pass an object:

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  logger: {
    next: (event) => {
      doSomething(event.pageIndex);
    },
    loaded: (event) => {
      doSomethingElse(event.url);
    }
  }
})
```

## loadOnScroll

**Type:** `boolean`\
**Default:** `true`\
**Required:** no

Configures if the next/previous page should automatically be loaded when the users scrolls to the bottom or the top of the page.

When `loadOnScroll` is disabled the [`hit`](/reference/events#hit) event is still emitted, allowing you to manually trigger the next/prev page (for example by calling [`next`](/reference/methods#next)).

We can use [`enableLoadOnScroll`](/reference/methods#enableloadonscroll) and [`disableLoadOnScroll`](/reference/methods#disableloadonscroll) to configure this setting on runtime.

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  loadOnScroll: false
})

// the hit event is still emitted, allowing to manually load the next page
ias.on('hit', (event) => {
  ias.next();
})
```

## prefill

**Type:** `boolean`\
**Default:** `true`\
**Required:** no

When enabled, and the content is shorter than the scroll container, Infinite Ajax Scroll will load the next page(s) until the content is taller than the scroll container. When disabled the responsibility to load the next page is in the hands of the developer. This can be done by calling [`next`](/reference/methods#next) manually.

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  prefill: false
})

// load first page
// notice: even with the first page loaded, the content could still be too short. In that case keep calling `next()` until there is scroll bar.
ias.next();
```

We can listen to the [`prefill`](/reference/events#prefill) and [`prefilled`](/reference/events#prefilled) events to act on respectively the start and finish of the prefill action.


# Methods

## constructor

| argument  | type            | description                                                                                                                                                                          |
| --------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| container | string\|Element | Selector or Element of the container (see [definitions/concepts](https://github.com/webcreate/infinite-ajax-scroll/blob/master/docs/getting-started/README.md#definitions-concepts)) |
| options   | object          | Configuration for this instance of Infinite Ajax Scroll (see [options](/reference/options))                                                                                          |

```js
// import if you use the NPM package (not needed if you use CDN)
import InfiniteAjaxScroll from '@webcreate/infinite-ajax-scroll';

let ias = new InfiniteAjaxScroll('.container', {
  item: '.item',
  next: '.next',
  pagination: '.pagination'
});
```

## bind

This will bind Infinite Ajax Scroll to the scroll and resize events of the scroll container.

## unbind

This will unbind Infinite Ajax Scroll from the scroll and resize events of the scroll container.

## next

This will load the next page manually.

## load

This wil load an url and returns a promise which represents the [`loaded`](/reference/events#loaded) event.

| argument | type   | description |
| -------- | ------ | ----------- |
| url      | string | Url to load |

If the request fails, the promise will be rejected with the [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) object.

```js
ias.load('http://my-domain.test/page1.html')
  .then((loadedEvent) => {
    console.log('Requested ' + loadedEvent.url + ' successfully');
  })
  .catch((xhr) => {
    console.log('Request failed with ' + xhr.status + ' (' + xhr.statusText + ')');
  });
```

## append

Use this method to append an array of items to the container.

It will return a promise.

| argument | type          | description                                                                                       |
| -------- | ------------- | ------------------------------------------------------------------------------------------------- |
| items    | array         | Array of element to append to the container                                                       |
| parent   | Element\|null | Container to append to. When none given it falls back to the [configured container](#constructor) |

## enableLoadOnScroll

Enables the [`loadOnScroll`](/reference/options#loadonscroll) setting on runtime.

## disableLoadOnScroll

Disables the [`loadOnScroll`](/reference/options#loadonscroll) setting on runtime.


# Events

Infinite Ajax Scroll provides a wide range of events which we can use to hook into its functionality and customize where needed.

## Working with events

You can bind and unbind to events with the `on`, `once` and `off` methods.

```javascript
let ias = new InfiniteAjaxScroll('.container', options);

function handler(event) {
  console.log('New items have been appended', event);
}

ias.on('appended', handler);
ias.off('appended', handler);
ias.once('appended', handler);
```

## Reference

### ready

This event is triggered when the DOM is ready. Right after this event Infinite Ajax Scroll will bind (unless the [`bind`](/reference/options#bind) option is set to `false`).

### binded

This event is triggered when Infinite Ajax Scroll binds to the scroll and resize events of the scroll container. This mostly happens right after the DOM is ready, but this can be configured with the `bind` option.

### unbinded

Triggered when Infinite Ajax Scroll removed its listeners from the scroll and resize events.

Infinite Ajax Scroll will only unbind when we call the `unbind` method.

### scrolled

Triggered when the user scrolls inside the scroll container.

| property      | type    | description                                                                    |
| ------------- | ------- | ------------------------------------------------------------------------------ |
| scroll.y      | integer | Current vertical scroll position from the top of the page (can be negative)    |
| scroll.x      | integer | Current horizontal scroll position from the left of the page (can be negative) |
| scroll.deltaY | integer | Delta between current vertical scroll position and previous position           |
| scroll.deltaX | integer | Delta between current horizontal scroll position and previous position         |

The delta values can be used to determine the scroll direction. A positive value means scrolling down (deltaY) or to the right (deltaX). A negative value means the opposite direction.

### resized

Triggered when the user resizes the scroll container.

| property | type   | description                                          |
| -------- | ------ | ---------------------------------------------------- |
| scroll   | object | Object with x y coord of the current scroll position |

### hit

Triggered when the user has hit the scroll threshold for the next page due to scrolling or resizing.

| property | type | description                                    |
| -------- | ---- | ---------------------------------------------- |
| distance | int  | The distance to the scroll threshold in pixels |

### top

*Introduced in Infinite Ajax Scroll 3.1.0*

Triggered when the user has hit the top of the scroll area for the previous page due to scrolling or resizing.

| property | type | description                              |
| -------- | ---- | ---------------------------------------- |
| distance | int  | The distance to the scroll top in pixels |

### next

Triggered right after the `hit` event. Indicating that the next page will be loaded.

| property  | type | description                                                           |
| --------- | ---- | --------------------------------------------------------------------- |
| pageIndex | int  | The page index of the next page (the page that is about to be loaded) |

> pageIndex is zero indexed. This means the index starts at 0 on the first page.

For example to notify the user about loading the next page, you can do:

```js
ias.on('next', function(event) {
  // pageIndex is 0-indexed, so we add 1
  alert(`Page ${event.pageIndex+1} is loading...`);
});
ias.on('nexted', function(event) {
    alert(`Page ${event.pageIndex+1} is loaded and added to the page.`);
});
```

### nexted

Trigger when loading and appending the next page is completed.

| property  | type | description                                                         |
| --------- | ---- | ------------------------------------------------------------------- |
| pageIndex | int  | The page index of the next page (the page that is finished loading) |

### prev

*Introduced in Infinite Ajax Scroll 3.1.0*

Triggered right after the `top` event. Indicating that the previous page will be loaded.

| property  | type | description                                                           |
| --------- | ---- | --------------------------------------------------------------------- |
| pageIndex | int  | The page index of the prev page (the page that is about to be loaded) |

> pageIndex is zero indexed. This means the index starts at 0 on the first page.

For example to notify the user about loading the previous page, you can do:

```js
ias.on('prev', function(event) {
  // pageIndex is 0-indexed, so we add 1
  alert(`Page ${event.pageIndex+1} is loading...`);
});
ias.on('preved', function(event) {
    alert(`Page ${event.pageIndex+1} is loaded and prepended to the page.`);
});
```

### preved

*Introduced in Infinite Ajax Scroll 3.1.0*

Trigger when loading and prepending the previous page is completed.

| property  | type | description                                                         |
| --------- | ---- | ------------------------------------------------------------------- |
| pageIndex | int  | The page index of the next page (the page that is finished loading) |

### load

This event is triggered before the next page is requested from the server.

| property     | type           | default                                  | description                                                                                                                         |
| ------------ | -------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| url          | string         |                                          | The url that is about to be requested                                                                                               |
| xhr          | XMLHttpRequest |                                          | The configured XMLHttpRequest that is going to be used (see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)) |
| method       | string         | `"GET"`                                  | The request method to use, e.g. "GET", "POST", etc.                                                                                 |
| body         | mixed          | `null`                                   | Body of the request in case of POST (see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send#Parameters))    |
| nocache      | boolean        | `false`                                  | Disables cache busting mechanism                                                                                                    |
| responseType | string         | `"document"`                             | The expected type of response, eg. "document", "json", etc. (also see [responseType](/reference/options#responseType) option)       |
| headers      | Object         | `{'X-Requested-With': 'XMLHttpRequest'}` | Key-value object containing request headers                                                                                         |

You can use this event to modify any of the above properties.

For example to disable the cache busting you can do:

```js
ias.on('load', function(event) {
  event.nocache = true; // prevent IAS from adding a timestamp query param to the url
});
```

### loaded

This event is triggered when the next page is requested from the server, right before the items will be appended.

| property | type           | description                                                                                                     |
| -------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
| items    | array          | Array of items that have loaded and will be appended. These items match the selector given in the `next` option |
| url      | string         | The url that is about to be requested                                                                           |
| xhr      | XMLHttpRequest | The configured XMLHttpRequest that is going to be used                                                          |

### error

This event is triggered when an error occurred while loading the next page.

| property | type           | description                                           |
| -------- | -------------- | ----------------------------------------------------- |
| url      | string         | The url that is about to be requested                 |
| method   | string         | The method used to fetch the url ("GET", "POST", etc) |
| xhr      | XMLHttpRequest | The configured XMLHttpRequest that was used           |

### append

This event is triggered before the items are about to be appended.

| property | type     | description                                     |
| -------- | -------- | ----------------------------------------------- |
| items    | array    | Array of items that will be appended            |
| parent   | Element  | The element to which the items will be appended |
| appendFn | function | Function used to append items to the container  |

See [src/append.js](https://github.com/webcreate/infinite-ajax-scroll/blob/master/src/append.js) for the default append function.

### appended

This event is triggered after the items have been appended.

| property | type    | description                                       |
| -------- | ------- | ------------------------------------------------- |
| items    | array   | Array of items that have been appended            |
| parent   | Element | The element to which the items have been appended |

### prepend

*Introduced in Infinite Ajax Scroll 3.1.0*

This event is triggered before the items are about to be prepended.

| property  | type     | description                                      |
| --------- | -------- | ------------------------------------------------ |
| items     | array    | Array of items that will be prepended            |
| parent    | Element  | The element to which the items will be prepended |
| prependFn | function | Function used to prepend items to the container  |

See [src/prepend.js](https://github.com/webcreate/infinite-ajax-scroll/blob/master/src/prepend.js) for the default prepend function.

### prepended

*Introduced in Infinite Ajax Scroll 3.1.0*

This event is triggered after the items have been prepended.

| property | type    | description                                        |
| -------- | ------- | -------------------------------------------------- |
| items    | array   | Array of items that have been prepended            |
| parent   | Element | The element to which the items have been prepended |

### last

Triggered when the last page is appended.

```javascript
ias.on('last', () => {
  console.log('User has reached the last page');
})
```

[Read more on how we can inform the user about reaching the last page](/advanced/last-page-message)

### first

*Introduced in Infinite Ajax Scroll 3.1.0*

Triggered when the last page is appended.

```javascript
ias.on('first', () => {
  console.log('User has reached the first page');
})
```

### page

Triggered when the user scrolls past a page break. The event provides information about the page in view.

| property  | type    | description                                                           |
| --------- | ------- | --------------------------------------------------------------------- |
| pageIndex | int     | The page index of the current page                                    |
| url       | string  | Url of the page                                                       |
| title     | string  | Title of the page                                                     |
| sentinel  | Element | Sentinel element. Element used to determine on which page the user is |

> pageIndex is zero-based. This means the index starts at 0 on the first page.

One use case for this event is to update the browser url and title:

```javascript
ias.on('page', (event) => {
  // update the title
  document.title = event.title;

  // update the url
  let state = history.state;
  history.replaceState(state, event.title, event.url);
})
```

[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/articles/)

### prefill

This event is triggered when Infinite Ajax Scroll starts prefill.

```javascript
ias.on('prefill', () => {
  // do something before prefill starts
})
```

### prefilled

This event is triggered when prefill is finished.

```javascript
ias.on('prefilled', () => {
  // do something when prefill finished
})
```


# Triggers

Instead of loading next pages on scroll you can use a trigger. A trigger is a link or button that has to be clicked before the next page is loaded.

Reasons for a trigger might be:

* To make the footer reachable.
* To ease the load on the server. Users have to click before loading the next page. This adds a natural delay.

First add a button to your document

```html
<button class="load-more">Load More</button>
```

Next add a bit of CSS to make it look nice and hide if from view (opacity 0)

```css
.load-more {
  display: inline-block;
  height: 32px;
  padding: 0 16px;
  border: 1px solid #aaa;
  border-radius: 4px;
  opacity: 0;
  font-family: Lucida Grande,Lucida Sans Unicode,Lucida Sans,Geneva,Arial,sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 30px;
  color: #555;
  background-color: #fff;
  cursor: pointer;
  transition: opacity .4s;
}

.load-more:hover {
  color: #F63840;
  border: solid 1px #F63840;
}
```

Next configure the trigger.

```javascript
let ias = new InfiniteAjaxScroll(/*..*/, {
  // other options here

  trigger: '.load-more'
});
```

See [trigger options](/reference/options#trigger) for information.

[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/button/)


# Last page message

When your pages are finite, it is best practise to inform the user that the last page was hit.

First add an element to your document with the message you want to show.

```html
<div class="no-more">No more pages</div>
```

Next add a bit of CSS to hide the element on default:

```css
.no-more {
  opacity: 0;
}
```

Then listen for the [`last`](/reference/events#last) event and show to element.

```javascript
let ias = new InfiniteAjaxScroll(/* config */);

ias.on('last', function() {
  let el = document.querySelector('.no-more');

  el.style.opacity = '1';
})
```

[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/articles/)


# History

## Updating url and title

When users are scrolling through pages we can update the browser url and page title. This allows the current page to be shared or bookmarked.

We can achieve this by listening for the [`page`](https://github.com/webcreate/infinite-ajax-scroll/blob/master/docs/advanced/events.md#page) event. The page event contains the `url` and `title` of the current page in view.

The [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) can be used to update the url.

```javascript
ias.on('page', (event) => {
  // update the title
  document.title = event.title;

  // update the url
  let state = history.state;
  history.replaceState(state, event.title, event.url);
});
```

[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/articles/)

## Loading previous pages

Infinite Ajax Scroll can also be used to load items above the current scroll position. This is useful when you want to load older items first.

[View upwards infinite scroll documentation](/advanced/upwards)


# Overflow

It is possible to have infinite scrolling pages inside an overflow element.

First define a container element.

```html
<div id="scroller">
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <!-- more items -->
</div>
```

Then configure the overflow using css. Don't forget to give the element a fixed height.

```css
#scroller {
  overflow: scroll;
  height: 200px;
}
```

Then configure the element as scroll container.

```javascript
let ias = new InfiniteAjaxScroll('#scroller', {
  scrollContainer: '#scroller'
});
```

[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/overflow/)


# Upward scroll

Infinite Ajax Scroll can also be used to load items above the current scroll position. This is useful when you want to load older items first.

*Introduced in Infinite Ajax Scroll 3.1.0*

## Caveats

### Fixed height images

Upward scroll works by calculation screen height and content height. Due to they way browser load content, especially images, this could cause incorrect measurements. This can be solved by using fixed height images.

## Setup

1. Add a previous page link to your pagination.

   ```html
    <div class="pagination">
       <a href="page1.html" class="prev">Prev</a>
       <span class="current">2</span>
       <a href="page3.html" class="next">Next</a>
   </div>
   ```
2. Configure the [`prev`](/reference/options#prev) option.

   ```javascript
   // import if you use the NPM package
   import InfiniteAjaxScroll from '@webcreate/infinite-ajax-scroll';

   let ias = new InfiniteAjaxScroll('.container', {
     item: '.item',
     next: '.next',
     prev: '.prev',
     pagination: '.pagination'
   });
   ```

## Hook into upward scroll with events

In this example we notify the user about loading the previous page.

```js
ias.on('prev', function(event) {
  // pageIndex is 0-indexed, so we add 1
  alert(`Page ${event.pageIndex+1} is loading...`);
});
ias.on('preved', function(event) {
    alert(`Page ${event.pageIndex+1} is loaded and prepended to the page.`);
});
```

## Inform user about first page reached

In this example we notify the user when the first page is reached.

```javascript
ias.on('first', () => {
  console.log('User has reached the first page');
})
```


