Files
armandine/static/assets/js/script.js
mifi e41c15c47e
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
Prettier
2026-02-17 01:31:35 -03:00

177 lines
6.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const root = document.documentElement;
const saved = window?.localStorage?.getItem('theme');
// Umami: safe track (no-op if script blocked or not loaded)
function umamiTrack(name, data) {
if (
typeof window.umami !== 'undefined' &&
typeof window.umami.track === 'function'
) {
if (data != null) window.umami.track(name, data);
else window.umami.track(name);
}
}
const sysDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (saved) {
root.setAttribute('data-theme', saved);
} else {
if (sysDark) {
root.setAttribute('data-theme', 'dark');
} else {
root.setAttribute('data-theme', 'light');
}
}
// Theme toggle
const themeToggle = document.getElementById('theme-toggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const current = root.getAttribute('data-theme') || 'light';
const next = current === 'light' ? 'dark' : 'light';
root.setAttribute('data-theme', next);
try {
localStorage.setItem('theme', next);
} catch {
/* localStorage unavailable (e.g. private browsing) */
}
});
}
// Umami: scroll depth (25%, 50%, 75%, 100%) once per milestone
const scrollMilestones = new Set();
function onScroll() {
const doc = document.documentElement;
const scrollTop = doc.scrollTop || document.body.scrollTop;
const scrollHeight =
(doc.scrollHeight || document.body.scrollHeight) - window.innerHeight;
if (scrollHeight <= 0) return;
const pct = Math.round((scrollTop / scrollHeight) * 100);
for (const m of [25, 50, 75, 100]) {
if (pct >= m && !scrollMilestones.has(m)) {
scrollMilestones.add(m);
umamiTrack('scroll-depth', { depth: String(m) });
}
}
}
window.addEventListener('scroll', onScroll, { passive: true });
// Lightbox (structure from Lightbox.svelte; we fill content and handle open/close)
const dialog = document.querySelector('dialog.lightbox');
const lbContent = dialog?.querySelector('.lb-content');
const lbCaption = dialog?.querySelector('#lb-caption, .lb-caption');
let lightboxOpener = null;
function openLightbox(name, type, caption) {
if (!dialog || !lbContent || !lbCaption) return;
lightboxOpener = document.activeElement;
document.body.style.overflow = 'hidden';
if (type === 'video') {
const video = document.createElement('video');
video.src = `/assets/media/videos/${name}.mp4`;
video.controls = true;
video.autoplay = true;
const track = document.createElement('track');
track.kind = 'captions';
track.src = `/assets/media/videos/${name}-captions.vtt`;
track.default = true;
video.appendChild(track);
lbContent.replaceChildren(video);
} else {
const srcset = (bp) =>
type === 'image'
? `/assets/media/${bp}/${name}@1x.webp 1x, /assets/media/${bp}/${name}.webp 2x`
: `/assets/media/${bp}/${name}_still@1x.webp 1x, /assets/media/${bp}/${name}_still.webp 2x`;
const picture = document.createElement('picture');
const s1 = document.createElement('source');
s1.media = '(min-width:1024px)';
s1.srcset = srcset('desktop');
const s2 = document.createElement('source');
s2.media = '(min-width:768px)';
s2.srcset = srcset('tablet');
const s3 = document.createElement('source');
s3.media = '(min-width:0px)';
s3.srcset = srcset('mobile');
const img = document.createElement('img');
img.src = `/assets/media/thumbnail/${name}.webp`;
img.alt = '';
picture.append(s1, s2, s3, img);
lbContent.replaceChildren(picture);
}
lbCaption.textContent = caption || '';
umamiTrack('gallery-view', { name, type });
dialog.removeAttribute('inert');
dialog.setAttribute('aria-hidden', 'false');
dialog.showModal();
}
function closeLightbox() {
if (!dialog) return;
if (lightboxOpener && typeof lightboxOpener.focus === 'function') {
lightboxOpener.focus();
}
lightboxOpener = null;
document.body.style.overflow = '';
if (lbContent) lbContent.replaceChildren();
if (lbCaption) lbCaption.textContent = '';
dialog.setAttribute('aria-hidden', 'true');
dialog.setAttribute('inert', '');
dialog.close();
}
if (dialog) {
// Add event handlers
dialog.querySelector('.lb-close').addEventListener('click', closeLightbox);
dialog.querySelector('.lb-close').addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
closeLightbox();
}
});
dialog.addEventListener('close', closeLightbox);
dialog.addEventListener('cancel', closeLightbox);
dialog.addEventListener('click', (e) => {
if (e.target === dialog) closeLightbox();
});
}
// Gallery items
document.querySelectorAll('.gallery-item[data-name]').forEach((el) => {
el.addEventListener('click', () => {
const name = el.getAttribute('data-name');
const type = el.getAttribute('data-type') || 'image';
const caption = el.getAttribute('data-caption') || '';
if (name) openLightbox(name, type, caption);
});
el.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
const name = el.getAttribute('data-name');
const type = el.getAttribute('data-type') || 'image';
const caption = el.getAttribute('data-caption') || '';
if (name) openLightbox(name, type, caption);
}
});
});
// Show video button (open lightbox with tour)
const showVideoBtn = document.getElementById('show_video');
if (showVideoBtn) {
const openTour = () => {
const name = showVideoBtn.getAttribute('data-name') || 'tour';
const type = showVideoBtn.getAttribute('data-type') || 'video';
const caption =
showVideoBtn.getAttribute('data-caption') ||
"Take the scenic route—explore your the home's highlights with a virtual walkthrough.";
openLightbox(name, type, caption);
};
showVideoBtn.addEventListener('click', openTour);
showVideoBtn.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
openTour();
}
});
}