lazysizes
Version:
High performance (jankfree) lazy loader for images (including responsive images), iframes and scripts (widgets).
204 lines (163 loc) • 5.28 kB
JavaScript
(function(window, factory) {
var globalInstall = function(){
factory(window.lazySizes);
window.removeEventListener('lazyunveilread', globalInstall, true);
};
factory = factory.bind(null, window, window.document);
if(typeof module == 'object' && module.exports){
factory(require('lazysizes'));
} else if (typeof define == 'function' && define.amd) {
define(['lazysizes'], factory);
} else if(window.lazySizes) {
globalInstall();
} else {
window.addEventListener('lazyunveilread', globalInstall, true);
}
}(window, function(window, document, lazySizes) {
'use strict';
if(!window.addEventListener){return;}
var lazySizesCfg = lazySizes.cfg;
var regWhite = /\s+/g;
var regSplitSet = /\s*\|\s+|\s+\|\s*/g;
var regSource = /^(.+?)(?:\s+\[\s*(.+?)\s*\])(?:\s+\[\s*(.+?)\s*\])?$/;
var regType = /^\s*\(*\s*type\s*:\s*(.+?)\s*\)*\s*$/;
var regBgUrlEscape = /\(|\)|'/;
var allowedBackgroundSize = {contain: 1, cover: 1};
var proxyWidth = function(elem){
var width = lazySizes.gW(elem, elem.parentNode);
if(!elem._lazysizesWidth || width > elem._lazysizesWidth){
elem._lazysizesWidth = width;
}
return elem._lazysizesWidth;
};
var getBgSize = function(elem){
var bgSize;
bgSize = (getComputedStyle(elem) || {getPropertyValue: function(){}}).getPropertyValue('background-size');
if(!allowedBackgroundSize[bgSize] && allowedBackgroundSize[elem.style.backgroundSize]){
bgSize = elem.style.backgroundSize;
}
return bgSize;
};
var setTypeOrMedia = function(source, match){
if(match){
var typeMatch = match.match(regType);
if(typeMatch && typeMatch[1]){
source.setAttribute('type', typeMatch[1]);
} else {
source.setAttribute('media', lazySizesCfg.customMedia[match] || match);
}
}
};
var createPicture = function(sets, elem, img){
var picture = document.createElement('picture');
var sizes = elem.getAttribute(lazySizesCfg.sizesAttr);
var ratio = elem.getAttribute('data-ratio');
var optimumx = elem.getAttribute('data-optimumx');
if(elem._lazybgset && elem._lazybgset.parentNode == elem){
elem.removeChild(elem._lazybgset);
}
Object.defineProperty(img, '_lazybgset', {
value: elem,
writable: true
});
Object.defineProperty(elem, '_lazybgset', {
value: picture,
writable: true
});
sets = sets.replace(regWhite, ' ').split(regSplitSet);
picture.style.display = 'none';
img.className = lazySizesCfg.lazyClass;
if(sets.length == 1 && !sizes){
sizes = 'auto';
}
sets.forEach(function(set){
var match;
var source = document.createElement('source');
if(sizes && sizes != 'auto'){
source.setAttribute('sizes', sizes);
}
if((match = set.match(regSource))){
source.setAttribute(lazySizesCfg.srcsetAttr, match[1]);
setTypeOrMedia(source, match[2]);
setTypeOrMedia(source, match[3]);
} else {
source.setAttribute(lazySizesCfg.srcsetAttr, set);
}
picture.appendChild(source);
});
if(sizes){
img.setAttribute(lazySizesCfg.sizesAttr, sizes);
elem.removeAttribute(lazySizesCfg.sizesAttr);
elem.removeAttribute('sizes');
}
if(optimumx){
img.setAttribute('data-optimumx', optimumx);
}
if(ratio) {
img.setAttribute('data-ratio', ratio);
}
picture.appendChild(img);
elem.appendChild(picture);
};
var proxyLoad = function(e){
if(!e.target._lazybgset){return;}
var image = e.target;
var elem = image._lazybgset;
var bg = image.currentSrc || image.src;
if(bg){
var useSrc = regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg;
var event = lazySizes.fire(elem, 'bgsetproxy', {
src: bg,
useSrc: useSrc,
fullSrc: null,
});
if(!event.defaultPrevented){
elem.style.backgroundImage = event.detail.fullSrc || 'url(' + event.detail.useSrc + ')';
}
}
if(image._lazybgsetLoading){
lazySizes.fire(elem, '_lazyloaded', {}, false, true);
delete image._lazybgsetLoading;
}
};
addEventListener('lazybeforeunveil', function(e){
var set, image, elem;
if(e.defaultPrevented || !(set = e.target.getAttribute('data-bgset'))){return;}
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
});
document.addEventListener('load', proxyLoad, true);
window.addEventListener('lazybeforesizes', function(e){
if(e.detail.instance != lazySizes){return;}
if(e.target._lazybgset && e.detail.dataAttr){
var elem = e.target._lazybgset;
var bgSize = getBgSize(elem);
if(allowedBackgroundSize[bgSize]){
e.target._lazysizesParentFit = bgSize;
lazySizes.rAF(function(){
e.target.setAttribute('data-parent-fit', bgSize);
if(e.target._lazysizesParentFit){
delete e.target._lazysizesParentFit;
}
});
}
}
}, true);
document.documentElement.addEventListener('lazybeforesizes', function(e){
if(e.defaultPrevented || !e.target._lazybgset || e.detail.instance != lazySizes){return;}
e.detail.width = proxyWidth(e.target._lazybgset);
});
}));