philomena/assets/js/burger.ts
2024-06-23 14:38:56 +02:00

76 lines
2.2 KiB
TypeScript

/**
* Hamburger menu.
*/
import { $, $$ } from './utils/dom';
import { assertNotNull } from './utils/assert';
function switchClasses(element: HTMLElement, oldClass: string, newClass: string) {
element.classList.remove(oldClass);
element.classList.add(newClass);
}
function open(burger: HTMLElement, content: HTMLElement, body: HTMLElement, root: HTMLElement) {
switchClasses(content, 'close', 'open');
switchClasses(burger, 'close', 'open');
root.classList.add('no-overflow-x');
body.classList.add('no-overflow');
}
function close(burger: HTMLElement, content: HTMLElement, body: HTMLElement, root: HTMLElement) {
switchClasses(content, 'open', 'close');
switchClasses(burger, 'open', 'close');
/* the CSS animation closing the menu finishes in 300ms */
setTimeout(() => {
root.classList.remove('no-overflow-x');
body.classList.remove('no-overflow');
}, 300);
}
function copyArtistLinksTo(burger: HTMLElement) {
const copy = (links: HTMLCollection) => {
burger.appendChild(document.createElement('hr'));
for (let i = 0; i < links.length; i++) {
// If we're here, this should not be null.
const link = assertNotNull(links.item(i));
const burgerLink = link.cloneNode(true) as HTMLElement;
burgerLink.className = '';
burger.appendChild(burgerLink);
}
};
$$<HTMLElement>('.js-burger-links').forEach(container => copy(container.children));
}
export function setupBurgerMenu() {
// Burger menu should exist on all pages.
const burger = assertNotNull($<HTMLElement>('#burger'));
const toggle = assertNotNull($<HTMLElement>('#js-burger-toggle'));
const content = assertNotNull($<HTMLElement>('#container'));
const body = document.body;
const root = document.documentElement;
copyArtistLinksTo(burger);
toggle.addEventListener('click', event => {
event.stopPropagation();
event.preventDefault();
if (content.classList.contains('open')) {
close(burger, content, body, root);
}
else {
open(burger, content, body, root);
}
});
content.addEventListener('click', () => {
if (content.classList.contains('open')) {
close(burger, content, body, root);
}
});
}