UNPKG

lazysizes

Version:

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

177 lines (144 loc) 4.4 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) { 'use strict'; if(!window.addEventListener){return;} var lazySizesConfig = lazySizes.cfg; var ElementPrototype = (window.Element || Node || window.HTMLElement).prototype; var regArtDirect = /artdirect/; var regDescriptors = /\s+(\d+)(w|h)\s+(\d+)(w|h)/; var regArtDirectTags = /artdirect["']*\s*:\s*["']*(.+?)(?=($|'|"|;))/; var regPicture = /^picture$/i; var regSplit = /[\s,]+/g; var slice = [].slice; function getCandidatesAspectRatio(element){ var match, width, height; var ratio = parseFloat(element.getAttribute('data-aspectratio')); var srcset = element.getAttribute(lazySizesConfig.srcsetAttr) || element.getAttribute('srcset'); if(!ratio){ match = srcset.match(regDescriptors); if (match) { if(match[2] == 'w'){ width = match[1]; height = match[3]; } else { width = match[3]; height = match[1]; } } else { width = element.getAttribute('width'); height = element.getAttribute('height'); } ratio = width / height; } return ratio; } function getLayoutAspectRatio(element){ return element.offsetWidth / element.offsetHeight; } function toTagSelector(tag){ return 'source[data-tag~="' + tag + '"]'; } function getArtDirectConfig(img){ var picture = img.parentNode; var isPicture = regPicture.test(picture.nodeName || ''); var content = (window.getComputedStyle(img) || {}).fontFamily; var config = null; if(isPicture && (lazySizesConfig.autoArtDirect || regArtDirect.test(content || ''))){ config = { picture: picture, img: img, tags: content.match(regArtDirectTags) }; if(config.tags){ config.selector = config.tags[1].split(regSplit).map(toTagSelector).join(','); } } return config; } function toSourceObj(source){ var media = source.getAttribute('media'); return { source: source, aspectRatio: getCandidatesAspectRatio(source), isSelected: !media || window.matchMedia(media).matches, }; } function sortAspectRatio(source1, source2){ return source1.aspectRatio < source2.aspectRatio; } function getClosestSource(sources, aspecRatio){ var i, len; var closest = sources[0]; for(i = 1, len = sources.length; i < len; i++){ if(Math.abs(closest.aspectRatio - aspecRatio) > Math.abs(sources[i].aspectRatio - aspecRatio)){ closest = sources[i]; } } return closest; } function setMedia(source, media){ source._lsMedia = media; lazySizes.rAF(function(){ if(source._lsMedia){ delete source._lsMedia; } source.setAttribute('media', media); }); } function selectSource(imgCfg){ var imgAspectRatio = getLayoutAspectRatio(imgCfg.img); var sources = slice.call(imgCfg.picture.getElementsByTagName('source')) .map(toSourceObj) .sort(sortAspectRatio) ; var matchedSources = imgCfg.selector ? sources.filter(function(source){ return source.source.matches(imgCfg.selector); }) : sources ; var closestSource = getClosestSource(matchedSources, imgAspectRatio); if(!closestSource.isSelected){ setMedia(closestSource.source, '(min-width: 1px)'); } sources .filter(function(source){ return (source != closestSource && source.isSelected); }) .forEach(function (source) { setMedia(source.source, '(x)'); }) ; } function addAutoArtDirection(e){ if(e.detail.instance != lazySizes){return;} var img = e.target; var imgCfg = getArtDirectConfig(img); if(imgCfg){ selectSource(imgCfg); } } if(!ElementPrototype.matches){ ElementPrototype.matches = ElementPrototype.matchesSelector || ElementPrototype.webkitMatchesSelector || ElementPrototype.msMatchesSelector || ElementPrototype.oMatchesSelector; } window.addEventListener('lazybeforesizes', addAutoArtDirection, true); }));