mirror of
https://github.com/Extroonie/extroonie.com.git
synced 2026-10-13 01:48:06 -07:00
84 lines
2.4 KiB
JavaScript
84 lines
2.4 KiB
JavaScript
(() => {
|
|
const contents = document.querySelector('.article-contents');
|
|
if (!contents) return;
|
|
const reopen = document.querySelector('.contents-reopen');
|
|
const closeButton = contents.querySelector('.contents-close');
|
|
const title = contents.querySelector('.contents-heading');
|
|
const wide = matchMedia('(min-width: 64rem)');
|
|
let desktopOpen = true;
|
|
let mobileOpen = false;
|
|
const links = [...contents.querySelectorAll('nav a')];
|
|
const headings = links.map((link) => document.getElementById(decodeURIComponent(link.hash.slice(1))));
|
|
function render() {
|
|
contents.classList.toggle('sidebar', wide.matches);
|
|
contents.open = wide.matches ? desktopOpen : mobileOpen;
|
|
title.hidden = !wide.matches;
|
|
reopen.hidden = !wide.matches || desktopOpen;
|
|
reopen.setAttribute('aria-expanded', String(desktopOpen));
|
|
}
|
|
function close() {
|
|
desktopOpen = false;
|
|
render();
|
|
reopen.focus({ preventScroll: true });
|
|
}
|
|
closeButton.addEventListener('click', close);
|
|
contents.addEventListener('keydown', (event) => {
|
|
if (event.key === 'Escape' && wide.matches && desktopOpen) close();
|
|
});
|
|
reopen.addEventListener('click', () => {
|
|
desktopOpen = true;
|
|
render();
|
|
closeButton.focus({ preventScroll: true });
|
|
});
|
|
contents.querySelector('summary').addEventListener('click', (event) => {
|
|
if (wide.matches) return;
|
|
event.preventDefault();
|
|
mobileOpen = !contents.open;
|
|
render();
|
|
});
|
|
contents.addEventListener('click', (event) => {
|
|
if (
|
|
event.defaultPrevented ||
|
|
event.button !== 0 ||
|
|
event.metaKey ||
|
|
event.ctrlKey ||
|
|
event.shiftKey ||
|
|
event.altKey
|
|
)
|
|
return;
|
|
const link = event.target.closest('nav a');
|
|
if (!link) return;
|
|
if (!wide.matches) {
|
|
mobileOpen = false;
|
|
render();
|
|
}
|
|
const heading = headings[links.indexOf(link)];
|
|
heading?.focus({ preventScroll: true });
|
|
});
|
|
wide.addEventListener('change', render);
|
|
let scheduled = false;
|
|
function update() {
|
|
scheduled = false;
|
|
let current = -1;
|
|
headings.forEach((heading, index) => {
|
|
if (heading && heading.getBoundingClientRect().top <= 120) current = index;
|
|
});
|
|
links.forEach((link, index) => {
|
|
if (index === current) link.setAttribute('aria-current', 'location');
|
|
else link.removeAttribute('aria-current');
|
|
});
|
|
}
|
|
window.addEventListener(
|
|
'scroll',
|
|
() => {
|
|
if (!scheduled) {
|
|
scheduled = true;
|
|
requestAnimationFrame(update);
|
|
}
|
|
},
|
|
{ passive: true },
|
|
);
|
|
window.addEventListener('resize', update);
|
|
render();
|
|
update();
|
|
})();
|