Created
August 31, 2019 07:10
-
-
Save CSElliyas/3e8e13a87964f7e884370ea0cb2b18fd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// generic throttle function | |
function throttle(func, wait) { | |
var timeout; | |
return function() { | |
var context = this, args = arguments; | |
if(!timeout) { | |
timeout = setTimeout(function() { | |
timeout = null; | |
}, wait); | |
func.apply(context, args); | |
} | |
}; | |
} | |
function isFunction(variable) { | |
return variable && {}.toString.call(variable) === '[object Function]'; | |
} | |
// naive function for seeing if element is visible in user's viewport | |
function isElementInViewport(element) { | |
var elementBounds = element.getBoundingClientRect(); | |
return window.innerHeight > elementBounds.top | |
&& 0 < elementBounds.bottom | |
&& window.innerWidth > elementBounds.left | |
&& 0 < elementBounds.right; | |
} | |
var noscriptImageLazyLoader = function(options) { | |
var container = document.createElement('div'), | |
defaultOptions = { | |
attribute: 'lazy-img', | |
events: ['resize', 'scroll', 'touchend'], | |
interval: 500, | |
placeholder: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' | |
}, | |
imageElementsInDOM = [], | |
interval, | |
processedLazyLoads = 0, | |
settingTextToNoscriptFailsInIE8AndBelow = document.createElement('noscript'); | |
try { | |
settingTextToNoscriptFailsInIE8AndBelow.innerText = ''; | |
} catch(err) { | |
return; | |
} | |
settingTextToNoscriptFailsInIE8AndBelow = void 0; | |
options = options || defaultOptions; | |
if(typeof options.attribute !== 'string') options.attribute = defaultOptions.attribute; | |
if(!Array.isArray(options.events)) options.events = defaultOptions.events; | |
if(typeof options.placeholder !== 'string') options.placeholder = defaultOptions.placeholder; | |
options.interval = options.interval == null ? defaultOptions.interval : ~~options.interval; | |
function attemptToLoadImage(temporaryImageElement, lazyLoadedImageSrc, imageElementInDOM) { | |
temporaryImageElement.onload = function() { | |
imageElementInDOM.src = temporaryImageElement.src; | |
processedLazyLoads++; | |
if(isFunction(options.lazyLoadCallback)) | |
options.lazyLoadCallback(imageElementInDOM, lazyLoadedImageSrc, true); | |
}; | |
temporaryImageElement.onerror = function() { | |
processedLazyLoads++; | |
if(isFunction(options.lazyLoadCallback)) | |
options.lazyLoadCallback(imageElementInDOM, lazyLoadedImageSrc, false); | |
}; | |
imageElementInDOM.removeAttribute('data-src'); | |
temporaryImageElement.src = lazyLoadedImageSrc; | |
} | |
var loadImagesVisibleInViewport = throttle(function() { | |
if(processedLazyLoads < imageElementsInDOM.length) { | |
imageElementsInDOM.forEach(function(imageElementInDOM) { | |
var src = imageElementInDOM.getAttribute('data-src'); | |
if(src && isElementInViewport(imageElementInDOM)) { | |
attemptToLoadImage(new Image(), src, imageElementInDOM); | |
} | |
}); | |
} else { | |
clearInterval(interval); | |
options.events.forEach(function(event) { | |
window.removeEventListener(event, loadImagesVisibleInViewport, false); | |
}); | |
imageElementsInDOM.length = 0; | |
} | |
}, 50); | |
Array.prototype.forEach.call(document.querySelectorAll('noscript[data-' + options.attribute + ']'), function(noscript) { | |
container.innerHTML = noscript.textContent || noscript.innerText; | |
var imageElementToLazyLoad = container.querySelector('img'); | |
if(imageElementToLazyLoad) { | |
imageElementToLazyLoad.setAttribute('data-src', imageElementToLazyLoad.src); | |
imageElementToLazyLoad.src = options.placeholder; | |
noscript.parentNode.replaceChild(imageElementToLazyLoad, noscript); | |
imageElementsInDOM.push(imageElementToLazyLoad); | |
} | |
}); | |
if(imageElementsInDOM.length) { | |
loadImagesVisibleInViewport(); | |
options.events.forEach(function(event) { | |
window.addEventListener(event, loadImagesVisibleInViewport, false); | |
}); | |
if(options.interval > 0) | |
interval = setInterval(loadImagesVisibleInViewport, options.interval); | |
} | |
container = void 0; | |
}; | |
// some sample usage | |
!function() { | |
var debug = document.getElementById('debug'); | |
debug.textContent = 'Initial viewport size: ' + window.innerWidth + 'x' + window.innerHeight; | |
setTimeout(function() { | |
debug.textContent += "\n" + 'Viewport size 1s later: ' + window.innerWidth + 'x' + window.innerHeight; | |
}, 1000); | |
noscriptImageLazyLoader({ | |
lazyLoadCallback: function(imageElement, imageSrc, loaded) { | |
var elementBounds = imageElement.getBoundingClientRect(); | |
debug.textContent += "\n" + imageElement.alt + ' [' + (loaded ? 'success' : 'fail') + '] @ ' + ~~elementBounds.left + 'x' + ~~elementBounds.top + ' / ' + ~~elementBounds.right + 'x' + ~~elementBounds.bottom; | |
} | |
}); | |
}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment