mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
83 lines
1.9 KiB
JavaScript
83 lines
1.9 KiB
JavaScript
/**
|
|
* Simple IntersectionObserver-based lazy loader for images (or videos).
|
|
*
|
|
* Usage:
|
|
* const mediaLoader = new MediaLoader();
|
|
* mediaLoader.observe(imgElement);
|
|
*
|
|
* This will load the real image source from `imgElement.dataset.lazy`
|
|
* once the image enters the viewport.
|
|
*/
|
|
export class MediaLoader {
|
|
constructor(rootMargin = "50px") {
|
|
this.observer = new IntersectionObserver((entries) => {
|
|
for (const entry of entries) {
|
|
if (!entry.isIntersecting) {
|
|
continue;
|
|
}
|
|
|
|
const el = entry.target;
|
|
const lazySrc =
|
|
typeof el.dataset.lazy === "string" ? el.dataset.lazy.trim() : "";
|
|
|
|
if (!lazySrc) {
|
|
continue;
|
|
}
|
|
|
|
const fallbackSrc =
|
|
(typeof el.dataset.fallbackSrc === "string"
|
|
? el.dataset.fallbackSrc.trim()
|
|
: "") ||
|
|
el.getAttribute("data-fallback-src") ||
|
|
"";
|
|
|
|
const tagName = typeof el.tagName === "string" ? el.tagName : "";
|
|
|
|
if (tagName === "IMG" || tagName === "IMAGE") {
|
|
el.src = lazySrc;
|
|
if (fallbackSrc) {
|
|
el.onerror = () => {
|
|
el.src = fallbackSrc;
|
|
};
|
|
}
|
|
} else if (tagName === "VIDEO") {
|
|
el.src = lazySrc;
|
|
if (fallbackSrc) {
|
|
el.poster = fallbackSrc;
|
|
}
|
|
} else if ("src" in el) {
|
|
el.src = lazySrc;
|
|
}
|
|
|
|
delete el.dataset.lazy;
|
|
this.observer.unobserve(el);
|
|
}
|
|
}, {
|
|
rootMargin,
|
|
threshold: 0.01,
|
|
});
|
|
}
|
|
|
|
observe(el) {
|
|
if (!el || typeof el !== "object") {
|
|
return;
|
|
}
|
|
|
|
if ("decoding" in HTMLImageElement.prototype) {
|
|
el.decoding = el.decoding || "async";
|
|
}
|
|
|
|
const lazySrc =
|
|
typeof el.dataset.lazy === "string" ? el.dataset.lazy.trim() : "";
|
|
if (lazySrc) {
|
|
this.observer.observe(el);
|
|
}
|
|
}
|
|
|
|
disconnect() {
|
|
this.observer.disconnect();
|
|
}
|
|
}
|
|
|
|
export default MediaLoader;
|