Initial commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// ── 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" });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user