1(function (Drupal) { 2 'use strict'; 3 4 Drupal.behaviors.mainMenuHover = { 5 attach(context) { 6 const containers = context.querySelectorAll( 7 '.header__secondary-menu-inner:not(.secondary-menu-initialized)' 8 ); 9 10 containers.forEach((container) => { 11 container.classList.add('secondary-menu-initialized'); 12 13 const menuItems = container.querySelectorAll( 14 '.menu-left .menu-item' 15 ); 16 17 const desktopSubmenus = container.querySelectorAll( 18 '.menu-right > .submenu' 19 ); 20 21 const desktopSubmenuItems = container.querySelectorAll( 22 '.menu-right .submenu-item' 23 ); 24 25 const thirdLevelMenus = container.querySelectorAll( 26 '.menu-third .third-level-menu' 27 ); 28 29 const isDesktop = () => window.innerWidth >= 1024; 30 31 const closeThirdLevelMenus = () => { 32 thirdLevelMenus.forEach((menu) => { 33 menu.classList.remove('is-active'); 34 }); 35 36 desktopSubmenuItems.forEach((item) => { 37 item.classList.remove('is-active'); 38 }); 39 }; 40 41 const closeDesktopMenus = () => { 42 desktopSubmenus.forEach((submenu) => { 43 submenu.classList.remove('is-active'); 44 }); 45 46 menuItems.forEach((item) => { 47 item.classList.remove('is-active'); 48 }); 49 50 closeThirdLevelMenus(); 51 }; 52 53 /* 54 * First-level menu hover. 55 */ 56 menuItems.forEach((menuItem) => { 57 menuItem.addEventListener('mouseenter', () => { 58 if (!isDesktop()) { 59 return; 60 } 61 62 const parentIndex = menuItem.dataset.index; 63 64 closeDesktopMenus(); 65 66 const targetSubmenu = container.querySelector( 67 `.menu-right > .submenu[data-submenu-index="${parentIndex}"]` 68 ); 69 70 if (targetSubmenu) { 71 targetSubmenu.classList.add('is-active'); 72 } 73 74 menuItem.classList.add('is-active'); 75 }); 76 }); 77 78 /* 79 * Second-level menu hover. 80 */ 81 desktopSubmenuItems.forEach((submenuItem) => { 82 submenuItem.addEventListener('mouseenter', () => { 83 if (!isDesktop()) { 84 return; 85 } 86 87 const parentIndex = submenuItem.dataset.parentIndex; 88 const thirdLevelIndex = 89 submenuItem.dataset.thirdLevelIndex; 90 91 closeThirdLevelMenus(); 92 93 submenuItem.classList.add('is-active'); 94 95 const targetThirdLevelMenu = container.querySelector( 96 `.menu-third .third-level-menu` + 97 `[data-parent-index="${parentIndex}"]` + 98 `[data-third-level-index="${thirdLevelIndex}"]` 99 ); 100 101 if (targetThirdLevelMenu) { 102 targetThirdLevelMenu.classList.add('is-active'); 103 } 104 }); 105 }); 106 107 /* 108 * Keep the selected second-level item active while the mouse 109 * is over its corresponding third-level column. 110 */ 111 thirdLevelMenus.forEach((thirdLevelMenu) => { 112 thirdLevelMenu.addEventListener('mouseenter', () => { 113 if (!isDesktop()) { 114 return; 115 } 116 117 const parentIndex = thirdLevelMenu.dataset.parentIndex; 118 const thirdLevelIndex = 119 thirdLevelMenu.dataset.thirdLevelIndex; 120 121 closeThirdLevelMenus(); 122 123 thirdLevelMenu.classList.add('is-active'); 124 125 const matchingSubmenuItem = container.querySelector( 126 `.menu-right .submenu-item` + 127 `[data-parent-index="${parentIndex}"]` + 128 `[data-third-level-index="${thirdLevelIndex}"]` 129 ); 130 131 if (matchingSubmenuItem) { 132 matchingSubmenuItem.classList.add('is-active'); 133 } 134 }); 135 }); 136 137 container.addEventListener('mouseleave', () => { 138 if (isDesktop()) { 139 closeDesktopMenus(); 140 } 141 }); 142 /* 143 * Mobile menu. 144 */
145 menuItems.forEach((menuItem) => { 146 const firstLevelToggle = menuItem.querySelector( 147 ':scope > .menu-item-text' 148 ); 149 150 const mobileSubmenu = menuItem.querySelector( 151 ':scope > .submenu' 152 ); 153 154 if (!firstLevelToggle || !mobileSubmenu) { 155 return; 156 } 157 158 /* 159 * First-level item opens the second-level menu. 160 */ 161 firstLevelToggle.addEventListener('click', (event) => { 162 if (isDesktop()) { 163 return; 164 } 165 166 event.preventDefault(); 167 168 const willOpen = !menuItem.classList.contains('is-active'); 169 170 /* 171 * Close other first-level menus. 172 */ 173 menuItems.forEach((otherMenuItem) => { 174 if (otherMenuItem === menuItem) { 175 return; 176 } 177 178 otherMenuItem.classList.remove('is-active'); 179 180 const otherSubmenu = otherMenuItem.querySelector( 181 ':scope > .submenu' 182 ); 183 184 otherSubmenu?.classList.remove('is-active'); 185 186 /* 187 * Close third-level menus belonging to the other item. 188 */ 189 otherMenuItem 190 .querySelectorAll('.submenu-item.is-active') 191 .forEach((submenuItem) => { 192 submenuItem.classList.remove('is-active'); 193 }); 194 195 otherMenuItem 196 .querySelectorAll('.third-level-menu.is-active') 197 .forEach((thirdLevelMenu) => { 198 thirdLevelMenu.classList.remove('is-active'); 199 }); 200 }); 201 202 menuItem.classList.toggle('is-active', willOpen); 203 mobileSubmenu.classList.toggle('is-active', willOpen); 204 205 /* 206 * Close third-level menus when the first-level item closes. 207 */ 208 if (!willOpen) { 209 mobileSubmenu 210 .querySelectorAll('.submenu-item.is-active') 211 .forEach((submenuItem) => { 212 submenuItem.classList.remove('is-active'); 213 }); 214 215 mobileSubmenu 216 .querySelectorAll('.third-level-menu.is-active') 217 .forEach((thirdLevelMenu) => { 218 thirdLevelMenu.classList.remove('is-active'); 219 }); 220 } 221 }); 222 223 /* 224 * Second-level items that have a third-level menu. 225 */ 226 const mobileSubmenuItems = mobileSubmenu.querySelectorAll( 227 ':scope > .submenu-item.has-third-level' 228 ); 229 230 mobileSubmenuItems.forEach((submenuItem) => { 231 const secondLevelToggle = submenuItem.querySelector( 232 ':scope > .submenu-item-text' 233 ); 234 235 const thirdLevelMenu = submenuItem.querySelector( 236 ':scope > .third-level-menu' 237 ); 238 239 if (!secondLevelToggle || !thirdLevelMenu) { 240 return; 241 } 242 243 secondLevelToggle.addEventListener('click', (event) => { 244 if (isDesktop()) { 245 return; 246 } 247 248 event.preventDefault(); 249 event.stopPropagation(); 250 251 const willOpen = !submenuItem.classList.contains('is-active'); 252 253 /* 254 * Close other third-level menus under the same second-level menu. 255 */ 256 mobileSubmenuItems.forEach((otherSubmenuItem) => { 257 if (otherSubmenuItem === submenuItem) { 258 return; 259 } 260 261 otherSubmenuItem.classList.remove('is-active'); 262 263 const otherThirdLevelMenu = 264 otherSubmenuItem.querySelector( 265 ':scope > .third-level-menu' 266 ); 267 268 otherThirdLevelMenu?.classList.remove('is-active'); 269 }); 270 271 submenuItem.classList.toggle('is-active', willOpen); 272 thirdLevelMenu.classList.toggle('is-active', willOpen); 273 }); 274 }); 275 }); 276 }); 277 }, 278 }; 279})(Drupal);
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.