UNPKG

lazysizes

Version:

High performance (jankfree) lazy loader for images (including responsive images), iframes and scripts (widgets).

312 lines (264 loc) 7.91 kB
(function(window, factory) { if(!window) {return;} 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); } }(typeof window != 'undefined' ? window : 0, function(window, document, lazySizes) { /*jshint eqnull:true */ 'use strict'; var polyfill; var lazySizesCfg = lazySizes.cfg; var img = document.createElement('img'); var supportSrcset = ('sizes' in img) && ('srcset' in img); var regHDesc = /\s+\d+h/g; var fixEdgeHDescriptor = (function(){ var regDescriptors = /\s+(\d+)(w|h)\s+(\d+)(w|h)/; var forEach = Array.prototype.forEach; return function(){ var img = document.createElement('img'); var removeHDescriptors = function(source){ var ratio, match; var srcset = source.getAttribute(lazySizesCfg.srcsetAttr); if(srcset){ if((match = srcset.match(regDescriptors))){ if(match[2] == 'w'){ ratio = match[1] / match[3]; } else { ratio = match[3] / match[1]; } if(ratio){ source.setAttribute('data-aspectratio', ratio); } source.setAttribute(lazySizesCfg.srcsetAttr, srcset.replace(regHDesc, '')); } } }; var handler = function(e){ if(e.detail.instance != lazySizes){return;} var picture = e.target.parentNode; if(picture && picture.nodeName == 'PICTURE'){ forEach.call(picture.getElementsByTagName('source'), removeHDescriptors); } removeHDescriptors(e.target); }; var test = function(){ if(!!img.currentSrc){ document.removeEventListener('lazybeforeunveil', handler); } }; document.addEventListener('lazybeforeunveil', handler); img.onload = test; img.onerror = test; img.srcset = 'data:,a 1w 1h'; if(img.complete){ test(); } }; })(); if(!lazySizesCfg.supportsType){ lazySizesCfg.supportsType = function(type/*, elem*/){ return !type; }; } if (window.HTMLPictureElement && supportSrcset) { if(!lazySizes.hasHDescriptorFix && document.msElementsFromPoint){ lazySizes.hasHDescriptorFix = true; fixEdgeHDescriptor(); } return; } if(window.picturefill || lazySizesCfg.pf){return;} lazySizesCfg.pf = function(options){ var i, len; if(window.picturefill){return;} for(i = 0, len = options.elements.length; i < len; i++){ polyfill(options.elements[i]); } }; // partial polyfill polyfill = (function(){ var ascendingSort = function( a, b ) { return a.w - b.w; }; var regPxLength = /^\s*\d+\.*\d*px\s*$/; var reduceCandidate = function (srces) { var lowerCandidate, bonusFactor; var len = srces.length; var candidate = srces[len -1]; var i = 0; for(i; i < len;i++){ candidate = srces[i]; candidate.d = candidate.w / srces.w; if(candidate.d >= srces.d){ if(!candidate.cached && (lowerCandidate = srces[i - 1]) && lowerCandidate.d > srces.d - (0.13 * Math.pow(srces.d, 2.2))){ bonusFactor = Math.pow(lowerCandidate.d - 0.6, 1.6); if(lowerCandidate.cached) { lowerCandidate.d += 0.15 * bonusFactor; } if(lowerCandidate.d + ((candidate.d - srces.d) * bonusFactor) > srces.d){ candidate = lowerCandidate; } } break; } } return candidate; }; var parseWsrcset = (function(){ var candidates; var regWCandidates = /(([^,\s].[^\s]+)\s+(\d+)w)/g; var regMultiple = /\s/; var addCandidate = function(match, candidate, url, wDescriptor){ candidates.push({ c: candidate, u: url, w: wDescriptor * 1 }); }; return function(input){ candidates = []; input = input.trim(); input .replace(regHDesc, '') .replace(regWCandidates, addCandidate) ; if(!candidates.length && input && !regMultiple.test(input)){ candidates.push({ c: input, u: input, w: 99 }); } return candidates; }; })(); var runMatchMedia = function(){ if(runMatchMedia.init){return;} runMatchMedia.init = true; addEventListener('resize', (function(){ var timer; var matchMediaElems = document.getElementsByClassName('lazymatchmedia'); var run = function(){ var i, len; for(i = 0, len = matchMediaElems.length; i < len; i++){ polyfill(matchMediaElems[i]); } }; return function(){ clearTimeout(timer); timer = setTimeout(run, 66); }; })()); }; var createSrcset = function(elem, isImage){ var parsedSet; var srcSet = elem.getAttribute('srcset') || elem.getAttribute(lazySizesCfg.srcsetAttr); if(!srcSet && isImage){ srcSet = !elem._lazypolyfill ? (elem.getAttribute(lazySizesCfg.srcAttr) || elem.getAttribute('src')) : elem._lazypolyfill._set ; } if(!elem._lazypolyfill || elem._lazypolyfill._set != srcSet){ parsedSet = parseWsrcset( srcSet || '' ); if(isImage && elem.parentNode){ parsedSet.isPicture = elem.parentNode.nodeName.toUpperCase() == 'PICTURE'; if(parsedSet.isPicture){ if(window.matchMedia){ lazySizes.aC(elem, 'lazymatchmedia'); runMatchMedia(); } } } parsedSet._set = srcSet; Object.defineProperty(elem, '_lazypolyfill', { value: parsedSet, writable: true }); } }; var getX = function(elem){ var dpr = window.devicePixelRatio || 1; var optimum = lazySizes.getX && lazySizes.getX(elem); return Math.min(optimum || dpr, 2.5, dpr); }; var matchesMedia = function(media){ if(window.matchMedia){ matchesMedia = function(media){ return !media || (matchMedia(media) || {}).matches; }; } else { return !media; } return matchesMedia(media); }; var getCandidate = function(elem){ var sources, i, len, media, source, srces, src, width; source = elem; createSrcset(source, true); srces = source._lazypolyfill; if(srces.isPicture){ for(i = 0, sources = elem.parentNode.getElementsByTagName('source'), len = sources.length; i < len; i++){ if( lazySizesCfg.supportsType(sources[i].getAttribute('type'), elem) && matchesMedia( sources[i].getAttribute('media')) ){ source = sources[i]; createSrcset(source); srces = source._lazypolyfill; break; } } } if(srces.length > 1){ width = source.getAttribute('sizes') || ''; width = regPxLength.test(width) && parseInt(width, 10) || lazySizes.gW(elem, elem.parentNode); srces.d = getX(elem); if(!srces.src || !srces.w || srces.w < width){ srces.w = width; src = reduceCandidate(srces.sort(ascendingSort)); srces.src = src; } else { src = srces.src; } } else { src = srces[0]; } return src; }; var p = function(elem){ if(supportSrcset && elem.parentNode && elem.parentNode.nodeName.toUpperCase() != 'PICTURE'){return;} var candidate = getCandidate(elem); if(candidate && candidate.u && elem._lazypolyfill.cur != candidate.u){ elem._lazypolyfill.cur = candidate.u; candidate.cached = true; elem.setAttribute(lazySizesCfg.srcAttr, candidate.u); elem.setAttribute('src', candidate.u); } }; p.parse = parseWsrcset; return p; })(); if(lazySizesCfg.loadedClass && lazySizesCfg.loadingClass){ (function(){ var sels = []; ['img[sizes$="px"][srcset].', 'picture > img:not([srcset]).'].forEach(function(sel){ sels.push(sel + lazySizesCfg.loadedClass); sels.push(sel + lazySizesCfg.loadingClass); }); lazySizesCfg.pf({ elements: document.querySelectorAll(sels.join(', ')) }); })(); } }));