/** * Navigation Menu Block JavaScript * 导航菜单区块交互功能 */ (function($) { 'use strict'; // 导航菜单类 class NavigationMenu { constructor(element) { this.element = element; this.menuList = element.querySelector('.navigation-menu-list'); this.dropdownItems = element.querySelectorAll('.has-dropdown'); this.isMobile = window.innerWidth <= 768; this.init(); } init() { this.setupDropdowns(); this.setupKeyboardNavigation(); this.setupMobileHandling(); this.setupResizeHandler(); this.setupClickOutside(); } // 设置下拉菜单功能 setupDropdowns() { this.dropdownItems.forEach(item => { const link = item.querySelector('a'); const submenu = item.querySelector('.sub-menu'); if (!submenu) return; // 鼠标悬停事件 item.addEventListener('mouseenter', () => { if (!this.isMobile) { this.showSubmenu(submenu); } }); item.addEventListener('mouseleave', () => { if (!this.isMobile) { this.hideSubmenu(submenu); } }); // 点击事件(移动端) link.addEventListener('click', (e) => { if (this.isMobile) { e.preventDefault(); this.toggleSubmenu(submenu); } }); // 添加ARIA属性 link.setAttribute('aria-haspopup', 'true'); link.setAttribute('aria-expanded', 'false'); submenu.setAttribute('aria-hidden', 'true'); }); } // 显示子菜单 showSubmenu(submenu) { submenu.style.opacity = '1'; submenu.style.visibility = 'visible'; submenu.style.transform = 'translateY(0)'; submenu.setAttribute('aria-hidden', 'false'); const parentLink = submenu.parentElement.querySelector('a'); if (parentLink) { parentLink.setAttribute('aria-expanded', 'true'); } } // 隐藏子菜单 hideSubmenu(submenu) { submenu.style.opacity = '0'; submenu.style.visibility = 'hidden'; submenu.style.transform = 'translateY(-10px)'; submenu.setAttribute('aria-hidden', 'true'); const parentLink = submenu.parentElement.querySelector('a'); if (parentLink) { parentLink.setAttribute('aria-expanded', 'false'); } } // 切换子菜单显示状态 toggleSubmenu(submenu) { const isVisible = submenu.style.opacity === '1' || submenu.getAttribute('aria-hidden') === 'false'; if (isVisible) { this.hideSubmenu(submenu); } else { // 先隐藏其他打开的子菜单 this.hideAllSubmenus(); this.showSubmenu(submenu); } } // 隐藏所有子菜单 hideAllSubmenus() { const allSubmenus = this.element.querySelectorAll('.sub-menu'); allSubmenus.forEach(submenu => { this.hideSubmenu(submenu); }); } // 设置键盘导航 setupKeyboardNavigation() { const menuLinks = this.element.querySelectorAll('a'); menuLinks.forEach((link, index) => { link.addEventListener('keydown', (e) => { switch(e.key) { case 'ArrowDown': e.preventDefault(); this.focusNextItem(menuLinks, index); break; case 'ArrowUp': e.preventDefault(); this.focusPrevItem(menuLinks, index); break; case 'ArrowRight': e.preventDefault(); this.openSubmenuOnFocus(link); break; case 'ArrowLeft': e.preventDefault(); this.closeSubmenuOnFocus(link); break; case 'Escape': e.preventDefault(); this.hideAllSubmenus(); link.blur(); break; case 'Enter': case ' ': if (link.getAttribute('aria-haspopup') === 'true') { e.preventDefault(); const submenu = link.parentElement.querySelector('.sub-menu'); if (submenu) { this.toggleSubmenu(submenu); } } break; } }); }); } // 焦点移动到下一个项目 focusNextItem(items, currentIndex) { const nextIndex = (currentIndex + 1) % items.length; items[nextIndex].focus(); } // 焦点移动到上一个项目 focusPrevItem(items, currentIndex) { const prevIndex = currentIndex === 0 ? items.length - 1 : currentIndex - 1; items[prevIndex].focus(); } // 在焦点时打开子菜单 openSubmenuOnFocus(link) { const submenu = link.parentElement.querySelector('.sub-menu'); if (submenu) { this.showSubmenu(submenu); const firstSubmenuLink = submenu.querySelector('a'); if (firstSubmenuLink) { firstSubmenuLink.focus(); } } } // 在焦点时关闭子菜单 closeSubmenuOnFocus(link) { const parentItem = link.closest('.sub-menu'); if (parentItem) { const parentLink = parentItem.parentElement.querySelector('a'); if (parentLink) { this.hideSubmenu(parentItem); parentLink.focus(); } } } // 设置移动端处理 setupMobileHandling() { // 移动端特殊处理逻辑 if (this.isMobile) { this.element.classList.add('mobile-menu'); // 为移动端添加展开/收起按钮 this.dropdownItems.forEach(item => { const link = item.querySelector('a'); const arrow = link.querySelector('.dropdown-arrow'); if (arrow) { arrow.addEventListener('click', (e) => { e.stopPropagation(); e.preventDefault(); const submenu = item.querySelector('.sub-menu'); if (submenu) { this.toggleSubmenu(submenu); } }); } }); } } // 设置窗口大小改变处理 setupResizeHandler() { let resizeTimer; window.addEventListener('resize', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { const wasMobile = this.isMobile; this.isMobile = window.innerWidth <= 768; if (wasMobile !== this.isMobile) { this.hideAllSubmenus(); if (this.isMobile) { this.element.classList.add('mobile-menu'); } else { this.element.classList.remove('mobile-menu'); } } }, 250); }); } // 设置点击外部关闭菜单 setupClickOutside() { document.addEventListener('click', (e) => { if (!this.element.contains(e.target)) { this.hideAllSubmenus(); } }); } // 销毁实例 destroy() { // 移除事件监听器 this.dropdownItems.forEach(item => { const link = item.querySelector('a'); const submenu = item.querySelector('.sub-menu'); if (link && submenu) { // 这里应该移除所有添加的事件监听器 // 为了简化,我们只是重置状态 this.hideSubmenu(submenu); } }); } } // 初始化所有导航菜单 function initNavigationMenus() { const menuElements = document.querySelectorAll('.navigation-menu-block'); const menuInstances = []; menuElements.forEach(element => { const instance = new NavigationMenu(element); menuInstances.push(instance); }); return menuInstances; } // DOM加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initNavigationMenus); } else { initNavigationMenus(); } // 为jQuery用户提供接口 if ($ && typeof $.fn !== 'undefined') { $.fn.navigationMenu = function() { return this.each(function() { if (!$(this).data('navigation-menu')) { const instance = new NavigationMenu(this); $(this).data('navigation-menu', instance); } }); }; } // 全局暴露NavigationMenu类 window.NavigationMenu = NavigationMenu; })(typeof jQuery !== 'undefined' ? jQuery : undefined);