// page-load ( function( window, factory ) { // universal module definition if ( typeof module == 'object' && module.exports ) { // CommonJS module.exports = factory( window, require('./core'), ); } else { // browser global factory( window, window.InfiniteScroll, ); } }( window, function factory( window, InfiniteScroll ) { let proto = InfiniteScroll.prototype; Object.assign( InfiniteScroll.defaults, { // append: false, loadOnScroll: true, checkLastPage: true, responseBody: 'text', domParseResponse: true, // prefill: false, // outlayer: null, } ); InfiniteScroll.create.pageLoad = function() { this.canLoad = true; this.on( 'scrollThreshold', this.onScrollThresholdLoad ); this.on( 'load', this.checkLastPage ); if ( this.options.outlayer ) { this.on( 'append', this.onAppendOutlayer ); } }; proto.onScrollThresholdLoad = function() { if ( this.options.loadOnScroll ) this.loadNextPage(); }; let domParser = new DOMParser(); proto.loadNextPage = function() { if ( this.isLoading || !this.canLoad ) return; let { responseBody, domParseResponse, fetchOptions } = this.options; let path = this.getAbsolutePath(); this.isLoading = true; if ( typeof fetchOptions == 'function' ) fetchOptions = fetchOptions(); let fetchPromise = fetch( path, fetchOptions ) .then( ( response ) => { if ( !response.ok ) { let error = new Error( response.statusText ); this.onPageError( error, path, response ); return { response }; } return response[ responseBody ]().then( ( body ) => { let canDomParse = responseBody == 'text' && domParseResponse; if ( canDomParse ) { body = domParser.parseFromString( body, 'text/html' ); } if ( response.status == 204 ) { this.lastPageReached( body, path ); return { body, response }; } else { return this.onPageLoad( body, path, response ); } } ); } ) .catch( ( error ) => { this.onPageError( error, path ); } ); this.dispatchEvent( 'request', null, [ path, fetchPromise ] ); return fetchPromise; }; proto.onPageLoad = function( body, path, response ) { // done loading if not appending if ( !this.options.append ) { this.isLoading = false; } this.pageIndex++; this.loadCount++; this.dispatchEvent( 'load', null, [ body, path, response ] ); return this.appendNextPage( body, path, response ); }; proto.appendNextPage = function( body, path, response ) { let { append, responseBody, domParseResponse } = this.options; // do not append json let isDocument = responseBody == 'text' && domParseResponse; if ( !isDocument || !append ) return { body, response }; let items = body.querySelectorAll( append ); let promiseValue = { body, response, items }; // last page hit if no items. #840 if ( !items || !items.length ) { this.lastPageReached( body, path ); return promiseValue; } let fragment = getItemsFragment( items ); let appendReady = () => { this.appendItems( items, fragment ); this.isLoading = false; this.dispatchEvent( 'append', null, [ body, path, items, response ] ); return promiseValue; }; // TODO add hook for option to trigger appendReady if ( this.options.outlayer ) { return this.appendOutlayerItems( fragment, appendReady ); } else { return appendReady(); } }; proto.appendItems = function( items, fragment ) { if ( !items || !items.length ) return; // get fragment if not provided fragment = fragment || getItemsFragment( items ); refreshScripts( fragment ); this.element.appendChild( fragment ); }; function getItemsFragment( items ) { // add items to fragment let fragment = document.createDocumentFragment(); if ( items ) fragment.append( ...items ); return fragment; } // replace