if (typeof window.db == 'undefined') window.db = { libs: {} }; (function () { 'use strict'; /** * Layzyload images * @namespace */ db.libs.imageSrcset = (function(){ var name = 'imageSrcset'; var ready = false; /** * Ranges for targeting sizes in srcset * @private * @memberof db.libs.imageSrcset * @constant {object} */ var range = { small: "(?:[0-9]|[0-9][0-9]|[0-6][0-3][0-9])", //Target 0-639 medium: "(?:6[4-9][0-9]|[7-9][0-9][0-9]|10[0-2][0-3])", //Target 640-1023 large: "(?:10[2-9][4-9]|[1-9][1-9][0-9][0-9])" //Target 1024 + }; /** * The threshold for when images in view should be loaded * @private * @memberof db.libs.imageSrcset * @constant {number} */ var threshold = 400; /** * The nodeList for all the images on the page using <code>data-srcset</code> * @private * @memberof db.libs.imageSrcset * @type {nodeList} */ var images = []; /** * The nodeList for all the images to lazyload using the <code>data-defer</code> attribute * @private * @memberof db.libs.imageSrcset * @type {nodeList} */ var deffered = []; /** * Returns the list of images * @public * @memberof db.libs.imageSrcset */ function getImages(){ return images; } /** * Returns the list of deferred images * @public * @memberof db.libs.imageSrcset */ function getDefferedImages(){ return deffered; } /** * Loads all images with <code>data-defer</code> attribute if they are within the viewport threshold * @private * @memberof db.libs.imageSrcset */ function loadImagesInView(){ var offset = (window.pageYOffset !== undefined) ? window.pageYOffset:document.body.scrollTop; var edge = offset + window.innerHeight + threshold; for(var i = 0; i < deffered.length; i++){ if(parseInt(deffered[i].getBoundingClientRect().top + offset) < edge){ setImageSrc(deffered[i]); } } images = document.querySelectorAll('img[data-srcset]:not([data-defer])'); deffered = document.querySelectorAll('img[data-defer]'); } /** * Re-evaluate all images and load the correct src from <code>data-srcset</code> * @private * @memberof db.libs.imageSrcset */ function loadImages(){ for(var i = 0; i < images.length; i++){ setImageSrc(images[i]); } } /** * Loads a given image * @public * @memberof db.libs.imageSrcset * @param {element} element * @return {element} element */ function load(el){ setImageSrc(el); return el; } /** * Set the image src based on width of page and what is in <code>data-srcset</code> or </code>data-src</code> * @private * @memberof db.libs.imageSrcset * @param {element} element * @return {element} element */ function setImageSrc(el){ var size, src; if(!el.getAttribute('data-srcset') && !el.getAttribute('data-src')){ return false; } if(el.getAttribute('data-src')){ src = el.dataset.src; } else { if(window.innerWidth <= 640){ size = range.small; } else if(window.innerWidth > 1024){ size = range.large; } else { size = range.medium; } src = parseSrcset(el.getAttribute('data-srcset'), size); } if( el.tagName == 'IMG' ){ if(src != el.getAttribute('src')){ el.setAttribute('src', src); } } else { el.style.backgroundImage = 'url('+src+')'; } el.removeAttribute('data-defer'); return el; } /** * Parse the <code>data-srcset</code> and return the url that matches given size * @private * @memberof db.libs.imageSrcset * @param {string} srcset A srcset formatted string * @param {string} size A string used in the regex to match a spesific size * @return {string} the url matching size */ function parseSrcset(srcset, size){ var re = new RegExp("([^\\s|\\d|w|,]\\S+)\\s"+size+"w", "i"); var src = srcset.match(re); if(src){ return src[1].trim(); } else { return ''; } } /** * Initialize the component * @public * @memberof db.libs.imageSrcset */ function init(){ if(!ready){ images = document.querySelectorAll('img[data-srcset]:not([data-defer])'); deffered = document.querySelectorAll('img[data-defer]'); loadImages(); loadImagesInView(); window.addEventListener('scroll', function(){ window.requestAnimationFrame(loadImagesInView); }); window.addEventListener('resize', function(){ window.requestAnimationFrame(loadImages); }); ready = true; } else { reflow(); } } /** * Load all images that can be loaded * @public * @memberof db.libs.imageSrcset */ function reflow(){ images = document.querySelectorAll('img[data-srcset]:not([data-defer])'); deffered = document.querySelectorAll('img[data-defer]'); loadImages(); loadImagesInView(); } return { init: init, reflow: reflow, getDefferedImages: getDefferedImages, getImages: getImages, load: load }; })(); })();