'use strict'; { function setupTheme() { const kCustomPreference = 'customDarkTheme'; const userSettings = sessionStorage.getItem(kCustomPreference); const themeToggleButton = document.getElementById('theme-toggle-btn'); if (userSettings === null && window.matchMedia) { const mq = window.matchMedia('(prefers-color-scheme: dark)'); if ('onchange' in mq) { function mqChangeListener(e) { document.documentElement.classList.toggle('dark-mode', e.matches); } mq.addEventListener('change', mqChangeListener); if (themeToggleButton) { themeToggleButton.addEventListener('click', function() { mq.removeEventListener('change', mqChangeListener); }, { once: true }); } } if (mq.matches) { document.documentElement.classList.add('dark-mode'); } } else if (userSettings === 'true') { document.documentElement.classList.add('dark-mode'); } if (themeToggleButton) { themeToggleButton.hidden = false; themeToggleButton.addEventListener('click', function() { sessionStorage.setItem( kCustomPreference, document.documentElement.classList.toggle('dark-mode') ); }); } } function setupPickers() { function closeAllPickers() { for (const picker of pickers) { picker.parentNode.classList.remove('expanded'); } window.removeEventListener('click', closeAllPickers); window.removeEventListener('keydown', onKeyDown); } function onKeyDown(e) { if (e.key === 'Escape') { closeAllPickers(); } } const pickers = document.querySelectorAll('.picker-header > a'); for (const picker of pickers) { const parentNode = picker.parentNode; picker.addEventListener('click', (e) => { e.preventDefault(); /* closeAllPickers as window event trigger already closed all the pickers, if it already closed there is nothing else to do here */ if (parentNode.classList.contains('expanded')) { return; } /* In the next frame reopen the picker if needed and also setup events to close pickers if needed. */ requestAnimationFrame(() => { parentNode.classList.add('expanded'); window.addEventListener('click', closeAllPickers); window.addEventListener('keydown', onKeyDown); }); }); } } function setupStickyHeaders() { const header = document.querySelector('.header'); let ignoreNextIntersection = false; new IntersectionObserver( ([e]) => { const currentStatus = header.classList.contains('is-pinned'); const newStatus = e.intersectionRatio < 1; // Same status, do nothing if (currentStatus === newStatus) { return; } else if (ignoreNextIntersection) { ignoreNextIntersection = false; return; } /* To avoid flickering, ignore the next changes event that is triggered as the visible elements in the header change once we pin it. The timer is reset anyway after few milliseconds. */ ignoreNextIntersection = true; setTimeout(() => { ignoreNextIntersection = false; }, 50); header.classList.toggle('is-pinned', newStatus); }, { threshold: [1] } ).observe(header); } function bootstrap() { // Check if we have JavaScript support document.documentElement.classList.add('has-js'); // Restore user mode preferences setupTheme(); // Handle pickers with click/taps rather than hovers setupPickers(); // Track when the header is in sticky position setupStickyHeaders(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', bootstrap, { once: true }); } else { bootstrap(); } }