PageSourceSearch

https://www.jaredleonmorgan.net/assets/js/lazyload.js

js jaredleonmorgan.net collected 2026-09-29 05:47:54 UTC 7,315 bytes, 258 lines download raw bytes

1/*! lazyload - v2.1.1 - 2018-04-01
2 * https://github.com/13twelve/lazyload
3 * Copyright (c) 2018
4 * License: MIT
5 * Author: Mike Byrne @13twelve https://github.com/13twelve
6 */
7
8(function (root, factory) {
9  if (typeof define === 'function' && define.amd) {
10    // AMD. Register as an anonymous module.
11    define([], factory);
12  } else if (typeof exports === 'object') {
13    // Node. Does not work with strict CommonJS, but
14    // only CommonJS-like environments that support module.exports,
15    // like Node.
16    module.exports = factory();
17  } else {
18    // Browser globals (root is window)
19    root.lazyLoad = factory();
20  }
21}(this, function () {
22
23  var options = {
24    pageUpdatedEventName: 'page:updated', // how your app tells the rest of the app an update happened
25    elements: 'img[data-src], img[data-srcset], source[data-srcset], iframe[data-src], video[data-src], [data-lazyload]', // maybe you just want images?
26    rootMargin: '0px', // IntersectionObserver option
27    threshold: 0, // IntersectionObserver option
28    maxFrameCount: 10, // 60fps / 10 = 6 times a second
29  };
30
31  // set up
32  var frameLoop;
33  var frameCount;
34  var els = [];
35  var elsLength;
36  var observer;
37  var checkType;
38
39  /**
40   * Converts HTML collections to an array
41   * @private
42   * @param {Array} array to convert
43   * a loop will work in more browsers than the slice method
44   */
45  function _htmlCollectionToArray(collection) {
46    var a = [];
47    var i = 0;
48    for (a = [], i = collection.length; i;) {
49      a[--i] = collection[i];
50    }
51    return a;
52  }
53
54  /**
55   * Checks if an element is in the viewport
56   * @private
57   * @param {Node} element to check.
58   * @returns {Boolean} true/false.
59   */
60  function _elInViewport(el) {
61    el = (el.tagName === 'SOURCE') ? el.parentNode : el;
62    var rect = el.getBoundingClientRect();
63    return rect.bottom > 0 && rect.right > 0 && rect.left < (window.innerWidth || document.documentElement.clientWidth) && rect.top < (window.innerHeight || document.documentElement.clientHeight);
64  }
65
66  /**
67   * Removes data- attributes
68   * @private
69   * @param {Node} element to update
70   */
71  function _removeDataAttrs(el) {
72    el.removeAttribute('data-src');
73    el.removeAttribute('data-srcset');
74    el.removeAttribute('data-lazyload');
75  }
76
77  /**
78   * On loaded, removes event listener, removes data- attributes
79   * @private
80   */
81  function _loaded() {
82    this.removeEventListener('load', _loaded);
83    _removeDataAttrs(this);
84  }
85
86  /**
87   * Update an element
88   * @private
89   * @param {Node} element to update
90   */
91  function _updateEl(el) {
92    var srcset = el.getAttribute('data-srcset');
93    var src = el.getAttribute('data-src');
94    var dlazyload = el.getAttribute('data-lazyload') !== null;
95    //
96    if (srcset) {
97      // if source set, update and try picturefill
98      el.setAttribute('srcset', srcset);
99      if (window.picturefill) {
100        window.picturefill({
101          elements: [el]
102        });
103      }
104    }
105    if (src) {
106      // if source set, update
107      el.src = src;
108    }
109    if (dlazyload) {
110      el.setAttribute('data-lazyloaded','');
111      el.removeEventListener('load', _loaded);
112      _removeDataAttrs(el);
113    }
114  }
115
116  /**
117   * The callback from the IntersectionObserver
118   * @private
119   * @entries {Nodes} elements being observed by the IntersectionObserver
120   */
121  function _intersection(entries) {
122    // Disconnect if we've already loaded all of the images
123    if (elsLength === 0) {
124      observer.disconnect();
125    }
126    // Loop through the entries
127    for (var i = 0; i < entries.length; i++) {
128      var entry = entries[i];
129      // Are we in viewport?
130      if (entry.intersectionRatio > 0) {
131        elsLength--;
132        // Stop watching this and load the image
133        observer.unobserve(entry.target);
134        entry.target.addEventListener('load', _loaded, false);
135        _updateEl(entry.target);
136      }
137    }
138  }
139
140  /**
141   * Loops images, checks if in viewport, updates src/src-set
142   * @private
143   */
144  function _setSrcs() {
145    var i;
146    // browser capability check
147    if (checkType === 'really-old') {
148      elsLength = els.length;
149      for (i = 0; i < elsLength; i++) {
150        if (els[i]) {
151          _updateEl(els[i]);
152          _removeDataAttrs(els[i]);
153        }
154      }
155      els = [];
156    } else if (checkType === 'old') {
157      // debounce checking
158      if (frameCount === options.maxFrameCount) {
159        // update cache of this for the loop
160        elsLength = els.length;
161        for (i = 0; i < elsLength; i++) {
162          // check if this array item exists, hasn't been loaded already and is in the viewport
163          if (els[i] && els[i].lazyloaded === undefined && _elInViewport(els[i])) {
164            // cache this array item
165            var thisEl = els[i];
166            // set this array item to be undefined to be cleaned up later
167            els[i] = undefined;
168            // give this element a property to stop us running twice on one thing
169            thisEl.lazyloaded = true;
170            // add an event listener to remove data- attributes on load
171            thisEl.addEventListener('load', _loaded, false);
172            // update
173            _updateEl(thisEl);
174          }
175        }
176        // clean up array
177        for (i = 0; i < elsLength; i++) {
178          if (els[i] === undefined) {
179            els.splice(i, 1);
180          }
181        }
182        // reset var to decide if to continue running
183        elsLength = els.length;
184        // will shortly be set to 0 to start counting
185        frameCount = -1;
186      }
187
188      // run again? kill if not
189      if (elsLength > 0) {
190        frameCount++;
191        frameLoop = window.requestAnimationFrame(_setSrcs);
192      }
193    } else if (checkType === 'new') {
194      observer = new IntersectionObserver(_intersection, {
195        rootMargin: options.rootMargin,
196        threshold: options.threshold,
197      });
198      elsLength = els.length;
199      for (i = 0; i < elsLength; i++) {
200        if (els[i] && els[i].lazyloaded === undefined) {
201          observer.observe(els[i]);
202        }
203      }
204    }
205  }
206
207  /**
208   * Gets the show on the road
209   * @private
210   */
211  function _init() {
212    // kill any old loops if there are any
213    if (checkType === 'old') {
214      try {
215        cancelAnimationFrame(frameLoop);
216      } catch(err) {}
217    } else if (checkType === 'new') {
218      try {
219        observer.disconnect();
220      } catch(err) {}
221    }
222    // grab elements to lazy load
223    els = _htmlCollectionToArray(document.querySelectorAll(options.elements));
224    elsLength = els.length;
225    frameCount = options.maxFrameCount;
226    // go go go
227    _setSrcs();
228  }
229
230  /**
231   * GO GO GO
232   * @public
233   * @param {object} options (see readme)
234   */
235  var lazyLoad = function(opts) {
236    for(var item in opts) {
237      if(opts.hasOwnProperty(item)) {
238        options[item] = opts[item];
239      }
240    }
241    if(!('addEventListener' in window) || !window.requestAnimationFrame || typeof document.body.getBoundingClientRect === undefined) {
242      checkType = 'really-old';
243    } else if ('IntersectionObserver' in window) {
244      checkType = 'new';
245    } else {
246      checkType = 'old';
247    }
248    _init();
249    if (options.pageUpdatedEventName) {
250      document.addEventListener(options.pageUpdatedEventName, _init, true);
251    }
252  };
253
254  return lazyLoad;
255}));
256
257lazyLoad();
258

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.