const slides = [...document.querySelectorAll('.slide')]; const counter = document.getElementById('counter'); const bar = document.getElementById('progress-bar'); const overview = document.getElementById('overview'); const scrim = document.getElementById('scrim'); const menu = document.getElementById('menu'); let current = 0; function closeOverview() { overview.classList.remove('open'); scrim.classList.remove('open'); overview.setAttribute('aria-hidden', 'true'); menu.setAttribute('aria-expanded', 'false'); } function openOverview() { overview.classList.add('open'); scrim.classList.add('open'); overview.setAttribute('aria-hidden', 'false'); menu.setAttribute('aria-expanded', 'true'); } function show(index, push = true) { current = Math.max(0, Math.min(slides.length - 1, index)); slides.forEach((slide, i) => slide.classList.toggle('active', i === current)); counter.textContent = `${current + 1} / ${slides.length}`; bar.style.width = `${(current + 1) / slides.length * 100}%`; document.querySelectorAll('[data-slide-target]').forEach(link => { link.classList.toggle('current', link.dataset.slideTarget === slides[current].id); }); document.title = `${slides[current].dataset.title || ''} ยท ${document.querySelector('.deck-nav strong').textContent}`; if (push) history.replaceState(null, '', `#${slides[current].id}`); slides[current].scrollTo({ top: 0, behavior: 'instant' }); closeOverview(); } function showById(id) { const index = slides.findIndex(slide => slide.id === id); if (index >= 0) show(index); } document.getElementById('prev').addEventListener('click', () => show(current - 1)); document.getElementById('next').addEventListener('click', () => show(current + 1)); document.getElementById('print').addEventListener('click', () => window.print()); menu.addEventListener('click', () => overview.classList.contains('open') ? closeOverview() : openOverview()); document.getElementById('close-overview').addEventListener('click', closeOverview); scrim.addEventListener('click', closeOverview); document.querySelectorAll('[data-slide-target]').forEach(link => { link.addEventListener('click', event => { event.preventDefault(); showById(link.dataset.slideTarget); }); }); document.querySelectorAll('.source-chips a').forEach(link => { link.addEventListener('click', event => { event.preventDefault(); const target = document.querySelector(link.getAttribute('href')); showById('references'); if (target) requestAnimationFrame(() => target.scrollIntoView({ block: 'center' })); }); }); document.addEventListener('keydown', event => { if (event.key === 'Escape') return closeOverview(); if (['ArrowRight', 'PageDown', ' '].includes(event.key)) show(current + 1); if (['ArrowLeft', 'PageUp'].includes(event.key)) show(current - 1); if (event.key === 'Home') show(0); if (event.key === 'End') show(slides.length - 1); }); let touchStartX = 0; document.addEventListener('touchstart', event => { touchStartX = event.changedTouches[0].screenX; }, { passive: true }); document.addEventListener('touchend', event => { const distance = event.changedTouches[0].screenX - touchStartX; if (Math.abs(distance) > 70) show(current + (distance < 0 ? 1 : -1)); }, { passive: true }); const hashId = location.hash.slice(1); const initial = slides.findIndex(slide => slide.id === hashId); show(initial >= 0 ? initial : 0, false);