Files
armandine/static/assets/js/script.js
mifi cbe900a8e4
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/build unknown status
ci/woodpecker/push/deploy unknown status
Umami tracking
2026-02-17 01:28:18 -03:00

173 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();
}
});
}