From f1e008db8dfd484998056c80d80eab980d24dab7 Mon Sep 17 00:00:00 2001 From: Andrea Verlicchi Date: Tue, 3 Mar 2020 00:13:01 +0100 Subject: [PATCH] Releasing 13.0.1 --- README.md | 12 +- dist/lazyload.amd.js | 124 +++++----- dist/lazyload.amd.min.js | 2 +- dist/lazyload.esm.js | 479 ++++++++++++++++++-------------------- dist/lazyload.esm.min.js | 2 +- dist/lazyload.iife.js | 124 +++++----- dist/lazyload.iife.min.js | 2 +- dist/lazyload.js | 124 +++++----- dist/lazyload.min.js | 2 +- package.json | 2 +- 10 files changed, 424 insertions(+), 449 deletions(-) diff --git a/README.md b/README.md index ad3b5f5e..83d969ca 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Please note that the video poster can be lazily loaded too. ## 👩‍💻 Getting started - Script -The latest, recommended version of LazyLoad is **13.0.0**. +The latest, recommended version of LazyLoad is **13.0.1**. ### To polyfill or not to polyfill IntersectionObserver? @@ -128,14 +128,14 @@ If you prefer to load a polyfill, the regular LazyLoad behaviour is granted. The easiest way to use LazyLoad is to include the script from a CDN: ```html - + ``` Or, with the IntersectionObserver polyfill: ```html - + ``` Then, in your javascript code: @@ -168,7 +168,7 @@ Include RequireJS: Then `require` the AMD version of LazyLoad, like this: ```js -var lazyLoadAmdUrl = "https://cdn.jsdelivr.net/npm/vanilla-lazyload@13.0.0/dist/lazyload.amd.min.js"; +var lazyLoadAmdUrl = "https://cdn.jsdelivr.net/npm/vanilla-lazyload@13.0.1/dist/lazyload.amd.min.js"; var polyfillAmdUrl = "https://cdn.jsdelivr.net/npm/intersection-observer-amd@2.0.1/intersection-observer-amd.js"; /// Dynamically define the dependencies @@ -214,7 +214,7 @@ Then include the script. ```html ``` @@ -247,7 +247,7 @@ Then include the script. ```html ``` diff --git a/dist/lazyload.amd.js b/dist/lazyload.amd.js index c641a01c..4c14735c 100644 --- a/dist/lazyload.amd.js +++ b/dist/lazyload.amd.js @@ -46,9 +46,9 @@ define(function () { 'use strict'; callback_finish: null, use_native: false }; - var getInstanceSettings = (function (customSettings) { + var getInstanceSettings = function getInstanceSettings(customSettings) { return _extends({}, defaultSettings, customSettings); - }); + }; /* Creates instance and notifies it through the window element */ var createInstance = function createInstance(classObj, options) { @@ -77,7 +77,7 @@ define(function () { 'use strict'; options passed in (plain object or an array) */ - function autoInitialize (classObj, options) { + var autoInitialize = function autoInitialize(classObj, options) { if (!options) { return; } @@ -91,7 +91,7 @@ define(function () { 'use strict'; createInstance(classObj, optionsItem); } } - } + }; var dataPrefix = "data-"; var processedDataName = "was-processed"; @@ -137,32 +137,6 @@ define(function () { 'use strict'; }); }; - var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { - if (!callback) { - return; - } - - if (arg3 !== undefined) { - callback(arg1, arg2, arg3); - return; - } - - if (arg2 !== undefined) { - callback(arg1, arg2); - return; - } - - callback(arg1); - }; - - var updateLoadingCount = function updateLoadingCount(instance, plusMinus) { - instance.loadingCount += plusMinus; - - if (instance._elements.length === 0 && instance.loadingCount === 0) { - safeCallback(instance._settings.callback_finish, instance); - } - }; - var getSourceTags = function getSourceTags(parentTag) { var sourceTags = []; @@ -234,7 +208,7 @@ define(function () { 'use strict'; if (setSourcesFunction) { setSourcesFunction(element, settings); - updateLoadingCount(instance, 1); + instance.loadingCount += 1; instance._elements = purgeOneElement(instance._elements, element); return; } @@ -259,6 +233,24 @@ define(function () { 'use strict'; element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, ""); }; + var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { + if (!callback) { + return; + } + + if (arg3 !== undefined) { + callback(arg1, arg2, arg3); + return; + } + + if (arg2 !== undefined) { + callback(arg1, arg2); + return; + } + + callback(arg1); + }; + var genericLoadEventName = "load"; var mediaLoadEventName = "loadeddata"; var errorEventName = "error"; @@ -291,7 +283,11 @@ define(function () { 'use strict'; removeClass(element, settings.class_loading); addClass(element, className); safeCallback(callback, element, instance); - updateLoadingCount(instance, -1); + instance.loadingCount -= 1; + + if (instance._elements.length === 0 && instance.loadingCount === 0) { + safeCallback(settings.callback_finish, instance); + } }; var addOneShotEventListeners = function addOneShotEventListeners(element, instance) { @@ -309,17 +305,6 @@ define(function () { 'use strict'; }; var managedTags = ["IMG", "IFRAME", "VIDEO"]; - var onEnter = function onEnter(element, entry, instance) { - var settings = instance._settings; - safeCallback(settings.callback_enter, element, entry, instance); - - if (!settings.load_delay) { - revealAndUnobserve(element, instance); - return; - } - - delayLoad(element, instance); - }; var revealAndUnobserve = function revealAndUnobserve(element, instance) { var observer = instance._observer; revealElement(element, instance); @@ -328,16 +313,23 @@ define(function () { 'use strict'; observer.unobserve(element); } }; - var onExit = function onExit(element, entry, instance) { + var revealElement = function revealElement(element, instance, force) { var settings = instance._settings; - safeCallback(settings.callback_exit, element, entry, instance); - if (!settings.load_delay) { - return; + if (!force && getWasProcessedData(element)) { + return; // element has already been processed and force wasn't true } - cancelDelayLoad(element); + if (managedTags.indexOf(element.tagName) > -1) { + addOneShotEventListeners(element, instance); + addClass(element, settings.class_loading); + } + + setSources(element, instance); + setWasProcessedData(element); + safeCallback(settings.callback_reveal, element, instance); }; + var cancelDelayLoad = function cancelDelayLoad(element) { var timeoutId = getTimeoutData(element); @@ -362,32 +354,40 @@ define(function () { 'use strict'; }, loadDelay); setTimeoutData(element, timeoutId); }; - var revealElement = function revealElement(element, instance, force) { + + var onEnter = function onEnter(element, entry, instance) { var settings = instance._settings; + safeCallback(settings.callback_enter, element, entry, instance); - if (!force && getWasProcessedData(element)) { - return; // element has already been processed and force wasn't true + if (!settings.load_delay) { + revealAndUnobserve(element, instance); + return; } - if (managedTags.indexOf(element.tagName) > -1) { - addOneShotEventListeners(element, instance); - addClass(element, settings.class_loading); + delayLoad(element, instance); + }; + var onExit = function onExit(element, entry, instance) { + var settings = instance._settings; + safeCallback(settings.callback_exit, element, entry, instance); + + if (!settings.load_delay) { + return; } - setSources(element, instance); - setWasProcessedData(element); - safeCallback(settings.callback_reveal, element, instance); + cancelDelayLoad(element); }; var isIntersecting = function isIntersecting(entry) { return entry.isIntersecting || entry.intersectionRatio > 0; }; + var getObserverSettings = function getObserverSettings(settings) { return { root: settings.container === document ? null : settings.container, rootMargin: settings.thresholds || settings.threshold + "px" }; }; + var setObserver = function setObserver(instance) { if (!supportsIntersectionObserver) { return false; @@ -416,13 +416,13 @@ define(function () { 'use strict'; }); }; - var nodeSetToArray = function nodeSetToArray(nodeSet) { - return Array.prototype.slice.call(nodeSet); - }; - var queryElements = function queryElements(settings) { return settings.container.querySelectorAll(settings.elements_selector); }; + + var nodeSetToArray = function nodeSetToArray(nodeSet) { + return Array.prototype.slice.call(nodeSet); + }; var getElements = function getElements(elements, settings) { return purgeProcessedElements(nodeSetToArray(elements || queryElements(settings))); }; @@ -430,7 +430,7 @@ define(function () { 'use strict'; var retryLazyLoad = function retryLazyLoad(instance) { var settings = instance._settings; var errorElements = settings.container.querySelectorAll("." + settings.class_error); - errorElements.forEach(function (element) { + nodeSetToArray(errorElements).forEach(function (element) { removeClass(element, settings.class_error); resetWasProcessedData(element); }); diff --git a/dist/lazyload.amd.min.js b/dist/lazyload.amd.min.js index 4677f1cf..88d2a9be 100644 --- a/dist/lazyload.amd.min.js +++ b/dist/lazyload.amd.min.js @@ -1 +1 @@ -define((function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(A(t,e),p(t,r.class_loading)),b(t,e),function(t){c(t,"was-processed","true")}(t),f(r.callback_reveal,t,e))},M=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?function(t,e,n){var r=n._settings;f(r.callback_enter,t,e,n),r.load_delay?N(t,n):O(t,n)}(e.target,e,t):function(t,e,n){var r=n._settings;f(r.callback_exit,t,e,n),r.load_delay&&z(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},R=["IMG","IFRAME"],x=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}((n=t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e),Array.prototype.slice.call(n)));var n},T=function(t){var e=t._settings;e.container.querySelectorAll("."+e.class_error).forEach((function(t){E(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},F=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,M(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return F.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=x(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==R.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),C(t,e))})),this._elements=x(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){C(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){O(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)s(t,n);else s(t,e)}(F,window.lazyLoadOptions),F})); +define((function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(k(t,e),m(t,r.class_loading)),h(t,e),function(t){c(t,"was-processed","true")}(t),p(r.callback_reveal,t,e))},z=function(t){var e=d(t);e&&(clearTimeout(e),u(t,null))},N=function(t,e,n){var r=n._settings;p(r.callback_enter,t,e,n),r.load_delay?function(t,e){var n=e._settings.load_delay,r=d(t);r||(r=setTimeout((function(){L(t,e),z(t)}),n),u(t,r))}(t,n):L(t,n)},C=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?N(e.target,e,t):function(t,e,n){var r=n._settings;p(r.callback_exit,t,e,n),r.load_delay&&z(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},M=["IMG","IFRAME"],R=function(t){return Array.prototype.slice.call(t)},x=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}(R(t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e)))},T=function(t){var e=t._settings,n=e.container.querySelectorAll("."+e.class_error);R(n).forEach((function(t){b(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},F=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,C(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return F.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=x(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==M.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),O(t,e))})),this._elements=x(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){O(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){L(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)s(t,n);else s(t,e)}(F,window.lazyLoadOptions),F})); diff --git a/dist/lazyload.esm.js b/dist/lazyload.esm.js index 95caca11..e8ccb432 100644 --- a/dist/lazyload.esm.js +++ b/dist/lazyload.esm.js @@ -12,65 +12,65 @@ const supportsClassList = runningOnBrowser && "classList" in document.createElement("p"); const defaultSettings = { - elements_selector: "img", - container: isBot || runningOnBrowser ? document : null, - threshold: 300, - thresholds: null, - data_src: "src", - data_srcset: "srcset", - data_sizes: "sizes", - data_bg: "bg", - data_poster: "poster", - class_loading: "loading", - class_loaded: "loaded", - class_error: "error", - load_delay: 0, - auto_unobserve: true, - callback_enter: null, - callback_exit: null, - callback_reveal: null, - callback_loaded: null, - callback_error: null, - callback_finish: null, - use_native: false -}; - -var getInstanceSettings = customSettings => { - return Object.assign({}, defaultSettings, customSettings); + elements_selector: "img", + container: isBot || runningOnBrowser ? document : null, + threshold: 300, + thresholds: null, + data_src: "src", + data_srcset: "srcset", + data_sizes: "sizes", + data_bg: "bg", + data_poster: "poster", + class_loading: "loading", + class_loaded: "loaded", + class_error: "error", + load_delay: 0, + auto_unobserve: true, + callback_enter: null, + callback_exit: null, + callback_reveal: null, + callback_loaded: null, + callback_error: null, + callback_finish: null, + use_native: false +}; + +const getInstanceSettings = customSettings => { + return Object.assign({}, defaultSettings, customSettings); }; /* Creates instance and notifies it through the window element */ const createInstance = function(classObj, options) { - var event; - let eventString = "LazyLoad::Initialized"; - let instance = new classObj(options); - try { - // Works in modern browsers - event = new CustomEvent(eventString, { detail: { instance } }); - } catch (err) { - // Works in Internet Explorer (all versions) - event = document.createEvent("CustomEvent"); - event.initCustomEvent(eventString, false, false, { instance }); - } - window.dispatchEvent(event); + var event; + let eventString = "LazyLoad::Initialized"; + let instance = new classObj(options); + try { + // Works in modern browsers + event = new CustomEvent(eventString, { detail: { instance } }); + } catch (err) { + // Works in Internet Explorer (all versions) + event = document.createEvent("CustomEvent"); + event.initCustomEvent(eventString, false, false, { instance }); + } + window.dispatchEvent(event); }; /* Auto initialization of one or more instances of lazyload, depending on the options passed in (plain object or an array) */ -function autoInitialize(classObj, options) { - if (!options) { - return; - } - if (!options.length) { - // Plain object - createInstance(classObj, options); - } else { - // Array of objects - for (let i = 0, optionsItem; (optionsItem = options[i]); i += 1) { - createInstance(classObj, optionsItem); - } - } -} +const autoInitialize = (classObj, options) => { + if (!options) { + return; + } + if (!options.length) { + // Plain object + createInstance(classObj, options); + } else { + // Array of objects + for (let i = 0, optionsItem; (optionsItem = options[i]); i += 1) { + createInstance(classObj, optionsItem); + } + } +}; const dataPrefix = "data-"; const processedDataName = "was-processed"; @@ -112,125 +112,86 @@ const purgeOneElement = (elements, elementToPurge) => { return elements.filter(element => element !== elementToPurge); }; -const safeCallback = (callback, arg1, arg2, arg3) => { - if (!callback) { - return; - } - - if (arg3 !== undefined) { - callback(arg1, arg2, arg3); - return; - } - if (arg2 !== undefined) { - callback(arg1, arg2); - return; - } - callback(arg1); -}; - -const updateLoadingCount = (instance, plusMinus) => { - instance.loadingCount += plusMinus; - if (instance._elements.length === 0 && instance.loadingCount === 0) { - safeCallback(instance._settings.callback_finish, instance); - } -}; - const getSourceTags = parentTag => { - let sourceTags = []; - for (let i = 0, childTag; (childTag = parentTag.children[i]); i += 1) { - if (childTag.tagName === "SOURCE") { - sourceTags.push(childTag); - } - } - return sourceTags; + let sourceTags = []; + for (let i = 0, childTag; (childTag = parentTag.children[i]); i += 1) { + if (childTag.tagName === "SOURCE") { + sourceTags.push(childTag); + } + } + return sourceTags; }; const setAttributeIfValue = (element, attrName, value) => { - if (!value) { - return; - } - element.setAttribute(attrName, value); + if (!value) { + return; + } + element.setAttribute(attrName, value); }; const setImageAttributes = (element, settings) => { - setAttributeIfValue( - element, - "sizes", - getData(element, settings.data_sizes) - ); - setAttributeIfValue( - element, - "srcset", - getData(element, settings.data_srcset) - ); - setAttributeIfValue(element, "src", getData(element, settings.data_src)); + setAttributeIfValue(element, "sizes", getData(element, settings.data_sizes)); + setAttributeIfValue(element, "srcset", getData(element, settings.data_srcset)); + setAttributeIfValue(element, "src", getData(element, settings.data_src)); }; const setSourcesImg = (element, settings) => { - const parent = element.parentNode; + const parent = element.parentNode; - if (parent && parent.tagName === "PICTURE") { - let sourceTags = getSourceTags(parent); - sourceTags.forEach(sourceTag => { - setImageAttributes(sourceTag, settings); - }); - } + if (parent && parent.tagName === "PICTURE") { + let sourceTags = getSourceTags(parent); + sourceTags.forEach(sourceTag => { + setImageAttributes(sourceTag, settings); + }); + } - setImageAttributes(element, settings); + setImageAttributes(element, settings); }; const setSourcesIframe = (element, settings) => { - setAttributeIfValue(element, "src", getData(element, settings.data_src)); + setAttributeIfValue(element, "src", getData(element, settings.data_src)); }; const setSourcesVideo = (element, settings) => { - let sourceTags = getSourceTags(element); - sourceTags.forEach(sourceTag => { - setAttributeIfValue( - sourceTag, - "src", - getData(sourceTag, settings.data_src) - ); - }); - setAttributeIfValue( - element, - "poster", - getData(element, settings.data_poster) - ); - setAttributeIfValue(element, "src", getData(element, settings.data_src)); - element.load(); + let sourceTags = getSourceTags(element); + sourceTags.forEach(sourceTag => { + setAttributeIfValue(sourceTag, "src", getData(sourceTag, settings.data_src)); + }); + setAttributeIfValue(element, "poster", getData(element, settings.data_poster)); + setAttributeIfValue(element, "src", getData(element, settings.data_src)); + element.load(); }; const setSourcesBgImage = (element, settings) => { - const srcDataValue = getData(element, settings.data_src); - const bgDataValue = getData(element, settings.data_bg); + const srcDataValue = getData(element, settings.data_src); + const bgDataValue = getData(element, settings.data_bg); - if (srcDataValue) { - element.style.backgroundImage = `url("${srcDataValue}")`; - } + if (srcDataValue) { + element.style.backgroundImage = `url("${srcDataValue}")`; + } - if (bgDataValue) { - element.style.backgroundImage = bgDataValue; - } + if (bgDataValue) { + element.style.backgroundImage = bgDataValue; + } }; const setSourcesFunctions = { - IMG: setSourcesImg, - IFRAME: setSourcesIframe, - VIDEO: setSourcesVideo + IMG: setSourcesImg, + IFRAME: setSourcesIframe, + VIDEO: setSourcesVideo }; const setSources = (element, instance) => { - const settings = instance._settings; - const tagName = element.tagName; - const setSourcesFunction = setSourcesFunctions[tagName]; - if (setSourcesFunction) { - setSourcesFunction(element, settings); - updateLoadingCount(instance, 1); - instance._elements = purgeOneElement(instance._elements, element); - return; - } - setSourcesBgImage(element, settings); + const settings = instance._settings; + const tagName = element.tagName; + const setSourcesFunction = setSourcesFunctions[tagName]; + if (setSourcesFunction) { + setSourcesFunction(element, settings); + instance.loadingCount += 1; + instance._elements = purgeOneElement(instance._elements, element); + return; + } + setSourcesBgImage(element, settings); }; const addClass = (element, className) => { @@ -252,142 +213,159 @@ const removeClass = (element, className) => { replace(/\s+$/, ""); }; +const safeCallback = (callback, arg1, arg2, arg3) => { + if (!callback) { + return; + } + + if (arg3 !== undefined) { + callback(arg1, arg2, arg3); + return; + } + if (arg2 !== undefined) { + callback(arg1, arg2); + return; + } + callback(arg1); +}; + const genericLoadEventName = "load"; const mediaLoadEventName = "loadeddata"; const errorEventName = "error"; const addEventListener = (element, eventName, handler) => { - element.addEventListener(eventName, handler); + element.addEventListener(eventName, handler); }; const removeEventListener = (element, eventName, handler) => { - element.removeEventListener(eventName, handler); + element.removeEventListener(eventName, handler); }; const addEventListeners = (element, loadHandler, errorHandler) => { - addEventListener(element, genericLoadEventName, loadHandler); - addEventListener(element, mediaLoadEventName, loadHandler); - addEventListener(element, errorEventName, errorHandler); + addEventListener(element, genericLoadEventName, loadHandler); + addEventListener(element, mediaLoadEventName, loadHandler); + addEventListener(element, errorEventName, errorHandler); }; const removeEventListeners = (element, loadHandler, errorHandler) => { - removeEventListener(element, genericLoadEventName, loadHandler); - removeEventListener(element, mediaLoadEventName, loadHandler); - removeEventListener(element, errorEventName, errorHandler); + removeEventListener(element, genericLoadEventName, loadHandler); + removeEventListener(element, mediaLoadEventName, loadHandler); + removeEventListener(element, errorEventName, errorHandler); }; const eventHandler = function(event, success, instance) { - var settings = instance._settings; - const className = success ? settings.class_loaded : settings.class_error; - const callback = success - ? settings.callback_loaded - : settings.callback_error; - const element = event.target; + var settings = instance._settings; + const className = success ? settings.class_loaded : settings.class_error; + const callback = success ? settings.callback_loaded : settings.callback_error; + const element = event.target; + + removeClass(element, settings.class_loading); + addClass(element, className); + safeCallback(callback, element, instance); - removeClass(element, settings.class_loading); - addClass(element, className); - safeCallback(callback, element, instance); + instance.loadingCount -= 1; - updateLoadingCount(instance, -1); + if (instance._elements.length === 0 && instance.loadingCount === 0) { + safeCallback(settings.callback_finish, instance); + } }; const addOneShotEventListeners = (element, instance) => { - const loadHandler = event => { - eventHandler(event, true, instance); - removeEventListeners(element, loadHandler, errorHandler); - }; - const errorHandler = event => { - eventHandler(event, false, instance); - removeEventListeners(element, loadHandler, errorHandler); - }; - addEventListeners(element, loadHandler, errorHandler); + const loadHandler = event => { + eventHandler(event, true, instance); + removeEventListeners(element, loadHandler, errorHandler); + }; + const errorHandler = event => { + eventHandler(event, false, instance); + removeEventListeners(element, loadHandler, errorHandler); + }; + addEventListeners(element, loadHandler, errorHandler); }; const managedTags = ["IMG", "IFRAME", "VIDEO"]; -const onEnter = (element, entry, instance) => { - const settings = instance._settings; - safeCallback(settings.callback_enter, element, entry, instance); - if (!settings.load_delay) { - revealAndUnobserve(element, instance); - return; - } - delayLoad(element, instance); -}; - const revealAndUnobserve = (element, instance) => { - var observer = instance._observer; - revealElement(element, instance); - if (observer && instance._settings.auto_unobserve) { - observer.unobserve(element); - } + var observer = instance._observer; + revealElement(element, instance); + if (observer && instance._settings.auto_unobserve) { + observer.unobserve(element); + } }; -const onExit = (element, entry, instance) => { - const settings = instance._settings; - safeCallback(settings.callback_exit, element, entry, instance); - if (!settings.load_delay) { - return; - } - cancelDelayLoad(element); +const revealElement = (element, instance, force) => { + var settings = instance._settings; + if (!force && getWasProcessedData(element)) { + return; // element has already been processed and force wasn't true + } + if (managedTags.indexOf(element.tagName) > -1) { + addOneShotEventListeners(element, instance); + addClass(element, settings.class_loading); + } + setSources(element, instance); + setWasProcessedData(element); + safeCallback(settings.callback_reveal, element, instance); }; const cancelDelayLoad = element => { - var timeoutId = getTimeoutData(element); - if (!timeoutId) { - return; // do nothing if timeout doesn't exist - } - clearTimeout(timeoutId); - setTimeoutData(element, null); + var timeoutId = getTimeoutData(element); + if (!timeoutId) { + return; // do nothing if timeout doesn't exist + } + clearTimeout(timeoutId); + setTimeoutData(element, null); }; const delayLoad = (element, instance) => { - var loadDelay = instance._settings.load_delay; - var timeoutId = getTimeoutData(element); - if (timeoutId) { - return; // do nothing if timeout already set - } - timeoutId = setTimeout(function() { - revealAndUnobserve(element, instance); - cancelDelayLoad(element); - }, loadDelay); - setTimeoutData(element, timeoutId); + var loadDelay = instance._settings.load_delay; + var timeoutId = getTimeoutData(element); + if (timeoutId) { + return; // do nothing if timeout already set + } + timeoutId = setTimeout(function() { + revealAndUnobserve(element, instance); + cancelDelayLoad(element); + }, loadDelay); + setTimeoutData(element, timeoutId); }; -const revealElement = (element, instance, force) => { - var settings = instance._settings; - if (!force && getWasProcessedData(element)) { - return; // element has already been processed and force wasn't true - } - if (managedTags.indexOf(element.tagName) > -1) { - addOneShotEventListeners(element, instance); - addClass(element, settings.class_loading); - } - setSources(element, instance); - setWasProcessedData(element); - safeCallback(settings.callback_reveal, element, instance); +const onEnter = (element, entry, instance) => { + const settings = instance._settings; + safeCallback(settings.callback_enter, element, entry, instance); + if (!settings.load_delay) { + revealAndUnobserve(element, instance); + return; + } + delayLoad(element, instance); }; -const isIntersecting = entry => - entry.isIntersecting || entry.intersectionRatio > 0; +const onExit = (element, entry, instance) => { + const settings = instance._settings; + safeCallback(settings.callback_exit, element, entry, instance); + if (!settings.load_delay) { + return; + } + cancelDelayLoad(element); +}; + +const isIntersecting = entry => entry.isIntersecting || entry.intersectionRatio > 0; const getObserverSettings = settings => ({ - root: settings.container === document ? null : settings.container, - rootMargin: settings.thresholds || settings.threshold + "px" + root: settings.container === document ? null : settings.container, + rootMargin: settings.thresholds || settings.threshold + "px" }); const setObserver = instance => { - if (!supportsIntersectionObserver) { - return false; - } - instance._observer = new IntersectionObserver(entries => { - entries.forEach(entry => - isIntersecting(entry) - ? onEnter(entry.target, entry, instance) - : onExit(entry.target, entry, instance) - ); - }, getObserverSettings(instance._settings)); - return true; + if (!supportsIntersectionObserver) { + return false; + } + instance._observer = new IntersectionObserver(entries => { + entries.forEach(entry => + isIntersecting(entry) + ? onEnter(entry.target, entry, instance) + : onExit(entry.target, entry, instance) + ); + }, getObserverSettings(instance._settings)); + return true; }; const nativeLazyTags = ["IMG", "IFRAME"]; @@ -405,33 +383,30 @@ const loadAllNative = instance => { }); }; -const nodeSetToArray = nodeSet => Array.prototype.slice.call(nodeSet); +const queryElements = settings => settings.container.querySelectorAll(settings.elements_selector); -const queryElements = settings => - settings.container.querySelectorAll(settings.elements_selector); +const nodeSetToArray = nodeSet => Array.prototype.slice.call(nodeSet); const getElements = (elements, settings) => - purgeProcessedElements(nodeSetToArray(elements || queryElements(settings))); + purgeProcessedElements(nodeSetToArray(elements || queryElements(settings))); const retryLazyLoad = instance => { - var settings = instance._settings; - var errorElements = settings.container.querySelectorAll( - "." + settings.class_error - ); - errorElements.forEach(element => { - removeClass(element, settings.class_error); - resetWasProcessedData(element); - }); - instance.update(); + var settings = instance._settings; + var errorElements = settings.container.querySelectorAll("." + settings.class_error); + nodeSetToArray(errorElements).forEach(element => { + removeClass(element, settings.class_error); + resetWasProcessedData(element); + }); + instance.update(); }; const setOnlineCheck = instance => { - if (!runningOnBrowser) { - return; - } - window.addEventListener("online", event => { - retryLazyLoad(instance); - }); + if (!runningOnBrowser) { + return; + } + window.addEventListener("online", event => { + retryLazyLoad(instance); + }); }; const LazyLoad = function(customSettings, elements) { diff --git a/dist/lazyload.esm.min.js b/dist/lazyload.esm.min.js index 29917641..d00ca479 100644 --- a/dist/lazyload.esm.min.js +++ b/dist/lazyload.esm.min.js @@ -1 +1 @@ -const e="undefined"!=typeof window,t=e&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),s=e&&"IntersectionObserver"in window,a=e&&"classList"in document.createElement("p"),r={elements_selector:"img",container:t||e?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_poster:"poster",class_loading:"loading",class_loaded:"loaded",class_error:"error",load_delay:0,auto_unobserve:!0,callback_enter:null,callback_exit:null,callback_reveal:null,callback_loaded:null,callback_error:null,callback_finish:null,use_native:!1};const n=function(e,t){var s;let a=new e(t);try{s=new CustomEvent("LazyLoad::Initialized",{detail:{instance:a}})}catch(e){(s=document.createEvent("CustomEvent")).initCustomEvent("LazyLoad::Initialized",!1,!1,{instance:a})}window.dispatchEvent(s)};const l=(e,t)=>e.getAttribute("data-"+t),o=(e,t,s)=>{var a="data-"+t;null!==s?e.setAttribute(a,s):e.removeAttribute(a)},i=e=>"true"===l(e,"was-processed"),c=(e,t)=>o(e,"ll-timeout",t),d=e=>l(e,"ll-timeout"),_=(e,t,s,a)=>{e&&(void 0===a?void 0===s?e(t):e(t,s):e(t,s,a))},u=(e,t)=>{e.loadingCount+=t,0===e._elements.length&&0===e.loadingCount&&_(e._settings.callback_finish,e)},g=e=>{let t=[];for(let s,a=0;s=e.children[a];a+=1)"SOURCE"===s.tagName&&t.push(s);return t},v=(e,t,s)=>{s&&e.setAttribute(t,s)},h=(e,t)=>{v(e,"sizes",l(e,t.data_sizes)),v(e,"srcset",l(e,t.data_srcset)),v(e,"src",l(e,t.data_src))},m={IMG:(e,t)=>{const s=e.parentNode;if(s&&"PICTURE"===s.tagName){g(s).forEach(e=>{h(e,t)})}h(e,t)},IFRAME:(e,t)=>{v(e,"src",l(e,t.data_src))},VIDEO:(e,t)=>{g(e).forEach(e=>{v(e,"src",l(e,t.data_src))}),v(e,"poster",l(e,t.data_poster)),v(e,"src",l(e,t.data_src)),e.load()}},b=(e,t)=>{const s=t._settings,a=e.tagName,r=m[a];if(r)return r(e,s),u(t,1),void(t._elements=(n=t._elements,o=e,n.filter(e=>e!==o)));var n,o;((e,t)=>{const s=l(e,t.data_src),a=l(e,t.data_bg);s&&(e.style.backgroundImage=`url("${s}")`),a&&(e.style.backgroundImage=a)})(e,s)},f=(e,t)=>{a?e.classList.add(t):e.className+=(e.className?" ":"")+t},p=(e,t)=>{a?e.classList.remove(t):e.className=e.className.replace(new RegExp("(^|\\s+)"+t+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")},E=(e,t,s)=>{e.addEventListener(t,s)},w=(e,t,s)=>{e.removeEventListener(t,s)},y=(e,t,s)=>{w(e,"load",t),w(e,"loadeddata",t),w(e,"error",s)},I=function(e,t,s){var a=s._settings;const r=t?a.class_loaded:a.class_error,n=t?a.callback_loaded:a.callback_error,l=e.target;p(l,a.class_loading),f(l,r),_(n,l,s),u(s,-1)},k=(e,t)=>{const s=r=>{I(r,!0,t),y(e,s,a)},a=r=>{I(r,!1,t),y(e,s,a)};((e,t,s)=>{E(e,"load",t),E(e,"loadeddata",t),E(e,"error",s)})(e,s,a)},A=["IMG","IFRAME","VIDEO"],L=(e,t)=>{var s=t._observer;O(e,t),s&&t._settings.auto_unobserve&&s.unobserve(e)},z=e=>{var t=d(e);t&&(clearTimeout(t),c(e,null))},N=(e,t)=>{var s=t._settings.load_delay,a=d(e);a||(a=setTimeout((function(){L(e,t),z(e)}),s),c(e,a))},O=(e,t,s)=>{var a=t._settings;!s&&i(e)||(A.indexOf(e.tagName)>-1&&(k(e,t),f(e,a.class_loading)),b(e,t),(e=>{o(e,"was-processed","true")})(e),_(a.callback_reveal,e,t))},C=e=>{return!!s&&(e._observer=new IntersectionObserver(t=>{t.forEach(t=>(e=>e.isIntersecting||e.intersectionRatio>0)(t)?((e,t,s)=>{const a=s._settings;_(a.callback_enter,e,t,s),a.load_delay?N(e,s):L(e,s)})(t.target,t,e):((e,t,s)=>{const a=s._settings;_(a.callback_exit,e,t,s),a.load_delay&&z(e)})(t.target,t,e))},{root:(t=e._settings).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}),!0);var t},M=["IMG","IFRAME"],x=(e,t)=>{return(e=>e.filter(e=>!i(e)))((s=e||(e=>e.container.querySelectorAll(e.elements_selector))(t),Array.prototype.slice.call(s)));var s},R=e=>{var t=e._settings;t.container.querySelectorAll("."+t.class_error).forEach(e=>{p(e,t.class_error),(e=>{o(e,"was-processed",null)})(e)}),e.update()},T=function(t,s){var a;this._settings=(e=>Object.assign({},r,e))(t),this.loadingCount=0,C(this),this.update(s),a=this,e&&window.addEventListener("online",e=>{R(a)})};T.prototype={update:function(e){var s,a=this._settings;(this._elements=x(e,a),!t&&this._observer)?((e=>e.use_native&&"loading"in HTMLImageElement.prototype)(a)&&((s=this)._elements.forEach(e=>{-1!==M.indexOf(e.tagName)&&(e.setAttribute("loading","lazy"),O(e,s))}),this._elements=x(e,a)),this._elements.forEach(e=>{this._observer.observe(e)})):this.loadAll()},destroy:function(){this._observer&&(this._elements.forEach(e=>{this._observer.unobserve(e)}),this._observer=null),this._elements=null,this._settings=null},load:function(e,t){O(e,this,t)},loadAll:function(){this._elements.forEach(e=>{L(e,this)})}},e&&function(e,t){if(t)if(t.length)for(let s,a=0;s=t[a];a+=1)n(e,s);else n(e,t)}(T,window.lazyLoadOptions);export default T; +const e="undefined"!=typeof window,t=e&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),s=e&&"IntersectionObserver"in window,a=e&&"classList"in document.createElement("p"),r={elements_selector:"img",container:t||e?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_poster:"poster",class_loading:"loading",class_loaded:"loaded",class_error:"error",load_delay:0,auto_unobserve:!0,callback_enter:null,callback_exit:null,callback_reveal:null,callback_loaded:null,callback_error:null,callback_finish:null,use_native:!1},l=function(e,t){var s;let a=new e(t);try{s=new CustomEvent("LazyLoad::Initialized",{detail:{instance:a}})}catch(e){(s=document.createEvent("CustomEvent")).initCustomEvent("LazyLoad::Initialized",!1,!1,{instance:a})}window.dispatchEvent(s)},n=(e,t)=>e.getAttribute("data-"+t),o=(e,t,s)=>{var a="data-"+t;null!==s?e.setAttribute(a,s):e.removeAttribute(a)},i=e=>"true"===n(e,"was-processed"),c=(e,t)=>o(e,"ll-timeout",t),d=e=>n(e,"ll-timeout"),_=e=>{let t=[];for(let s,a=0;s=e.children[a];a+=1)"SOURCE"===s.tagName&&t.push(s);return t},u=(e,t,s)=>{s&&e.setAttribute(t,s)},g=(e,t)=>{u(e,"sizes",n(e,t.data_sizes)),u(e,"srcset",n(e,t.data_srcset)),u(e,"src",n(e,t.data_src))},h={IMG:(e,t)=>{const s=e.parentNode;if(s&&"PICTURE"===s.tagName){_(s).forEach(e=>{g(e,t)})}g(e,t)},IFRAME:(e,t)=>{u(e,"src",n(e,t.data_src))},VIDEO:(e,t)=>{_(e).forEach(e=>{u(e,"src",n(e,t.data_src))}),u(e,"poster",n(e,t.data_poster)),u(e,"src",n(e,t.data_src)),e.load()}},v=(e,t)=>{const s=t._settings,a=e.tagName,r=h[a];if(r)return r(e,s),t.loadingCount+=1,void(t._elements=(l=t._elements,o=e,l.filter(e=>e!==o)));var l,o;((e,t)=>{const s=n(e,t.data_src),a=n(e,t.data_bg);s&&(e.style.backgroundImage=`url("${s}")`),a&&(e.style.backgroundImage=a)})(e,s)},m=(e,t)=>{a?e.classList.add(t):e.className+=(e.className?" ":"")+t},b=(e,t)=>{a?e.classList.remove(t):e.className=e.className.replace(new RegExp("(^|\\s+)"+t+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")},f=(e,t,s,a)=>{e&&(void 0===a?void 0===s?e(t):e(t,s):e(t,s,a))},p=(e,t,s)=>{e.addEventListener(t,s)},E=(e,t,s)=>{e.removeEventListener(t,s)},w=(e,t,s)=>{E(e,"load",t),E(e,"loadeddata",t),E(e,"error",s)},y=function(e,t,s){var a=s._settings;const r=t?a.class_loaded:a.class_error,l=t?a.callback_loaded:a.callback_error,n=e.target;b(n,a.class_loading),m(n,r),f(l,n,s),s.loadingCount-=1,0===s._elements.length&&0===s.loadingCount&&f(a.callback_finish,s)},I=(e,t)=>{const s=r=>{y(r,!0,t),w(e,s,a)},a=r=>{y(r,!1,t),w(e,s,a)};((e,t,s)=>{p(e,"load",t),p(e,"loadeddata",t),p(e,"error",s)})(e,s,a)},k=["IMG","IFRAME","VIDEO"],A=(e,t)=>{var s=t._observer;L(e,t),s&&t._settings.auto_unobserve&&s.unobserve(e)},L=(e,t,s)=>{var a=t._settings;!s&&i(e)||(k.indexOf(e.tagName)>-1&&(I(e,t),m(e,a.class_loading)),v(e,t),(e=>{o(e,"was-processed","true")})(e),f(a.callback_reveal,e,t))},z=e=>{var t=d(e);t&&(clearTimeout(t),c(e,null))},N=(e,t,s)=>{const a=s._settings;f(a.callback_enter,e,t,s),a.load_delay?((e,t)=>{var s=t._settings.load_delay,a=d(e);a||(a=setTimeout((function(){A(e,t),z(e)}),s),c(e,a))})(e,s):A(e,s)},C=e=>{return!!s&&(e._observer=new IntersectionObserver(t=>{t.forEach(t=>(e=>e.isIntersecting||e.intersectionRatio>0)(t)?N(t.target,t,e):((e,t,s)=>{const a=s._settings;f(a.callback_exit,e,t,s),a.load_delay&&z(e)})(t.target,t,e))},{root:(t=e._settings).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}),!0);var t},O=["IMG","IFRAME"],M=e=>Array.prototype.slice.call(e),x=(e,t)=>(e=>e.filter(e=>!i(e)))(M(e||(e=>e.container.querySelectorAll(e.elements_selector))(t))),R=e=>{var t=e._settings,s=t.container.querySelectorAll("."+t.class_error);M(s).forEach(e=>{b(e,t.class_error),(e=>{o(e,"was-processed",null)})(e)}),e.update()},T=function(t,s){var a;this._settings=(e=>Object.assign({},r,e))(t),this.loadingCount=0,C(this),this.update(s),a=this,e&&window.addEventListener("online",e=>{R(a)})};T.prototype={update:function(e){var s,a=this._settings;(this._elements=x(e,a),!t&&this._observer)?((e=>e.use_native&&"loading"in HTMLImageElement.prototype)(a)&&((s=this)._elements.forEach(e=>{-1!==O.indexOf(e.tagName)&&(e.setAttribute("loading","lazy"),L(e,s))}),this._elements=x(e,a)),this._elements.forEach(e=>{this._observer.observe(e)})):this.loadAll()},destroy:function(){this._observer&&(this._elements.forEach(e=>{this._observer.unobserve(e)}),this._observer=null),this._elements=null,this._settings=null},load:function(e,t){L(e,this,t)},loadAll:function(){this._elements.forEach(e=>{A(e,this)})}},e&&((e,t)=>{if(t)if(t.length)for(let s,a=0;s=t[a];a+=1)l(e,s);else l(e,t)})(T,window.lazyLoadOptions);export default T; diff --git a/dist/lazyload.iife.js b/dist/lazyload.iife.js index 52f71e2f..a7258c25 100644 --- a/dist/lazyload.iife.js +++ b/dist/lazyload.iife.js @@ -47,9 +47,9 @@ var LazyLoad = (function () { callback_finish: null, use_native: false }; - var getInstanceSettings = (function (customSettings) { + var getInstanceSettings = function getInstanceSettings(customSettings) { return _extends({}, defaultSettings, customSettings); - }); + }; /* Creates instance and notifies it through the window element */ var createInstance = function createInstance(classObj, options) { @@ -78,7 +78,7 @@ var LazyLoad = (function () { options passed in (plain object or an array) */ - function autoInitialize (classObj, options) { + var autoInitialize = function autoInitialize(classObj, options) { if (!options) { return; } @@ -92,7 +92,7 @@ var LazyLoad = (function () { createInstance(classObj, optionsItem); } } - } + }; var dataPrefix = "data-"; var processedDataName = "was-processed"; @@ -138,32 +138,6 @@ var LazyLoad = (function () { }); }; - var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { - if (!callback) { - return; - } - - if (arg3 !== undefined) { - callback(arg1, arg2, arg3); - return; - } - - if (arg2 !== undefined) { - callback(arg1, arg2); - return; - } - - callback(arg1); - }; - - var updateLoadingCount = function updateLoadingCount(instance, plusMinus) { - instance.loadingCount += plusMinus; - - if (instance._elements.length === 0 && instance.loadingCount === 0) { - safeCallback(instance._settings.callback_finish, instance); - } - }; - var getSourceTags = function getSourceTags(parentTag) { var sourceTags = []; @@ -235,7 +209,7 @@ var LazyLoad = (function () { if (setSourcesFunction) { setSourcesFunction(element, settings); - updateLoadingCount(instance, 1); + instance.loadingCount += 1; instance._elements = purgeOneElement(instance._elements, element); return; } @@ -260,6 +234,24 @@ var LazyLoad = (function () { element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, ""); }; + var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { + if (!callback) { + return; + } + + if (arg3 !== undefined) { + callback(arg1, arg2, arg3); + return; + } + + if (arg2 !== undefined) { + callback(arg1, arg2); + return; + } + + callback(arg1); + }; + var genericLoadEventName = "load"; var mediaLoadEventName = "loadeddata"; var errorEventName = "error"; @@ -292,7 +284,11 @@ var LazyLoad = (function () { removeClass(element, settings.class_loading); addClass(element, className); safeCallback(callback, element, instance); - updateLoadingCount(instance, -1); + instance.loadingCount -= 1; + + if (instance._elements.length === 0 && instance.loadingCount === 0) { + safeCallback(settings.callback_finish, instance); + } }; var addOneShotEventListeners = function addOneShotEventListeners(element, instance) { @@ -310,17 +306,6 @@ var LazyLoad = (function () { }; var managedTags = ["IMG", "IFRAME", "VIDEO"]; - var onEnter = function onEnter(element, entry, instance) { - var settings = instance._settings; - safeCallback(settings.callback_enter, element, entry, instance); - - if (!settings.load_delay) { - revealAndUnobserve(element, instance); - return; - } - - delayLoad(element, instance); - }; var revealAndUnobserve = function revealAndUnobserve(element, instance) { var observer = instance._observer; revealElement(element, instance); @@ -329,16 +314,23 @@ var LazyLoad = (function () { observer.unobserve(element); } }; - var onExit = function onExit(element, entry, instance) { + var revealElement = function revealElement(element, instance, force) { var settings = instance._settings; - safeCallback(settings.callback_exit, element, entry, instance); - if (!settings.load_delay) { - return; + if (!force && getWasProcessedData(element)) { + return; // element has already been processed and force wasn't true } - cancelDelayLoad(element); + if (managedTags.indexOf(element.tagName) > -1) { + addOneShotEventListeners(element, instance); + addClass(element, settings.class_loading); + } + + setSources(element, instance); + setWasProcessedData(element); + safeCallback(settings.callback_reveal, element, instance); }; + var cancelDelayLoad = function cancelDelayLoad(element) { var timeoutId = getTimeoutData(element); @@ -363,32 +355,40 @@ var LazyLoad = (function () { }, loadDelay); setTimeoutData(element, timeoutId); }; - var revealElement = function revealElement(element, instance, force) { + + var onEnter = function onEnter(element, entry, instance) { var settings = instance._settings; + safeCallback(settings.callback_enter, element, entry, instance); - if (!force && getWasProcessedData(element)) { - return; // element has already been processed and force wasn't true + if (!settings.load_delay) { + revealAndUnobserve(element, instance); + return; } - if (managedTags.indexOf(element.tagName) > -1) { - addOneShotEventListeners(element, instance); - addClass(element, settings.class_loading); + delayLoad(element, instance); + }; + var onExit = function onExit(element, entry, instance) { + var settings = instance._settings; + safeCallback(settings.callback_exit, element, entry, instance); + + if (!settings.load_delay) { + return; } - setSources(element, instance); - setWasProcessedData(element); - safeCallback(settings.callback_reveal, element, instance); + cancelDelayLoad(element); }; var isIntersecting = function isIntersecting(entry) { return entry.isIntersecting || entry.intersectionRatio > 0; }; + var getObserverSettings = function getObserverSettings(settings) { return { root: settings.container === document ? null : settings.container, rootMargin: settings.thresholds || settings.threshold + "px" }; }; + var setObserver = function setObserver(instance) { if (!supportsIntersectionObserver) { return false; @@ -417,13 +417,13 @@ var LazyLoad = (function () { }); }; - var nodeSetToArray = function nodeSetToArray(nodeSet) { - return Array.prototype.slice.call(nodeSet); - }; - var queryElements = function queryElements(settings) { return settings.container.querySelectorAll(settings.elements_selector); }; + + var nodeSetToArray = function nodeSetToArray(nodeSet) { + return Array.prototype.slice.call(nodeSet); + }; var getElements = function getElements(elements, settings) { return purgeProcessedElements(nodeSetToArray(elements || queryElements(settings))); }; @@ -431,7 +431,7 @@ var LazyLoad = (function () { var retryLazyLoad = function retryLazyLoad(instance) { var settings = instance._settings; var errorElements = settings.container.querySelectorAll("." + settings.class_error); - errorElements.forEach(function (element) { + nodeSetToArray(errorElements).forEach(function (element) { removeClass(element, settings.class_error); resetWasProcessedData(element); }); diff --git a/dist/lazyload.iife.min.js b/dist/lazyload.iife.min.js index e95de442..498d3ab6 100644 --- a/dist/lazyload.iife.min.js +++ b/dist/lazyload.iife.min.js @@ -1 +1 @@ -var LazyLoad=function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(A(t,e),p(t,r.class_loading)),b(t,e),function(t){c(t,"was-processed","true")}(t),f(r.callback_reveal,t,e))},M=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?function(t,e,n){var r=n._settings;f(r.callback_enter,t,e,n),r.load_delay?N(t,n):z(t,n)}(e.target,e,t):function(t,e,n){var r=n._settings;f(r.callback_exit,t,e,n),r.load_delay&&O(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},R=["IMG","IFRAME"],x=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}((n=t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e),Array.prototype.slice.call(n)));var n},T=function(t){var e=t._settings;e.container.querySelectorAll("."+e.class_error).forEach((function(t){E(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},F=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,M(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return F.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=x(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==R.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),C(t,e))})),this._elements=x(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){C(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){z(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)s(t,n);else s(t,e)}(F,window.lazyLoadOptions),F}(); +var LazyLoad=function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(k(t,e),m(t,r.class_loading)),h(t,e),function(t){c(t,"was-processed","true")}(t),p(r.callback_reveal,t,e))},O=function(t){var e=d(t);e&&(clearTimeout(e),u(t,null))},N=function(t,e,n){var r=n._settings;p(r.callback_enter,t,e,n),r.load_delay?function(t,e){var n=e._settings.load_delay,r=d(t);r||(r=setTimeout((function(){L(t,e),O(t)}),n),u(t,r))}(t,n):L(t,n)},C=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?N(e.target,e,t):function(t,e,n){var r=n._settings;p(r.callback_exit,t,e,n),r.load_delay&&O(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},M=["IMG","IFRAME"],R=function(t){return Array.prototype.slice.call(t)},x=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}(R(t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e)))},T=function(t){var e=t._settings,n=e.container.querySelectorAll("."+e.class_error);R(n).forEach((function(t){b(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},F=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,C(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return F.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=x(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==M.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),z(t,e))})),this._elements=x(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){z(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){L(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)s(t,n);else s(t,e)}(F,window.lazyLoadOptions),F}(); diff --git a/dist/lazyload.js b/dist/lazyload.js index ed5c22c9..846d88ce 100644 --- a/dist/lazyload.js +++ b/dist/lazyload.js @@ -50,9 +50,9 @@ callback_finish: null, use_native: false }; - var getInstanceSettings = (function (customSettings) { + var getInstanceSettings = function getInstanceSettings(customSettings) { return _extends({}, defaultSettings, customSettings); - }); + }; /* Creates instance and notifies it through the window element */ var createInstance = function createInstance(classObj, options) { @@ -81,7 +81,7 @@ options passed in (plain object or an array) */ - function autoInitialize (classObj, options) { + var autoInitialize = function autoInitialize(classObj, options) { if (!options) { return; } @@ -95,7 +95,7 @@ createInstance(classObj, optionsItem); } } - } + }; var dataPrefix = "data-"; var processedDataName = "was-processed"; @@ -141,32 +141,6 @@ }); }; - var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { - if (!callback) { - return; - } - - if (arg3 !== undefined) { - callback(arg1, arg2, arg3); - return; - } - - if (arg2 !== undefined) { - callback(arg1, arg2); - return; - } - - callback(arg1); - }; - - var updateLoadingCount = function updateLoadingCount(instance, plusMinus) { - instance.loadingCount += plusMinus; - - if (instance._elements.length === 0 && instance.loadingCount === 0) { - safeCallback(instance._settings.callback_finish, instance); - } - }; - var getSourceTags = function getSourceTags(parentTag) { var sourceTags = []; @@ -238,7 +212,7 @@ if (setSourcesFunction) { setSourcesFunction(element, settings); - updateLoadingCount(instance, 1); + instance.loadingCount += 1; instance._elements = purgeOneElement(instance._elements, element); return; } @@ -263,6 +237,24 @@ element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, ""); }; + var safeCallback = function safeCallback(callback, arg1, arg2, arg3) { + if (!callback) { + return; + } + + if (arg3 !== undefined) { + callback(arg1, arg2, arg3); + return; + } + + if (arg2 !== undefined) { + callback(arg1, arg2); + return; + } + + callback(arg1); + }; + var genericLoadEventName = "load"; var mediaLoadEventName = "loadeddata"; var errorEventName = "error"; @@ -295,7 +287,11 @@ removeClass(element, settings.class_loading); addClass(element, className); safeCallback(callback, element, instance); - updateLoadingCount(instance, -1); + instance.loadingCount -= 1; + + if (instance._elements.length === 0 && instance.loadingCount === 0) { + safeCallback(settings.callback_finish, instance); + } }; var addOneShotEventListeners = function addOneShotEventListeners(element, instance) { @@ -313,17 +309,6 @@ }; var managedTags = ["IMG", "IFRAME", "VIDEO"]; - var onEnter = function onEnter(element, entry, instance) { - var settings = instance._settings; - safeCallback(settings.callback_enter, element, entry, instance); - - if (!settings.load_delay) { - revealAndUnobserve(element, instance); - return; - } - - delayLoad(element, instance); - }; var revealAndUnobserve = function revealAndUnobserve(element, instance) { var observer = instance._observer; revealElement(element, instance); @@ -332,16 +317,23 @@ observer.unobserve(element); } }; - var onExit = function onExit(element, entry, instance) { + var revealElement = function revealElement(element, instance, force) { var settings = instance._settings; - safeCallback(settings.callback_exit, element, entry, instance); - if (!settings.load_delay) { - return; + if (!force && getWasProcessedData(element)) { + return; // element has already been processed and force wasn't true } - cancelDelayLoad(element); + if (managedTags.indexOf(element.tagName) > -1) { + addOneShotEventListeners(element, instance); + addClass(element, settings.class_loading); + } + + setSources(element, instance); + setWasProcessedData(element); + safeCallback(settings.callback_reveal, element, instance); }; + var cancelDelayLoad = function cancelDelayLoad(element) { var timeoutId = getTimeoutData(element); @@ -366,32 +358,40 @@ }, loadDelay); setTimeoutData(element, timeoutId); }; - var revealElement = function revealElement(element, instance, force) { + + var onEnter = function onEnter(element, entry, instance) { var settings = instance._settings; + safeCallback(settings.callback_enter, element, entry, instance); - if (!force && getWasProcessedData(element)) { - return; // element has already been processed and force wasn't true + if (!settings.load_delay) { + revealAndUnobserve(element, instance); + return; } - if (managedTags.indexOf(element.tagName) > -1) { - addOneShotEventListeners(element, instance); - addClass(element, settings.class_loading); + delayLoad(element, instance); + }; + var onExit = function onExit(element, entry, instance) { + var settings = instance._settings; + safeCallback(settings.callback_exit, element, entry, instance); + + if (!settings.load_delay) { + return; } - setSources(element, instance); - setWasProcessedData(element); - safeCallback(settings.callback_reveal, element, instance); + cancelDelayLoad(element); }; var isIntersecting = function isIntersecting(entry) { return entry.isIntersecting || entry.intersectionRatio > 0; }; + var getObserverSettings = function getObserverSettings(settings) { return { root: settings.container === document ? null : settings.container, rootMargin: settings.thresholds || settings.threshold + "px" }; }; + var setObserver = function setObserver(instance) { if (!supportsIntersectionObserver) { return false; @@ -420,13 +420,13 @@ }); }; - var nodeSetToArray = function nodeSetToArray(nodeSet) { - return Array.prototype.slice.call(nodeSet); - }; - var queryElements = function queryElements(settings) { return settings.container.querySelectorAll(settings.elements_selector); }; + + var nodeSetToArray = function nodeSetToArray(nodeSet) { + return Array.prototype.slice.call(nodeSet); + }; var getElements = function getElements(elements, settings) { return purgeProcessedElements(nodeSetToArray(elements || queryElements(settings))); }; @@ -434,7 +434,7 @@ var retryLazyLoad = function retryLazyLoad(instance) { var settings = instance._settings; var errorElements = settings.container.querySelectorAll("." + settings.class_error); - errorElements.forEach(function (element) { + nodeSetToArray(errorElements).forEach(function (element) { removeClass(element, settings.class_error); resetWasProcessedData(element); }); diff --git a/dist/lazyload.min.js b/dist/lazyload.min.js index 291a3d31..5c27745c 100644 --- a/dist/lazyload.min.js +++ b/dist/lazyload.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).LazyLoad=e()}(this,(function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(A(t,e),p(t,r.class_loading)),b(t,e),function(t){c(t,"was-processed","true")}(t),f(r.callback_reveal,t,e))},C=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?function(t,e,n){var r=n._settings;f(r.callback_enter,t,e,n),r.load_delay?N(t,n):z(t,n)}(e.target,e,t):function(t,e,n){var r=n._settings;f(r.callback_exit,t,e,n),r.load_delay&&O(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},M=["IMG","IFRAME"],R=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}((n=t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e),Array.prototype.slice.call(n)));var n},T=function(t){var e=t._settings;e.container.querySelectorAll("."+e.class_error).forEach((function(t){y(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},j=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,C(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return j.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=R(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==M.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),x(t,e))})),this._elements=R(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){x(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){z(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)s(t,n);else s(t,e)}(j,window.lazyLoadOptions),j})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).LazyLoad=e()}(this,(function(){"use strict";function t(){return(t=Object.assign||function(t){for(var e=1;e-1&&(k(t,e),m(t,r.class_loading)),h(t,e),function(t){c(t,"was-processed","true")}(t),p(r.callback_reveal,t,e))},O=function(t){var e=d(t);e&&(clearTimeout(e),u(t,null))},N=function(t,e,n){var r=n._settings;p(r.callback_enter,t,e,n),r.load_delay?function(t,e){var n=e._settings.load_delay,r=d(t);r||(r=setTimeout((function(){L(t,e),O(t)}),n),u(t,r))}(t,n):L(t,n)},C=function(t){return!!r&&(t._observer=new IntersectionObserver((function(e){e.forEach((function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?N(e.target,e,t):function(t,e,n){var r=n._settings;p(r.callback_exit,t,e,n),r.load_delay&&O(t)}(e.target,e,t)}))}),{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},x=["IMG","IFRAME"],M=function(t){return Array.prototype.slice.call(t)},R=function(t,e){return function(t){return t.filter((function(t){return!l(t)}))}(M(t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e)))},T=function(t){var e=t._settings,n=e.container.querySelectorAll("."+e.class_error);M(n).forEach((function(t){b(t,e.class_error),function(t){c(t,"was-processed",null)}(t)})),t.update()},j=function(n,r){var a;this._settings=function(e){return t({},o,e)}(n),this.loadingCount=0,C(this),this.update(r),a=this,e&&window.addEventListener("online",(function(t){T(a)}))};return j.prototype={update:function(t){var e,r=this,a=this._settings;(this._elements=R(t,a),!n&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(a)&&((e=this)._elements.forEach((function(t){-1!==x.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),z(t,e))})),this._elements=R(t,a)),this._elements.forEach((function(t){r._observer.observe(t)}))):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach((function(e){t._observer.unobserve(e)})),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){z(t,this,e)},loadAll:function(){var t=this;this._elements.forEach((function(e){L(e,t)}))}},e&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)i(t,n);else i(t,e)}(j,window.lazyLoadOptions),j})); diff --git a/package.json b/package.json index 9f572356..f0bd77e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vanilla-lazyload", - "version": "13.0.0", + "version": "13.0.1", "description": "A fast, lightweight script to load images as they enter the viewport. SEO friendly, it supports responsive images (both srcset + sizes and picture) and progressive JPEG", "main": "dist/lazyload.min.js", "module": "dist/lazyload.esm.js",