1document.addEventListener("DOMContentLoaded", () => { 2 // ==================== DESKTOP MENU FUNCTIONALITY ==================== 3 const dropdownItems = document.querySelectorAll(".ng-has-dropdown") 4 5 dropdownItems.forEach((item) => { 6 const dropdownMenu = item.querySelector(".ng-dropdown-menu") 7 if (!dropdownMenu) return 8 9 let hoverTimeout 10 11 item.addEventListener("mouseenter", () => { 12 clearTimeout(hoverTimeout) 13 14 // Hide all other dropdown menus 15 dropdownItems.forEach((otherItem) => { 16 if (otherItem !== item) { 17 const otherMenu = otherItem.querySelector(".ng-dropdown-menu") 18 if (otherMenu) { 19 otherMenu.style.opacity = "0" 20 otherMenu.style.visibility = "hidden" 21 otherMenu.style.transform = "translateY(-10px)" 22 } 23 } 24 }) 25 26 // Show the current menu 27 dropdownMenu.style.opacity = "1" 28 dropdownMenu.style.visibility = "visible" 29 dropdownMenu.style.transform = "translateY(0)" 30 }) 31 32 item.addEventListener("mouseleave", () => { 33 hoverTimeout = setTimeout(() => { 34 dropdownMenu.style.opacity = "0" 35 dropdownMenu.style.visibility = "hidden" 36 dropdownMenu.style.transform = "translateY(-10px)" 37 }, 100) 38 }) 39 40 dropdownMenu.addEventListener("mouseenter", () => { 41 clearTimeout(hoverTimeout) 42 }) 43 44 dropdownMenu.addEventListener("mouseleave", () => { 45 dropdownMenu.style.opacity = "0" 46 dropdownMenu.style.visibility = "hidden" 47 dropdownMenu.style.transform = "translateY(-10px)" 48 }) 49 }) 50 51 // ==================== ACCESSIBILITY IMPROVEMENTS ==================== 52 const menuLinks = document.querySelectorAll(".ng-menu-link") 53 54 menuLinks.forEach((link) => { 55 link.addEventListener("focus", () => { 56 const parentItem = link.closest(".ng-has-dropdown") 57 if (parentItem) { 58 const dropdownMenu = parentItem.querySelector(".ng-dropdown-menu") 59 if (dropdownMenu) { 60 dropdownMenu.style.opacity = "1" 61 dropdownMenu.style.visibility = "visible" 62 dropdownMenu.style.transform = "translateY(0)" 63 } 64 } 65 }) 66 67 link.addEventListener("blur", (event) => { 68 const parentItem = link.closest(".ng-has-dropdown") 69 if (parentItem) { 70 setTimeout(() => { 71 const focusedElement = document.activeElement 72 const isInsideDropdown = parentItem.contains(focusedElement) 73 74 if (!isInsideDropdown) { 75 const dropdownMenu = parentItem.querySelector(".ng-dropdown-menu") 76 if (dropdownMenu) { 77 dropdownMenu.style.opacity = "0" 78 dropdownMenu.style.visibility = "hidden" 79 dropdownMenu.style.transform = "translateY(-10px)" 80 } 81 } 82 }, 100) 83 } 84 }) 85 }) 86 87 // ==================== MOBILE MENU FUNCTIONALITY ==================== 88 const mobileToggle = document.querySelector(".ng-mobile-menu-toggle") 89 const mobileOverlay = document.querySelector(".ng-mobile-menu-overlay") 90 const htmlElement = document.documentElement 91 const bodyElement = document.body 92 93 // Function for getting scrollbar width 94 function getScrollbarWidth() { 95 const scrollDiv = document.createElement("div") 96 scrollDiv.style.cssText = "width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px;" 97 document.body.appendChild(scrollDiv) 98 const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 99 document.body.removeChild(scrollDiv) 100 return scrollbarWidth 101 } 102 103 if (mobileToggle && mobileOverlay) { 104 mobileToggle.addEventListener("click", function (e) { 105 e.preventDefault() 106 e.stopPropagation() 107 108 const isOpening = !this.classList.contains("active") 109 110 if (isOpening) { 111 const scrollbarWidth = getScrollbarWidth() 112 document.documentElement.style.setProperty("--scrollbar-width", scrollbarWidth + "px") 113 } 114 115 this.classList.toggle("active") 116 mobileOverlay.classList.toggle("active") 117 htmlElement.classList.toggle("ng-menu-open") 118 bodyElement.classList.toggle("ng-menu-open") 119 120 if (!isOpening) { 121 document.documentElement.style.removeProperty("--scrollbar-width") 122 } 123 }) 124 125 // Close menu on overlay click (but not on menu content) 126 mobileOverlay.addEventListener("click", (e) => { 127 if (e.target === mobileOverlay) { 128 closeMobileMenu() 129 } 130 }) 131 132 // Close menu on Escape key 133 document.addEventListener("keydown", (e) => { 134 if (e.key === "Escape" && mobileOverlay.classList.contains("active")) { 135 closeMobileMenu() 136 } 137 }) 138 139 function closeMobileMenu() { 140 mobileToggle.classList.remove("active") 141 mobileOverlay.classList.remove("active") 142 htmlElement.classList.remove("ng-menu-open") 143 bodyElement.classList.remove("ng-menu-open") 144 document.documentElement.style.removeProperty("--scrollbar-width") 145 146 // Close all open submenus 147 const activeItems = document.querySelectorAll(".ng-mobile-menu-item.active")
148 activeItems.forEach((item) => { 149 item.classList.remove("active") 150 }) 151 } 152 } 153 154 // Mobile submenu functionality 155 const mobileMenuItems = document.querySelectorAll(".ng-mobile-menu-item.ng-has-dropdown") 156 157 mobileMenuItems.forEach((menuItem) => { 158 const menuLink = menuItem.querySelector(".ng-mobile-menu-link") 159 const arrow = menuItem.querySelector(".ng-mobile-dropdown-arrow") 160 const submenu = menuItem.querySelector(".ng-mobile-submenu") 161 162 if (submenu && arrow) { 163 // Create wrapper for better click handling 164 const wrapper = document.createElement("div") 165 wrapper.className = "ng-mobile-menu-item-wrapper" 166 167 // Move link and arrow into wrapper 168 menuItem.insertBefore(wrapper, submenu) 169 wrapper.appendChild(menuLink) 170 wrapper.appendChild(arrow) 171 172 // Handle clicks on the wrapper (entire top area) 173 wrapper.addEventListener("click", (e) => { 174 e.preventDefault() 175 e.stopPropagation() 176 177 // Close other open submenus 178 mobileMenuItems.forEach((otherItem) => { 179 if (otherItem !== menuItem && otherItem.classList.contains("active")) { 180 otherItem.classList.remove("active") 181 } 182 }) 183 184 // Toggle current submenu 185 menuItem.classList.toggle("active") 186 }) 187 188 // Prevent link navigation for items with submenus 189 if (menuLink) { 190 menuLink.addEventListener("click", (e) => { 191 e.preventDefault() 192 }) 193 } 194 } 195 }) 196 197 console.log("Mobile menu initialized successfully") 198 console.log("Found mobile menu items with dropdowns:", mobileMenuItems.length) 199})
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.