100 lines
3.6 KiB
JavaScript
100 lines
3.6 KiB
JavaScript
import navigationHtml from "./navigation.html?raw";
|
|
|
|
/**
|
|
* Bindet das mit Vite gebündelte Navbar-Fragment (navigation.html) ein und
|
|
* ersetzt damit den Platzhalter im Header der jeweiligen Seite.
|
|
* Aufruf z. B. in main.js: initNavbar('#navbar-placeholder')
|
|
*/
|
|
export function initNavbar(placeholderSelector = "#navbar-placeholder") {
|
|
const placeholder = document.querySelector(placeholderSelector);
|
|
if (!placeholder) {
|
|
console.warn("Navbar-Platzhalter nicht gefunden:", placeholderSelector);
|
|
return;
|
|
}
|
|
|
|
placeholder.outerHTML = navigationHtml; // Platzhalter durch echtes Navbar-Markup ersetzen
|
|
setupBehavior();
|
|
markCurrentPage();
|
|
}
|
|
|
|
/**
|
|
* Richtet alle interaktiven Funktionen der Navbar ein:
|
|
* - Mobiles Menü öffnen/schließen per Klick
|
|
* - Automatischer Fokus auf ersten Link, wenn per Tastatur geöffnet
|
|
* - Escape schließt das Menü und gibt den Fokus zurück
|
|
* - Menü schließt sich, wenn der Fokus die Navbar per Tab verlässt
|
|
* - Klick außerhalb der Navbar schließt das Menü (Maus/Touch)
|
|
*/
|
|
export function setupBehavior() {
|
|
const navbar = document.querySelector(".navbar");
|
|
const toggle = document.querySelector(".navbar__toggle");
|
|
const nav = document.querySelector(".navbar__nav");
|
|
const menu = document.querySelector(".navbar__menu");
|
|
if (!navbar || !toggle || !nav || !menu) return;
|
|
|
|
let openedViaKeyboard = false;
|
|
|
|
toggle.addEventListener("keydown", (e) => {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
openedViaKeyboard = true;
|
|
}
|
|
});
|
|
|
|
toggle.addEventListener("click", () => {
|
|
const isOpen = nav.classList.toggle("is-open");
|
|
toggle.setAttribute("aria-expanded", String(isOpen));
|
|
toggle.setAttribute(
|
|
"aria-label",
|
|
isOpen ? "Menü schließen" : "Menü öffnen",
|
|
);
|
|
|
|
if (isOpen && openedViaKeyboard) {
|
|
const firstLink = menu.querySelector(".navbar__link");
|
|
if (firstLink) firstLink.focus();
|
|
}
|
|
openedViaKeyboard = false;
|
|
});
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
if (e.key === "Escape" && nav.classList.contains("is-open")) {
|
|
nav.classList.remove("is-open");
|
|
toggle.setAttribute("aria-expanded", "false");
|
|
toggle.setAttribute("aria-label", "Menü öffnen");
|
|
toggle.focus();
|
|
}
|
|
});
|
|
|
|
navbar.addEventListener("focusout", (e) => {
|
|
const leavingNavbar = !navbar.contains(e.relatedTarget);
|
|
if (leavingNavbar && nav.classList.contains("is-open")) {
|
|
nav.classList.remove("is-open");
|
|
toggle.setAttribute("aria-expanded", "false");
|
|
toggle.setAttribute("aria-label", "Menü öffnen");
|
|
}
|
|
});
|
|
|
|
document.addEventListener("click", (e) => {
|
|
if (!navbar.contains(e.target) && nav.classList.contains("is-open")) {
|
|
nav.classList.remove("is-open");
|
|
toggle.setAttribute("aria-expanded", "false");
|
|
toggle.setAttribute("aria-label", "Menü öffnen");
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Markiert den Menüpunkt der aktuell geöffneten Seite mit aria-current="page",
|
|
* damit er optisch hervorgehoben wird (siehe .navbar__link[aria-current="page"] in der CSS).
|
|
*/
|
|
export function markCurrentPage() {
|
|
const links = document.querySelectorAll(".navbar__link");
|
|
const current = window.location.pathname.replace(/\/index\.html$/, "/");
|
|
links.forEach((link) => {
|
|
if (link.getAttribute("href") === current) {
|
|
link.setAttribute("aria-current", "page");
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => initNavbar());
|