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.