function _extends() { _extends = object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (object.prototype.hasownproperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _typeof(obj) { if (typeof symbol === "function" && typeof symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof symbol === "function" && obj.constructor === symbol && obj !== symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } (function (global, factory) { (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.lazyload = factory(); })(this, function () { 'use strict'; var runningonbrowser = typeof window !== "undefined"; var isbot = runningonbrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro)bot|crawl|spider/i.test(navigator.useragent); var supportsintersectionobserver = runningonbrowser && "intersectionobserver" in window; var supportsclasslist = runningonbrowser && "classlist" in document.createelement("p"); var 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", 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 = function getinstancesettings(customsettings) { return _extends({}, defaultsettings, customsettings); }; /* creates instance and notifies it through the window element */ var createinstance = function createinstance(classobj, options) { var event; var eventstring = "lazyload::initialized"; var instance = new classobj(options); try { // works in modern browsers event = new customevent(eventstring, { detail: { instance: instance } }); } catch (err) { // works in internet explorer (all versions) event = document.createevent("customevent"); event.initcustomevent(eventstring, false, false, { instance: 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 (var i = 0, optionsitem; optionsitem = options[i]; i += 1) { createinstance(classobj, optionsitem); } } } var dataprefix = "data-"; var processeddataname = "was-processed"; var timeoutdataname = "ll-timeout"; var truestring = "true"; var getdata = function getdata(element, attribute) { return element.getattribute(dataprefix + attribute); }; var setdata = function setdata(element, attribute, value) { var attrname = dataprefix + attribute; if (value === null) { element.removeattribute(attrname); return; } element.setattribute(attrname, value); }; var setwasprocesseddata = function setwasprocesseddata(element) { return setdata(element, processeddataname, truestring); }; var getwasprocesseddata = function getwasprocesseddata(element) { return getdata(element, processeddataname) === truestring; }; var settimeoutdata = function settimeoutdata(element, value) { return setdata(element, timeoutdataname, value); }; var gettimeoutdata = function gettimeoutdata(element) { return getdata(element, timeoutdataname); }; var purgeprocessedelements = function purgeprocessedelements(elements) { return elements.filter(function (element) { return !getwasprocesseddata(element); }); }; var purgeoneelement = function purgeoneelement(elements, elementtopurge) { return elements.filter(function (element) { return element !== elementtopurge; }); }; var callbackifset = function callbackifset(callback, argument) { if (callback) { callback(argument); } }; var updateloadingcount = function updateloadingcount(instance, plusminus) { instance._loadingcount += plusminus; if (instance._elements.length === 0 && instance._loadingcount === 0) { callbackifset(instance._settings.callback_finish); } }; var getsourcetags = function getsourcetags(parenttag) { var sourcetags = []; for (var i = 0, childtag; childtag = parenttag.children[i]; i += 1) { if (childtag.tagname === "source") { sourcetags.push(childtag); } } return sourcetags; }; var setattributeifvalue = function setattributeifvalue(element, attrname, value) { if (!value) { return; } element.setattribute(attrname, value); }; var setimageattributes = function 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)); }; var setsourcesimg = function setsourcesimg(element, settings) { var parent = element.parentnode; if (parent && parent.tagname === "picture") { var sourcetags = getsourcetags(parent); sourcetags.foreach(function (sourcetag) { setimageattributes(sourcetag, settings); }); } setimageattributes(element, settings); }; var setsourcesiframe = function setsourcesiframe(element, settings) { setattributeifvalue(element, "src", getdata(element, settings.data_src)); }; var setsourcesvideo = function setsourcesvideo(element, settings) { var sourcetags = getsourcetags(element); sourcetags.foreach(function (sourcetag) { setattributeifvalue(sourcetag, "src", getdata(sourcetag, settings.data_src)); }); setattributeifvalue(element, "src", getdata(element, settings.data_src)); element.load(); }; var setsourcesbgimage = function setsourcesbgimage(element, settings) { var srcdatavalue = getdata(element, settings.data_src); var bgdatavalue = getdata(element, settings.data_bg); if (srcdatavalue) { element.style.backgroundimage = "url(\"".concat(srcdatavalue, "\")"); } if (bgdatavalue) { element.style.backgroundimage = bgdatavalue; } }; var setsourcesfunctions = { img: setsourcesimg, iframe: setsourcesiframe, video: setsourcesvideo }; var setsources = function setsources(element, instance) { var settings = instance._settings; var tagname = element.tagname; var setsourcesfunction = setsourcesfunctions[tagname]; if (setsourcesfunction) { setsourcesfunction(element, settings); updateloadingcount(instance, 1); instance._elements = purgeoneelement(instance._elements, element); return; } setsourcesbgimage(element, settings); }; var addclass = function addclass(element, classname) { if (supportsclasslist) { element.classlist.add(classname); return; } element.classname += (element.classname ? " " : "") + classname; }; var removeclass = function removeclass(element, classname) { if (supportsclasslist) { element.classlist.remove(classname); return; } element.classname = element.classname.replace(new regexp("(^|\\s+)" + classname + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, ""); }; var genericloadeventname = "load"; var medialoadeventname = "loadeddata"; var erroreventname = "error"; var addeventlistener = function addeventlistener(element, eventname, handler) { element.addeventlistener(eventname, handler); }; var removeeventlistener = function removeeventlistener(element, eventname, handler) { element.removeeventlistener(eventname, handler); }; var addeventlisteners = function addeventlisteners(element, loadhandler, errorhandler) { addeventlistener(element, genericloadeventname, loadhandler); addeventlistener(element, medialoadeventname, loadhandler); addeventlistener(element, erroreventname, errorhandler); }; var removeeventlisteners = function removeeventlisteners(element, loadhandler, errorhandler) { removeeventlistener(element, genericloadeventname, loadhandler); removeeventlistener(element, medialoadeventname, loadhandler); removeeventlistener(element, erroreventname, errorhandler); }; var eventhandler = function eventhandler(event, success, instance) { var settings = instance._settings; var classname = success ? settings.class_loaded : settings.class_error; var callback = success ? settings.callback_loaded : settings.callback_error; var element = event.target; removeclass(element, settings.class_loading); addclass(element, classname); callbackifset(callback, element); updateloadingcount(instance, -1); }; var addoneshoteventlisteners = function addoneshoteventlisteners(element, instance) { var loadhandler = function loadhandler(event) { eventhandler(event, true, instance); removeeventlisteners(element, loadhandler, errorhandler); }; var errorhandler = function errorhandler(event) { eventhandler(event, false, instance); removeeventlisteners(element, loadhandler, errorhandler); }; addeventlisteners(element, loadhandler, errorhandler); }; var managedtags = ["img", "iframe", "video"]; var onenter = function onenter(element, instance) { var settings = instance._settings; callbackifset(settings.callback_enter, element); if (!settings.load_delay) { revealandunobserve(element, instance); return; } delayload(element, instance); }; var revealandunobserve = function revealandunobserve(element, instance) { var observer = instance._observer; revealelement(element, instance); if (observer && instance._settings.auto_unobserve) { observer.unobserve(element); } }; var onexit = function onexit(element, instance) { var settings = instance._settings; callbackifset(settings.callback_exit, element); if (!settings.load_delay) { return; } canceldelayload(element); }; var canceldelayload = function canceldelayload(element) { var timeoutid = gettimeoutdata(element); if (!timeoutid) { return; // do nothing if timeout doesn't exist } cleartimeout(timeoutid); settimeoutdata(element, null); }; var delayload = function 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 revealelement = function 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); callbackifset(settings.callback_reveal, element); callbackifset(settings.callback_set, 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; } instance._observer = new intersectionobserver(function (entries) { entries.foreach(function (entry) { return isintersecting(entry) ? onenter(entry.target, instance) : onexit(entry.target, instance); }); }, getobserversettings(instance._settings)); return true; }; var nativelazytags = ["img", "iframe"]; var shouldusenative = function shouldusenative(settings) { return settings.use_native && "loading" in htmlimageelement.prototype; }; var loadallnative = function loadallnative(instance) { instance._elements.foreach(function (element) { if (nativelazytags.indexof(element.tagname) === -1) { return; } element.setattribute("loading", "lazy"); revealelement(element, instance); }); }; var nodesettoarray = function nodesettoarray(nodeset) { return array.prototype.slice.call(nodeset); }; var queryelements = function queryelements(settings) { return settings.container.queryselectorall(settings.elements_selector); }; var getelements = function getelements(elements, settings) { return purgeprocessedelements(nodesettoarray(elements || queryelements(settings))); }; var lazyload = function lazyload(customsettings, elements) { this._settings = getinstancesettings(customsettings); this._loadingcount = 0; setobserver(this); this.update(elements); }; lazyload.prototype = { update: function update(elements) { var _this = this; var settings = this._settings; this._elements = getelements(elements, settings); if (isbot || !this._observer) { this.loadall(); return; } if (shouldusenative(settings)) { loadallnative(this); this._elements = getelements(elements, settings); } this._elements.foreach(function (element) { _this._observer.observe(element); }); }, destroy: function destroy() { var _this2 = this; if (this._observer) { this._elements.foreach(function (element) { _this2._observer.unobserve(element); }); this._observer = null; } this._elements = null; this._settings = null; }, load: function load(element, force) { revealelement(element, this, force); }, loadall: function loadall() { var _this3 = this; this._elements.foreach(function (element) { revealandunobserve(element, _this3); }); } }; /* automatic instances creation if required (useful for async script loading) */ if (runningonbrowser) { autoinitialize(lazyload, window.lazyloadoptions); } return lazyload; });