2022-03-22 22:31:56 +01:00
|
|
|
'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) {
|
2022-04-17 16:51:42 +02:00
|
|
|
themeToggleButton.addEventListener(
|
|
|
|
'click',
|
|
|
|
function() {
|
|
|
|
mq.removeEventListener('change', mqChangeListener);
|
|
|
|
},
|
|
|
|
{ once: true }
|
|
|
|
);
|
2022-03-22 22:31:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
picker.addEventListener('click', function(e) {
|
2022-03-22 22:31:56 +01:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
requestAnimationFrame(function() {
|
2022-03-22 22:31:56 +01:00
|
|
|
parentNode.classList.add('expanded');
|
|
|
|
window.addEventListener('click', closeAllPickers);
|
|
|
|
window.addEventListener('keydown', onKeyDown);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function setupStickyHeaders() {
|
|
|
|
const header = document.querySelector('.header');
|
|
|
|
let ignoreNextIntersection = false;
|
|
|
|
|
|
|
|
new IntersectionObserver(
|
2022-04-17 16:51:42 +02:00
|
|
|
function(e) {
|
2022-03-22 22:31:56 +01:00
|
|
|
const currentStatus = header.classList.contains('is-pinned');
|
2022-04-17 16:51:42 +02:00
|
|
|
const newStatus = e[0].intersectionRatio < 1;
|
2022-03-22 22:31:56 +01:00
|
|
|
|
|
|
|
// 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;
|
2022-04-17 16:51:42 +02:00
|
|
|
setTimeout(function() {
|
2022-03-22 22:31:56 +01:00
|
|
|
ignoreNextIntersection = false;
|
|
|
|
}, 50);
|
|
|
|
|
|
|
|
header.classList.toggle('is-pinned', newStatus);
|
|
|
|
},
|
|
|
|
{ threshold: [1] }
|
|
|
|
).observe(header);
|
|
|
|
}
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
function setupAltDocsLink() {
|
|
|
|
const linkWrapper = document.getElementById('alt-docs');
|
|
|
|
|
|
|
|
function updateHashes() {
|
|
|
|
for (const link of linkWrapper.querySelectorAll('a')) {
|
|
|
|
link.hash = location.hash;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addEventListener('hashchange', updateHashes);
|
|
|
|
updateHashes();
|
|
|
|
}
|
|
|
|
|
2022-03-22 22:31:56 +01:00
|
|
|
function bootstrap() {
|
2022-04-17 16:51:42 +02:00
|
|
|
// Check if we have JavaScript support.
|
2022-03-22 22:31:56 +01:00
|
|
|
document.documentElement.classList.add('has-js');
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
// Restore user mode preferences.
|
2022-03-22 22:31:56 +01:00
|
|
|
setupTheme();
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
// Handle pickers with click/taps rather than hovers.
|
2022-03-22 22:31:56 +01:00
|
|
|
setupPickers();
|
|
|
|
|
2022-04-17 16:51:42 +02:00
|
|
|
// Track when the header is in sticky position.
|
2022-03-22 22:31:56 +01:00
|
|
|
setupStickyHeaders();
|
2022-04-17 16:51:42 +02:00
|
|
|
|
|
|
|
// Make link to other versions of the doc open to the same hash target (if it exists).
|
|
|
|
setupAltDocsLink();
|
2022-03-22 22:31:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (document.readyState === 'loading') {
|
|
|
|
document.addEventListener('DOMContentLoaded', bootstrap, { once: true });
|
|
|
|
} else {
|
|
|
|
bootstrap();
|
|
|
|
}
|
|
|
|
}
|