UNPKG

vanilla-lazyload

Version:

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

178 lines (153 loc) 4.36 kB
import getDefaultSettings from "./lazyload.defaults"; import { purgeProcessedElements } from "./lazyload.purge"; import isInsideViewport from "./lazyload.viewport"; import autoInitialize from "./lazyload.autoInitialize"; import { addClass } from "./lazyload.class"; import { isBot, runningOnBrowser } from "./lazyload.environment"; import { revealElement } from "./lazyload.reveal"; import { removeFromArray } from "./lazyload.array"; import { callbackIfSet } from "./lazyload.callback"; /* * Constructor */ const LazyLoad = function(instanceSettings) { this._settings = Object.assign({}, getDefaultSettings(), instanceSettings); this._loadingCount = 0; this._queryOriginNode = this._settings.container === window ? document : this._settings.container; this._previousLoopTime = 0; this._loopTimeout = null; this._boundHandleScroll = this.handleScroll.bind(this); this._isFirstLoop = true; window.addEventListener("resize", this._boundHandleScroll); this.update(); }; LazyLoad.prototype = { _loopThroughElements: function(forceDownload) { const settings = this._settings, elements = this._elements, elementsLength = !elements ? 0 : elements.length; let i, processedIndexes = [], isFirstLoop = this._isFirstLoop; if (isFirstLoop) { this._isFirstLoop = false; } if (elementsLength === 0) { this._stopScrollHandler(); return; } for (i = 0; i < elementsLength; i++) { let element = elements[i]; /* If must skip_invisible and element is invisible, skip it */ if (settings.skip_invisible && element.offsetParent === null) { continue; } if ( forceDownload || isInsideViewport( element, settings.container, settings.threshold ) ) { if (isFirstLoop) { addClass(element, settings.class_initial); } this.load(element); processedIndexes.push(i); } } // Removing processed elements from this._elements. removeFromArray(elements, processedIndexes); }, _startScrollHandler: function() { if (!this._isHandlingScroll) { this._isHandlingScroll = true; this._settings.container.addEventListener( "scroll", this._boundHandleScroll ); } }, _stopScrollHandler: function() { if (this._isHandlingScroll) { this._isHandlingScroll = false; this._settings.container.removeEventListener( "scroll", this._boundHandleScroll ); } }, _updateLoadingCount: function(plusMinus) { this._loadingCount += plusMinus; if (this._elements.length === 0 && this._loadingCount === 0) { callbackIfSet(this._settings.callback_finish); } }, handleScroll: function() { const throttle = this._settings.throttle; if (throttle !== 0) { let now = Date.now(); let remainingTime = throttle - (now - this._previousLoopTime); if (remainingTime <= 0 || remainingTime > throttle) { if (this._loopTimeout) { clearTimeout(this._loopTimeout); this._loopTimeout = null; } this._previousLoopTime = now; this._loopThroughElements(); } else if (!this._loopTimeout) { this._loopTimeout = setTimeout( function() { this._previousLoopTime = Date.now(); this._loopTimeout = null; this._loopThroughElements(); }.bind(this), remainingTime ); } } else { this._loopThroughElements(); } }, loadAll: function() { this._loopThroughElements(true); }, update: function(elements) { const settings = this._settings; const nodeSet = elements || this._queryOriginNode.querySelectorAll(settings.elements_selector); this._elements = purgeProcessedElements( Array.prototype.slice.call(nodeSet) // NOTE: nodeset to array for IE compatibility ); if (isBot) { this.loadAll(); return; } this._loopThroughElements(); this._startScrollHandler(); }, destroy: function() { window.removeEventListener("resize", this._boundHandleScroll); if (this._loopTimeout) { clearTimeout(this._loopTimeout); this._loopTimeout = null; } this._stopScrollHandler(); this._elements = null; this._queryOriginNode = null; this._settings = null; }, load: function(element, force) { revealElement(element, this, force); } }; /* Automatic instances creation if required (useful for async script loading) */ if (runningOnBrowser) { autoInitialize(LazyLoad, window.lazyLoadOptions); } export default LazyLoad;