// version 5.3.0 (function(window, factory) { var lazySizes = factory(window, window.document, Date); window.lazySizes = lazySizes; if(typeof module == 'object' && module.exports){ module.exports = lazySizes; } }(typeof window != 'undefined' ? window : {}, function l(window, document, Date) { // Pass in the windoe Date function also for SSR because the Date class can be lost 'use strict'; /*jshint eqnull:true */ var lazysizes, lazySizesCfg; (function(){ var prop; var lazySizesDefaults = { lazyClass: 'lazyload', loadedClass: 'lazyloaded', loadingClass: 'lazyloading', preloadClass: 'lazypreload', errorClass: 'lazyerror', //strictClass: 'lazystrict', autosizesClass: 'lazyautosizes', fastLoadedClass: 'ls-is-cached', iframeLoadMode: 0, srcAttr: 'data-src', srcsetAttr: 'data-srcset', sizesAttr: 'data-sizes', //preloadAfterLoad: false, minSize: 40, customMedia: {}, init: true, expFactor: 1.5, hFac: 0.8, loadMode: 2, loadHidden: true, ricTimeout: 0, throttleDelay: 125, }; lazySizesCfg = window.lazySizesConfig || window.lazysizesConfig || {}; for(prop in lazySizesDefaults){ if(!(prop in lazySizesCfg)){ lazySizesCfg[prop] = lazySizesDefaults[prop]; } } })(); if (!document || !document.getElementsByClassName) { return { init: function () {}, cfg: lazySizesCfg, noSupport: true, }; } var docElem = document.documentElement; var supportPicture = window.HTMLPictureElement; var _addEventListener = 'addEventListener'; var _getAttribute = 'getAttribute'; /** * Update to bind to window because 'this' becomes null during SSR * builds. */ var addEventListener = window[_addEventListener].bind(window); var setTimeout = window.setTimeout; var requestAnimationFrame = window.requestAnimationFrame || setTimeout; var requestIdleCallback = window.requestIdleCallback; var regPicture = /^picture$/i; var loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded']; var regClassCache = {}; var forEach = Array.prototype.forEach; var hasClass = function(ele, cls) { if(!regClassCache[cls]){ regClassCache[cls] = new RegExp('(\\s|^)'+cls+'(\\s|$)'); } return regClassCache[cls].test(ele[_getAttribute]('class') || '') && regClassCache[cls]; }; var addClass = function(ele, cls) { if (!hasClass(ele, cls)){ ele.setAttribute('class', (ele[_getAttribute]('class') || '').trim() + ' ' + cls); } }; var removeClass = function(ele, cls) { var reg; if ((reg = hasClass(ele,cls))) { ele.setAttribute('class', (ele[_getAttribute]('class') || '').replace(reg, ' ')); } }; var addRemoveLoadEvents = function(dom, fn, add){ var action = add ? _addEventListener : 'removeEventListener'; if(add){ addRemoveLoadEvents(dom, fn); } loadEvents.forEach(function(evt){ dom[action](evt, fn); }); }; var triggerEvent = function(elem, name, detail, noBubbles, noCancelable){ var event = document.createEvent('Event'); if(!detail){ detail = {}; } detail.instance = lazysizes; event.initEvent(name, !noBubbles, !noCancelable); event.detail = detail; elem.dispatchEvent(event); return event; }; var updatePolyfill = function (el, full){ var polyfill; if( !supportPicture && ( polyfill = (window.picturefill || lazySizesCfg.pf) ) ){ if(full && full.src && !el[_getAttribute]('srcset')){ el.setAttribute('srcset', full.src); } polyfill({reevaluate: true, elements: [el]}); } else if(full && full.src){ el.src = full.src; } }; var getCSS = function (elem, style){ return (getComputedStyle(elem, null) || {})[style]; }; var getWidth = function(elem, parent, width){ width = width || elem.offsetWidth; while(width < lazySizesCfg.minSize && parent && !elem._lazysizesWidth){ width = parent.offsetWidth; parent = parent.parentNode; } return width; }; var rAF = (function(){ var running, waiting; var firstFns = []; var secondFns = []; var fns = firstFns; var run = function(){ var runFns = fns; fns = firstFns.length ? secondFns : firstFns; running = true; waiting = false; while(runFns.length){ runFns.shift()(); } running = false; }; var rafBatch = function(fn, queue){ if(running && !queue){ fn.apply(this, arguments); } else { fns.push(fn); if(!waiting){ waiting = true; (document.hidden ? setTimeout : requestAnimationFrame)(run); } } }; rafBatch._lsFlush = run; return rafBatch; })(); var rAFIt = function(fn, simple){ return simple ? function() { rAF(fn); } : function(){ var that = this; var args = arguments; rAF(function(){ fn.apply(that, args); }); } ; }; var throttle = function(fn){ var running; var lastTime = 0; var gDelay = lazySizesCfg.throttleDelay; var rICTimeout = lazySizesCfg.ricTimeout; var run = function(){ running = false; lastTime = Date.now(); fn(); }; var idleCallback = requestIdleCallback && rICTimeout > 49 ? function(){ requestIdleCallback(run, {timeout: rICTimeout}); if(rICTimeout !== lazySizesCfg.ricTimeout){ rICTimeout = lazySizesCfg.ricTimeout; } } : rAFIt(function(){ setTimeout(run); }, true) ; return function(isPriority){ var delay; if((isPriority = isPriority === true)){ rICTimeout = 33; } if(running){ return; } running = true; delay = gDelay - (Date.now() - lastTime); if(delay < 0){ delay = 0; } if(isPriority || delay < 9){ idleCallback(); } else { setTimeout(idleCallback, delay); } }; }; //based on http://modernjavascript.blogspot.de/2013/08/building-better-debounce.html var debounce = function(func) { var timeout, timestamp; var wait = 99; var run = function(){ timeout = null; func(); }; var later = function() { var last = Date.now() - timestamp; if (last < wait) { setTimeout(later, wait - last); } else { (requestIdleCallback || run)(run); } }; return function() { timestamp = Date.now(); if (!timeout) { timeout = setTimeout(later, wait); } }; }; var loader = (function(){ var preloadElems, isCompleted, resetPreloadingTimer, loadMode, started; var eLvW, elvH, eLtop, eLleft, eLright, eLbottom, isBodyHidden; var regImg = /^img$/i; var regIframe = /^iframe$/i; var supportScroll = ('onscroll' in window) && !(/(gle|ing)bot/.test(navigator.userAgent)); var shrinkExpand = 0; var currentExpand = 0; var isLoading = 0; var lowRuns = -1; var resetPreloading = function(e){ isLoading--; if(!e || isLoading < 0 || !e.target){ isLoading = 0; } }; var isVisible = function (elem) { if (isBodyHidden == null) { isBodyHidden = getCSS(document.body, 'visibility') == 'hidden'; } return isBodyHidden || !(getCSS(elem.parentNode, 'visibility') == 'hidden' && getCSS(elem, 'visibility') == 'hidden'); }; var isNestedVisible = function(elem, elemExpand){ var outerRect; var parent = elem; var visible = isVisible(elem); eLtop -= elemExpand; eLbottom += elemExpand; eLleft -= elemExpand; eLright += elemExpand; while(visible && (parent = parent.offsetParent) && parent != document.body && parent != docElem){ visible = ((getCSS(parent, 'opacity') || 1) > 0); if(visible && getCSS(parent, 'overflow') != 'visible'){ outerRect = parent.getBoundingClientRect(); visible = eLright > outerRect.left && eLleft < outerRect.right && eLbottom > outerRect.top - 1 && eLtop < outerRect.bottom + 1 ; } } return visible; }; var checkElements = function() { var eLlen, i, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal, beforeExpandVal, defaultExpand, preloadExpand, hFac; var lazyloadElems = lazysizes.elements; if((loadMode = lazySizesCfg.loadMode) && isLoading < 8 && (eLlen = lazyloadElems.length)){ i = 0; lowRuns++; for(; i < eLlen; i++){ if(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;} if(!supportScroll || (lazysizes.prematureUnveil && lazysizes.prematureUnveil(lazyloadElems[i]))){unveilElement(lazyloadElems[i]);continue;} if(!(elemExpandVal = lazyloadElems[i][_getAttribute]('data-expand')) || !(elemExpand = elemExpandVal * 1)){ elemExpand = currentExpand; } if (!defaultExpand) { defaultExpand = (!lazySizesCfg.expand || lazySizesCfg.expand < 1) ? docElem.clientHeight > 500 && docElem.clientWidth > 500 ? 500 : 370 : lazySizesCfg.expand; lazysizes._defEx = defaultExpand; preloadExpand = defaultExpand * lazySizesCfg.expFactor; hFac = lazySizesCfg.hFac; isBodyHidden = null; if(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 2 && loadMode > 2 && !document.hidden){ currentExpand = preloadExpand; lowRuns = 0; } else if(loadMode > 1 && lowRuns > 1 && isLoading < 6){ currentExpand = defaultExpand; } else { currentExpand = shrinkExpand; } } if(beforeExpandVal !== elemExpand){ eLvW = innerWidth + (elemExpand * hFac); elvH = innerHeight + elemExpand; elemNegativeExpand = elemExpand * -1; beforeExpandVal = elemExpand; } rect = lazyloadElems[i].getBoundingClientRect(); if ((eLbottom = rect.bottom) >= elemNegativeExpand && (eLtop = rect.top) <= elvH && (eLright = rect.right) >= elemNegativeExpand * hFac && (eLleft = rect.left) <= eLvW && (eLbottom || eLright || eLleft || eLtop) && (lazySizesCfg.loadHidden || isVisible(lazyloadElems[i])) && ((isCompleted && isLoading < 3 && !elemExpandVal && (loadMode < 3 || lowRuns < 4)) || isNestedVisible(lazyloadElems[i], elemExpand))){ unveilElement(lazyloadElems[i]); loadedSomething = true; if(isLoading > 9){break;} } else if(!loadedSomething && isCompleted && !autoLoadElem && isLoading < 4 && lowRuns < 4 && loadMode > 2 && (preloadElems[0] || lazySizesCfg.preloadAfterLoad) && (preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i][_getAttribute](lazySizesCfg.sizesAttr) != 'auto')))){ autoLoadElem = preloadElems[0] || lazyloadElems[i]; } } if(autoLoadElem && !loadedSomething){ unveilElement(autoLoadElem); } } }; var throttledCheckElements = throttle(checkElements); var switchLoadingClass = function(e){ var elem = e.target; if (elem._lazyCache) { delete elem._lazyCache; return; } resetPreloading(e); addClass(elem, lazySizesCfg.loadedClass); removeClass(elem, lazySizesCfg.loadingClass); addRemoveLoadEvents(elem, rafSwitchLoadingClass); triggerEvent(elem, 'lazyloaded'); }; var rafedSwitchLoadingClass = rAFIt(switchLoadingClass); var rafSwitchLoadingClass = function(e){ rafedSwitchLoadingClass({target: e.target}); }; var changeIframeSrc = function(elem, src){ var loadMode = elem.getAttribute('data-load-mode') || lazySizesCfg.iframeLoadMode; // loadMode can be also a string! if (loadMode == 0) { elem.contentWindow.location.replace(src); } else if (loadMode == 1) { elem.src = src; } }; var handleSources = function(source){ var customMedia; var sourceSrcset = source[_getAttribute](lazySizesCfg.srcsetAttr); if( (customMedia = lazySizesCfg.customMedia[source[_getAttribute]('data-media') || source[_getAttribute]('media')]) ){ source.setAttribute('media', customMedia); } if(sourceSrcset){ source.setAttribute('srcset', sourceSrcset); } }; var lazyUnveil = rAFIt(function (elem, detail, isAuto, sizes, isImg){ var src, srcset, parent, isPicture, event, firesLoad; if(!(event = triggerEvent(elem, 'lazybeforeunveil', detail)).defaultPrevented){ if(sizes){ if(isAuto){ addClass(elem, lazySizesCfg.autosizesClass); } else { elem.setAttribute('sizes', sizes); } } srcset = elem[_getAttribute](lazySizesCfg.srcsetAttr); src = elem[_getAttribute](lazySizesCfg.srcAttr); if(isImg) { parent = elem.parentNode; isPicture = parent && regPicture.test(parent.nodeName || ''); } firesLoad = detail.firesLoad || (('src' in elem) && (srcset || src || isPicture)); event = {target: elem}; addClass(elem, lazySizesCfg.loadingClass); if(firesLoad){ clearTimeout(resetPreloadingTimer); resetPreloadingTimer = setTimeout(resetPreloading, 2500); addRemoveLoadEvents(elem, rafSwitchLoadingClass, true); } if(isPicture){ forEach.call(parent.getElementsByTagName('source'), handleSources); } if(srcset){ elem.setAttribute('srcset', srcset); } else if(src && !isPicture){ if(regIframe.test(elem.nodeName)){ changeIframeSrc(elem, src); } else { elem.src = src; } } if(isImg && (srcset || isPicture)){ updatePolyfill(elem, {src: src}); } } if(elem._lazyRace){ delete elem._lazyRace; } removeClass(elem, lazySizesCfg.lazyClass); rAF(function(){ // Part of this can be removed as soon as this fix is older: https://bugs.chromium.org/p/chromium/issues/detail?id=7731 (2015) var isLoaded = elem.complete && elem.naturalWidth > 1; if( !firesLoad || isLoaded){ if (isLoaded) { addClass(elem, lazySizesCfg.fastLoadedClass); } switchLoadingClass(event); elem._lazyCache = true; setTimeout(function(){ if ('_lazyCache' in elem) { delete elem._lazyCache; } }, 9); } if (elem.loading == 'lazy') { isLoading--; } }, true); }); var unveilElement = function (elem){ if (elem._lazyRace) {return;} var detail; var isImg = regImg.test(elem.nodeName); //allow using sizes="auto", but don't use. it's invalid. Use data-sizes="auto" or a valid value for sizes instead (i.e.: sizes="80vw") var sizes = isImg && (elem[_getAttribute](lazySizesCfg.sizesAttr) || elem[_getAttribute]('sizes')); var isAuto = sizes == 'auto'; if( (isAuto || !isCompleted) && isImg && (elem[_getAttribute]('src') || elem.srcset) && !elem.complete && !hasClass(elem, lazySizesCfg.errorClass) && hasClass(elem, lazySizesCfg.lazyClass)){return;} detail = triggerEvent(elem, 'lazyunveilread').detail; if(isAuto){ autoSizer.updateElem(elem, true, elem.offsetWidth); } elem._lazyRace = true; isLoading++; lazyUnveil(elem, detail, isAuto, sizes, isImg); }; var afterScroll = debounce(function(){ lazySizesCfg.loadMode = 3; throttledCheckElements(); }); var altLoadmodeScrollListner = function(){ if(lazySizesCfg.loadMode == 3){ lazySizesCfg.loadMode = 2; } afterScroll(); }; var onload = function(){ if(isCompleted){return;} if(Date.now() - started < 999){ setTimeout(onload, 999); return; } isCompleted = true; lazySizesCfg.loadMode = 3; throttledCheckElements(); addEventListener('scroll', altLoadmodeScrollListner, true); }; return { _: function(){ started = Date.now(); lazysizes.elements = document.getElementsByClassName(lazySizesCfg.lazyClass); preloadElems = document.getElementsByClassName(lazySizesCfg.lazyClass + ' ' + lazySizesCfg.preloadClass); addEventListener('scroll', throttledCheckElements, true); addEventListener('resize', throttledCheckElements, true); addEventListener('pageshow', function (e) { if (e.persisted) { var loadingElements = document.querySelectorAll('.' + lazySizesCfg.loadingClass); if (loadingElements.length && loadingElements.forEach) { requestAnimationFrame(function () { loadingElements.forEach( function (img) { if (img.complete) { unveilElement(img); } }); }); } } }); if(window.MutationObserver){ new MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} ); } else { docElem[_addEventListener]('DOMNodeInserted', throttledCheckElements, true); docElem[_addEventListener]('DOMAttrModified', throttledCheckElements, true); setInterval(throttledCheckElements, 999); } addEventListener('hashchange', throttledCheckElements, true); //, 'fullscreenchange' ['focus', 'mouseover', 'click', 'load', 'transitionend', 'animationend'].forEach(function(name){ document[_addEventListener](name, throttledCheckElements, true); }); if((/d$|^c/.test(document.readyState))){ onload(); } else { addEventListener('load', onload); document[_addEventListener]('DOMContentLoaded', throttledCheckElements); setTimeout(onload, 20000); } if(lazysizes.elements.length){ checkElements(); rAF._lsFlush(); } else { throttledCheckElements(); } }, checkElems: throttledCheckElements, unveil: unveilElement, _aLSL: altLoadmodeScrollListner, }; })(); var autoSizer = (function(){ var autosizesElems; var sizeElement = rAFIt(function(elem, parent, event, width){ var sources, i, len; elem._lazysizesWidth = width; width += 'px'; elem.setAttribute('sizes', width); if(regPicture.test(parent.nodeName || '')){ sources = parent.getElementsByTagName('source'); for(i = 0, len = sources.length; i < len; i++){ sources[i].setAttribute('sizes', width); } } if(!event.detail.dataAttr){ updatePolyfill(elem, event.detail); } }); var getSizeElement = function (elem, dataAttr, width){ var event; var parent = elem.parentNode; if(parent){ width = getWidth(elem, parent, width); event = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr}); if(!event.defaultPrevented){ width = event.detail.width; if(width && width !== elem._lazysizesWidth){ sizeElement(elem, parent, event, width); } } } }; var updateElementsSizes = function(){ var i; var len = autosizesElems.length; if(len){ i = 0; for(; i < len; i++){ getSizeElement(autosizesElems[i]); } } }; var debouncedUpdateElementsSizes = debounce(updateElementsSizes); return { _: function(){ autosizesElems = document.getElementsByClassName(lazySizesCfg.autosizesClass); addEventListener('resize', debouncedUpdateElementsSizes); }, checkElems: debouncedUpdateElementsSizes, updateElem: getSizeElement }; })(); var init = function(){ if(!init.i && document.getElementsByClassName){ init.i = true; autoSizer._(); loader._(); } }; setTimeout(function(){ if(lazySizesCfg.init){ init(); } }); lazysizes = { cfg: lazySizesCfg, autoSizer: autoSizer, loader: loader, init: init, uP: updatePolyfill, aC: addClass, rC: removeClass, hC: hasClass, fire: triggerEvent, gW: getWidth, rAF: rAF, }; return lazysizes; } ));