/* ─── Dynamic Navigation with Dropdown Submenus ─── */ /* Fetches nav items from /api/navigation and renders dropdowns */ (function() { 'use strict'; async function loadNavigation() { const navMenu = document.getElementById('navMenu'); if (!navMenu) return; try { const res = await fetch('/api/navigation'); if (!res.ok) throw new Error('Nav API ' + res.status); const items = await res.json(); // Sort by order items.sort((a, b) => (a.order || 0) - (b.order || 0)); // Determine current page for active state const path = window.location.pathname; const search = window.location.search; const fullPath = path + search; // Build nav HTML let html = ''; items.forEach(item => { const url = item.url || '/'; const label = (item.label || '').toUpperCase(); const children = item.children || []; const hasChildren = children.length > 0; // Determine if this link is active let isActive = false; if (url === '/' && (path === '/' || path === '/index.html')) { isActive = true; } else if (url !== '/' && path.startsWith(url.split('?')[0])) { isActive = true; } const activeClass = isActive ? ' active' : ''; const hasDropdownClass = hasChildren ? ' has-dropdown' : ''; // Check if it's an anchor link (homepage sections) const isAnchor = url.startsWith('#') || url.startsWith('/#'); const href = isAnchor && path !== '/' ? '/' + url.replace(/^\//, '') : url; html += `\n`; }); navMenu.innerHTML = html; // Bind mobile dropdown toggles after rendering initMobileDropdowns(); } catch (err) { console.warn('Nav load failed, keeping existing:', err); } } // Mobile: tap parent to toggle dropdown function initMobileDropdowns() { const isMobile = () => window.innerWidth <= 768; document.querySelectorAll('.nav-item.has-dropdown > .nav-link').forEach(link => { link.addEventListener('click', function(e) { if (!isMobile()) return; // desktop uses hover const parent = this.parentElement; const dropdown = parent.querySelector('.dropdown'); if (!dropdown) return; // If dropdown is closed, prevent navigation and open it if (!parent.classList.contains('dropdown-open')) { e.preventDefault(); // Close all other dropdowns document.querySelectorAll('.nav-item.dropdown-open').forEach(item => { if (item !== parent) item.classList.remove('dropdown-open'); }); parent.classList.add('dropdown-open'); } else { // Dropdown already open — allow navigation or close // If tapped again on same parent link, close dropdown e.preventDefault(); parent.classList.remove('dropdown-open'); } }); }); // Close dropdowns when tapping outside document.addEventListener('click', function(e) { if (!isMobile()) return; if (!e.target.closest('.nav-item.has-dropdown')) { document.querySelectorAll('.nav-item.dropdown-open').forEach(item => { item.classList.remove('dropdown-open'); }); } }); } // Nav toggle (hamburger menu) function initNavToggle() { const toggle = document.getElementById('navToggle'); const menu = document.getElementById('navMenu'); if (toggle && menu) { toggle.addEventListener('click', () => { menu.classList.toggle('open'); toggle.classList.toggle('active'); // Close any open dropdowns when closing menu if (!menu.classList.contains('open')) { document.querySelectorAll('.nav-item.dropdown-open').forEach(item => { item.classList.remove('dropdown-open'); }); } }); } } // Run on DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { loadNavigation(); initNavToggle(); }); } else { loadNavigation(); initNavToggle(); } })();