{"version":3,"sources":["jsdelivr-header.js","/npm/infinite-scroller@0.0.11/src/infinite-scroller.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,ACNA,aAOA,SAAS,iBAAiB,EAAS,GAGjC,IAAI,EACA,EACA,GAAO,EACP,EAAgB,KAGhB,EAAU,CACZ,iBAAkB,cAUlB,QAAS,SAAS,GAChB,OAAO,IAAI,SAAQ,SAAS,EAAS,GACnC,EAAQ,qFACV,GACF,EAMA,eAAgB,SAAS,GAEzB,GAIF,IAAK,IAAI,KAAY,EACf,EAAQ,eAAe,KACzB,EAAQ,GAAY,EAAO,IAmB/B,SAAS,IACP,EAAc,EAEd,EAAQ,CACN,MAAO,CAAC,GAGV,EAAQ,UAAY,GAEpB,GACF,CAKA,SAAS,IAEP,IACG,MAAK,WACD,KACD,GAEJ,GACJ,CAKA,SAAS,IACP,IAAI,IAAS,EAEb,GAAO,EAOP,IAAI,EAAc,SAAS,cAAc,OACzC,EAAY,UAAU,IAAI,EAAQ,kBAClC,EAAQ,YAAY,GAGpB,IAAI,EAAU,EAAQ,GACnB,MAAK,SAAS,GAIb,EAAQ,eAAe,GAEvB,EAAQ,aAAa,EAAS,GAE9B,GAAO,CACT,IAKF,OAFA,IAAU,GAEH,CACT,CAOA,SAAS,EAAQ,GACf,OAAO,IAAI,SAAQ,SAAS,EAAS,GAGhC,EAAM,MAAM,GACb,EAAQ,EAAM,MAAM,IAGpB,EAAQ,QAAQ,GACb,MAAK,SAAS,GAIb,IAAI,EAAW,SAAS,yBACpB,EAAO,SAAS,cAAc,OAIlC,IADA,EAAK,UAAY,EACV,EAAK,iBACV,EAAS,YAAY,EAAK,YAAY,EAAK,aAI7C,EAAM,MAAM,GAAiB,EAG7B,EAAQ,EACV,GAGN,GACF,CAMA,SAAS,EAAe,GACtB,aAAa,GACb,EAAgB,YAAW,YACrB,GAAQ,KACV,GAEJ,GAAG,IACL,CAMA,SAAS,IACP,OAAQ,EAAQ,wBAAwB,IAAM,EAAQ,aAAe,OAAO,YAAc,GAAO,OAAO,YAAc,OAAO,WAC/H,CAkBA,MANW,CACT,KA/IF,WACE,IAGA,OAAO,iBAAiB,SAAU,EACpC,EA2IE,MAAO,EACP,QAVF,WACE,OAAO,oBAAoB,SAAU,EACvC,EAYF,CAGsB,oBAAX,QAA0B,OAAO,QAC1C,OAAO,QAAU,iBAGjB,OAAO,iBAAmB","file":"/npm/infinite-scroller@0.0.11/src/infinite-scroller.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/infinite-scroller@0.0.11/src/infinite-scroller.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict';\n\n/**\n * Infinite Scroll\n * @param {Element} element Target DOM element\n * @param {Object}  config  Configuration object\n */\nfunction InfiniteScroller(element, config) {\n\n  // Private variables\n  var currentPage;\n  var state;\n  var busy = false;\n  var scrollTimeout = null;\n\n  // Default options\n  var options = {\n    placeholderClass: 'placeholder',\n\n    /**\n     * AJAX request handler.\n     * When instantiating this module this function must be specified as an option.\n     * This function is where you should do your AJAX call to return HTML to this plugin.\n     *\n     * @param  {Number} page Page number to fetch. 1 based.\n     * @return {Promise}     Promise which should resolve with the HTML to be appended to the main element\n     */\n    request: function(page) {\n      return new Promise(function(resolve, reject) {\n        resolve('<p>Please override <code>options.request</code> when instantiating this plugin</p>');\n      });\n    },\n\n    /**\n     * Callback which can be used to process the returned results before they are put in the DOM\n     * @param  {DocumentFragment} results Collection of DOM items\n     */\n    processResults: function(results) {\n\n    }\n  };\n\n  // Lightweight extend to avoid dependency on a deep extend function\n  for (var property in options) {\n    if (options.hasOwnProperty(property)) {\n      options[property] = config[property];\n    }\n  }\n\n  /**\n   * Init method\n   */\n  function init() {\n    reset();\n\n    // Bind a scroll listener which we'll use to trigger new pages to load\n    window.addEventListener('scroll', scrollListener);\n  }\n\n  /**\n   * Public method to reset the product list\n   * Called on init() and also exposed publicy so the list can be reset from\n   * the calling script.\n   */\n  function reset() {\n    currentPage = 0;\n\n    state = {\n      pages: {}\n    };\n\n    element.innerHTML = '';\n\n    loadInitialBatch();\n  }\n\n  /**\n   * Private helper method to load an initial batch of results\n   */\n  function loadInitialBatch() {\n    // For as long as the bottom of the element is visible, let's request pages to fill up the viewport\n    requestNextPage()\n      .then(function() {\n        if(pageAtBottom()) {\n          loadInitialBatch();\n        }\n      });\n  }\n\n  /**\n   * Private method to request the next page of results\n   */\n  function requestNextPage() {\n    var page = ++currentPage;\n\n    busy = true;\n\n    // Pop a placeholder in the DOM straight away which we will replace with\n    // the results later\n    // Otherwise, if multiple pages got requested in quick succession, there\n    // would be a race condition which could result in the pages being\n    // appended to the DOM out of order.\n    var placeholder = document.createElement('div');\n    placeholder.classList.add(options.placeholderClass);\n    element.appendChild(placeholder);\n\n    // Get the next page and append the results to the DOM\n    var promise = getPage(page)\n      .then(function(results) {\n\n        // Fire off our callback to process the results\n        // Used by the product listing to add adverts\n        options.processResults(results);\n\n        element.replaceChild(results, placeholder);\n\n        busy = false;\n      });\n\n    // Pre-fetch the page after that, but don't do anything with the results\n    getPage(++page);\n\n    return promise;\n  }\n\n  /**\n   * Private method to get a page of results\n   * @param  {Number} requestedPage Page number to fetch\n   * @return {Promise}              Promise that resolves when the request is complete\n   */\n  function getPage(requestedPage) {\n    return new Promise(function(resolve, reject) {\n\n      // If we have already fetched this page, send it right back\n      if(state.pages[requestedPage]) {\n        resolve(state.pages[requestedPage]);\n      } else {\n        // Fire off a request using the passed in handler\n        options.request(requestedPage)\n          .then(function(html) {\n\n            // And then append the resulting items to the DOM\n            // We will do this via a document fragment in order to keep DOM manipulation to a minimum\n            var fragment = document.createDocumentFragment();\n            var temp = document.createElement('div');\n\n            // Pop the html into a temporary element before slurping it out again as you cannot use innerHTML on a document fragment\n            temp.innerHTML = html;\n            while (temp.hasChildNodes()) {\n              fragment.appendChild(temp.removeChild(temp.firstChild));\n            }\n\n            // Store the fragment on our state object\n            state.pages[requestedPage] = fragment;\n\n            // And then return the fragment\n            resolve(fragment);\n          });\n      }\n\n    });\n  }\n\n  /**\n   * Scroll event listener to trigger new page loads\n   * @param  {Event} e The scroll event\n   */\n  function scrollListener(e) {\n    clearTimeout(scrollTimeout);\n    scrollTimeout = setTimeout(function() {\n      if(!busy && pageAtBottom()) {\n        requestNextPage();\n      }\n    }, 100);\n  }\n\n  /**\n   * Helper method to determine if the page is at the bottom\n   * @return {Boolean} Boolean representing whether the page is at the bottom\n   */\n  function pageAtBottom() {\n    return (element.getBoundingClientRect().top + element.clientHeight + window.pageYOffset - 50) < (window.pageYOffset + window.innerHeight);\n  }\n\n  /**\n   * Tear everything down again\n   */\n  function destroy() {\n    window.removeEventListener('scroll', scrollListener);\n  }\n\n  /**\n   * Public methods\n   */\n  var self = {\n    init: init,\n    reset: reset,\n    destroy: destroy\n  };\n\n  return self;\n}\n\n// Expose as a CommonJS module for browserify\nif (typeof module !== 'undefined' && module.exports) {\n  module.exports = InfiniteScroller;\n} else {\n// Otherwise expose as a global for non browserify users\n  window.InfiniteScroller = InfiniteScroller;\n}\n"]}