diff --git a/docs/advanced/triggers.md b/docs/advanced/triggers.md index c79dd633..99825b92 100644 --- a/docs/advanced/triggers.md +++ b/docs/advanced/triggers.md @@ -1,9 +1,5 @@ # Triggers -{% hint style='working' %} -This feature is still work in progress -{% endhint %} - 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: @@ -11,3 +7,49 @@ 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 + +``` + +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](../options.md#trigger) for information. + +[View this behaviour in a live demo](https://infiniteajaxscroll.com/examples/button/) + diff --git a/docs/options.md b/docs/options.md index 810979dc..dfdd6f46 100644 --- a/docs/options.md +++ b/docs/options.md @@ -176,17 +176,20 @@ You can also set advanced spinner options. ```javascript let ias = new InfiniteAjaxScroll(/*..*/, { spinner: { - // element + // 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 @@ -217,6 +220,16 @@ let ias = new InfiniteAjaxScroll(/*..*/, { // 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; + }, }) ``` @@ -225,16 +238,19 @@ We can also set advanced trigger options. ```javascript let ias = new InfiniteAjaxScroll(/*..*/, { trigger: { - // element + // 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 diff --git a/examples/button/index.html b/examples/button/index.html index 5fd5109c..f37341ef 100644 --- a/examples/button/index.html +++ b/examples/button/index.html @@ -16,7 +16,7 @@
- +
diff --git a/examples/button/index.js b/examples/button/index.js index b2c51faa..8eaf478c 100644 --- a/examples/button/index.js +++ b/examples/button/index.js @@ -37,6 +37,19 @@ window.ias = new InfiniteAjaxScroll('.blocks', { trigger: { element: '.trigger', + // alternatively we could pass an Element directly + // element: document.getElementById('btn1'), + + // alternatively we could pass a factory function + // element: function() { + // let el = document.createElement('button'); + // el.innerText = 'Load More...'; + // document.querySelector('.status').appendChild(el); + // + // // we have to return the element so IAS can add the necessary event listeners + // return el; + // }, + // first page (pageIndex is -1) is generated, after that we show a load more button when: (pageIndex) => pageIndex >= 0, diff --git a/src/trigger.js b/src/trigger.js index 8a58990f..f4af5238 100644 --- a/src/trigger.js +++ b/src/trigger.js @@ -15,12 +15,16 @@ const defaults = { }; function expand(options) { - if (typeof options === 'string' || (typeof options === 'object' && options.nodeType === Node.ELEMENT_NODE)) { + if (typeof options === 'string' || typeof options === 'function' || (typeof options === 'object' && options.nodeType === Node.ELEMENT_NODE)) { options = { element: options, } } + if (typeof options.element === 'function') { + options.element = options.element(); + } + // expand array to a function, e.g.: // [0, 1, 2] -> function(pageIndex) { /* return true when pageIndex in [0, 1, 2] */ } if (options.when && Array.isArray(options.when)) { diff --git a/test/trigger_spec.js b/test/trigger_spec.js index 759fb9cb..cb7c3b6e 100644 --- a/test/trigger_spec.js +++ b/test/trigger_spec.js @@ -5,7 +5,7 @@ describe('Trigger', () => { cy.visit('http://localhost:8080/test/fixtures/default/page1.html'); }); - it('accepts a selector', () => { + it('should accept a selector', () => { cy.InfiniteAjaxScroll().then((InfiniteAjaxScroll) => { let ias = new InfiniteAjaxScroll('.blocks', { item: '.blocks__block', @@ -55,6 +55,28 @@ describe('Trigger', () => { }); }); + it('should accept a factory function', () => { + cy.InfiniteAjaxScroll().then((InfiniteAjaxScroll) => { + cy.document().then((doc) => { + let ias = new InfiniteAjaxScroll('.blocks', { + item: '.blocks__block', + next: '.pager__next', + trigger: () => { + let el = doc.createElement('a'); + el.id = 'btn1'; + el.innerText = 'Load More Items'; + + doc.body.appendChild(el); + + return el; + }, + }); + + cy.get('#btn1').should((el) => expect(el[0]).to.be.eq(ias.trigger.element)); + }); + }); + }); + it('should hide trigger on bind', () => { cy.InfiniteAjaxScroll().then((InfiniteAjaxScroll) => { let ias = new InfiniteAjaxScroll('.blocks', {