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
};
})();
})();