babel.min.js
2 months ago
component.cdn.js
2 months ago
component.crawler.js
2 months ago
css_async.js
2 months ago
css_async.min.js
2 months ago
guest.docref.js
2 months ago
guest.docref.min.js
2 months ago
guest.js
2 months ago
guest.min.js
2 months ago
instant_click.min.js
2 months ago
instant_click.ori.js
2 months ago
iziModal.min.js
2 months ago
js_delay.js
2 months ago
js_delay.min.js
2 months ago
lazyload.init.js
2 months ago
lazyload.lib.js
2 months ago
lazyload.min.js
2 months ago
litespeed-cache-admin.js
2 months ago
react.min.js
2 months ago
webfontloader.js
2 months ago
webfontloader.min.js
2 months ago
lazyload.lib.js
818 lines
| 1 | (function (global, factory) { |
| 2 | typeof exports === 'object' && typeof module !== 'undefined' |
| 3 | ? (module.exports = factory()) |
| 4 | : typeof define === 'function' && define.amd |
| 5 | ? define(factory) |
| 6 | : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), (global.LazyLoad = factory())); |
| 7 | })(this, function () { |
| 8 | 'use strict'; |
| 9 | |
| 10 | function _extends() { |
| 11 | _extends = |
| 12 | Object.assign || |
| 13 | function (target) { |
| 14 | for (var i = 1; i < arguments.length; i++) { |
| 15 | var source = arguments[i]; |
| 16 | |
| 17 | for (var key in source) { |
| 18 | if (Object.prototype.hasOwnProperty.call(source, key)) { |
| 19 | target[key] = source[key]; |
| 20 | } |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | return target; |
| 25 | }; |
| 26 | |
| 27 | return _extends.apply(this, arguments); |
| 28 | } |
| 29 | |
| 30 | var runningOnBrowser = typeof window !== 'undefined'; |
| 31 | var isBot = (runningOnBrowser && !('onscroll' in window)) || (typeof navigator !== 'undefined' && /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent)); |
| 32 | var supportsIntersectionObserver = runningOnBrowser && 'IntersectionObserver' in window; |
| 33 | var supportsClassList = runningOnBrowser && 'classList' in document.createElement('p'); |
| 34 | var isHiDpi = runningOnBrowser && window.devicePixelRatio > 1; |
| 35 | |
| 36 | var defaultSettings = { |
| 37 | elements_selector: '.lazy', |
| 38 | container: isBot || runningOnBrowser ? document : null, |
| 39 | threshold: 300, |
| 40 | thresholds: null, |
| 41 | data_src: 'src', |
| 42 | data_srcset: 'srcset', |
| 43 | data_sizes: 'sizes', |
| 44 | data_bg: 'bg', |
| 45 | data_bg_hidpi: 'bg-hidpi', |
| 46 | data_bg_multi: 'bg-multi', |
| 47 | data_bg_multi_hidpi: 'bg-multi-hidpi', |
| 48 | data_poster: 'poster', |
| 49 | class_applied: 'applied', |
| 50 | class_loading: 'litespeed-loading', |
| 51 | class_loaded: 'litespeed-loaded', // https://docs.litespeedtech.com/lscache/lscwp/pageopt/#lazy-load-images |
| 52 | class_error: 'error', |
| 53 | class_entered: 'entered', |
| 54 | class_exited: 'exited', |
| 55 | unobserve_completed: true, |
| 56 | unobserve_entered: false, |
| 57 | cancel_on_exit: true, |
| 58 | callback_enter: null, |
| 59 | callback_exit: null, |
| 60 | callback_applied: null, |
| 61 | callback_loading: null, |
| 62 | callback_loaded: null, |
| 63 | callback_error: null, |
| 64 | callback_finish: null, |
| 65 | callback_cancel: null, |
| 66 | use_native: false, |
| 67 | }; |
| 68 | var getExtendedSettings = function getExtendedSettings(customSettings) { |
| 69 | return _extends({}, defaultSettings, customSettings); |
| 70 | }; |
| 71 | |
| 72 | /* Creates instance and notifies it through the window element */ |
| 73 | var createInstance = function createInstance(classObj, options) { |
| 74 | var event; |
| 75 | var eventString = 'LazyLoad::Initialized'; |
| 76 | var instance = new classObj(options); |
| 77 | |
| 78 | try { |
| 79 | // Works in modern browsers |
| 80 | event = new CustomEvent(eventString, { |
| 81 | detail: { |
| 82 | instance: instance, |
| 83 | }, |
| 84 | }); |
| 85 | } catch (err) { |
| 86 | // Works in Internet Explorer (all versions) |
| 87 | event = document.createEvent('CustomEvent'); |
| 88 | event.initCustomEvent(eventString, false, false, { |
| 89 | instance: instance, |
| 90 | }); |
| 91 | } |
| 92 | |
| 93 | window.dispatchEvent(event); |
| 94 | }; |
| 95 | /* Auto initialization of one or more instances of lazyload, depending on the |
| 96 | options passed in (plain object or an array) */ |
| 97 | |
| 98 | var autoInitialize = function autoInitialize(classObj, options) { |
| 99 | if (!options) { |
| 100 | return; |
| 101 | } |
| 102 | |
| 103 | if (!options.length) { |
| 104 | // Plain object |
| 105 | createInstance(classObj, options); |
| 106 | } else { |
| 107 | // Array of objects |
| 108 | for (var i = 0, optionsItem; (optionsItem = options[i]); i += 1) { |
| 109 | createInstance(classObj, optionsItem); |
| 110 | } |
| 111 | } |
| 112 | }; |
| 113 | |
| 114 | var SRC = 'src'; |
| 115 | var SRCSET = 'srcset'; |
| 116 | var SIZES = 'sizes'; |
| 117 | var POSTER = 'poster'; |
| 118 | var ORIGINALS = 'llOriginalAttrs'; |
| 119 | |
| 120 | var statusLoading = 'loading'; |
| 121 | var statusLoaded = 'loaded'; |
| 122 | var statusApplied = 'applied'; |
| 123 | var statusEntered = 'entered'; |
| 124 | var statusError = 'error'; |
| 125 | var statusNative = 'native'; |
| 126 | |
| 127 | var dataPrefix = 'data-'; |
| 128 | var statusDataName = 'll-status'; |
| 129 | var getData = function getData(element, attribute) { |
| 130 | return element.getAttribute(dataPrefix + attribute); |
| 131 | }; |
| 132 | var setData = function setData(element, attribute, value) { |
| 133 | var attrName = dataPrefix + attribute; |
| 134 | |
| 135 | if (value === null) { |
| 136 | element.removeAttribute(attrName); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | element.setAttribute(attrName, value); |
| 141 | }; |
| 142 | var getStatus = function getStatus(element) { |
| 143 | return getData(element, statusDataName); |
| 144 | }; |
| 145 | var setStatus = function setStatus(element, status) { |
| 146 | return setData(element, statusDataName, status); |
| 147 | }; |
| 148 | var resetStatus = function resetStatus(element) { |
| 149 | return setStatus(element, null); |
| 150 | }; |
| 151 | var hasEmptyStatus = function hasEmptyStatus(element) { |
| 152 | return getStatus(element) === null; |
| 153 | }; |
| 154 | var hasStatusLoading = function hasStatusLoading(element) { |
| 155 | return getStatus(element) === statusLoading; |
| 156 | }; |
| 157 | var hasStatusError = function hasStatusError(element) { |
| 158 | return getStatus(element) === statusError; |
| 159 | }; |
| 160 | var hasStatusNative = function hasStatusNative(element) { |
| 161 | return getStatus(element) === statusNative; |
| 162 | }; |
| 163 | var statusesAfterLoading = [statusLoading, statusLoaded, statusApplied, statusError]; |
| 164 | var hadStartedLoading = function hadStartedLoading(element) { |
| 165 | return statusesAfterLoading.indexOf(getStatus(element)) >= 0; |
| 166 | }; |
| 167 | |
| 168 | var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { |
| 169 | if (!callback) { |
| 170 | return; |
| 171 | } |
| 172 | |
| 173 | if (arg3 !== undefined) { |
| 174 | callback(arg1, arg2, arg3); |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | if (arg2 !== undefined) { |
| 179 | callback(arg1, arg2); |
| 180 | return; |
| 181 | } |
| 182 | |
| 183 | callback(arg1); |
| 184 | }; |
| 185 | |
| 186 | var addClass = function addClass(element, className) { |
| 187 | if (supportsClassList) { |
| 188 | element.classList.add(className); |
| 189 | return; |
| 190 | } |
| 191 | |
| 192 | element.className += (element.className ? ' ' : '') + className; |
| 193 | }; |
| 194 | var removeClass = function removeClass(element, className) { |
| 195 | if (supportsClassList) { |
| 196 | element.classList.remove(className); |
| 197 | return; |
| 198 | } |
| 199 | |
| 200 | element.className = element.className |
| 201 | .replace(new RegExp('(^|\\s+)' + className + '(\\s+|$)'), ' ') |
| 202 | .replace(/^\s+/, '') |
| 203 | .replace(/\s+$/, ''); |
| 204 | }; |
| 205 | |
| 206 | var addTempImage = function addTempImage(element) { |
| 207 | element.llTempImage = document.createElement('IMG'); |
| 208 | }; |
| 209 | var deleteTempImage = function deleteTempImage(element) { |
| 210 | delete element.llTempImage; |
| 211 | }; |
| 212 | var getTempImage = function getTempImage(element) { |
| 213 | return element.llTempImage; |
| 214 | }; |
| 215 | |
| 216 | var unobserve = function unobserve(element, instance) { |
| 217 | if (!instance) return; |
| 218 | var observer = instance._observer; |
| 219 | if (!observer) return; |
| 220 | observer.unobserve(element); |
| 221 | }; |
| 222 | var resetObserver = function resetObserver(observer) { |
| 223 | observer.disconnect(); |
| 224 | }; |
| 225 | var unobserveEntered = function unobserveEntered(element, settings, instance) { |
| 226 | if (settings.unobserve_entered) unobserve(element, instance); |
| 227 | }; |
| 228 | |
| 229 | var updateLoadingCount = function updateLoadingCount(instance, delta) { |
| 230 | if (!instance) return; |
| 231 | instance.loadingCount += delta; |
| 232 | }; |
| 233 | var decreaseToLoadCount = function decreaseToLoadCount(instance) { |
| 234 | if (!instance) return; |
| 235 | instance.toLoadCount -= 1; |
| 236 | }; |
| 237 | var setToLoadCount = function setToLoadCount(instance, value) { |
| 238 | if (!instance) return; |
| 239 | instance.toLoadCount = value; |
| 240 | }; |
| 241 | var isSomethingLoading = function isSomethingLoading(instance) { |
| 242 | return instance.loadingCount > 0; |
| 243 | }; |
| 244 | var haveElementsToLoad = function haveElementsToLoad(instance) { |
| 245 | return instance.toLoadCount > 0; |
| 246 | }; |
| 247 | |
| 248 | var getSourceTags = function getSourceTags(parentTag) { |
| 249 | var sourceTags = []; |
| 250 | |
| 251 | for (var i = 0, childTag; (childTag = parentTag.children[i]); i += 1) { |
| 252 | if (childTag.tagName === 'SOURCE') { |
| 253 | sourceTags.push(childTag); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | return sourceTags; |
| 258 | }; |
| 259 | |
| 260 | var forEachPictureSource = function forEachPictureSource(element, fn) { |
| 261 | var parent = element.parentNode; |
| 262 | |
| 263 | if (!parent || parent.tagName !== 'PICTURE') { |
| 264 | return; |
| 265 | } |
| 266 | |
| 267 | var sourceTags = getSourceTags(parent); |
| 268 | sourceTags.forEach(fn); |
| 269 | }; |
| 270 | var forEachVideoSource = function forEachVideoSource(element, fn) { |
| 271 | var sourceTags = getSourceTags(element); |
| 272 | sourceTags.forEach(fn); |
| 273 | }; |
| 274 | |
| 275 | var attrsSrc = [SRC]; |
| 276 | var attrsSrcPoster = [SRC, POSTER]; |
| 277 | var attrsSrcSrcsetSizes = [SRC, SRCSET, SIZES]; |
| 278 | var hasOriginalAttrs = function hasOriginalAttrs(element) { |
| 279 | return !!element[ORIGINALS]; |
| 280 | }; |
| 281 | var getOriginalAttrs = function getOriginalAttrs(element) { |
| 282 | return element[ORIGINALS]; |
| 283 | }; |
| 284 | var deleteOriginalAttrs = function deleteOriginalAttrs(element) { |
| 285 | return delete element[ORIGINALS]; |
| 286 | }; // ## SAVE ## |
| 287 | |
| 288 | var setOriginalsObject = function setOriginalsObject(element, attributes) { |
| 289 | if (hasOriginalAttrs(element)) { |
| 290 | return; |
| 291 | } |
| 292 | |
| 293 | var originals = {}; |
| 294 | attributes.forEach(function (attribute) { |
| 295 | originals[attribute] = element.getAttribute(attribute); |
| 296 | }); |
| 297 | element[ORIGINALS] = originals; |
| 298 | }; |
| 299 | var saveOriginalBackgroundStyle = function saveOriginalBackgroundStyle(element) { |
| 300 | if (hasOriginalAttrs(element)) { |
| 301 | return; |
| 302 | } |
| 303 | |
| 304 | element[ORIGINALS] = { |
| 305 | backgroundImage: element.style.backgroundImage, |
| 306 | }; |
| 307 | }; // ## RESTORE ## |
| 308 | |
| 309 | var setOrResetAttribute = function setOrResetAttribute(element, attrName, value) { |
| 310 | if (!value) { |
| 311 | element.removeAttribute(attrName); |
| 312 | return; |
| 313 | } |
| 314 | |
| 315 | element.setAttribute(attrName, value); |
| 316 | }; |
| 317 | |
| 318 | var restoreOriginalAttrs = function restoreOriginalAttrs(element, attributes) { |
| 319 | if (!hasOriginalAttrs(element)) { |
| 320 | return; |
| 321 | } |
| 322 | |
| 323 | var originals = getOriginalAttrs(element); |
| 324 | attributes.forEach(function (attribute) { |
| 325 | setOrResetAttribute(element, attribute, originals[attribute]); |
| 326 | }); |
| 327 | }; |
| 328 | var restoreOriginalBgImage = function restoreOriginalBgImage(element) { |
| 329 | if (!hasOriginalAttrs(element)) { |
| 330 | return; |
| 331 | } |
| 332 | |
| 333 | var originals = getOriginalAttrs(element); |
| 334 | element.style.backgroundImage = originals.backgroundImage; |
| 335 | }; |
| 336 | |
| 337 | var manageApplied = function manageApplied(element, settings, instance) { |
| 338 | addClass(element, settings.class_applied); |
| 339 | setStatus(element, statusApplied); // Instance is not provided when loading is called from static class |
| 340 | |
| 341 | if (!instance) return; |
| 342 | |
| 343 | if (settings.unobserve_completed) { |
| 344 | // Unobserve now because we can't do it on load |
| 345 | unobserve(element, settings); |
| 346 | } |
| 347 | |
| 348 | safeCallback(settings.callback_applied, element, instance); |
| 349 | }; |
| 350 | var manageLoading = function manageLoading(element, settings, instance) { |
| 351 | addClass(element, settings.class_loading); |
| 352 | setStatus(element, statusLoading); // Instance is not provided when loading is called from static class |
| 353 | |
| 354 | if (!instance) return; |
| 355 | updateLoadingCount(instance, +1); |
| 356 | safeCallback(settings.callback_loading, element, instance); |
| 357 | }; |
| 358 | var setAttributeIfValue = function setAttributeIfValue(element, attrName, value) { |
| 359 | if (!value) { |
| 360 | return; |
| 361 | } |
| 362 | |
| 363 | element.setAttribute(attrName, value); |
| 364 | }; |
| 365 | var setImageAttributes = function setImageAttributes(element, settings) { |
| 366 | setAttributeIfValue(element, SIZES, getData(element, settings.data_sizes)); |
| 367 | setAttributeIfValue(element, SRCSET, getData(element, settings.data_srcset)); |
| 368 | setAttributeIfValue(element, SRC, getData(element, settings.data_src)); |
| 369 | }; |
| 370 | var setSourcesImg = function setSourcesImg(imgEl, settings) { |
| 371 | forEachPictureSource(imgEl, function (sourceTag) { |
| 372 | setOriginalsObject(sourceTag, attrsSrcSrcsetSizes); |
| 373 | setImageAttributes(sourceTag, settings); |
| 374 | }); |
| 375 | setOriginalsObject(imgEl, attrsSrcSrcsetSizes); |
| 376 | setImageAttributes(imgEl, settings); |
| 377 | }; |
| 378 | var setSourcesIframe = function setSourcesIframe(iframe, settings) { |
| 379 | setOriginalsObject(iframe, attrsSrc); |
| 380 | setAttributeIfValue(iframe, SRC, getData(iframe, settings.data_src)); |
| 381 | }; |
| 382 | var setSourcesVideo = function setSourcesVideo(videoEl, settings) { |
| 383 | forEachVideoSource(videoEl, function (sourceEl) { |
| 384 | setOriginalsObject(sourceEl, attrsSrc); |
| 385 | setAttributeIfValue(sourceEl, SRC, getData(sourceEl, settings.data_src)); |
| 386 | }); |
| 387 | setOriginalsObject(videoEl, attrsSrcPoster); |
| 388 | setAttributeIfValue(videoEl, POSTER, getData(videoEl, settings.data_poster)); |
| 389 | setAttributeIfValue(videoEl, SRC, getData(videoEl, settings.data_src)); |
| 390 | videoEl.load(); |
| 391 | }; |
| 392 | var setBackground = function setBackground(element, settings, instance) { |
| 393 | var bg1xValue = getData(element, settings.data_bg); |
| 394 | var bgHiDpiValue = getData(element, settings.data_bg_hidpi); |
| 395 | var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue; |
| 396 | if (!bgDataValue) return; |
| 397 | element.style.backgroundImage = 'url("'.concat(bgDataValue, '")'); |
| 398 | getTempImage(element).setAttribute(SRC, bgDataValue); |
| 399 | manageLoading(element, settings, instance); |
| 400 | }; // NOTE: THE TEMP IMAGE TRICK CANNOT BE DONE WITH data-multi-bg |
| 401 | // BECAUSE INSIDE ITS VALUES MUST BE WRAPPED WITH URL() AND ONE OF THEM |
| 402 | // COULD BE A GRADIENT BACKGROUND IMAGE |
| 403 | |
| 404 | var setMultiBackground = function setMultiBackground(element, settings, instance) { |
| 405 | var bg1xValue = getData(element, settings.data_bg_multi); |
| 406 | var bgHiDpiValue = getData(element, settings.data_bg_multi_hidpi); |
| 407 | var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue; |
| 408 | |
| 409 | if (!bgDataValue) { |
| 410 | return; |
| 411 | } |
| 412 | |
| 413 | element.style.backgroundImage = bgDataValue; |
| 414 | manageApplied(element, settings, instance); |
| 415 | }; |
| 416 | var setSourcesFunctions = { |
| 417 | IMG: setSourcesImg, |
| 418 | IFRAME: setSourcesIframe, |
| 419 | VIDEO: setSourcesVideo, |
| 420 | }; |
| 421 | var setSourcesNative = function setSourcesNative(element, settings) { |
| 422 | var setSourcesFunction = setSourcesFunctions[element.tagName]; |
| 423 | |
| 424 | if (!setSourcesFunction) { |
| 425 | return; |
| 426 | } |
| 427 | |
| 428 | setSourcesFunction(element, settings); |
| 429 | }; |
| 430 | var setSources = function setSources(element, settings, instance) { |
| 431 | var setSourcesFunction = setSourcesFunctions[element.tagName]; |
| 432 | |
| 433 | if (!setSourcesFunction) { |
| 434 | return; |
| 435 | } |
| 436 | |
| 437 | setSourcesFunction(element, settings); |
| 438 | manageLoading(element, settings, instance); |
| 439 | }; |
| 440 | |
| 441 | var elementsWithLoadEvent = ['IMG', 'IFRAME', 'VIDEO']; |
| 442 | var hasLoadEvent = function hasLoadEvent(element) { |
| 443 | return elementsWithLoadEvent.indexOf(element.tagName) > -1; |
| 444 | }; |
| 445 | var checkFinish = function checkFinish(settings, instance) { |
| 446 | if (instance && !isSomethingLoading(instance) && !haveElementsToLoad(instance)) { |
| 447 | safeCallback(settings.callback_finish, instance); |
| 448 | } |
| 449 | }; |
| 450 | var addEventListener = function addEventListener(element, eventName, handler) { |
| 451 | element.addEventListener(eventName, handler); |
| 452 | element.llEvLisnrs[eventName] = handler; |
| 453 | }; |
| 454 | var removeEventListener = function removeEventListener(element, eventName, handler) { |
| 455 | element.removeEventListener(eventName, handler); |
| 456 | }; |
| 457 | var hasEventListeners = function hasEventListeners(element) { |
| 458 | return !!element.llEvLisnrs; |
| 459 | }; |
| 460 | var addEventListeners = function addEventListeners(element, loadHandler, errorHandler) { |
| 461 | if (!hasEventListeners(element)) element.llEvLisnrs = {}; |
| 462 | var loadEventName = element.tagName === 'VIDEO' ? 'loadeddata' : 'load'; |
| 463 | addEventListener(element, loadEventName, loadHandler); |
| 464 | addEventListener(element, 'error', errorHandler); |
| 465 | }; |
| 466 | var removeEventListeners = function removeEventListeners(element) { |
| 467 | if (!hasEventListeners(element)) { |
| 468 | return; |
| 469 | } |
| 470 | |
| 471 | var eventListeners = element.llEvLisnrs; |
| 472 | |
| 473 | for (var eventName in eventListeners) { |
| 474 | var handler = eventListeners[eventName]; |
| 475 | removeEventListener(element, eventName, handler); |
| 476 | } |
| 477 | |
| 478 | delete element.llEvLisnrs; |
| 479 | }; |
| 480 | var doneHandler = function doneHandler(element, settings, instance) { |
| 481 | deleteTempImage(element); |
| 482 | updateLoadingCount(instance, -1); |
| 483 | decreaseToLoadCount(instance); |
| 484 | removeClass(element, settings.class_loading); |
| 485 | |
| 486 | if (settings.unobserve_completed) { |
| 487 | unobserve(element, instance); |
| 488 | } |
| 489 | }; |
| 490 | var loadHandler = function loadHandler(event, element, settings, instance) { |
| 491 | var goingNative = hasStatusNative(element); |
| 492 | doneHandler(element, settings, instance); |
| 493 | addClass(element, settings.class_loaded); |
| 494 | setStatus(element, statusLoaded); |
| 495 | safeCallback(settings.callback_loaded, element, instance); |
| 496 | if (!goingNative) checkFinish(settings, instance); |
| 497 | }; |
| 498 | var errorHandler = function errorHandler(event, element, settings, instance) { |
| 499 | var goingNative = hasStatusNative(element); |
| 500 | doneHandler(element, settings, instance); |
| 501 | addClass(element, settings.class_error); |
| 502 | setStatus(element, statusError); |
| 503 | safeCallback(settings.callback_error, element, instance); |
| 504 | if (!goingNative) checkFinish(settings, instance); |
| 505 | }; |
| 506 | var addOneShotEventListeners = function addOneShotEventListeners(element, settings, instance) { |
| 507 | var elementToListenTo = getTempImage(element) || element; |
| 508 | |
| 509 | if (hasEventListeners(elementToListenTo)) { |
| 510 | // This happens when loading is retried twice |
| 511 | return; |
| 512 | } |
| 513 | |
| 514 | var _loadHandler = function _loadHandler(event) { |
| 515 | loadHandler(event, element, settings, instance); |
| 516 | removeEventListeners(elementToListenTo); |
| 517 | }; |
| 518 | |
| 519 | var _errorHandler = function _errorHandler(event) { |
| 520 | errorHandler(event, element, settings, instance); |
| 521 | removeEventListeners(elementToListenTo); |
| 522 | }; |
| 523 | |
| 524 | addEventListeners(elementToListenTo, _loadHandler, _errorHandler); |
| 525 | }; |
| 526 | |
| 527 | var loadBackground = function loadBackground(element, settings, instance) { |
| 528 | addTempImage(element); |
| 529 | addOneShotEventListeners(element, settings, instance); |
| 530 | saveOriginalBackgroundStyle(element); |
| 531 | setBackground(element, settings, instance); |
| 532 | setMultiBackground(element, settings, instance); |
| 533 | }; |
| 534 | |
| 535 | var loadRegular = function loadRegular(element, settings, instance) { |
| 536 | addOneShotEventListeners(element, settings, instance); |
| 537 | setSources(element, settings, instance); |
| 538 | }; |
| 539 | |
| 540 | var load = function load(element, settings, instance) { |
| 541 | if (hasLoadEvent(element)) { |
| 542 | loadRegular(element, settings, instance); |
| 543 | } else { |
| 544 | loadBackground(element, settings, instance); |
| 545 | } |
| 546 | }; |
| 547 | var loadNative = function loadNative(element, settings, instance) { |
| 548 | element.setAttribute('loading', 'lazy'); |
| 549 | addOneShotEventListeners(element, settings, instance); |
| 550 | setSourcesNative(element, settings); |
| 551 | setStatus(element, statusNative); |
| 552 | }; |
| 553 | |
| 554 | var removeImageAttributes = function removeImageAttributes(element) { |
| 555 | element.removeAttribute(SRC); |
| 556 | element.removeAttribute(SRCSET); |
| 557 | element.removeAttribute(SIZES); |
| 558 | }; |
| 559 | |
| 560 | var resetSourcesImg = function resetSourcesImg(element) { |
| 561 | forEachPictureSource(element, function (sourceTag) { |
| 562 | removeImageAttributes(sourceTag); |
| 563 | }); |
| 564 | removeImageAttributes(element); |
| 565 | }; |
| 566 | |
| 567 | var restoreImg = function restoreImg(imgEl) { |
| 568 | forEachPictureSource(imgEl, function (sourceEl) { |
| 569 | restoreOriginalAttrs(sourceEl, attrsSrcSrcsetSizes); |
| 570 | }); |
| 571 | restoreOriginalAttrs(imgEl, attrsSrcSrcsetSizes); |
| 572 | }; |
| 573 | var restoreVideo = function restoreVideo(videoEl) { |
| 574 | forEachVideoSource(videoEl, function (sourceEl) { |
| 575 | restoreOriginalAttrs(sourceEl, attrsSrc); |
| 576 | }); |
| 577 | restoreOriginalAttrs(videoEl, attrsSrcPoster); |
| 578 | videoEl.load(); |
| 579 | }; |
| 580 | var restoreIframe = function restoreIframe(iframeEl) { |
| 581 | restoreOriginalAttrs(iframeEl, attrsSrc); |
| 582 | }; |
| 583 | var restoreFunctions = { |
| 584 | IMG: restoreImg, |
| 585 | IFRAME: restoreIframe, |
| 586 | VIDEO: restoreVideo, |
| 587 | }; |
| 588 | |
| 589 | var restoreAttributes = function restoreAttributes(element) { |
| 590 | var restoreFunction = restoreFunctions[element.tagName]; |
| 591 | |
| 592 | if (!restoreFunction) { |
| 593 | restoreOriginalBgImage(element); |
| 594 | return; |
| 595 | } |
| 596 | |
| 597 | restoreFunction(element); |
| 598 | }; |
| 599 | |
| 600 | var resetClasses = function resetClasses(element, settings) { |
| 601 | if (hasEmptyStatus(element) || hasStatusNative(element)) { |
| 602 | return; |
| 603 | } |
| 604 | |
| 605 | removeClass(element, settings.class_entered); |
| 606 | removeClass(element, settings.class_exited); |
| 607 | removeClass(element, settings.class_applied); |
| 608 | removeClass(element, settings.class_loading); |
| 609 | removeClass(element, settings.class_loaded); |
| 610 | removeClass(element, settings.class_error); |
| 611 | }; |
| 612 | |
| 613 | var restore = function restore(element, settings) { |
| 614 | restoreAttributes(element); |
| 615 | resetClasses(element, settings); |
| 616 | resetStatus(element); |
| 617 | deleteOriginalAttrs(element); |
| 618 | }; |
| 619 | |
| 620 | var cancelLoading = function cancelLoading(element, entry, settings, instance) { |
| 621 | if (!settings.cancel_on_exit) return; |
| 622 | if (!hasStatusLoading(element)) return; |
| 623 | if (element.tagName !== 'IMG') return; //Works only on images |
| 624 | |
| 625 | removeEventListeners(element); |
| 626 | resetSourcesImg(element); |
| 627 | restoreImg(element); |
| 628 | removeClass(element, settings.class_loading); |
| 629 | updateLoadingCount(instance, -1); |
| 630 | resetStatus(element); |
| 631 | safeCallback(settings.callback_cancel, element, entry, instance); |
| 632 | }; |
| 633 | |
| 634 | var onEnter = function onEnter(element, entry, settings, instance) { |
| 635 | var dontLoad = hadStartedLoading(element); |
| 636 | /* Save status |
| 637 | before setting it, to prevent loading it again. Fixes #526. */ |
| 638 | |
| 639 | setStatus(element, statusEntered); |
| 640 | addClass(element, settings.class_entered); |
| 641 | removeClass(element, settings.class_exited); |
| 642 | unobserveEntered(element, settings, instance); |
| 643 | safeCallback(settings.callback_enter, element, entry, instance); |
| 644 | if (dontLoad) return; |
| 645 | load(element, settings, instance); |
| 646 | }; |
| 647 | var onExit = function onExit(element, entry, settings, instance) { |
| 648 | if (hasEmptyStatus(element)) return; //Ignore the first pass, at landing |
| 649 | |
| 650 | addClass(element, settings.class_exited); |
| 651 | cancelLoading(element, entry, settings, instance); |
| 652 | safeCallback(settings.callback_exit, element, entry, instance); |
| 653 | }; |
| 654 | |
| 655 | var tagsWithNativeLazy = ['IMG', 'IFRAME', 'VIDEO']; |
| 656 | var shouldUseNative = function shouldUseNative(settings) { |
| 657 | return settings.use_native && 'loading' in HTMLImageElement.prototype; |
| 658 | }; |
| 659 | var loadAllNative = function loadAllNative(elements, settings, instance) { |
| 660 | elements.forEach(function (element) { |
| 661 | if (tagsWithNativeLazy.indexOf(element.tagName) === -1) { |
| 662 | return; |
| 663 | } |
| 664 | |
| 665 | loadNative(element, settings, instance); |
| 666 | }); |
| 667 | setToLoadCount(instance, 0); |
| 668 | }; |
| 669 | |
| 670 | var isIntersecting = function isIntersecting(entry) { |
| 671 | return entry.isIntersecting || entry.intersectionRatio > 0; |
| 672 | }; |
| 673 | |
| 674 | var getObserverSettings = function getObserverSettings(settings) { |
| 675 | return { |
| 676 | root: settings.container === document ? null : settings.container, |
| 677 | rootMargin: settings.thresholds || settings.threshold + 'px', |
| 678 | }; |
| 679 | }; |
| 680 | |
| 681 | var intersectionHandler = function intersectionHandler(entries, settings, instance) { |
| 682 | entries.forEach(function (entry) { |
| 683 | return isIntersecting(entry) ? onEnter(entry.target, entry, settings, instance) : onExit(entry.target, entry, settings, instance); |
| 684 | }); |
| 685 | }; |
| 686 | |
| 687 | var observeElements = function observeElements(observer, elements) { |
| 688 | elements.forEach(function (element) { |
| 689 | observer.observe(element); |
| 690 | }); |
| 691 | }; |
| 692 | var updateObserver = function updateObserver(observer, elementsToObserve) { |
| 693 | resetObserver(observer); |
| 694 | observeElements(observer, elementsToObserve); |
| 695 | }; |
| 696 | var setObserver = function setObserver(settings, instance) { |
| 697 | if (!supportsIntersectionObserver || shouldUseNative(settings)) { |
| 698 | return; |
| 699 | } |
| 700 | |
| 701 | instance._observer = new IntersectionObserver(function (entries) { |
| 702 | intersectionHandler(entries, settings, instance); |
| 703 | }, getObserverSettings(settings)); |
| 704 | }; |
| 705 | |
| 706 | var toArray = function toArray(nodeSet) { |
| 707 | return Array.prototype.slice.call(nodeSet); |
| 708 | }; |
| 709 | var queryElements = function queryElements(settings) { |
| 710 | return settings.container.querySelectorAll(settings.elements_selector); |
| 711 | }; |
| 712 | var excludeManagedElements = function excludeManagedElements(elements) { |
| 713 | return toArray(elements).filter(hasEmptyStatus); |
| 714 | }; |
| 715 | var hasError = function hasError(element) { |
| 716 | return hasStatusError(element); |
| 717 | }; |
| 718 | var filterErrorElements = function filterErrorElements(elements) { |
| 719 | return toArray(elements).filter(hasError); |
| 720 | }; |
| 721 | var getElementsToLoad = function getElementsToLoad(elements, settings) { |
| 722 | return excludeManagedElements(elements || queryElements(settings)); |
| 723 | }; |
| 724 | |
| 725 | var retryLazyLoad = function retryLazyLoad(settings, instance) { |
| 726 | var errorElements = filterErrorElements(queryElements(settings)); |
| 727 | errorElements.forEach(function (element) { |
| 728 | removeClass(element, settings.class_error); |
| 729 | resetStatus(element); |
| 730 | }); |
| 731 | instance.update(); |
| 732 | }; |
| 733 | var setOnlineCheck = function setOnlineCheck(settings, instance) { |
| 734 | if (!runningOnBrowser) { |
| 735 | return; |
| 736 | } |
| 737 | |
| 738 | window.addEventListener('online', function () { |
| 739 | retryLazyLoad(settings, instance); |
| 740 | }); |
| 741 | }; |
| 742 | |
| 743 | var LazyLoad = function LazyLoad(customSettings, elements) { |
| 744 | var settings = getExtendedSettings(customSettings); |
| 745 | this._settings = settings; |
| 746 | this.loadingCount = 0; |
| 747 | setObserver(settings, this); |
| 748 | setOnlineCheck(settings, this); |
| 749 | this.update(elements); |
| 750 | }; |
| 751 | |
| 752 | LazyLoad.prototype = { |
| 753 | update: function update(givenNodeset) { |
| 754 | var settings = this._settings; |
| 755 | var elementsToLoad = getElementsToLoad(givenNodeset, settings); |
| 756 | setToLoadCount(this, elementsToLoad.length); |
| 757 | |
| 758 | if (isBot || !supportsIntersectionObserver) { |
| 759 | this.loadAll(elementsToLoad); |
| 760 | return; |
| 761 | } |
| 762 | |
| 763 | if (shouldUseNative(settings)) { |
| 764 | loadAllNative(elementsToLoad, settings, this); |
| 765 | return; |
| 766 | } |
| 767 | |
| 768 | updateObserver(this._observer, elementsToLoad); |
| 769 | }, |
| 770 | destroy: function destroy() { |
| 771 | // Observer |
| 772 | if (this._observer) { |
| 773 | this._observer.disconnect(); |
| 774 | } // Clean custom attributes on elements |
| 775 | |
| 776 | queryElements(this._settings).forEach(function (element) { |
| 777 | deleteOriginalAttrs(element); |
| 778 | }); // Delete all internal props |
| 779 | |
| 780 | delete this._observer; |
| 781 | delete this._settings; |
| 782 | delete this.loadingCount; |
| 783 | delete this.toLoadCount; |
| 784 | }, |
| 785 | loadAll: function loadAll(elements) { |
| 786 | var _this = this; |
| 787 | |
| 788 | var settings = this._settings; |
| 789 | var elementsToLoad = getElementsToLoad(elements, settings); |
| 790 | elementsToLoad.forEach(function (element) { |
| 791 | unobserve(element, _this); |
| 792 | load(element, settings, _this); |
| 793 | }); |
| 794 | }, |
| 795 | restoreAll: function restoreAll() { |
| 796 | var settings = this._settings; |
| 797 | queryElements(settings).forEach(function (element) { |
| 798 | restore(element, settings); |
| 799 | }); |
| 800 | }, |
| 801 | }; |
| 802 | |
| 803 | LazyLoad.load = function (element, customSettings) { |
| 804 | var settings = getExtendedSettings(customSettings); |
| 805 | load(element, settings); |
| 806 | }; |
| 807 | |
| 808 | LazyLoad.resetStatus = function (element) { |
| 809 | resetStatus(element); |
| 810 | }; // Automatic instances creation if required (useful for async script loading) |
| 811 | |
| 812 | // if (runningOnBrowser) { |
| 813 | // autoInitialize(LazyLoad, window.lazyLoadOptions); |
| 814 | // } |
| 815 | |
| 816 | return LazyLoad; |
| 817 | }); |
| 818 |