diff --git a/CHANGELOG.md b/CHANGELOG.md index 7aacde3f..11f687c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.1.0] + +This version introduces upwards scroll support (fixes [#466](https://github.com/webcreate/infinite-ajax-scroll/issues/466)). See [`upwards scroll`](docs/advanced/upwards.md) documentation on how to use this feature. + +* Adds all features from 3.1.0-beta.1 +* Added [`upwards`](docs/advanced/upwards.md) documentation + +## [3.1.0-beta.1] + +This version introduces upwards scroll support (fixes [#466](https://github.com/webcreate/infinite-ajax-scroll/issues/466)). See documentation on the [`prev`](docs/options.md#prev) option on how to enable this feature. + +* Added [`prev`](docs/options.md#prev) option +* Added [`prev`](docs/events.md#prev) event +* Added [`preved`](docs/events.md#preved) event +* Added [`top`](docs/events.md#top) event +* Added [`first`](docs/events.md#first) event +* Added [`prepend`](docs/events.md#prepend) event +* Added [`prepended`](docs/events.md#prepended) event + ## [3.0.1] * Fixed prefill not filling past the scroll threshold @@ -111,6 +130,8 @@ See [LICENSE](LICENSE) for more details. * Extensible through events * Added an extensive test suite +[3.1.0]: https://github.com/webcreate/infinite-ajax-scroll/compare/3.0.1...3.1.0 +[3.1.0-beta.1]: https://github.com/webcreate/infinite-ajax-scroll/compare/3.0.1...3.1.0-beta.1 [3.0.1]: https://github.com/webcreate/infinite-ajax-scroll/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/webcreate/infinite-ajax-scroll/compare/3.0.0-rc.1...3.0.0 [3.0.0-rc.1]: https://github.com/webcreate/infinite-ajax-scroll/compare/v2.3.1...3.0.0-rc.1 diff --git a/Makefile b/Makefile index 0749d346..4e4c9305 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ install: update: npm ci npm run build - $(foreach ex,$(EXAMPLES),(cd $(ex) && npm ci) || exit $$?;) + $(foreach ex,$(EXAMPLES),(cd $(ex) && npm install) || exit $$?;) .PHONY: update up: diff --git a/README.md b/README.md index 1208a79e..cb54c9b1 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,9 @@ Infinite Ajax Scroll works on a container with item elements which get appended. ``` @@ -62,6 +64,7 @@ import InfiniteAjaxScroll from '@webcreate/infinite-ajax-scroll'; let ias = new InfiniteAjaxScroll('.container', { item: '.item', next: '.next', + prev: '.prev', pagination: '.pagination' }); ``` diff --git a/UPGRADE.md b/UPGRADE.md index 2db5b755..7144ce78 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,8 @@ +Upgrade from 3.0.x to 3.1.0 +=========================== + +Version 3.1.0 is backwards-compatible with 3.0.x. + Upgrade from 2.3.x to 3.0 ========================= diff --git a/docs/README.md b/docs/README.md index 717ab8c2..b9fa2b79 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,3 +18,4 @@ * [Last page message](advanced/last-page-message.md) * [History](advanced/history.md) * [Overflow](advanced/overflow.md) +* [Upward scroll](advanced/upwards.md) diff --git a/docs/advanced/history.md b/docs/advanced/history.md index 6e00e827..1fd27b25 100644 --- a/docs/advanced/history.md +++ b/docs/advanced/history.md @@ -23,6 +23,7 @@ ias.on('page', (event) => { ## Loading previous pages -{% hint style='working' %} -This feature is still work in progress -{% endhint %} +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](upwards.md) + diff --git a/docs/advanced/upwards.md b/docs/advanced/upwards.md new file mode 100644 index 00000000..0185e513 --- /dev/null +++ b/docs/advanced/upwards.md @@ -0,0 +1,61 @@ +# Upward Infinite 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 + + ``` + +2. Configure the [`prev`](../options.md#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'); +}) +``` diff --git a/docs/events.md b/docs/events.md index 6852983e..51483d1f 100644 --- a/docs/events.md +++ b/docs/events.md @@ -63,6 +63,16 @@ Triggered when the user has hit the scroll threshold for the next page due to sc | :--- | :--- | :--- | | 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. @@ -93,6 +103,40 @@ Trigger when loading and appending the next page is completed. | :--- | :--- | :--- | | 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. @@ -158,18 +202,55 @@ This event is triggered after the items have been appended. | 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](../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('Users has reached the last page'); + 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.md) +### 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. diff --git a/docs/options.md b/docs/options.md index 2d26bf6e..2f728ee8 100644 --- a/docs/options.md +++ b/docs/options.md @@ -44,6 +44,29 @@ let ias = new InfiniteAjaxScroll(/*..*/, { }) ``` +## 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 +Prev +2 +Next +``` + +```javascript +let ias = new InfiniteAjaxScroll(/*..*/, { + next: '.pager__next', + prev: '.pager__prev' +}) +``` + ## pagination **Type:** `boolean|string|Element`
diff --git a/examples/articles/index.js b/examples/articles/index.js index d1da4e44..dfc81d27 100644 --- a/examples/articles/index.js +++ b/examples/articles/index.js @@ -3,6 +3,7 @@ import InfiniteAjaxScroll from '@webcreate/infinite-ajax-scroll'; window.ias = new InfiniteAjaxScroll('.surface-container', { item: '.article', next: '.pager__next', + prev: '.pager__prev', pagination: '.pager', spinner: '.loader' }); @@ -21,3 +22,8 @@ ias.on('page', (e) => { history.replaceState(state, e.title, e.url); }); + +// disable cache busting +ias.on('load', function(event) { + event.nocache = true; +}); diff --git a/examples/articles/package.json b/examples/articles/package.json index 27ebb643..906fcb2c 100644 --- a/examples/articles/package.json +++ b/examples/articles/package.json @@ -29,7 +29,7 @@ "jquery-ias" ], "dependencies": { - "@webcreate/infinite-ajax-scroll": "^3.0.0" + "@webcreate/infinite-ajax-scroll": "^3.1.0" }, "devDependencies": { "parcel": "^2.0.0" diff --git a/package.json b/package.json index 8bd8251b..c4c680ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@webcreate/infinite-ajax-scroll", - "version": "3.0.1", + "version": "3.1.0", "title": "Infinite Ajax Scroll", "description": "Turn your existing pagination into infinite scrolling pages with ease", "license": "AGPL-3.0-only", diff --git a/src/defaults.js b/src/defaults.js index 4a80994d..c9a37001 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -1,6 +1,7 @@ export default { item: undefined, next: undefined, + prev: undefined, pagination: undefined, responseType: 'document', bind: true, diff --git a/src/events.js b/src/events.js index 736cdcd4..140c6507 100644 --- a/src/events.js +++ b/src/events.js @@ -1,14 +1,20 @@ export const APPEND = 'append'; export const APPENDED = 'appended'; +export const PREPEND = 'prepend'; +export const PREPENDED = 'prepended'; export const BINDED = 'binded'; export const UNBINDED = 'unbinded'; export const HIT = 'hit'; +export const TOP = 'top'; export const LOAD = 'load'; export const LOADED = 'loaded'; export const ERROR = 'error'; +export const FIRST = 'first'; export const LAST = 'last'; export const NEXT = 'next'; export const NEXTED = 'nexted'; +export const PREV = 'prev'; +export const PREVED = 'preved'; export const READY = 'ready'; export const SCROLLED = 'scrolled'; export const RESIZED = 'resized'; @@ -19,15 +25,21 @@ export const PREFILLED = 'prefilled'; const events = { APPEND, APPENDED, + PREPEND, + PREPENDED, BINDED, UNBINDED, HIT, + TOP, LOAD, LOADED, ERROR, + FIRST, LAST, NEXT, NEXTED, + PREV, + PREVED, READY, SCROLLED, RESIZED, diff --git a/src/infinite-ajax-scroll.js b/src/infinite-ajax-scroll.js index 30487b71..33569cee 100644 --- a/src/infinite-ajax-scroll.js +++ b/src/infinite-ajax-scroll.js @@ -7,12 +7,14 @@ import {scrollHandler} from "./event-handlers"; import Emitter from "tiny-emitter"; import {getDistanceToFold, getRootRect, getScrollPosition} from "./dimensions"; import {nextHandler} from './next-handler'; +import {prevHandler} from './prev-handler'; import Pagination from './pagination'; import Spinner from './spinner'; import Logger from './logger'; import Paging from './paging'; import Trigger from './trigger'; import {appendFn} from './append'; +import {prependFn} from './prepend'; import * as Events from './events'; import ResizeObserverFactory from './resize-observer'; import Prefill from "./prefill"; @@ -36,6 +38,7 @@ export default class InfiniteAjaxScroll { } this.nextHandler = nextHandler; + this.prevHandler = prevHandler; if (this.options.next === false) { this.nextHandler = function() {} @@ -43,6 +46,12 @@ export default class InfiniteAjaxScroll { this.nextHandler = this.options.next; } + if (this.options.prev === false) { + this.prevHandler = function() {} + } else if (typeof this.options.prev === 'function') { + this.prevHandler = this.options.prev; + } + this.resizeObserver = ResizeObserverFactory(this, this.scrollContainer); this._scrollListener = throttle(scrollHandler, 200).bind(this); @@ -50,7 +59,8 @@ export default class InfiniteAjaxScroll { this.bindOnReady = true; this.binded = false; this.paused = false; - this.pageIndex = this.sentinel() ? 0 : -1; + this.pageIndexPrev = 0; + this.pageIndex = this.pageIndexNext = this.sentinel() ? 0 : -1; this.on(Events.HIT, () => { if (!this.loadOnScroll) { @@ -60,6 +70,14 @@ export default class InfiniteAjaxScroll { this.next(); }); + this.on(Events.TOP, () => { + if (!this.loadOnScroll) { + return; + } + + this.prev(); + }); + this.on(Events.SCROLLED, this.measure); this.on(Events.RESIZED, this.measure); @@ -74,6 +92,11 @@ export default class InfiniteAjaxScroll { // prefill/measure after all plugins are done binding this.on(Events.BINDED, this.prefill.prefill.bind(this.prefill)); + this.hitFirst = this.hitLast = false; + + this.on(Events.LAST, () => this.hitLast = true); + this.on(Events.FIRST, () => this.hitFirst = true); + let ready = () => { if (this.ready) { return; @@ -132,6 +155,10 @@ export default class InfiniteAjaxScroll { } next() { + if (this.hitLast) { + return; + } + if (!this.binded) { if (!this.ready) { return this.once(Events.BINDED, this.next); @@ -142,30 +169,57 @@ export default class InfiniteAjaxScroll { this.pause(); - const pageIndex = this.pageIndex + 1; + const pageIndex = this.pageIndexNext + 1; - this.emitter.emit(Events.NEXT, {pageIndex: this.pageIndex + 1}); + this.emitter.emit(Events.NEXT, {pageIndex: this.pageIndexNext + 1}); return Promise.resolve(this.nextHandler(pageIndex)) .then((hasNextUrl) => { - this.pageIndex = pageIndex; + this.pageIndexNext = pageIndex; if (!hasNextUrl) { this.emitter.emit(Events.LAST); - - return; } this.resume(); return hasNextUrl; }).then((hasNextUrl) => { - this.emitter.emit(Events.NEXTED, {pageIndex: this.pageIndex}); + this.emitter.emit(Events.NEXTED, {pageIndex: this.pageIndexNext}); return hasNextUrl; }); } + prev() { + if (!this.binded || this.hitFirst) { + return; + } + + this.pause(); + + const pageIndex = this.pageIndexPrev - 1; + + this.emitter.emit(Events.PREV, {pageIndex: this.pageIndexPrev - 1}); + + return Promise.resolve(this.prevHandler(pageIndex)) + .then((hasPrevUrl) => { + this.pageIndexPrev = pageIndex; + + this.resume(); + + if (!hasPrevUrl) { + this.emitter.emit(Events.FIRST); + } + + return hasPrevUrl; + }).then((hasPrevUrl) => { + this.emitter.emit(Events.PREVED, {pageIndex: this.pageIndexPrev}); + + return hasPrevUrl; + }); + } + /** * @param {string} url * @returns {Promise} returns LOADED event on success @@ -276,6 +330,48 @@ export default class InfiniteAjaxScroll { }); } + /** + * @param {array} items + * @param {Element|null} parent + */ + prepend(items, parent) { + let ias = this; + parent = parent || ias.container; + + let event = { + items, + parent, + prependFn + }; + + ias.emitter.emit(Events.PREPEND, event); + + let executor = (resolve) => { + window.requestAnimationFrame(() => { + const first = ias.first(); + const scrollPositionStart = getScrollPosition(this.scrollContainer); + const topStart = first.getBoundingClientRect().top + scrollPositionStart.y; + + Promise.resolve(event.prependFn(event.items, event.parent, ias.first())) + .then(() => { + const scrollPositionEnd = getScrollPosition(this.scrollContainer); + const topEnd = first.getBoundingClientRect().top + scrollPositionEnd.y; + + let deltaY = topEnd - topStart; + + this.scrollContainer.scrollTo(scrollPositionEnd.x, deltaY); + }) + .then(() => { + resolve({items, parent}); + }); + }); + }; + + return (new Promise(executor)).then((event) => { + ias.emitter.emit(Events.PREPENDED, event); + }); + } + sentinel() { const items = $(this.options.item, this.container); @@ -286,6 +382,16 @@ export default class InfiniteAjaxScroll { return items[items.length-1]; } + first() { + const items = $(this.options.item, this.container); + + if (!items.length) { + return null; + } + + return items[0]; + } + pause() { this.paused = true; } @@ -302,9 +408,15 @@ export default class InfiniteAjaxScroll { this.loadOnScroll = false; } + /** + * @deprecated replaced by distanceBottom + */ distance(rootRect, sentinel) { - const _rootRect = rootRect || getRootRect(this.scrollContainer); + return this.distanceBottom(rootRect, sentinel); + } + distanceBottom(rootRect, sentinel) { + const _rootRect = rootRect || getRootRect(this.scrollContainer); const _sentinel = sentinel || this.sentinel(); const scrollPosition = getScrollPosition(this.scrollContainer); @@ -317,8 +429,14 @@ export default class InfiniteAjaxScroll { return distance; } + distanceTop() { + const scrollPosition = getScrollPosition(this.scrollContainer); + + return scrollPosition.y - this.negativeMargin; + } + measure() { - if (this.paused) { + if (this.paused || (this.hitFirst && this.hitLast)) { return; } @@ -334,12 +452,20 @@ export default class InfiniteAjaxScroll { return; } - const sentinel = this.sentinel(); + if (!this.hitFirst) { + let distanceTop = this.distanceTop(); - let distance = this.distance(rootRect, sentinel); + if (distanceTop <= 0) { + this.emitter.emit(Events.TOP, {distance: distanceTop}); + } + } - if (distance <= 0) { - this.emitter.emit(Events.HIT, {distance}); + if (!this.hitLast) { + let distanceBottom = this.distanceBottom(rootRect, this.sentinel()); + + if (distanceBottom <= 0) { + this.emitter.emit(Events.HIT, {distance: distanceBottom}); + } } } diff --git a/src/logger.js b/src/logger.js index 6003b6f1..7bbdc62b 100644 --- a/src/logger.js +++ b/src/logger.js @@ -4,6 +4,9 @@ const defaultLogger = { hit: () => { console.log(`Hit scroll threshold`); }, + top: () => { + console.log(`Hit top scroll threshold`); + }, binded: () => { console.log(`Binded event handlers`); }, @@ -22,6 +25,12 @@ const defaultLogger = { nexted: (event) => { console.log(`Next page completed [pageIndex=${event.pageIndex}]`); }, + prev: (event) => { + console.log(`Previous page triggered [pageIndex=${event.pageIndex}]`); + }, + preved: (event) => { + console.log(`Previous page completed [pageIndex=${event.pageIndex}]`); + }, load: (event) => { console.log(`Start loading ${event.url}`); }, @@ -34,9 +43,18 @@ const defaultLogger = { appended: (event) => { console.log(`Finished appending ${event.items.length} item(s)`); }, + prepend: () => { + console.log(`Start prepending items`); + }, + prepended: (event) => { + console.log(`Finished prepending ${event.items.length} item(s)`); + }, last: () => { console.log(`No more pages left to load`); }, + first: () => { + console.log(`Reached first page`); + }, page: (event) => { console.log(`Page changed [pageIndex=${event.pageIndex}]`); }, diff --git a/src/next-handler.js b/src/next-handler.js index 52188833..29077650 100644 --- a/src/next-handler.js +++ b/src/next-handler.js @@ -3,7 +3,7 @@ import Assert from './assert'; export function nextHandler(pageIndex) { let ias = this; - let lastResponse = ias._lastResponse || document; + let lastResponse = ias._lastResponse || document.body; let nextEl = $(ias.options.next, lastResponse)[0]; diff --git a/src/paging.js b/src/paging.js index 9a82856b..6e20e639 100644 --- a/src/paging.js +++ b/src/paging.js @@ -27,6 +27,7 @@ export default class Paging { ias.on(Events.BINDED, this.binded.bind(this)); ias.on(Events.NEXT, this.next.bind(this)); + ias.on(Events.PREV, this.prev.bind(this)); ias.on(Events.SCROLLED, this.scrolled.bind(this)); ias.on(Events.RESIZED, this.scrolled.bind(this)); } @@ -73,6 +74,34 @@ export default class Paging { }); } + prev() { + let url = document.location.toString(); + let title = document.title; + + let loaded = (event) => { + url = event.url; + + if (event.xhr.response) { + title = event.xhr.response.title + } + }; + + this.ias.once(Events.LOADED, loaded); + + this.ias.once(Events.PREVED, (event) => { + this.pageBreaks.unshift({ + pageIndex: event.pageIndex, + url, + title, + sentinel: this.ias.first() + }); + + this.update(); + + this.ias.off(Events.LOADED, loaded); + }); + } + scrolled(event) { this.update(event.scroll.y); } diff --git a/src/prefill.js b/src/prefill.js index 6188b2c0..292c75d4 100644 --- a/src/prefill.js +++ b/src/prefill.js @@ -11,15 +11,9 @@ export default class Prefill { return; } - let distance = this.ias.distance(); - - if (distance > 0) { - return; - } - this.ias.emitter.emit(Events.PREFILL); - return this._prefill().then(() => { + return Promise.all([this._prefillNext(), this._prefillPrev()]).then(() => { this.ias.emitter.emit(Events.PREFILLED); // @todo reevaluate if we should actually call `measure` here. @@ -27,17 +21,33 @@ export default class Prefill { }); } - _prefill() { - return this.ias.next().then((hasNextUrl) => { - if (!hasNextUrl) { - return; - } + _prefillNext() { + let distance = this.ias.distance(); + + if (distance > 0) { + return; + } + + return this.ias.next() + .then((hasNextUrl) => { + if (!hasNextUrl) { + return; + } - let distance = this.ias.distance(); + let distance = this.ias.distance(); - if (distance < 0) { - return this._prefill(); - } - }); + if (distance < 0) { + return this._prefillNext(); + } + }) + ; + } + + _prefillPrev() { + if (!this.ias.options.prev) { + return; + } + + return this.ias.prev(); } } diff --git a/src/prepend.js b/src/prepend.js new file mode 100644 index 00000000..77a4f789 --- /dev/null +++ b/src/prepend.js @@ -0,0 +1,9 @@ +export function prependFn(items, parent, first) { + let insert = document.createDocumentFragment(); + + items.forEach((item) => { + insert.appendChild(item); + }); + + parent.insertBefore(insert, first); +} diff --git a/src/prev-handler.js b/src/prev-handler.js new file mode 100644 index 00000000..5e0c5a7a --- /dev/null +++ b/src/prev-handler.js @@ -0,0 +1,27 @@ +import $ from 'tealight'; +import Assert from './assert'; + +export function prevHandler(pageIndex) { + let ias = this; + let prevEl = ias._prevEl || $(ias.options.prev, document.body)[0]; + + if (ias.options.prev === undefined) { + return; + } + + if (!prevEl) { + Assert.warn(Assert.singleElement, ias.options.prev, 'options.prev'); + + return; + } + + let prevUrl = prevEl.href; + + return ias.load(prevUrl) + .then((data) => { + let prevEl = ias._prevEl = $(ias.options.prev, data.xhr.response)[0]; + + return ias.prepend(data.items) + .then(() => !!prevEl) // TODO: evaluate if this makes sense + }); +} diff --git a/test/logger_spec.js b/test/logger_spec.js index 848d099e..a428333d 100644 --- a/test/logger_spec.js +++ b/test/logger_spec.js @@ -20,7 +20,6 @@ describe('Logger', () => { }); cy.get('@spy').should((consoleSpy) => { - expect(consoleSpy).to.have.been.calledOnce; expect(consoleSpy).to.have.been.calledWith( "Binded event handlers" );