PageSourceSearch

https://ardatep.ru/wp-content/plugins/responsive-lightbox/assets/i…/infinite-scroll.pkgd.js?ver=5.5.22

js ardatep.ru collected 2026-10-02 19:32:56 UTC 52,024 bytes, 1,909 lines download raw bytes

vendor: 9,028 bytes, lines 1-359
1/*!
2 * Infinite Scroll PACKAGED v4.0.1
3 * Automatically add next page
4 *
5 * Licensed GPLv3 for open source use
6 * or Infinite Scroll Commercial License for commercial use
7 *
8 * https://infinite-scroll.com
9 * Copyright 2018-2020 Metafizzy
10 */
11
12/**
13 * Bridget makes jQuery widgets
14 * v3.0.0
15 * MIT license
16 */
17
18( function( window, factory ) {
19  // module definition
20 if ( typeof module == 'object' && module.exports ) {
21   // CommonJS
22   module.exports = factory(
23       window,
24       require('jquery'),
25   );
26 } else {
27   // browser global
28   window.jQueryBridget = factory(
29       window,
30       window.jQuery,
31   );
32 }
33
34}( window, function factory( window, jQuery ) {
35
36// ----- utils ----- //
37
38// helper function for logging errors
39// $.error breaks jQuery chaining
40let console = window.console;
41let logError = typeof console == 'undefined' ? function() {} :
42  function( message ) {
43    console.error( message );
44  };
45
46// ----- jQueryBridget ----- //
47
48function jQueryBridget( namespace, PluginClass, $ ) {
49  $ = $ || jQuery || window.jQuery;
50  if ( !$ ) {
51    return;
52  }
53
54  // add option method -> $().plugin('option', {...})
55  if ( !PluginClass.prototype.option ) {
56    // option setter
57    PluginClass.prototype.option = function( opts ) {
58      if ( !opts ) return;
59
60      this.options = Object.assign( this.options || {}, opts );
61    };
62  }
63
64  // make jQuery plugin
65  $.fn[ namespace ] = function( arg0, ...args ) {
66    if ( typeof arg0 == 'string' ) {
67      // method call $().plugin( 'methodName', { options } )
68      return methodCall( this, arg0, args );
69    }
70    // just $().plugin({ options })
71    plainCall( this, arg0 );
72    return this;
73  };
74
75  // $().plugin('methodName')
76  function methodCall( $elems, methodName, args ) {
77    let returnValue;
78    let pluginMethodStr = `$().${namespace}("${methodName}")`;
79
80    $elems.each( function( i, elem ) {
81      // get instance
82      let instance = $.data( elem, namespace );
83      if ( !instance ) {
84        logError( `${namespace} not initialized.` +
85          ` Cannot call method ${pluginMethodStr}` );
86        return;
87      }
88
89      let method = instance[ methodName ];
90      if ( !method || methodName.charAt( 0 ) == '_' ) {
91        logError(`${pluginMethodStr} is not a valid method`);
92        return;
93      }
94
95      // apply method, get return value
96      let value = method.apply( instance, args );
97      // set return value if value is returned, use only first value
98      returnValue = returnValue === undefined ? value : returnValue;
99    } );
100
101    return returnValue !== undefined ? returnValue : $elems;
102  }
103
104  function plainCall( $elems, options ) {
105    $elems.each( function( i, elem ) {
106      let instance = $.data( elem, namespace );
107      if ( instance ) {
108        // set options & init
109        instance.option( options );
110        instance._init();
111      } else {
112        // initialize new instance
113        instance = new PluginClass( elem, options );
114        $.data( elem, namespace, instance );
115      }
116    } );
117  }
118
119}
120
121// -----  ----- //
122
123return jQueryBridget;
124
125} ) );
126/**
127 * EvEmitter v2.0.0
128 * Lil' event emitter
129 * MIT License
130 */
131
132( function( global, factory ) {
133  // universal module definition
134  if ( typeof module == 'object' && module.exports ) {
135    // CommonJS - Browserify, Webpack
136    module.exports = factory();
137  } else {
138    // Browser globals
139    global.EvEmitter = factory();
140  }
141
142}( typeof window != 'undefined' ? window : this, function() {
143
144function EvEmitter() {}
145
146let proto = EvEmitter.prototype;
147
148proto.on = function( eventName, listener ) {
149  if ( !eventName || !listener ) return this;
150
151  // set events hash
152  let events = this._events = this._events || {};
153  // set listeners array
154  let listeners = events[ eventName ] = events[ eventName ] || [];
155  // only add once
156  if ( !listeners.includes( listener ) ) {
157    listeners.push( listener );
158  }
159
160  return this;
161};
162
163proto.once = function( eventName, listener ) {
164  if ( !eventName || !listener ) return this;
165
166  // add event
167  this.on( eventName, listener );
168  // set once flag
169  // set onceEvents hash
170  let onceEvents = this._onceEvents = this._onceEvents || {};
171  // set onceListeners object
172  let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
173  // set flag
174  onceListeners[ listener ] = true;
175
176  return this;
177};
178
179proto.off = function( eventName, listener ) {
180  let listeners = this._events && this._events[ eventName ];
181  if ( !listeners || !listeners.length ) return this;
182
183  let index = listeners.indexOf( listener );
184  if ( index != -1 ) {
185    listeners.splice( index, 1 );
186  }
187
188  return this;
189};
190
191proto.emitEvent = function( eventName, args ) {
192  let listeners = this._events && this._events[ eventName ];
193  if ( !listeners || !listeners.length ) return this;
194
195  // copy over to avoid interference if .off() in listener
196  listeners = listeners.slice( 0 );
197  args = args || [];
198  // once stuff
199  let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
200
201  for ( let listener of listeners ) {
202    let isOnce = onceListeners && onceListeners[ listener ];
203    if ( isOnce ) {
204      // remove listener
205      // remove before trigger to prevent recursion
206      this.off( eventName, listener );
207      // unset once flag
208      delete onceListeners[ listener ];
209    }
210    // trigger listener
211    listener.apply( this, args );
212  }
213
214  return this;
215};
216
217proto.allOff = function() {
218  delete this._events;
219  delete this._onceEvents;
220  return this;
221};
222
223return EvEmitter;
224
225} ) );
226/**
227 * Fizzy UI utils v3.0.0
228 * MIT license
229 */
230
231( function( global, factory ) {
232  // universal module definition
233  if ( typeof module == 'object' && module.exports ) {
234    // CommonJS
235    module.exports = factory( global );
236  } else {
237    // browser global
238    global.fizzyUIUtils = factory( global );
239  }
240
241}( this, function factory( global ) {
242
243let utils = {};
244
245// ----- extend ----- //
246
247// extends objects
248utils.extend = function( a, b ) {
249  return Object.assign( a, b );
250};
251
252// ----- modulo ----- //
253
254utils.modulo = function( num, div ) {
255  return ( ( num % div ) + div ) % div;
256};
257
258// ----- makeArray ----- //
259
260// turn element or nodeList into an array
261utils.makeArray = function( obj ) {
262  // use object if already an array
263  if ( Array.isArray( obj ) ) return obj;
264
265  // return empty array if undefined or null. #6
266  if ( obj === null || obj === undefined ) return [];
267
268  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
269  // convert nodeList to array
270  if ( isArrayLike ) return [ ...obj ];
271
272  // array of single index
273  return [ obj ];
274};
275
276// ----- removeFrom ----- //
277
278utils.removeFrom = function( ary, obj ) {
279  let index = ary.indexOf( obj );
280  if ( index != -1 ) {
281    ary.splice( index, 1 );
282  }
283};
284
285// ----- getParent ----- //
286
287utils.getParent = function( elem, selector ) {
288  while ( elem.parentNode && elem != document.body ) {
289    elem = elem.parentNode;
290    if ( elem.matches( selector ) ) return elem;
291  }
292};
293
294// ----- getQueryElement ----- //
295
296// use element as selector string
297utils.getQueryElement = function( elem ) {
298  if ( typeof elem == 'string' ) {
299    return document.querySelector( elem );
300  }
301  return elem;
302};
303
304// ----- handleEvent ----- //
305
306// enable .ontype to trigger from .addEventListener( elem, 'type' )
307utils.handleEvent = function( event ) {
308  let method = 'on' + event.type;
309  if ( this[ method ] ) {
310    this[ method ]( event );
311  }
312};
313
314// ----- filterFindElements ----- //
315
316utils.filterFindElements = function( elems, selector ) {
317  // make array of elems
318  elems = utils.makeArray( elems );
319
320  return elems
321    // check that elem is an actual element
322    .filter( ( elem ) => elem instanceof HTMLElement )
323    .reduce( ( ffElems, elem ) => {
324      // add elem if no selector
325      if ( !selector ) {
326        ffElems.push( elem );
327        return ffElems;
328      }
329      // filter & find items if we have a selector
330      // filter
331      if ( elem.matches( selector ) ) {
332        ffElems.push( elem );
333      }
334      // find children
335      let childElems = elem.querySelectorAll( selector );
336      // concat childElems to filterFound array
337      ffElems = ffElems.concat( ...childElems );
338      return ffElems;
339    }, [] );
340};
341
342// ----- debounceMethod ----- //
343
344utils.debounceMethod = function( _class, methodName, threshold ) {
345  threshold = threshold || 100;
346  // original method
347  let method = _class.prototype[ methodName ];
348  let timeoutName = methodName + 'Timeout';
349
350  _class.prototype[ methodName ] = function() {
351    clearTimeout( this[ timeoutName ] );
352
353    let args = arguments;
354    this[ timeoutName ] = setTimeout( () => {
355      method.apply( this, args );
356      delete this[ timeoutName ];
357    }, threshold );
358  };
359};
vendor: 35,833 bytes, lines 360-1659
360
361// ----- docReady ----- //
362
363utils.docReady = function( onDocReady ) {
364  let readyState = document.readyState;
365  if ( readyState == 'complete' || readyState == 'interactive' ) {
366    // do async to allow for other scripts to run. metafizzy/flickity#441
367    setTimeout( onDocReady );
368  } else {
369    document.addEventListener( 'DOMContentLoaded', onDocReady );
370  }
371};
372
373// ----- htmlInit ----- //
374
375// http://bit.ly/3oYLusc
376utils.toDashed = function( str ) {
377  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
378    return $1 + '-' + $2;
379  } ).toLowerCase();
380};
381
382let console = global.console;
383
384// allow user to initialize classes via [data-namespace] or .js-namespace class
385// htmlInit( Widget, 'widgetName' )
386// options are parsed from data-namespace-options
387utils.htmlInit = function( WidgetClass, namespace ) {
388  utils.docReady( function() {
389    let dashedNamespace = utils.toDashed( namespace );
390    let dataAttr = 'data-' + dashedNamespace;
391    let dataAttrElems = document.querySelectorAll( `[${dataAttr}]` );
392    let jQuery = global.jQuery;
393
394    [ ...dataAttrElems ].forEach( ( elem ) => {
395      let attr = elem.getAttribute( dataAttr );
396      let options;
397      try {
398        options = attr && JSON.parse( attr );
399      } catch ( error ) {
400        // log error, do not initialize
401        if ( console ) {
402          console.error( `Error parsing ${dataAttr} on ${elem.className}: ${error}` );
403        }
404        return;
405      }
406      // initialize
407      let instance = new WidgetClass( elem, options );
408      // make available via $().data('namespace')
409      if ( jQuery ) {
410        jQuery.data( elem, namespace, instance );
411      }
412    } );
413
414  } );
415};
416
417// -----  ----- //
418
419return utils;
420
421} ) );
422// core
423( function( window, factory ) {
424  // universal module definition
425  if ( typeof module == 'object' && module.exports ) {
426    // CommonJS
427    module.exports = factory(
428        window,
429        require('ev-emitter'),
430        require('fizzy-ui-utils'),
431    );
432  } else {
433    // browser global
434    window.InfiniteScroll = factory(
435        window,
436        window.EvEmitter,
437        window.fizzyUIUtils,
438    );
439  }
440
441}( window, function factory( window, EvEmitter, utils ) {
442
443let jQuery = window.jQuery;
444// internal store of all InfiniteScroll intances
445let instances = {};
446
447function InfiniteScroll( element, options ) {
448  let queryElem = utils.getQueryElement( element );
449
450  if ( !queryElem ) {
451    console.error( 'Bad element for InfiniteScroll: ' + ( queryElem || element ) );
452    return;
453  }
454  element = queryElem;
455  // do not initialize twice on same element
456  if ( element.infiniteScrollGUID ) {
457    let instance = instances[ element.infiniteScrollGUID ];
458    instance.option( options );
459    return instance;
460  }
461
462  this.element = element;
463  // options
464  this.options = { ...InfiniteScroll.defaults };
465  this.option( options );
466  // add jQuery
467  if ( jQuery ) {
468    this.$element = jQuery( this.element );
469  }
470
471  this.create();
472}
473
474// defaults
475InfiniteScroll.defaults = {
476  // path: null,
477  // hideNav: null,
478  // debug: false,
479};
480
481// create & destroy methods
482InfiniteScroll.create = {};
483InfiniteScroll.destroy = {};
484
485let proto = InfiniteScroll.prototype;
486// inherit EvEmitter
487Object.assign( proto, EvEmitter.prototype );
488
489// --------------------------  -------------------------- //
490
491// globally unique identifiers
492let GUID = 0;
493
494proto.create = function() {
495  // create core
496  // add id for InfiniteScroll.data
497  let id = this.guid = ++GUID;
498  this.element.infiniteScrollGUID = id; // expando
499  instances[ id ] = this; // associate via id
500  // properties
501  this.pageIndex = 1; // default to first page
502  this.loadCount = 0;
503  this.updateGetPath();
504  // bail if getPath not set, or returns falsey #776
505  let hasPath = this.getPath && this.getPath();
506  if ( !hasPath ) {
507    console.error('Disabling InfiniteScroll');
508    return;
509  }
510  this.updateGetAbsolutePath();
511  this.log( 'initialized', [ this.element.className ] );
512  this.callOnInit();
513  // create features
514  for ( let method in InfiniteScroll.create ) {
515    InfiniteScroll.create[ method ].call( this );
516  }
517};
518
519proto.option = function( opts ) {
520  Object.assign( this.options, opts );
521};
522
523// call onInit option, used for binding events on init
524proto.callOnInit = function() {
525  let onInit = this.options.onInit;
526  if ( onInit ) {
527    onInit.call( this, this );
528  }
529};
530
531// ----- events ----- //
532
533proto.dispatchEvent = function( type, event, args ) {
534  this.log( type, args );
535  let emitArgs = event ? [ event ].concat( args ) : args;
536  this.emitEvent( type, emitArgs );
537  // trigger jQuery event
538  if ( !jQuery || !this.$element ) {
539    return;
540  }
541  // namespace jQuery event
542  type += '.infiniteScroll';
543  let $event = type;
544  if ( event ) {
545    // create jQuery event
546    /* eslint-disable-next-line new-cap */
547    let jQEvent = jQuery.Event( event );
548    jQEvent.type = type;
549    $event = jQEvent;
550  }
551  this.$element.trigger( $event, args );
552};
553
554let loggers = {
555  initialized: ( className ) => `on ${className}`,
556  request: ( path ) => `URL: ${path}`,
557  load: ( response, path ) => `${response.title || ''}. URL: ${path}`,
558  error: ( error, path ) => `${error}. URL: ${path}`,
559  append: ( response, path, items ) => `${items.length} items. URL: ${path}`,
560  last: ( response, path ) => `URL: ${path}`,
561  history: ( title, path ) => `URL: ${path}`,
562  pageIndex: function( index, origin ) {
563    return `current page determined to be: ${index} from ${origin}`;
564  },
565};
566
567// log events
568proto.log = function( type, args ) {
569  if ( !this.options.debug ) return;
570
571  let message = `[InfiniteScroll] ${type}`;
572  let logger = loggers[ type ];
573  if ( logger ) message += '. ' + logger.apply( this, args );
574  console.log( message );
575};
576
577// -------------------------- methods used amoung features -------------------------- //
578
579proto.updateMeasurements = function() {
580  this.windowHeight = window.innerHeight;
581  let rect = this.element.getBoundingClientRect();
582  this.top = rect.top + window.scrollY;
583};
584
585proto.updateScroller = function() {
586  let elementScroll = this.options.elementScroll;
587  if ( !elementScroll ) {
588    // default, use window
589    this.scroller = window;
590    return;
591  }
592  // if true, set to element, otherwise use option
593  this.scroller = elementScroll === true ? this.element :
594    utils.getQueryElement( elementScroll );
595  if ( !this.scroller ) {
596    throw new Error(`Unable to find elementScroll: ${elementScroll}`);
597  }
598};
599
600// -------------------------- page path -------------------------- //
601
602proto.updateGetPath = function() {
603  let optPath = this.options.path;
604  if ( !optPath ) {
605    console.error(`InfiniteScroll path option required. Set as: ${optPath}`);
606    return;
607  }
608  // function
609  let type = typeof optPath;
610  if ( type == 'function' ) {
611    this.getPath = optPath;
612    return;
613  }
614  // template string: '/pages/{{#}}.html'
615  let templateMatch = type == 'string' && optPath.match('{{#}}');
616  if ( templateMatch ) {
617    this.updateGetPathTemplate( optPath );
618    return;
619  }
620  // selector: '.next-page-selector'
621  this.updateGetPathSelector( optPath );
622};
623
624proto.updateGetPathTemplate = function( optPath ) {
625  // set getPath with template string
626  this.getPath = () => {
627    let nextIndex = this.pageIndex + 1;
628    return optPath.replace( '{{#}}', nextIndex );
629  };
630  // get pageIndex from location
631  // convert path option into regex to look for pattern in location
632  // escape query (?) in url, allows for parsing GET parameters
633  let regexString = optPath
634    .replace( /(\\\?|\?)/, '\\?' )
635    .replace( '{{#}}', '(\\d\\d?\\d?)' );
636  let templateRe = new RegExp( regexString );
637  let match = location.href.match( templateRe );
638
639  if ( match ) {
640    this.pageIndex = parseInt( match[1], 10 );
641    this.log( 'pageIndex', [ this.pageIndex, 'template string' ] );
642  }
643};
644
645let pathRegexes = [
646  // WordPress & Tumblr - example.com/page/2
647  // Jekyll - example.com/page2
648  /^(.*?\/?page\/?)(\d\d?\d?)(.*?$)/,
649  // Drupal - example.com/?page=1
650  /^(.*?\/?\?page=)(\d\d?\d?)(.*?$)/,
651  // catch all, last occurence of a number
652  /(.*?)(\d\d?\d?)(?!.*\d)(.*?$)/,
653];
654
655// try matching href to pathRegexes patterns
656let getPathParts = InfiniteScroll.getPathParts = function( href ) {
657  if ( !href ) return;
658  for ( let regex of pathRegexes ) {
659    let match = href.match( regex );
660    if ( match ) {
661      let [ , begin, index, end ] = match;
662      return { begin, index, end };
663    }
664  }
665};
666
667proto.updateGetPathSelector = function( optPath ) {
668  // parse href of link: '.next-page-link'
669  let hrefElem = document.querySelector( optPath );
670  if ( !hrefElem ) {
671    console.error(`Bad InfiniteScroll path option. Next link not found: ${optPath}`);
672    return;
673  }
674
675  let href = hrefElem.getAttribute('href');
676  let pathParts = getPathParts( href );
677  if ( !pathParts ) {
678    console.error(`InfiniteScroll unable to parse next link href: ${href}`);
679    return;
680  }
681
682  let { begin, index, end } = pathParts;
683  this.isPathSelector = true; // flag for checkLastPage()
684  this.getPath = () => begin + ( this.pageIndex + 1 ) + end;
685  // get pageIndex from href
686  this.pageIndex = parseInt( index, 10 ) - 1;
687  this.log( 'pageIndex', [ this.pageIndex, 'next link' ] );
688};
689
690proto.updateGetAbsolutePath = function() {
691  let path = this.getPath();
692  // path doesn't start with http or /
693  let isAbsolute = path.match( /^http/ ) || path.match( /^\// );
694  if ( isAbsolute ) {
695    this.getAbsolutePath = this.getPath;
696    return;
697  }
698
699  let { pathname } = location;
700  // query parameter #829. example.com/?pg=2
701  let isQuery = path.match( /^\?/ );
702  // /foo/bar/index.html => /foo/bar
703  let directory = pathname.substring( 0, pathname.lastIndexOf('/') );
704  let pathStart = isQuery ? pathname : directory + '/';
705
706  this.getAbsolutePath = () => pathStart + this.getPath();
707};
708
709// -------------------------- nav -------------------------- //
710
711// hide navigation
712InfiniteScroll.create.hideNav = function() {
713  let nav = utils.getQueryElement( this.options.hideNav );
714  if ( !nav ) return;
715
716  nav.style.display = 'none';
717  this.nav = nav;
718};
719
720InfiniteScroll.destroy.hideNav = function() {
721  if ( this.nav ) this.nav.style.display = '';
722};
723
724// -------------------------- destroy -------------------------- //
725
726proto.destroy = function() {
727  this.allOff(); // remove all event listeners
728  // call destroy methods
729  for ( let method in InfiniteScroll.destroy ) {
730    InfiniteScroll.destroy[ method ].call( this );
731  }
732
733  delete this.element.infiniteScrollGUID;
734  delete instances[ this.guid ];
735  // remove jQuery data. #807
736  if ( jQuery && this.$element ) {
737    jQuery.removeData( this.element, 'infiniteScroll' );
738  }
739};
740
741// -------------------------- utilities -------------------------- //
742
743// https://remysharp.com/2010/07/21/throttling-function-calls
744InfiniteScroll.throttle = function( fn, threshold ) {
745  threshold = threshold || 200;
746  let last, timeout;
747
748  return function() {
749    let now = +new Date();
750    let args = arguments;
751    let trigger = () => {
752      last = now;
753      fn.apply( this, args );
754    };
755    if ( last && now < last + threshold ) {
756      // hold on to it
757      clearTimeout( timeout );
758      timeout = setTimeout( trigger, threshold );
759    } else {
760      trigger();
761    }
762  };
763};
764
765InfiniteScroll.data = function( elem ) {
766  elem = utils.getQueryElement( elem );
767  let id = elem && elem.infiniteScrollGUID;
768  return id && instances[ id ];
769};
770
771// set internal jQuery, for Webpack + jQuery v3
772InfiniteScroll.setJQuery = function( jqry ) {
773  jQuery = jqry;
774};
775
776// -------------------------- setup -------------------------- //
777
778utils.htmlInit( InfiniteScroll, 'infinite-scroll' );
779
780// add noop _init method for jQuery Bridget. #768
781proto._init = function() {};
782
783let { jQueryBridget } = window;
784if ( jQuery && jQueryBridget ) {
785  jQueryBridget( 'infiniteScroll', InfiniteScroll, jQuery );
786}
787
788// --------------------------  -------------------------- //
789
790return InfiniteScroll;
791
792} ) );
793// page-load
794( function( window, factory ) {
795  // universal module definition
796  if ( typeof module == 'object' && module.exports ) {
797    // CommonJS
798    module.exports = factory(
799        window,
800        require('./core'),
801    );
802  } else {
803    // browser global
804    factory(
805        window,
806        window.InfiniteScroll,
807    );
808  }
809
810}( window, function factory( window, InfiniteScroll ) {
811
812let proto = InfiniteScroll.prototype;
813
814Object.assign( InfiniteScroll.defaults, {
815  // append: false,
816  loadOnScroll: true,
817  checkLastPage: true,
818  responseBody: 'text',
819  domParseResponse: true,
820  // prefill: false,
821  // outlayer: null,
822} );
823
824InfiniteScroll.create.pageLoad = function() {
825  this.canLoad = true;
826  this.on( 'scrollThreshold', this.onScrollThresholdLoad );
827  this.on( 'load', this.checkLastPage );
828  if ( this.options.outlayer ) {
829    this.on( 'append', this.onAppendOutlayer );
830  }
831};
832
833proto.onScrollThresholdLoad = function() {
834  if ( this.options.loadOnScroll ) this.loadNextPage();
835};
836
837let domParser = new DOMParser();
838
839proto.loadNextPage = function() {
840  if ( this.isLoading || !this.canLoad ) return;
841
842  let { responseBody, domParseResponse, fetchOptions } = this.options;
843  let path = this.getAbsolutePath();
844  this.isLoading = true;
845  if ( typeof fetchOptions == 'function' ) fetchOptions = fetchOptions();
846
847  let fetchPromise = fetch( path, fetchOptions )
848    .then( ( response ) => {
849      if ( !response.ok ) {
850        let error = new Error( response.statusText );
851        this.onPageError( error, path, response );
852        return { response };
853      }
854
855      return response[ responseBody ]().then( ( body ) => {
856        let canDomParse = responseBody == 'text' && domParseResponse;
857        if ( canDomParse ) {
858          body = domParser.parseFromString( body, 'text/html' );
859        }
860        if ( response.status == 204 ) {
861          this.lastPageReached( body, path );
862          return { body, response };
863        } else {
864          return this.onPageLoad( body, path, response );
865        }
866      } );
867    } )
868    .catch( ( error ) => {
869      this.onPageError( error, path );
870    } );
871
872  this.dispatchEvent( 'request', null, [ path, fetchPromise ] );
873
874  return fetchPromise;
875};
876
877proto.onPageLoad = function( body, path, response ) {
878  // done loading if not appending
879  if ( !this.options.append ) {
880    this.isLoading = false;
881  }
882  this.pageIndex++;
883  this.loadCount++;
884  this.dispatchEvent( 'load', null, [ body, path, response ] );
885  return this.appendNextPage( body, path, response );
886};
887
888proto.appendNextPage = function( body, path, response ) {
889  let { append, responseBody, domParseResponse } = this.options;
890  // do not append json
891  let isDocument = responseBody == 'text' && domParseResponse;
892  if ( !isDocument || !append ) return { body, response };
893
894  let items = body.querySelectorAll( append );
895  let promiseValue = { body, response, items };
896  // last page hit if no items. #840
897  if ( !items || !items.length ) {
898    this.lastPageReached( body, path );
899    return promiseValue;
900  }
901
902  let fragment = getItemsFragment( items );
903  let appendReady = () => {
904    this.appendItems( items, fragment );
905    this.isLoading = false;
906    this.dispatchEvent( 'append', null, [ body, path, items, response ] );
907    return promiseValue;
908  };
909
910  // TODO add hook for option to trigger appendReady
911  if ( this.options.outlayer ) {
912    return this.appendOutlayerItems( fragment, appendReady );
913  } else {
914    return appendReady();
915  }
916};
917
918proto.appendItems = function( items, fragment ) {
919  if ( !items || !items.length ) return;
920
921  // get fragment if not provided
922  fragment = fragment || getItemsFragment( items );
923  refreshScripts( fragment );
924  this.element.appendChild( fragment );
925};
926
927function getItemsFragment( items ) {
928  // add items to fragment
929  let fragment = document.createDocumentFragment();
930  if ( items ) fragment.append( ...items );
931  return fragment;
932}
933
934// replace <script>s with copies so they load
935// <script>s added by InfiniteScroll will not load
936// similar to https://stackoverflow.com/questions/610995
937function refreshScripts( fragment ) {
938  let scripts = fragment.querySelectorAll('script');
939  for ( let script of scripts ) {
940    let freshScript = document.createElement('script');
941    // copy attributes
942    let attrs = script.attributes;
943    for ( let attr of attrs ) {
944      freshScript.setAttribute( attr.name, attr.value );
945    }
946    // copy inner script code. #718, #782
947    freshScript.innerHTML = script.innerHTML;
948    script.parentNode.replaceChild( freshScript, script );
949  }
950}
951
952// ----- outlayer ----- //
953
954proto.appendOutlayerItems = function( fragment, appendReady ) {
955  let imagesLoaded = InfiniteScroll.imagesLoaded || window.imagesLoaded;
956  if ( !imagesLoaded ) {
957    console.error('[InfiniteScroll] imagesLoaded required for outlayer option');
958    this.isLoading = false;
959    return;
960  }
961  // append once images loaded
962  return new Promise( function( resolve ) {
963    imagesLoaded( fragment, function() {
964      let bodyResponse = appendReady();
965      resolve( bodyResponse );
966    } );
967  } );
968};
969
970proto.onAppendOutlayer = function( response, path, items ) {
971  this.options.outlayer.appended( items );
972};
973
974// ----- checkLastPage ----- //
975
976// check response for next element
977proto.checkLastPage = function( body, path ) {
978  let { checkLastPage, path: pathOpt } = this.options;
979  if ( !checkLastPage ) return;
980
981  // if path is function, check if next path is truthy
982  if ( typeof pathOpt == 'function' ) {
983    let nextPath = this.getPath();
984    if ( !nextPath ) {
985      this.lastPageReached( body, path );
986      return;
987    }
988  }
989  // get selector from checkLastPage or path option
990  let selector;
991  if ( typeof checkLastPage == 'string' ) {
992    selector = checkLastPage;
993  } else if ( this.isPathSelector ) {
994    // path option is selector string
995    selector = pathOpt;
996  }
997  // check last page for selector
998  // bail if no selector or not document response
999  if ( !selector || !body.querySelector ) return;
1000
1001  // check if response has selector
1002  let nextElem = body.querySelector( selector );
1003  if ( !nextElem ) this.lastPageReached( body, path );
1004};
1005
1006proto.lastPageReached = function( body, path ) {
1007  this.canLoad = false;
1008  this.dispatchEvent( 'last', null, [ body, path ] );
1009};
1010
1011// ----- error ----- //
1012
1013proto.onPageError = function( error, path, response ) {
1014  this.isLoading = false;
1015  this.canLoad = false;
1016  this.dispatchEvent( 'error', null, [ error, path, response ] );
1017  return error;
1018};
1019
1020// -------------------------- prefill -------------------------- //
1021
1022InfiniteScroll.create.prefill = function() {
1023  if ( !this.options.prefill ) return;
1024
1025  let append = this.options.append;
1026  if ( !append ) {
1027    console.error(`append option required for prefill. Set as :${append}`);
1028    return;
1029  }
1030  this.updateMeasurements();
1031  this.updateScroller();
1032  this.isPrefilling = true;
1033  this.on( 'append', this.prefill );
1034  this.once( 'error', this.stopPrefill );
1035  this.once( 'last', this.stopPrefill );
1036  this.prefill();
1037};
1038
1039proto.prefill = function() {
1040  let distance = this.getPrefillDistance();
1041  this.isPrefilling = distance >= 0;
1042  if ( this.isPrefilling ) {
1043    this.log('prefill');
1044    this.loadNextPage();
1045  } else {
1046    this.stopPrefill();
1047  }
1048};
1049
1050proto.getPrefillDistance = function() {
1051  // element scroll
1052  if ( this.options.elementScroll ) {
1053    return this.scroller.clientHeight - this.scroller.scrollHeight;
1054  }
1055  // window
1056  return this.windowHeight - this.element.clientHeight;
1057};
1058
1059proto.stopPrefill = function() {
1060  this.log('stopPrefill');
1061  this.off( 'append', this.prefill );
1062};
1063
1064// --------------------------  -------------------------- //
1065
1066return InfiniteScroll;
1067
1068} ) );
1069// scroll-watch
1070( function( window, factory ) {
1071  // universal module definition
1072  if ( typeof module == 'object' && module.exports ) {
1073    // CommonJS
1074    module.exports = factory(
1075        window,
1076        require('./core'),
1077        require('fizzy-ui-utils'),
1078    );
1079  } else {
1080    // browser global
1081    factory(
1082        window,
1083        window.InfiniteScroll,
1084        window.fizzyUIUtils,
1085    );
1086  }
1087
1088}( window, function factory( window, InfiniteScroll, utils ) {
1089
1090let proto = InfiniteScroll.prototype;
1091
1092// default options
1093Object.assign( InfiniteScroll.defaults, {
1094  scrollThreshold: 400,
1095  // elementScroll: null,
1096} );
1097
1098InfiniteScroll.create.scrollWatch = function() {
1099  // events
1100  this.pageScrollHandler = this.onPageScroll.bind( this );
1101  this.resizeHandler = this.onResize.bind( this );
1102
1103  let scrollThreshold = this.options.scrollThreshold;
1104  let isEnable = scrollThreshold || scrollThreshold === 0;
1105  if ( isEnable ) this.enableScrollWatch();
1106};
1107
1108InfiniteScroll.destroy.scrollWatch = function() {
1109  this.disableScrollWatch();
1110};
1111
1112proto.enableScrollWatch = function() {
1113  if ( this.isScrollWatching ) return;
1114
1115  this.isScrollWatching = true;
1116  this.updateMeasurements();
1117  this.updateScroller();
1118  // TODO disable after error?
1119  this.on( 'last', this.disableScrollWatch );
1120  this.bindScrollWatchEvents( true );
1121};
1122
1123proto.disableScrollWatch = function() {
1124  if ( !this.isScrollWatching ) return;
1125
1126  this.bindScrollWatchEvents( false );
1127  delete this.isScrollWatching;
1128};
1129
1130proto.bindScrollWatchEvents = function( isBind ) {
1131  let addRemove = isBind ? 'addEventListener' : 'removeEventListener';
1132  this.scroller[ addRemove ]( 'scroll', this.pageScrollHandler );
1133  window[ addRemove ]( 'resize', this.resizeHandler );
1134};
1135
1136proto.onPageScroll = InfiniteScroll.throttle( function() {
1137  let distance = this.getBottomDistance();
1138  if ( distance <= this.options.scrollThreshold ) {
1139    this.dispatchEvent('scrollThreshold');
1140  }
1141} );
1142
1143proto.getBottomDistance = function() {
1144  let bottom, scrollY;
1145  if ( this.options.elementScroll ) {
1146    bottom = this.scroller.scrollHeight;
1147    scrollY = this.scroller.scrollTop + this.scroller.clientHeight;
1148  } else {
1149    bottom = this.top + this.element.clientHeight;
1150    scrollY = window.scrollY + this.windowHeight;
1151  }
1152  return bottom - scrollY;
1153};
1154
1155proto.onResize = function() {
1156  this.updateMeasurements();
1157};
1158
1159utils.debounceMethod( InfiniteScroll, 'onResize', 150 );
1160
1161// --------------------------  -------------------------- //
1162
1163return InfiniteScroll;
1164
1165} ) );
1166// history
1167( function( window, factory ) {
1168  // universal module definition
1169  if ( typeof module == 'object' && module.exports ) {
1170    // CommonJS
1171    module.exports = factory(
1172        window,
1173        require('./core'),
1174        require('fizzy-ui-utils'),
1175    );
1176  } else {
1177    // browser global
1178    factory(
1179        window,
1180        window.InfiniteScroll,
1181        window.fizzyUIUtils,
1182    );
1183  }
1184
1185}( window, function factory( window, InfiniteScroll, utils ) {
1186
1187let proto = InfiniteScroll.prototype;
1188
1189Object.assign( InfiniteScroll.defaults, {
1190  history: 'replace',
1191  // historyTitle: false,
1192} );
1193
1194let link = document.createElement('a');
1195
1196// ----- create/destroy ----- //
1197
1198InfiniteScroll.create.history = function() {
1199  if ( !this.options.history ) return;
1200
1201  // check for same origin
1202  link.href = this.getAbsolutePath();
1203  // MS Edge does not have origin on link
1204  // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12236493/
1205  let linkOrigin = link.origin || link.protocol + '//' + link.host;
1206  let isSameOrigin = linkOrigin == location.origin;
1207  if ( !isSameOrigin ) {
1208    console.error( '[InfiniteScroll] cannot set history with different origin: ' +
1209      `${link.origin} on ${location.origin} . History behavior disabled.` );
1210    return;
1211  }
1212
1213  // two ways to handle changing history
1214  if ( this.options.append ) {
1215    this.createHistoryAppend();
1216  } else {
1217    this.createHistoryPageLoad();
1218  }
1219};
1220
1221proto.createHistoryAppend = function() {
1222  this.updateMeasurements();
1223  this.updateScroller();
1224  // array of scroll positions of appended pages
1225  this.scrollPages = [
1226    // first page
1227    {
1228      top: 0,
1229      path: location.href,
1230      title: document.title,
1231    },
1232  ];
1233  this.scrollPage = this.scrollPages[0];
1234  // events
1235  this.scrollHistoryHandler = this.onScrollHistory.bind( this );
1236  this.unloadHandler = this.onUnload.bind( this );
1237  this.scroller.addEventListener( 'scroll', this.scrollHistoryHandler );
1238  this.on( 'append', this.onAppendHistory );
1239  this.bindHistoryAppendEvents( true );
1240};
1241
1242proto.bindHistoryAppendEvents = function( isBind ) {
1243  let addRemove = isBind ? 'addEventListener' : 'removeEventListener';
1244  this.scroller[ addRemove ]( 'scroll', this.scrollHistoryHandler );
1245  window[ addRemove ]( 'unload', this.unloadHandler );
1246};
1247
1248proto.createHistoryPageLoad = function() {
1249  this.on( 'load', this.onPageLoadHistory );
1250};
1251
1252InfiniteScroll.destroy.history =
1253proto.destroyHistory = function() {
1254  let isHistoryAppend = this.options.history && this.options.append;
1255  if ( isHistoryAppend ) {
1256    this.bindHistoryAppendEvents( false );
1257  }
1258};
1259
1260// ----- append history ----- //
1261
1262proto.onAppendHistory = function( response, path, items ) {
1263  // do not proceed if no items. #779
1264  if ( !items || !items.length ) return;
1265
1266  let firstItem = items[0];
1267  let elemScrollY = this.getElementScrollY( firstItem );
1268  // resolve path
1269  link.href = path;
1270  // add page data to hash
1271  this.scrollPages.push({
1272    top: elemScrollY,
1273    path: link.href,
1274    title: response.title,
1275  });
1276};
1277
1278proto.getElementScrollY = function( elem ) {
1279  if ( this.options.elementScroll ) {
1280    return elem.offsetTop - this.top;
1281  } else {
1282    let rect = elem.getBoundingClientRect();
1283    return rect.top + window.scrollY;
1284  }
1285};
1286
1287proto.onScrollHistory = function() {
1288  // cycle through positions, find biggest without going over
1289  let scrollPage = this.getClosestScrollPage();
1290  // set history if changed
1291  if ( scrollPage != this.scrollPage ) {
1292    this.scrollPage = scrollPage;
1293    this.setHistory( scrollPage.title, scrollPage.path );
1294  }
1295};
1296
1297utils.debounceMethod( InfiniteScroll, 'onScrollHistory', 150 );
1298
1299proto.getClosestScrollPage = function() {
1300  let scrollViewY;
1301  if ( this.options.elementScroll ) {
1302    scrollViewY = this.scroller.scrollTop + this.scroller.clientHeight / 2;
1303  } else {
1304    scrollViewY = window.scrollY + this.windowHeight / 2;
1305  }
1306
1307  let scrollPage;
1308  for ( let page of this.scrollPages ) {
1309    if ( page.top >= scrollViewY ) break;
1310
1311    scrollPage = page;
1312  }
1313  return scrollPage;
1314};
1315
1316proto.setHistory = function( title, path ) {
1317  let optHistory = this.options.history;
1318  let historyMethod = optHistory && history[ optHistory + 'State' ];
1319  if ( !historyMethod ) return;
1320
1321  history[ optHistory + 'State' ]( null, title, path );
1322  if ( this.options.historyTitle ) document.title = title;
1323  this.dispatchEvent( 'history', null, [ title, path ] );
1324};
1325
1326// scroll to top to prevent initial scroll-reset after page refresh
1327// https://stackoverflow.com/a/18633915/182183
1328proto.onUnload = function() {
1329  if ( this.scrollPage.top === 0 ) return;
1330
1331  // calculate where scroll position would be on refresh
1332  let scrollY = window.scrollY - this.scrollPage.top + this.top;
1333  // disable scroll event before setting scroll #679
1334  this.destroyHistory();
1335  scrollTo( 0, scrollY );
1336};
1337
1338// ----- load history ----- //
1339
1340// update URL
1341proto.onPageLoadHistory = function( response, path ) {
1342  this.setHistory( response.title, path );
1343};
1344
1345// --------------------------  -------------------------- //
1346
1347return InfiniteScroll;
1348
1349} ) );
1350// button
1351( function( window, factory ) {
1352  // universal module definition
1353  if ( typeof module == 'object' && module.exports ) {
1354    // CommonJS
1355    module.exports = factory(
1356        window,
1357        require('./core'),
1358        require('fizzy-ui-utils'),
1359    );
1360  } else {
1361    // browser global
1362    factory(
1363        window,
1364        window.InfiniteScroll,
1365        window.fizzyUIUtils,
1366    );
1367  }
1368
1369}( window, function factory( window, InfiniteScroll, utils ) {
1370
1371// -------------------------- InfiniteScrollButton -------------------------- //
1372
1373class InfiniteScrollButton {
1374  constructor( element, infScroll ) {
1375    this.element = element;
1376    this.infScroll = infScroll;
1377    // events
1378    this.clickHandler = this.onClick.bind( this );
1379    this.element.addEventListener( 'click', this.clickHandler );
1380    infScroll.on( 'request', this.disable.bind( this ) );
1381    infScroll.on( 'load', this.enable.bind( this ) );
1382    infScroll.on( 'error', this.hide.bind( this ) );
1383    infScroll.on( 'last', this.hide.bind( this ) );
1384  }
1385
1386  onClick( event ) {
1387    event.preventDefault();
1388    this.infScroll.loadNextPage();
1389  }
1390
1391  enable() {
1392    this.element.removeAttribute('disabled');
1393  }
1394
1395  disable() {
1396    this.element.disabled = 'disabled';
1397  }
1398
1399  hide() {
1400    this.element.style.display = 'none';
1401  }
1402
1403  destroy() {
1404    this.element.removeEventListener( 'click', this.clickHandler );
1405  }
1406
1407}
1408
1409// -------------------------- InfiniteScroll methods -------------------------- //
1410
1411// InfiniteScroll.defaults.button = null;
1412
1413InfiniteScroll.create.button = function() {
1414  let buttonElem = utils.getQueryElement( this.options.button );
1415  if ( buttonElem ) {
1416    this.button = new InfiniteScrollButton( buttonElem, this );
1417  }
1418};
1419
1420InfiniteScroll.destroy.button = function() {
1421  if ( this.button ) this.button.destroy();
1422};
1423
1424// --------------------------  -------------------------- //
1425
1426InfiniteScroll.Button = InfiniteScrollButton;
1427
1428return InfiniteScroll;
1429
1430} ) );
1431// status
1432( function( window, factory ) {
1433  // universal module definition
1434  if ( typeof module == 'object' && module.exports ) {
1435    // CommonJS
1436    module.exports = factory(
1437        window,
1438        require('./core'),
1439        require('fizzy-ui-utils'),
1440    );
1441  } else {
1442    // browser global
1443    factory(
1444        window,
1445        window.InfiniteScroll,
1446        window.fizzyUIUtils,
1447    );
1448  }
1449
1450}( window, function factory( window, InfiniteScroll, utils ) {
1451
1452let proto = InfiniteScroll.prototype;
1453
1454// InfiniteScroll.defaults.status = null;
1455
1456InfiniteScroll.create.status = function() {
1457  let statusElem = utils.getQueryElement( this.options.status );
1458  if ( !statusElem ) return;
1459
1460  // elements
1461  this.statusElement = statusElem;
1462  this.statusEventElements = {
1463    request: statusElem.querySelector('.infinite-scroll-request'),
1464    error: statusElem.querySelector('.infinite-scroll-error'),
1465    last: statusElem.querySelector('.infinite-scroll-last'),
1466  };
1467  // events
1468  this.on( 'request', this.showRequestStatus );
1469  this.on( 'error', this.showErrorStatus );
1470  this.on( 'last', this.showLastStatus );
1471  this.bindHideStatus('on');
1472};
1473
1474proto.bindHideStatus = function( bindMethod ) {
1475  let hideEvent = this.options.append ? 'append' : 'load';
1476  this[ bindMethod ]( hideEvent, this.hideAllStatus );
1477};
1478
1479proto.showRequestStatus = function() {
1480  this.showStatus('request');
1481};
1482
1483proto.showErrorStatus = function() {
1484  this.showStatus('error');
1485};
1486
1487proto.showLastStatus = function() {
1488  this.showStatus('last');
1489  // prevent last then append event race condition from showing last status #706
1490  this.bindHideStatus('off');
1491};
1492
1493proto.showStatus = function( eventName ) {
1494  show( this.statusElement );
1495  this.hideStatusEventElements();
1496  let eventElem = this.statusEventElements[ eventName ];
1497  show( eventElem );
1498};
1499
1500proto.hideAllStatus = function() {
1501  hide( this.statusElement );
1502  this.hideStatusEventElements();
1503};
1504
1505proto.hideStatusEventElements = function() {
1506  for ( let type in this.statusEventElements ) {
1507    let eventElem = this.statusEventElements[ type ];
1508    hide( eventElem );
1509  }
1510};
1511
1512// --------------------------  -------------------------- //
1513
1514function hide( elem ) {
1515  setDisplay( elem, 'none' );
1516}
1517
1518function show( elem ) {
1519  setDisplay( elem, 'block' );
1520}
1521
1522function setDisplay( elem, value ) {
1523  if ( elem ) {
1524    elem.style.display = value;
1525  }
1526}
1527
1528// --------------------------  -------------------------- //
1529
1530return InfiniteScroll;
1531
1532} ) );
1533/*!
1534 * imagesLoaded v4.1.4
1535 * JavaScript is all like "You images are done yet or what?"
1536 * MIT License
1537 */
1538
1539( function( window, factory ) { 'use strict';
1540  // universal module definition
1541
1542  /*global define: false, module: false, require: false */
1543
1544  if ( typeof define == 'function' && define.amd ) {
1545    // AMD
1546    define( [
1547      'ev-emitter/ev-emitter'
1548    ], function( EvEmitter ) {
1549      return factory( window, EvEmitter );
1550    });
1551  } else if ( typeof module == 'object' && module.exports ) {
1552    // CommonJS
1553    module.exports = factory(
1554      window,
1555      require('ev-emitter')
1556    );
1557  } else {
1558    // browser global
1559    window.imagesLoaded = factory(
1560      window,
1561      window.EvEmitter
1562    );
1563  }
1564
1565})( typeof window !== 'undefined' ? window : this,
1566
1567// --------------------------  factory -------------------------- //
1568
1569function factory( window, EvEmitter ) {
1570
1571'use strict';
1572
1573var $ = window.jQuery;
1574var console = window.console;
1575
1576// -------------------------- helpers -------------------------- //
1577
1578// extend objects
1579function extend( a, b ) {
1580  for ( var prop in b ) {
1581    a[ prop ] = b[ prop ];
1582  }
1583  return a;
1584}
1585
1586var arraySlice = Array.prototype.slice;
1587
1588// turn element or nodeList into an array
1589function makeArray( obj ) {
1590  if ( Array.isArray( obj ) ) {
1591    // use object if already an array
1592    return obj;
1593  }
1594
1595  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
1596  if ( isArrayLike ) {
1597    // convert nodeList to array
1598    return arraySlice.call( obj );
1599  }
1600
1601  // array of single index
1602  return [ obj ];
1603}
1604
1605// -------------------------- imagesLoaded -------------------------- //
1606
1607/**
1608 * @param {Array, Element, NodeList, String} elem
1609 * @param {Object or Function} options - if function, use as callback
1610 * @param {Function} onAlways - callback function
1611 */
1612function ImagesLoaded( elem, options, onAlways ) {
1613  // coerce ImagesLoaded() without new, to be new ImagesLoaded()
1614  if ( !( this instanceof ImagesLoaded ) ) {
1615    return new ImagesLoaded( elem, options, onAlways );
1616  }
1617  // use elem as selector string
1618  var queryElem = elem;
1619  if ( typeof elem == 'string' ) {
1620    queryElem = document.querySelectorAll( elem );
1621  }
1622  // bail if bad element
1623  if ( !queryElem ) {
1624    console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) );
1625    return;
1626  }
1627
1628  this.elements = makeArray( queryElem );
1629  this.options = extend( {}, this.options );
1630  // shift arguments if no options set
1631  if ( typeof options == 'function' ) {
1632    onAlways = options;
1633  } else {
1634    extend( this.options, options );
1635  }
1636
1637  if ( onAlways ) {
1638    this.on( 'always', onAlways );
1639  }
1640
1641  this.getImages();
1642
1643  if ( $ ) {
1644    // add jQuery Deferred object
1645    this.jqDeferred = new $.Deferred();
1646  }
1647
1648  // HACK check async to allow time to bind listeners
1649  setTimeout( this.check.bind( this ) );
1650}
1651
1652ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
1653
1654ImagesLoaded.prototype.options = {};
1655
1656ImagesLoaded.prototype.getImages = function() {
1657  this.images = [];
1658
1659  // filter & find items if we have an item selector
vendor: 4,504 bytes, lines 1660-1816
1660  this.elements.forEach( this.addElementImages, this );
1661};
1662
1663/**
1664 * @param {Node} element
1665 */
1666ImagesLoaded.prototype.addElementImages = function( elem ) {
1667  // filter siblings
1668  if ( elem.nodeName == 'IMG' ) {
1669    this.addImage( elem );
1670  }
1671  // get background image on element
1672  if ( this.options.background === true ) {
1673    this.addElementBackgroundImages( elem );
1674  }
1675
1676  // find children
1677  // no non-element nodes, #143
1678  var nodeType = elem.nodeType;
1679  if ( !nodeType || !elementNodeTypes[ nodeType ] ) {
1680    return;
1681  }
1682  var childImgs = elem.querySelectorAll('img');
1683  // concat childElems to filterFound array
1684  for ( var i=0; i < childImgs.length; i++ ) {
1685    var img = childImgs[i];
1686    this.addImage( img );
1687  }
1688
1689  // get child background images
1690  if ( typeof this.options.background == 'string' ) {
1691    var children = elem.querySelectorAll( this.options.background );
1692    for ( i=0; i < children.length; i++ ) {
1693      var child = children[i];
1694      this.addElementBackgroundImages( child );
1695    }
1696  }
1697};
1698
1699var elementNodeTypes = {
1700  1: true,
1701  9: true,
1702  11: true
1703};
1704
1705ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
1706  var style = getComputedStyle( elem );
1707  if ( !style ) {
1708    // Firefox returns null if in a hidden iframe https://bugzil.la/548397
1709    return;
1710  }
1711  // get url inside url("...")
1712  var reURL = /url\((['"])?(.*?)\1\)/gi;
1713  var matches = reURL.exec( style.backgroundImage );
1714  while ( matches !== null ) {
1715    var url = matches && matches[2];
1716    if ( url ) {
1717      this.addBackground( url, elem );
1718    }
1719    matches = reURL.exec( style.backgroundImage );
1720  }
1721};
1722
1723/**
1724 * @param {Image} img
1725 */
1726ImagesLoaded.prototype.addImage = function( img ) {
1727  var loadingImage = new LoadingImage( img );
1728  this.images.push( loadingImage );
1729};
1730
1731ImagesLoaded.prototype.addBackground = function( url, elem ) {
1732  var background = new Background( url, elem );
1733  this.images.push( background );
1734};
1735
1736ImagesLoaded.prototype.check = function() {
1737  var _this = this;
1738  this.progressedCount = 0;
1739  this.hasAnyBroken = false;
1740  // complete if no images
1741  if ( !this.images.length ) {
1742    this.complete();
1743    return;
1744  }
1745
1746  function onProgress( image, elem, message ) {
1747    // HACK - Chrome triggers event before object properties have changed. #83
1748    setTimeout( function() {
1749      _this.progress( image, elem, message );
1750    });
1751  }
1752
1753  this.images.forEach( function( loadingImage ) {
1754    loadingImage.once( 'progress', onProgress );
1755    loadingImage.check();
1756  });
1757};
1758
1759ImagesLoaded.prototype.progress = function( image, elem, message ) {
1760  this.progressedCount++;
1761  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
1762  // progress event
1763  this.emitEvent( 'progress', [ this, image, elem ] );
1764  if ( this.jqDeferred && this.jqDeferred.notify ) {
1765    this.jqDeferred.notify( this, image );
1766  }
1767  // check if completed
1768  if ( this.progressedCount == this.images.length ) {
1769    this.complete();
1770  }
1771
1772  if ( this.options.debug && console ) {
1773    console.log( 'progress: ' + message, image, elem );
1774  }
1775};
1776
1777ImagesLoaded.prototype.complete = function() {
1778  var eventName = this.hasAnyBroken ? 'fail' : 'done';
1779  this.isComplete = true;
1780  this.emitEvent( eventName, [ this ] );
1781  this.emitEvent( 'always', [ this ] );
1782  if ( this.jqDeferred ) {
1783    var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
1784    this.jqDeferred[ jqMethod ]( this );
1785  }
1786};
1787
1788// --------------------------  -------------------------- //
1789
1790function LoadingImage( img ) {
1791  this.img = img;
1792}
1793
1794LoadingImage.prototype = Object.create( EvEmitter.prototype );
1795
1796LoadingImage.prototype.check = function() {
1797  // If complete is true and browser supports natural sizes,
1798  // try to check for image status manually.
1799  var isComplete = this.getIsImageComplete();
1800  if ( isComplete ) {
1801    // report based on naturalWidth
1802    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
1803    return;
1804  }
1805
1806  // If none of the checks above matched, simulate loading on detached element.
1807  this.proxyImage = new Image();
1808  this.proxyImage.addEventListener( 'load', this );
1809  this.proxyImage.addEventListener( 'error', this );
1810  // bind to image as well for Firefox. #191
1811  this.img.addEventListener( 'load', this );
1812  this.img.addEventListener( 'error', this );
1813  this.proxyImage.src = this.img.src;
1814};
1815
1816LoadingImage.prototype.getIsImageComplete = function() {
vendor: 2,659 bytes, lines 1817-1909
1817  // check for non-zero, non-undefined naturalWidth
1818  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
1819  return this.img.complete && this.img.naturalWidth;
1820};
1821
1822LoadingImage.prototype.confirm = function( isLoaded, message ) {
1823  this.isLoaded = isLoaded;
1824  this.emitEvent( 'progress', [ this, this.img, message ] );
1825};
1826
1827// ----- events ----- //
1828
1829// trigger specified handler for event type
1830LoadingImage.prototype.handleEvent = function( event ) {
1831  var method = 'on' + event.type;
1832  if ( this[ method ] ) {
1833    this[ method ]( event );
1834  }
1835};
1836
1837LoadingImage.prototype.onload = function() {
1838  this.confirm( true, 'onload' );
1839  this.unbindEvents();
1840};
1841
1842LoadingImage.prototype.onerror = function() {
1843  this.confirm( false, 'onerror' );
1844  this.unbindEvents();
1845};
1846
1847LoadingImage.prototype.unbindEvents = function() {
1848  this.proxyImage.removeEventListener( 'load', this );
1849  this.proxyImage.removeEventListener( 'error', this );
1850  this.img.removeEventListener( 'load', this );
1851  this.img.removeEventListener( 'error', this );
1852};
1853
1854// -------------------------- Background -------------------------- //
1855
1856function Background( url, element ) {
1857  this.url = url;
1858  this.element = element;
1859  this.img = new Image();
1860}
1861
1862// inherit LoadingImage prototype
1863Background.prototype = Object.create( LoadingImage.prototype );
1864
1865Background.prototype.check = function() {
1866  this.img.addEventListener( 'load', this );
1867  this.img.addEventListener( 'error', this );
1868  this.img.src = this.url;
1869  // check if image is already complete
1870  var isComplete = this.getIsImageComplete();
1871  if ( isComplete ) {
1872    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
1873    this.unbindEvents();
1874  }
1875};
1876
1877Background.prototype.unbindEvents = function() {
1878  this.img.removeEventListener( 'load', this );
1879  this.img.removeEventListener( 'error', this );
1880};
1881
1882Background.prototype.confirm = function( isLoaded, message ) {
1883  this.isLoaded = isLoaded;
1884  this.emitEvent( 'progress', [ this, this.element, message ] );
1885};
1886
1887// -------------------------- jQuery -------------------------- //
1888
1889ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
1890  jQuery = jQuery || window.jQuery;
1891  if ( !jQuery ) {
1892    return;
1893  }
1894  // set local variable
1895  $ = jQuery;
1896  // $().imagesLoaded()
1897  $.fn.imagesLoaded = function( options, callback ) {
1898    var instance = new ImagesLoaded( this, options, callback );
1899    return instance.jqDeferred.promise( $(this) );
1900  };
1901};
1902// try making plugin
1903ImagesLoaded.makeJQueryPlugin();
1904
1905// --------------------------  -------------------------- //
1906
1907return ImagesLoaded;
1908
1909});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.