48 lines
1.8 KiB
JavaScript
48 lines
1.8 KiB
JavaScript
/*
|
|
* RustPad media player helpers.
|
|
* Project-owned code: keeps native video playback and YouTube embeds responsive.
|
|
*/
|
|
|
|
const initialized = new WeakSet();
|
|
|
|
function createYouTubeFrame(node) {
|
|
const videoId = String(node.dataset.videoId || "").trim();
|
|
if (!/^[A-Za-z0-9_-]{6,20}$/.test(videoId)) return;
|
|
|
|
const iframe = document.createElement("iframe");
|
|
iframe.src = `https://www.youtube-nocookie.com/embed/${encodeURIComponent(videoId)}?rel=0&modestbranding=1&playsinline=1`;
|
|
iframe.title = node.dataset.playerTitle || "YouTube video";
|
|
iframe.loading = "lazy";
|
|
iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share";
|
|
iframe.referrerPolicy = "strict-origin-when-cross-origin";
|
|
iframe.allowFullscreen = true;
|
|
node.replaceChildren(iframe);
|
|
}
|
|
|
|
function initializeNativeVideo(video) {
|
|
video.controls = true;
|
|
video.playsInline = true;
|
|
video.preload = video.preload || "metadata";
|
|
|
|
const fallback = video.closest(".rustpad-media")?.querySelector(".rustpad-media__fallback");
|
|
if (!fallback) return;
|
|
const revealFallback = () => { fallback.hidden = false; };
|
|
video.addEventListener("error", revealFallback, { once: true });
|
|
video.querySelectorAll("source").forEach(source => source.addEventListener("error", revealFallback, { once: true }));
|
|
}
|
|
|
|
export function hydrateMediaPlayers(root = document) {
|
|
root.querySelectorAll("[data-rustpad-player]").forEach(node => {
|
|
if (initialized.has(node)) return;
|
|
initialized.add(node);
|
|
if (node.dataset.playerKind === "youtube") createYouTubeFrame(node);
|
|
else if (node instanceof HTMLVideoElement) initializeNativeVideo(node);
|
|
});
|
|
}
|
|
|
|
export function destroyMediaPlayers(root = document) {
|
|
root.querySelectorAll('[data-rustpad-player][data-player-kind="youtube"] iframe').forEach(frame => {
|
|
frame.src = "about:blank";
|
|
});
|
|
}
|