diff --git a/loading-attribute-polyfill.js b/loading-attribute-polyfill.js index 213012ca..4b045d60 100755 --- a/loading-attribute-polyfill.js +++ b/loading-attribute-polyfill.js @@ -10,254 +10,275 @@ * Use an IntersectionObserver polyfill in case of IE11 support necessary. */ -(function (noscriptClass, rootMargin) { - 'use strict'; - - var config = { - // Start download if the item gets within 256px in the Y axis - rootMargin: rootMargin || '0px 0px 256px 0px', - threshold: 0.01, - lazyImage: 'img[loading="lazy"]', - lazyIframe: 'iframe[loading="lazy"]' - }; - - // Device/browser capabilities object - var capabilities = { - loading: - 'loading' in HTMLImageElement.prototype && - 'loading' in HTMLIFrameElement.prototype, - scrolling: 'onscroll' in window - }; - - // Nodelist foreach polyfill / source: https://stackoverflow.com/a/46929259 - if ( - typeof NodeList !== 'undefined' && - NodeList.prototype && - !NodeList.prototype.forEach - ) { - // Yes, there's really no need for `Object.defineProperty` here - NodeList.prototype.forEach = Array.prototype.forEach; +'use strict'; + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + factory(); } +}(typeof self === 'undefined' ? this : self, function () { + function lazyload(noscriptClass, rootMargin) { + var config = { + // Start download if the item gets within 256px in the Y axis + rootMargin: rootMargin || '0px 0px 256px 0px', + threshold: 0.01, + lazyImage: 'img[loading="lazy"]', + lazyIframe: 'iframe[loading="lazy"]' + }; - // Define according to browsers support of the IntersectionObserver feature (missing e.g. on IE11 or Safari 11) - var intersectionObserver; + // Device/browser capabilities object + var capabilities = { + loading: + 'loading' in HTMLImageElement.prototype && + 'loading' in HTMLIFrameElement.prototype, + scrolling: 'onscroll' in window + }; - if ('IntersectionObserver' in window) { - intersectionObserver = new IntersectionObserver(onIntersection, config); - } + // Nodelist foreach polyfill / source: https://stackoverflow.com/a/46929259 + if ( + typeof NodeList !== 'undefined' && + NodeList.prototype && + !NodeList.prototype.forEach + ) { + // Yes, there's really no need for `Object.defineProperty` here + NodeList.prototype.forEach = Array.prototype.forEach; + } - // On using a browser w/o requestAnimationFrame support (IE9, Opera Mini), just run the passed function - var rAFWrapper; + // Define according to browsers support of the IntersectionObserver feature (missing e.g. on IE11 or Safari 11) + var intersectionObserver; - if ('requestAnimationFrame' in window) { - rAFWrapper = window.requestAnimationFrame; - } else { - rAFWrapper = function (func) { - func(); - }; - } - - /** - * Put the source and srcset back where it belongs - now that the elements content is attached to the document, it will load now - * @param {Object} lazyItem Current item to be restored after lazy loading. - */ - function restoreSource(lazyItem) { - var srcsetItems = []; + if ('IntersectionObserver' in window) { + intersectionObserver = new IntersectionObserver(onIntersection, config); + } - // Just in case the img is the decendent of a picture element, check for source tags - if (lazyItem.parentNode.tagName.toLowerCase() === 'picture') { - removePlaceholderSource(lazyItem.parentNode); + // On using a browser w/o requestAnimationFrame support (IE9, Opera Mini), just run the passed function + var rAFWrapper; - srcsetItems = Array.prototype.slice.call( - lazyItem.parentNode.querySelectorAll('source') - ); + if ('requestAnimationFrame' in window) { + rAFWrapper = window.requestAnimationFrame; + } else { + rAFWrapper = function (func) { + func(); + }; } - srcsetItems.push(lazyItem); + /** + * Put the source and srcset back where it belongs - now that the elements content is attached to the document, it will load now + * @param {Object} lazyItem Current item to be restored after lazy loading. + */ + function restoreSource(lazyItem) { + var srcsetItems = []; - // Not using .dataset within those upfollowing lines of code for polyfill independent compatibility down to IE9 - srcsetItems.forEach(function (item) { - if (item.hasAttribute('data-lazy-srcset')) { - item.setAttribute('srcset', item.getAttribute('data-lazy-srcset')); - item.removeAttribute('data-lazy-srcset'); // Not using delete .dataset here for compatibility down to IE9 + // Just in case the img is the decendent of a picture element, check for source tags + if (lazyItem.parentNode.tagName.toLowerCase() === 'picture') { + removePlaceholderSource(lazyItem.parentNode); + + srcsetItems = Array.prototype.slice.call( + lazyItem.parentNode.querySelectorAll('source') + ); } - }); - lazyItem.setAttribute('src', lazyItem.getAttribute('data-lazy-src')); - lazyItem.removeAttribute('data-lazy-src'); // Not using delete .dataset here for compatibility down to IE9 - } + srcsetItems.push(lazyItem); + + // Not using .dataset within those upfollowing lines of code for polyfill independent compatibility down to IE9 + srcsetItems.forEach(function (item) { + if (item.hasAttribute('data-lazy-srcset')) { + item.setAttribute('srcset', item.getAttribute('data-lazy-srcset')); + item.removeAttribute('data-lazy-srcset'); // Not using delete .dataset here for compatibility down to IE9 + } + }); - /** - * Remove the source tag preventing the loading of picture assets - * @param {Object} lazyItemPicture Current item to be restored after lazy loading. - */ - function removePlaceholderSource(lazyItemPicture) { - var placeholderSource = lazyItemPicture.querySelector( - 'source[data-lazy-remove]' - ); - - if (placeholderSource) { - lazyItemPicture.removeChild(placeholderSource); // Preferred .removeChild over .remove here for IE + lazyItem.setAttribute('src', lazyItem.getAttribute('data-lazy-src')); + lazyItem.removeAttribute('data-lazy-src'); // Not using delete .dataset here for compatibility down to IE9 } - } - /** - * Handle IntersectionObservers callback - * @param {Object} entries Target elements Intersection observed changes - * @param {Object} observer IntersectionObserver instance reference - */ - function onIntersection(entries, observer) { - entries.forEach(function (entry) { - // Mitigation for EDGE lacking support of .isIntersecting until v15, compare to e.g. https://github.com/w3c/IntersectionObserver/issues/211#issuecomment-309144669 - if (entry.intersectionRatio === 0) { - return; + /** + * Remove the source tag preventing the loading of picture assets + * @param {Object} lazyItemPicture Current item to be restored after lazy loading. + */ + function removePlaceholderSource(lazyItemPicture) { + var placeholderSource = lazyItemPicture.querySelector( + 'source[data-lazy-remove]' + ); + + if (placeholderSource) { + lazyItemPicture.removeChild(placeholderSource); // Preferred .removeChild over .remove here for IE } + } - // If the item is visible now, load it and stop watching it - var lazyItem = entry.target; + /** + * Handle IntersectionObservers callback + * @param {Object} entries Target elements Intersection observed changes + * @param {Object} observer IntersectionObserver instance reference + */ + function onIntersection(entries, observer) { + entries.forEach(function (entry) { + // Mitigation for EDGE lacking support of .isIntersecting until v15, compare to e.g. https://github.com/w3c/IntersectionObserver/issues/211#issuecomment-309144669 + if (entry.intersectionRatio === 0) { + return; + } - observer.unobserve(lazyItem); + // If the item is visible now, load it and stop watching it + var lazyItem = entry.target; - restoreSource(lazyItem); - }); - } + observer.unobserve(lazyItem); - /** - * Handle printing the page - */ - function onPrinting() { - if (typeof window.matchMedia === 'undefined') { - return; + restoreSource(lazyItem); + }); } - var mediaQueryList = window.matchMedia('print'); - - mediaQueryList.addListener(function (mql) { - if (mql.matches) { - document - .querySelectorAll( - config.lazyImage + - '[data-lazy-src],' + - config.lazyIframe + - '[data-lazy-src]' - ) - .forEach(function (lazyItem) { - restoreSource(lazyItem); - }); + /** + * Handle printing the page + */ + function onPrinting() { + if (typeof window.matchMedia === 'undefined') { + return; } - }); - } - /** - * Get and prepare the HTML code depending on feature detection for both image as well as iframe, - * and if not scrolling supported, because it's a Google or Bing Bot - * @param {String} lazyAreaHtml Noscript inner HTML code that src-urls need to get rewritten - */ - function getAndPrepareHTMLCode(noScriptTag) { - // The contents of a