80 lines
2.8 KiB
JavaScript
80 lines
2.8 KiB
JavaScript
// ── Pivoine — main.js ─────────────────────────────────────────────
|
|
|
|
// ── HTMX progress bar ─────────────────────────────────────────────
|
|
(function () {
|
|
const bar = document.getElementById("progress-bar");
|
|
if (!bar) return;
|
|
|
|
document.body.addEventListener("htmx:beforeRequest", () => {
|
|
bar.style.width = "0";
|
|
bar.style.opacity = "1";
|
|
requestAnimationFrame(() => {
|
|
bar.style.width = "55%";
|
|
});
|
|
});
|
|
|
|
document.body.addEventListener("htmx:afterSettle", () => {
|
|
bar.style.width = "100%";
|
|
setTimeout(() => {
|
|
bar.style.opacity = "0";
|
|
setTimeout(() => { bar.style.width = "0"; }, 350);
|
|
}, 150);
|
|
});
|
|
})();
|
|
|
|
// ── Lazy-load videos (data-src attribute) ─────────────────────────
|
|
function initLazyVideos(root) {
|
|
if (!("IntersectionObserver" in window)) return;
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (!entry.isIntersecting) return;
|
|
const video = entry.target;
|
|
if (video.dataset.src) {
|
|
video.src = video.dataset.src;
|
|
video.load();
|
|
}
|
|
observer.unobserve(video);
|
|
});
|
|
},
|
|
{ rootMargin: "300px" }
|
|
);
|
|
(root || document).querySelectorAll("video[data-src]").forEach((v) => observer.observe(v));
|
|
}
|
|
|
|
initLazyVideos();
|
|
|
|
// ── After HTMX partial swap ────────────────────────────────────────
|
|
document.body.addEventListener("htmx:afterSwap", (e) => {
|
|
initLazyVideos(e.target);
|
|
if (window.Alpine) Alpine.initTree(e.target);
|
|
window.scrollTo({ top: 0, behavior: "instant" });
|
|
});
|
|
|
|
// ── After HTMX history restore (back / forward navigation) ────────
|
|
document.body.addEventListener("htmx:historyRestore", () => {
|
|
// Sync nav active state to the restored URL
|
|
if (window.Alpine) Alpine.store("nav").path = window.location.pathname;
|
|
|
|
// Complete the progress bar (htmx:afterSettle never fires on history restore)
|
|
const bar = document.getElementById("progress-bar");
|
|
if (bar) {
|
|
bar.style.width = "100%";
|
|
setTimeout(() => {
|
|
bar.style.opacity = "0";
|
|
setTimeout(() => { bar.style.width = "0"; }, 350);
|
|
}, 150);
|
|
}
|
|
|
|
const main = document.getElementById("main-content");
|
|
if (!main) return;
|
|
if (window.Alpine) Alpine.initTree(main);
|
|
// Reload and replay autoplay videos (autoplay attr is ignored on restore)
|
|
main.querySelectorAll("video[autoplay]").forEach((v) => {
|
|
v.load();
|
|
v.play().catch(() => {});
|
|
});
|
|
window.scrollTo({ top: 0, behavior: "instant" });
|
|
});
|
|
|