Created
August 31, 2019 07:03
-
-
Save CSElliyas/58e2f330ea2adc6cc2c6fc3bba5e1c7d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| (function() { | |
| "use strict"; | |
| var config = { | |
| // If the image gets within 50px in the Y axis, start the download. | |
| rootMargin: "50px 0px", | |
| threshold: 0.01 | |
| }; | |
| var observer; | |
| //If we're using a browser without the IntersectionObserver (IE11, Safari 11), skip the lazy part and just load the resources | |
| if ("IntersectionObserver" in window) {observer = new IntersectionObserver(onIntersection, config);} | |
| //If we're using a browser without requestAnimationFrame (IE9, Opera Mini), just run the passed function | |
| var rAF; | |
| if ("requestAnimationFrame" in window) rAF = window.requestAnimationFrame; | |
| else rAF = function(func) { func(); }; | |
| var tempImg = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="; | |
| /** | |
| * Temporarily replace a expensive resource load with a cheap one | |
| */ | |
| function storeSourceForLater(lazyItem, tempData) { | |
| //Store our ACTUAL source for later | |
| lazyItem.setAttribute("data-lazy-src", lazyItem.getAttribute("src")); | |
| //Set the item to point to a temporary replacement (like a data URI) | |
| lazyItem.setAttribute("src", tempData); | |
| //Now observe the item so that we can start loading when it gets close to the viewport | |
| observer.observe(lazyItem); | |
| } | |
| /** | |
| * Temporarily prevent expensive resource loading by inserting a <source> tag pointing to a cheap one (like a data URI) | |
| */ | |
| function jamSourceLoading(lazyItem, tempData) { | |
| var newSource = document.createElement("source"); | |
| newSource.setAttribute("srcset", tempData); | |
| newSource.setAttribute("data-lazy-remove", "true"); | |
| //adding this source tag at the start of the picture tag means the browser will load it first | |
| lazyItem.insertBefore(newSource, lazyItem.firstChild); | |
| var baseImage = lazyItem.getElementsByTagName("img")[0]; | |
| if (baseImage) { | |
| //this is a picture tag, so we need to watch the image (as the picture tag is smaller than the image usually) | |
| observer.observe(baseImage); | |
| } | |
| } | |
| /** | |
| * Set up the lazy items so that they won't try to load when we add them to the document, but will once the user is close to seeing them | |
| */ | |
| function prepareLazyContents(lazyArea) { | |
| var lazyImgs = lazyArea.getElementsByTagName("img"); | |
| for(var i = lazyImgs.length; i--;){ | |
| storeSourceForLater(lazyImgs[i], tempImg); | |
| } | |
| var lazyPictures = lazyArea.getElementsByTagName("picture"); | |
| for(var i3 = lazyPictures.length; i3--;) { | |
| jamSourceLoading(lazyPictures[i3], tempImg); | |
| } | |
| } | |
| /** | |
| * Put the source back where we found it - now that the element is attached to the document, it will load now | |
| */ | |
| function restoreSource(lazyItem) { | |
| lazyItem.setAttribute("src", lazyItem.getAttribute("data-lazy-src")); | |
| lazyItem.removeAttribute("data-lazy-src"); | |
| } | |
| /** | |
| * Remove the source tag preventing the loading of picture/audio/video | |
| */ | |
| function removeJammingSource(lazyItem) { | |
| var jammingSource = lazyItem.querySelector("source[data-lazy-remove]"); | |
| if (jammingSource) lazyItem.removeChild(jammingSource); | |
| } | |
| /** | |
| * Handle the intersection postback | |
| */ | |
| function onIntersection(entries, obsvr) { | |
| entries.forEach(function(entry) { | |
| if(entry.intersectionRatio === 0) return; | |
| //if the item is now visible, load it and stop watching it | |
| var lazyItem = entry.target; | |
| obsvr.unobserve(lazyItem); | |
| //Just in case the img is the decendent of a picture element, check for source tags | |
| removeJammingSource(lazyItem.parentNode); | |
| restoreSource(lazyItem); | |
| }); | |
| } | |
| /** | |
| * Retrieve the elements from the 'lazy load' no script tags and prepare them for display | |
| */ | |
| function setUp() { | |
| //Get all the noscript tags on the page | |
| var lazyLoadAreas = document.getElementsByTagName("noscript"); | |
| for(var i = lazyLoadAreas.length; i--;) { | |
| var noScriptTag = lazyLoadAreas[i]; | |
| //only process the ones marked for lazy loading | |
| if (!noScriptTag.hasAttribute("data-lazy-load")) continue; | |
| // The contents of a noscript tag are treated as text to JavaScript | |
| var lazyAreaHtml = noScriptTag.textContent||noScriptTag.innerHTML; | |
| // So we stick them in the innerHTML of a new div tag to 'load' them | |
| var lazyArea = document.createElement("div"); | |
| lazyArea.innerHTML = lazyAreaHtml; | |
| //Only delay loading if we can use the IntersectionObserver to check for visibility | |
| if(!observer) { | |
| noScriptTag.parentNode.replaceChild(lazyArea, noScriptTag); | |
| } else { | |
| prepareLazyContents(lazyArea); | |
| noScriptTag.parentNode.replaceChild(lazyArea, noScriptTag); | |
| } | |
| } | |
| } | |
| //If the page has loaded already, run setup - if it hasn't, run as soon as it has. | |
| //Use requestAnimationFrame as this will propably cause repaints | |
| if (/comp|inter/.test(document.readyState)) { | |
| rAF(setUp); | |
| } else if ("addEventListener" in document) { | |
| document.addEventListener("DOMContentLoaded", | |
| function(){rAF(setUp);}); | |
| } else { | |
| document.attachEvent("onreadystatechange", function() { | |
| if (document.readyState=="complete") { | |
| setUp(); | |
| } | |
| }); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment