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());