unlazy
Version:
Universal lazy loading library for placeholder images leveraging native browser APIs
1 lines • 4.33 kB
JavaScript
const e=!(typeof window>`u`)&&(!(`onscroll`in window)||/(?:gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent));function t(e,t=document){return typeof e==`string`?[...t.querySelectorAll(e)]:e instanceof Element?[e]:[...e]}function n(e){let t=Date.now();return`data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3C/svg%3E`.replace(/\s/,` data-id='${t}-${e}' `)}function r(e,t){let n;return function(...r){n!=null&&clearTimeout(n),n=setTimeout(()=>{e(...r),n=void 0},t)}}let i=!1;function a(){if(!i){i=!0;try{new PerformanceObserver(e=>{for(let t of e.getEntries()){let e=t.element;if(!e||e.tagName!==`IMG`)continue;let n=e.loading===`lazy`,r=e.hasAttribute(`data-src`)||e.hasAttribute(`data-srcset`);(n||r)&&console.warn('[unlazy] LCP element is configured for lazy loading. Set `loading="eager"` to improve Largest Contentful Paint.',e)}}).observe({type:`largest-contentful-paint`,buffered:!0})}catch{}}}const o=new WeakSet;function s(r=`img[loading="lazy"], img[loading="eager"][data-src], img[loading="eager"][data-srcset]`,{hash:i=!0,hashType:s=`blurhash`,placeholderSize:u=32,updateSizesOnResize:d=!1,onImageLoad:f,onImageError:p}={}){let g=new Set;(typeof __UNLAZY_LOGGING__>`u`||__UNLAZY_LOGGING__)&&a();for(let[i,a]of t(r).entries()){if(o.has(a))continue;let t=a.loading===`eager`;if(t&&!a.hasAttribute(`fetchpriority`)&&a.setAttribute(`fetchpriority`,`high`),g.add(c(a,{updateOnResize:d})),!a.dataset.src&&!a.dataset.srcset){(typeof __UNLAZY_LOGGING__>`u`||__UNLAZY_LOGGING__)&&console.error("[unlazy] Missing `data-src` or `data-srcset` attribute",a);continue}if(o.add(a),t||e){if(f){let e=()=>f(a);a.addEventListener(`load`,e,{once:!0}),g.add(()=>a.removeEventListener(`load`,e))}if(p){let e=e=>p(a,e);a.addEventListener(`error`,e,{once:!0}),g.add(()=>a.removeEventListener(`error`,e))}h(a),m(a,`srcset`),m(a,`src`);continue}if(a.src||=n(i),a.complete&&a.naturalWidth>0){g.add(l(a,{onImageLoad:f,onImageError:p}));continue}let r=()=>{g.add(l(a,{onImageLoad:f,onImageError:p}))};a.addEventListener(`load`,r,{once:!0}),g.add(()=>a.removeEventListener(`load`,r))}return()=>{for(let e of g)e();g.clear()}}function c(e=`img[data-sizes="auto"], source[data-sizes="auto"]`,{updateOnResize:n=!1}={}){let r=[];for(let i of t(e))r.push(u(i,n));return()=>{for(let e of r)e();r.length=0}}function l(e,{onImageLoad:t,onImageError:n}={}){let r=[],i=()=>{for(let e of r)e();r.length=0};if(_(e)){if(t){let n=()=>t(e);e.addEventListener(`load`,n,{once:!0}),r.push(()=>e.removeEventListener(`load`,n))}if(n){let t=t=>n(e,t);e.addEventListener(`error`,t,{once:!0}),r.push(()=>e.removeEventListener(`error`,t))}return h(e),m(e,`srcset`),m(e,`src`),i}let{srcset:a,src:o,sizes:s}=e.dataset;if(!a&&!o)return i;let c=new Image,l=()=>{m(e,`srcset`),m(e,`src`),t?.(e)},u=t=>{e.dispatchEvent(new Event(`error`)),n?.(e,t)};if(c.addEventListener(`load`,l,{once:!0}),c.addEventListener(`error`,u,{once:!0}),r.push(()=>{c.removeEventListener(`load`,l),c.removeEventListener(`error`,u),c.src=``}),s===`auto`){let t=g(e);t&&(c.sizes=`${t}px`)}else e.sizes&&(c.sizes=e.sizes);return a&&(c.srcset=a),o&&(c.src=o),i}function u(e,t){let n=f(e);for(let e of n)p(e);if(!t||!n.some(d))return v;let i=e instanceof HTMLImageElement?e:e.parentElement?.getElementsByTagName(`img`)[0]??null;if(!i)return v;let a=r(()=>{for(let t of f(e))p(t)},500),o=new ResizeObserver(a);return o.observe(i),()=>o.disconnect()}function d(e){return e.dataset.sizes===`auto`}function f(e){let t=[e];if(e instanceof HTMLImageElement&&e.parentElement?.tagName.toLowerCase()===`picture`)for(let n of e.parentElement.querySelectorAll(`source[data-sizes="auto"]`))t.push(n);return t}function p(e){if(e.dataset.sizes!==`auto`)return;let t=g(e);if(!t)return;let n=`${t}px`;e.sizes!==n&&(e.sizes=n)}function m(e,t){let n=e.dataset[t];n&&(e[t]=n,e.removeAttribute(`data-${t}`))}function h(e){let t=e.parentElement;if(t?.tagName.toLowerCase()===`picture`)for(let e of t.querySelectorAll(`source[data-srcset]`))p(e),m(e,`srcset`)}function g(e){return e instanceof HTMLSourceElement?e.parentElement?.getElementsByTagName(`img`)[0]?.offsetWidth:e.offsetWidth}function _(e){return e.parentElement?.tagName.toLowerCase()===`picture`}function v(){}document.currentScript?.hasAttribute(`init`)&&s();export{c as autoSizes,s as lazyLoad,l as triggerLoad};