1 2 3// ============================================================================ 4// Global Variables 5// ============================================================================ 6 7// Debug Configuration 8const DEBUG_MENU = false; // Set to false to disable all menu.js console logs 9 10// Helper function for conditional logging 11function debugLog(...args) { 12 if (DEBUG_MENU) { 13 console.log(...args); 14 } 15 16} 17 18// DOM Elements (initialized on DOMContentLoaded) 19let topBrandMenu, stickyBrandMenu, menuToggle, searchToggle; 20let mastHead, hlogo, mainMenu, siteMenu, header, searchFields, headerSiteLogo; 21 22// State Variables 23let registerPage = false; 24let wasMobileView = false; 25let MobileView = window.innerWidth < 768; 26let moreMenuInitialized = false; 27 28// More Menu State Variables (Global for external access) 29let isAdjusting = false; 30let topNav = null; 31let moreDropdown = null; 32let moreSubNav = null; 33let moreSubNavUl = null; 34let headerMenu = null; 35 36// Constants 37const MOBILE_BREAKPOINT = 768; 38const RESIZE_DEBOUNCE_TIME = 200; 39const MORE_MENU_ADJUST_DELAY = 150; 40const MOBILE_ARROW_WIDTH = 25; 41 42// ============================================================================ 43// Utility Functions 44// ============================================================================ 45 46function isMobileView() { 47 return window.innerWidth < MOBILE_BREAKPOINT; 48} 49 50function desktopView() { 51 return window.innerWidth > MOBILE_BREAKPOINT; 52} 53 54function debounce(func, wait) { 55 let timeout; 56 return function () { 57 clearTimeout(timeout); 58 timeout = setTimeout(func, wait); 59 }; 60} 61 62 63 64 65// ============================================================================ 66// Scroll & Sticky Navigation Functions 67// ============================================================================ 68function handleScroll() { 69 if (!mastHead.classList.contains("header--alist") && !registerPage) { 70 // Get mastHead height once 71 const mastHeadHeight = mastHead.offsetHeight; 72 if (!isMobileView()) { 73 // Always set padding to maintain layout 74 75 if (window.scrollY > 30) { 76 document.body.style.paddingTop = `${mastHeadHeight}px`; 77 if (stickyBrandMenu) { 78 stickyBrandMenu.style.display = "block"; 79 } 80 if (topBrandMenu) { 81 topBrandMenu.style.opacity = "0"; 82 topBrandMenu.classList.add("addClass"); 83 } 84 85 //topBrandLogo.style.width = "200px"; 86 header.classList.add("stickyHeader"); 87 if (siteMenu) { 88 siteMenu.style.display = "none"; 89 } 90 } else { 91 document.body.style.paddingTop = "0"; 92 if (stickyBrandMenu) { 93 stickyBrandMenu.style.display = "none"; 94 } 95 if (topBrandMenu) { 96 topBrandMenu.style.opacity = "1"; 97 topBrandMenu.classList.remove("addClass"); 98 } 99 100 //topBrandLogo.style.width = "300px"; 101 header.classList.remove("stickyHeader"); 102 if (siteMenu) { 103 siteMenu.style.display = "block"; 104 } 105 } 106 } 107 else { 108 // Reset padding in mobile view 109 110 if (topBrandMenu) { 111 topBrandMenu.style.opacity = "1"; 112 topBrandMenu.classList.remove("addClass"); 113 } 114 115 //topBrandLogo.style.width = "200px"; 116 header.classList.remove("stickyHeader"); 117 if (siteMenu) { 118 siteMenu.style.display = "none"; 119 } 120 } 121 } 122} 123 124// ============================================================================ 125// Menu Visibility Functions 126// ============================================================================ 127 128function positionHeaderWrapper() { 129 debugLog('positionHeaderWrapper called'); 130 131 const headerWrapper = document.querySelector('.header__wrapper'); 132 const mobileNav = document.querySelector('.header__mobileNav'); 133 134 if (!headerWrapper || !mobileNav) { 135 debugLog('positionHeaderWrapper: elements not found', { 136 'headerWrapper': !!headerWrapper, 137 'mobileNav': !!mobileNav 138 }); 139 return; 140 } 141 142 if (isMobileView()) { 143 const mobileNavHeight = mobileNav.offsetHeight; 144 const topBannerEl = document.querySelector('.commercialSlot--fixed, .commercialSlot[data-mobile-behaviour="fixed"]'); 145 const topBannerOffset = topBannerEl?.offsetHeight || 0; 146 const pageContent = document.querySelector('.page-main-content-tracked'); 147 if (topBannerOffset > 0) { 148 mobileNav.style.top = `${topBannerOffset}px`; 149 if (pageContent) { 150 pageContent.style.top = `${topBannerOffset + mobileNavHeight}px`; 151 } 152 } 153 headerWrapper.style.top = `${mobileNavHeight}px`; 154 debugLog('positionHeaderWrapper: set top position', { mobileNavHeight }); 155 } else { 156 headerWrapper.style.top = ''; 157 debugLog('positionHeaderWrapper: cleared top position (desktop)'); 158 } 159} 160 161function toggleMenuVisibility() { 162 debugLog('toggleMenuVisibility called', { 163 'isMobile': isMobileView(), 164 'menuItems count': document.querySelectorAll(".hideOnMobile").length 165 }); 166 167 const menuItems = document.querySelectorAll(".hideOnMobile"); 168 const isMobile = isMobileView(); 169
170 menuItems.forEach(item => { 171 item.classList.toggle("hiddenItem", isMobile); 172 }); 173} 174 175// ============================================================================ 176// Brand Menu Navigation 177// ============================================================================ 178 179function highlightCurrentNavItem(menuContainer, fullDomain) { 180 debugLog('highlightCurrentNavItem called', { 181 'menuContainer': !!menuContainer, 182 'fullDomain': fullDomain 183 }); 184 185 if (!menuContainer) { 186 debugLog('highlightCurrentNavItem: menuContainer is null - exiting'); 187 return; 188 } 189 190 const links = menuContainer.querySelectorAll('.brandSwitchingBar__inner ul li a'); 191 debugLog('highlightCurrentNavItem: found', links.length, 'links'); 192 193 links.forEach(link => { 194 const li = link.closest('li'); 195 const linkHref = new URL(link.getAttribute('href'), window.location.origin).href; 196 const normalizedLink = linkHref.replace(/^https?:\/\//, '').replace(/\/$/, ''); 197 const normalizedFull = fullDomain.replace(/^https?:\/\//, '').replace(/\/$/, ''); 198 199 if (normalizedLink === normalizedFull) { 200 li.classList.add('currentNavItem'); 201 } 202 }); 203} 204 205// ============================================================================ 206// More Menu (Desktop Overflow Menu) 207// ============================================================================ 208 209// More Menu Helper Functions (Global Scope) 210function unlockMenu() { 211 debugLog('unlockMenu called'); 212 if (headerMenu) headerMenu.style.pointerEvents = 'auto'; 213} 214 215function getNavItems() { 216 if (!topNav) { 217 debugLog('getNavItems: topNav is null'); 218 return []; 219 } 220 debugLog('getNavItems called'); 221 // Get fresh list of navigation items, excluding More menu and site menu items 222 return Array.from( 223 topNav.querySelectorAll('.primaryLink:not(.moreSubNavigation):not(.header__siteMenu)') 224 ); 225} 226 227function clearMoreMenu() { 228 if (!moreSubNavUl) { 229 debugLog('clearMoreMenu: moreSubNavUl is null'); 230 return; 231 } 232 debugLog('clearMoreMenu called'); 233 // Clear the More dropdown 234 while (moreSubNavUl.firstChild) { 235 moreSubNavUl.removeChild(moreSubNavUl.firstChild); 236 } 237 238 // Reset all nav items display
239 getNavItems().forEach(item => { 240 item.style.display = ''; 241 item.classList.remove('moved-to-more'); 242 const subNav = item.querySelector('.subNav'); 243 if (subNav) subNav.style.display = ''; 244 }); 245} 246 247function setupHoverProtection(items) { 248 items.forEach(item => { 249 const link = item.querySelector('a'); 250 if (!link) return; 251 252 link.onmouseenter = e => { 253 if (isAdjusting) { 254 e.preventDefault(); 255 e.stopPropagation(); 256 } 257 }; 258 }); 259} 260 261function adjustNavItems() { 262 debugLog('adjustNavItems called', { 263 'isDesktop': desktopView(), 264 'isAdjusting': isAdjusting, 265 'topNav exists': !!topNav, 266 'moreDropdown exists': !!moreDropdown 267 }); 268 269 if (!desktopView() || isAdjusting || !topNav || !moreDropdown) { 270 debugLog('adjustNavItems: skipping - conditions not met'); 271 return; 272 } 273 274 isAdjusting = true; 275 clearMoreMenu(); 276 277 // Get fresh list of items each time 278 const navItems = getNavItems(); 279 280 // Force layout read 281 void topNav.offsetWidth; 282 283 // First pass: Check if all items fit WITHOUT More button 284 let totalWidth = 0; 285 const fullWidth = topNav.offsetWidth; 286 let allItemsFit = true; 287 288 for (const item of navItems) { 289 totalWidth += item.offsetWidth; 290 if (totalWidth > fullWidth) { 291 allItemsFit = false; 292 break; 293 } 294 } 295 296 // If everything fits without More button, we're done 297 if (allItemsFit) { 298 navItems.forEach(item => { 299 item.style.display = ''; 300 }); 301 moreDropdown.style.display = 'none'; 302 unlockMenu(); 303 setupHoverProtection(navItems); 304 isAdjusting = false; 305 return; 306 } 307 308 // Second pass: Items don't fit, so we need More button 309 // Get More button width (temporarily show it if hidden to measure) 310 const wasHidden = moreDropdown.style.display === 'none'; 311 if (wasHidden) { 312 moreDropdown.style.display = 'inline-block'; 313 } 314 const moreButtonWidth = moreDropdown.offsetWidth; 315 if (wasHidden) { 316 moreDropdown.style.display = 'none'; 317 } 318 319 totalWidth = 0; 320 let movedToMore = false; 321 const availableWidth = fullWidth - moreButtonWidth; 322 323 navItems.forEach(item => { 324 const itemWidth = item.offsetWidth; 325 326 if (movedToMore || totalWidth + itemWidth > availableWidth) { 327 item.style.display = 'none'; 328 item.classList.add('moved-to-more'); 329 330 const clonedItem = item.cloneNode(true); 331 clonedItem.style.display = ''; 332 clonedItem.classList.remove('active', 'open', 'moved-to-more'); 333 334 const subNav = clonedItem.querySelector('.subNav'); 335 if (subNav) subNav.style.display = 'none'; 336 337 moreSubNavUl.appendChild(clonedItem); 338 movedToMore = true; 339 } else { 340 totalWidth += itemWidth; 341 item.style.display = ''; 342 } 343 }); 344 345 moreDropdown.style.display = movedToMore ? 'inline-block' : 'none'; 346 347 unlockMenu(); 348 setupHoverProtection(navItems); 349 isAdjusting = false; 350} 351 352// Expose adjustNavItems to window for external script access 353window.adjustNavItems = adjustNavItems; 354 355function initMoreMenu(fullDomain) { 356 debugLog('initMoreMenu called', { 357 'fullDomain': fullDomain, 358 'isAlist': window.location.href.includes("alist"), 359 'registerPage': registerPage, 360 'isDesktop': desktopView(), 361 'moreMenuInitialized': moreMenuInitialized 362 }); 363 364 // Skip on alist or register pages 365 if (window.location.href.includes("alist") || registerPage) { 366 debugLog('initMoreMenu: skipping - alist page or register page'); 367 return; 368 } 369 370 // Skip if not desktop view 371 if (!desktopView()) { 372 debugLog('initMoreMenu: skipping - mobile view'); 373 return; 374 } 375 376 // Skip if already initialized (make idempotent) 377 if (moreMenuInitialized) { 378 debugLog('initMoreMenu: already initialized - skipping setup'); 379 return; 380 } 381 382 // Initialize global references 383 headerMenu = document.querySelector('.header__mainMenu'); 384 const nav = document.querySelector('.header__mainMenu #mainMenu'); 385 386 if (!headerMenu) { 387 debugLog('initMoreMenu: headerMenu not found'); 388 return; 389 } 390 391 if (!nav) { 392 debugLog('initMoreMenu: nav element not found'); 393 return; 394 } 395 396 topNav = nav.querySelector('.topNav'); 397 398 if (!topNav) { 399 debugLog('initMoreMenu: topNav not found'); 400 return; 401 } 402 403 // Create or find More dropdown 404 moreDropdown = topNav.querySelector('.moreSubNavigation'); 405 if (!moreDropdown) { 406 moreDropdown = document.createElement('li'); 407 moreDropdown.className = 'primaryLink dropdown moreSubNavigation'; 408 moreDropdown.innerHTML = ` 409 <a href="#" onclick="event.preventDefault()">More</a> 410 <nav class="moreSubNav"> 411 <ul></ul> 412 </nav> 413 `; 414 topNav.appendChild(moreDropdown); 415 } 416 417 moreSubNav = moreDropdown.querySelector('.moreSubNav'); 418 moreSubNavUl = moreDropdown.querySelector('ul'); 419 moreDropdown.style.display = 'none'; 420 421 // More dropdown click handler 422 moreDropdown.addEventListener('click', function (e) { 423 e.stopPropagation(); 424 if (isAdjusting) return; 425 426 this.classList.toggle('open'); 427 moreSubNav.style.display = this.classList.contains('open') ? 'block' : 'none'; 428 }); 429 430 // Close dropdown on outside click 431 document.addEventListener('click', function (e) { 432 if (!e.target.closest('.dropdown')) { 433 moreDropdown.classList.remove('open'); 434 moreSubNav.style.display = 'none'; 435 } 436 }); 437 438 // Handle resize 439 let resizeTimeout; 440 window.addEventListener('resize', () => { 441 clearTimeout(resizeTimeout); 442 resizeTimeout = setTimeout(adjustNavItems, MORE_MENU_ADJUST_DELAY); 443 }); 444 445 // Mark as initialized 446 moreMenuInitialized = true; 447 debugLog('initMoreMenu: setup complete, moreMenuInitialized set to true'); 448 449 // Initial adjustment 450 adjustNavItems(); 451} 452 453// ============================================================================ 454// Mobile Navigation 455// ============================================================================ 456 457function initializeMobileDropdowns() { 458 debugLog('initializeMobileDropdowns called', { 459 'dropdown links count': document.querySelectorAll('.primaryLink.dropdown > a').length 460 }); 461 462 document.querySelectorAll('.primaryLink.dropdown > a').forEach((link) => { 463 link.addEventListener('click', (e) => { 464 if (desktopView()) return; 465 466 const parentLi = link.closest('.primaryLink.dropdown'); 467 const subNav = parentLi.querySelector('.subNav ul'); 468 const rect = link.getBoundingClientRect(); 469 const clickedOnArrow = e.clientX > rect.right - MOBILE_ARROW_WIDTH; 470 471 if (clickedOnArrow) { 472 e.preventDefault(); 473 e.stopPropagation(); 474 475 parentLi.classList.toggle('active'); 476 const isActive = parentLi.classList.contains('active'); 477 link.setAttribute('aria-expanded', isActive ? 'true' : 'false'); 478 479 if (subNav) { 480 subNav.style.display = isActive ? 'block' : 'none'; 481 } 482 } 483 }); 484 }); 485} 486 487function createActionNavItem() { 488 489 debugLog('createActionNavItem called', { 490 'isMobile': isMobileView(), 491 'wasMobileView': wasMobileView, 492 'siteMenu exists': !!siteMenu, 493 'siteMenu li count': siteMenu?.querySelectorAll('li').length || 0 494 }); 495 496 const topNav = document.querySelector('.header__mainMenu #mainMenu .topNav'); 497 498 if (!topNav) { 499 debugLog('topNav not found - exiting'); 500 return; 501 } 502 503 const isMobile = isMobileView(); 504 505 if (isMobile && !wasMobileView) { 506 debugLog('Transitioning to mobile - adding site menu items'); 507 508 // Remove existing mobile menu items 509 document.querySelectorAll('.topNav .header__siteMenu')?.forEach(el => el.remove()); 510 511 // Add site menu items to mobile navigation 512 if (!siteMenu) { 513 debugLog('siteMenu is null/undefined - cannot add items'); 514 } else { 515 const menuItems = siteMenu.querySelectorAll('li'); 516 debugLog('Found', menuItems.length, 'li items to clone'); 517
518 menuItems.forEach((item, index) => { 519 const newItem = item.cloneNode(true); 520 newItem.classList.add('header__siteMenu'); 521 topNav.appendChild(newItem); 522 debugLog('Appended item', index + 1); 523 }); 524 } 525 526 wasMobileView = true; 527 } else if (!isMobile && wasMobileView) { 528 debugLog('Transitioning to desktop - removing site menu items'); 529 530 // Remove mobile menu items on desktop 531 document.querySelectorAll('.topNav .header__siteMenu')?.forEach(el => el.remove()); 532 wasMobileView = false; 533 } else { 534 debugLog('No transition - skipping', { isMobile, wasMobileView }); 535 } 536} 537 538function resetDropdownsForDesktop() { 539 debugLog('resetDropdownsForDesktop called', { 540 'dropdown count': document.querySelectorAll('.primaryLink.dropdown').length 541 }); 542 543 document.querySelectorAll('.primaryLink.dropdown').forEach((parentLi) => { 544 parentLi.classList.remove('active'); 545 const subNav = parentLi.querySelector('.subNav ul'); 546 if (subNav) { 547 subNav.style.display = ''; 548 } 549 }); 550} 551 552function setupDropdownAccessibility() { 553 debugLog('setupDropdownAccessibility called', { 554 'isAlist': window.location.href.includes("alist"), 555 'mainMenu exists': !!mainMenu 556 }); 557 558 if (window.location.href.includes("alist") || !mainMenu) { 559 debugLog('setupDropdownAccessibility: skipping - alist page or mainMenu not found'); 560 return; 561 } 562 563 const dropdownItems = mainMenu.querySelectorAll(':scope > ul > li.dropdown'); 564 if (dropdownItems.length === 0) return; 565 566 const lastDropdown = dropdownItems[dropdownItems.length - 1]; 567 const arrowIcon = lastDropdown.querySelector('.arrowIcon'); 568 const submenuLinks = lastDropdown.querySelectorAll('.subNav ul li a'); 569 570 // Add keyboard navigation for arrow icon 571 if (arrowIcon && !arrowIcon.dataset.accessibilityBound) { 572 arrowIcon.addEventListener('keydown', (e) => { 573 if (e.key === 'Tab' && !e.shiftKey) { 574 if (lastDropdown.classList.contains('active')) { 575 e.preventDefault(); 576 if (submenuLinks.length > 0) submenuLinks[0].focus(); 577 } else { 578 toggleMenu(); 579 } 580 } 581 }); 582 arrowIcon.dataset.accessibilityBound = "true"; 583 } 584 585 // Add keyboard navigation for last submenu link 586 if (submenuLinks.length > 0) { 587 const lastSubmenuLink = submenuLinks[submenuLinks.length - 1]; 588 if (!lastSubmenuLink.dataset.accessibilityBound) { 589 lastSubmenuLink.addEventListener('keydown', (e) => { 590 if (e.key === 'Tab' && !e.shiftKey) { 591 toggleMenu(); 592 } 593 }); 594 lastSubmenuLink.dataset.accessibilityBound = "true"; 595 } 596 } 597} 598 599// Mobile brand menu toggle functionality 600function initMobileBrandMenu() { 601 const stickyBrandMenu = document.querySelector('.header__logoWithNav .header__brandMenuSticky #brandMenu'); 602 603 if (!stickyBrandMenu) { 604 debugLog('initMobileBrandMenu: stickyBrandMenu not found'); 605 return; 606 } 607 608 const brandMenuList = stickyBrandMenu.querySelector('.brandSwitchingBar__inner ul'); 609 610 if (!brandMenuList) { 611 debugLog('initMobileBrandMenu: brandMenuList not found'); 612 return; 613 } 614 615 if (!mobileToggle) { 616 debugLog('initMobileBrandMenu: mobileToggle not found'); 617 return; 618 } 619 620 if (mobileToggle && brandMenuList) { 621 // Toggle menu on click 622 mobileToggle.addEventListener('click', function () { 623 brandMenuList.classList.toggle('mobile-open'); 624 this.classList.toggle('open'); 625 626 // Optional: Add ARIA attributes for accessibility 627 const isExpanded = brandMenuList.classList.contains('mobile-open'); 628 this.setAttribute('aria-expanded', isExpanded); 629 brandMenuList.setAttribute('aria-hidden', !isExpanded); 630 }); 631 632 // Initialize ARIA attributes 633 mobileToggle.setAttribute('aria-expanded', 'false'); 634 mobileToggle.setAttribute('role', 'button'); 635 brandMenuList.setAttribute('aria-hidden', 'true'); 636 637 // Close menu when clicking outside (optional) 638 document.addEventListener('click', function (event) { 639 if (!stickyBrandMenu.contains(event.target) && brandMenuList.classList.contains('mobile-open')) { 640 brandMenuList.classList.remove('mobile-open'); 641 mobileToggle.setAttribute('aria-expanded', 'false'); 642 brandMenuList.setAttribute('aria-hidden', 'true'); 643 } 644 }); 645 } 646} 647 648// ============================================================================ 649// Toggle Functions 650// ============================================================================ 651 652function toggleMenu() { 653 654 debugLog('toggleMenu called'); 655 656 if (!header || !mainMenu || !menuToggle) return; 657 658 header.style.top = '0px'; 659 660 // Reset search toggle state 661 if (searchToggle?.classList.contains('close-icon')) { 662 searchToggle.classList.remove('close-icon');
663 searchToggle.setAttribute('aria-label', 'Show search field'); 664 } 665 666 667 668 if (searchFields) searchFields.style.display = 'none'; 669 if (headerSiteLogo) headerSiteLogo.style.display = "none"; 670 671 mainMenu.classList.toggle('active'); 672 const navList = mainMenu.querySelector('ul'); 673 674 if (mainMenu.classList.contains('active')) { 675 // Reset brand toggle state 676 if (mobileToggle) mobileToggle.classList.remove('open'); 677 678 mainMenu.classList.add("opened"); 679 if (stickyBrandMenu) { 680 stickyBrandMenu.style.display = "block"; 681 } 682 683 menuToggle.classList.add('close-icon'); 684 menuToggle.setAttribute('aria-label', 'Hide menu field'); 685 if (navList) navList.style.display = 'block'; 686 } else { 687 mainMenu.classList.remove("opened"); 688 689 if (stickyBrandMenu) { 690 stickyBrandMenu.style.display = "none"; 691 } 692 693 menuToggle.classList.remove('close-icon'); 694 menuToggle.setAttribute('aria-label', 'Show menu field'); 695 if (navList) navList.style.display = 'none'; 696 header.style.top = ''; 697 } 698 699 setupDropdownAccessibility(); 700} 701 702function toggleSearch() { 703 debugLog('toggleSearch called', { 704 'header exists': !!header, 705 'searchToggle exists': !!searchToggle, 706 'searchToggle has close-icon': searchToggle?.classList.contains('close-icon') 707 }); 708 709 if (!header || !searchToggle) { 710 debugLog('toggleSearch: header or searchToggle not found - exiting'); 711 return; 712 } 713 714 header.style.top = '0px'; 715 716 // Reset menu toggle state 717 if (menuToggle?.classList.contains('close-icon')) { 718 menuToggle.classList.remove('close-icon'); 719 menuToggle.setAttribute('aria-label', 'Show menu field'); 720 } 721 722 if (mainMenu) { 723 mainMenu.classList.remove('active', 'opened'); 724 } 725 726 if (stickyBrandMenu) { 727 stickyBrandMenu.style.display = "none"; 728 } 729 730 if (headerSiteLogo) headerSiteLogo.style.display = "none"; 731 732 const sidebar = document.querySelector('.swipeNavigation .sidebar'); 733 734 if (!searchToggle.classList.contains('close-icon')) { 735 searchToggle.classList.add('close-icon'); 736 searchToggle.setAttribute('aria-label', 'Hide search field'); 737 if (searchFields) searchFields.style.display = 'block'; 738 if (sidebar) sidebar.style.height = 'calc(100% - 146px)'; 739 } else { 740 searchToggle.classList.remove('close-icon'); 741 searchToggle.setAttribute('aria-label', 'Show search field'); 742 if (searchFields) searchFields.style.display = 'none'; 743 header.style.top = ''; 744 if (sidebar) sidebar.style.height = ''; 745 } 746} 747 748// ============================================================================ 749// Resize Handler 750// ============================================================================ 751 752function handleResize() { 753 754 debugLog('handleResize called') 755 756 if (!mastHead) { 757 debugLog('handleResize: mastHead not found - exiting'); 758 return; 759 } 760 761 if (registerPage || mastHead.classList.contains("header--alist")) { 762 debugLog('handleResize: register page or alist - exiting'); 763 return; 764 } 765 766 MobileView = isMobileView(); 767 768 if (hlogo && !hlogo.classList.contains('rightMobNav') && typeof handleScroll === 'function') { 769 handleScroll(); 770 } 771 772 createActionNavItem(); 773 774 // Position header wrapper below mobile nav on mobile 775 positionHeaderWrapper(); 776 777 // Reset menu visibility on desktop 778 if (!MobileView) { 779 // Initialize More menu if not already done (handles mobile â desktop transition) 780 if (!moreMenuInitialized && !window.location.href.includes("alist") && !registerPage) { 781 debugLog('handleResize: transitioning to desktop, initializing More menu'); 782 try { 783 if (typeof ContentInfo !== 'undefined' && ContentInfo && ContentInfo.Site) { 784 const site = ContentInfo.Site; 785 const domain = site.Domain || ''; 786 const path = site.Path || ''; 787 const fullDomain = path 788 ? `${domain.replace(/\/$/, '')}/${path.replace(/^\//, '')}` 789 : domain; 790 initMoreMenu(fullDomain); 791 } else { 792 debugLog('handleResize: ContentInfo.Site not available for initMoreMenu'); 793 } 794 } catch (error) { 795 console.error('MENU.JS: Error initializing More menu on resize:', error); 796 } 797 } 798 799 if (siteMenu) siteMenu.style.display = "block"; 800 if (mainMenu) { 801 // Remove mobile menu states 802 mainMenu.classList.remove("active", "opened"); 803 804 // Get navList 805 const navList = mainMenu.querySelector('ul'); 806 if (navList) { 807 // ALWAYS reset navList display to ensure it's visible on de
807sktop 808 navList.style.display = ''; 809 810 // Clear inline styles from primaryLink items, but preserve items moved to More menu 811 navList.querySelectorAll('.primaryLink:not(.moreSubNavigation)').forEach(item => { 812 // Skip items that are in the More dropdown - they should stay hidden 813 if (!item.classList.contains('moved-to-more')) { 814 item.style.display = ''; 815 } 816 }); 817 818 // Note: More dropdown visibility is managed by adjustNavItems() based on whether items were moved to it 819 } 820 } 821 822 // Reset all element states 823 if (stickyBrandMenu) stickyBrandMenu.style.display = "none"; 824 if (headerSiteLogo) headerSiteLogo.style.display = ''; 825 if (menuToggle) { 826 menuToggle.classList.remove('close-icon'); 827 menuToggle.setAttribute('aria-label', 'Show menu field'); 828 } 829 if (searchToggle) { 830 searchToggle.classList.remove('close-icon'); 831 searchToggle.setAttribute('aria-label', 'Show search field'); 832 } 833 if (searchFields) searchFields.style.display = ''; // Reset to let CSS control visibility 834 if (header) header.style.top = ''; 835 836 // Reset dropdown states 837 resetDropdownsForDesktop(); 838 } else { 839 // Mobile view - clear More menu state and show all items 840 if (siteMenu) siteMenu.style.display = "none"; 841 842 if (mainMenu) { 843 const navList = mainMenu.querySelector('ul'); 844 if (navList) { 845 // If menu is closed on mobile, keep navList hidden 846 // If menu is open, it will be visible via CSS 847 // Don't force display here - let toggleMenu control it 848 849 // Remove moved-to-more class and show all items (except More dropdown itself) 850 navList.querySelectorAll('.primaryLink:not(.moreSubNavigation)').forEach(item => { 851 item.classList.remove('moved-to-more'); 852 item.style.display = ''; 853 }); 854 855 // Hide the More dropdown in mobile 856 const moreDropdown = navList.querySelector('.moreSubNavigation'); 857 if (moreDropdown) { 858 moreDropdown.style.display = 'none'; 859 } 860 } 861 } 862 } 863} 864 865// ============================================================================ 866// Initialization 867// ============================================================================ 868 869document.addEventListener("DOMContentLoaded", function () { 870 debugLog('=== MENU.JS: DOM fully loaded and parsed ==='); 871 872 // Initialize DOM element references 873 topBrandMenu = document.querySelector('#brandMenu'); 874 stickyBrandMenu = document.querySelector(".header__brandMenuSticky"); 875 menuToggle = document.querySelector('.header__mobileNavToggle'); 876 searchToggle = document.querySelector('.header__mobileSearchToggle'); 877 878 mobileToggle = stickyBrandMenu?.querySelector('.menuMobileTextForBrandNavbar'); 879 mastHead = document.querySelector('#masthead') || document.querySelector('.header'); 880 hlogo = document.querySelector('.header__logoWithNav'); 881 mainMenu = document.querySelector('#mainMenu'); 882 siteMenu = document.querySelector('#siteMenu'); // Changed from '.header__siteMenu' to '#siteMenu' 883 header = document.querySelector('.header__container'); 884 //header = document.querySelector('.header__mainMenu'); 885 886 searchFields = document.querySelector('.header__siteSearch'); 887 headerSiteLogo = document.querySelector('.header__siteLogo'); 888 889 debugLog('DOM Elements initialized:', { 890 'topBrandMenu': !!topBrandMenu, 891 'stickyBrandMenu': !!stickyBrandMenu, 892 'menuToggle': !!menuToggle, 893 'searchToggle': !!searchToggle, 894 'mastHead': !!mastHead, 895 'hlogo': !!hlogo, 896 'mainMenu': !!mainMenu, 897 'siteMenu': !!siteMenu, 898 'header': !!header, 899 'searchFields': !!searchFields, 900 'headerSiteLogo': !!headerSiteLogo, 901 'mobileToggle': !!mobileToggle 902 }); 903 904 // Check for critical missing elements 905 const criticalElements = { 906 'mastHead': mastHead, 907 'header': header, 908 'mainMenu': mainMenu 909 }; 910 911 const missingCritical = Object.entries(criticalElements) 912 .filter(([name, element]) => !element) 913 .map(([name]) => name); 914 915 if (missingCritical.length > 0) { 916 debugLog('Missing critical elements - some functionality may not work:', missingCritical.join(', ')); 917 } 918 919 // Determine if this is a register page 920 registerPage = document.querySelector('.registerPage') && !document.querySelector('.myaccountPage'); 921 debugLog('registerPage:', registerPage); 922 923 // Get site domain information with error handling 924 let fullDomain = ''; 925 try { 926 if (typeof ContentInfo !== 'undefined' && ContentInfo && ContentInfo.Site) { 927 const site = ContentInfo.Site; 928 const domain = site.Domain || ''; 929 const path = site.Path || ''; 930 fullDomain = path 931 ? `${domain.replace(/\/$/, '')}/${path.replace(/^\//, '')}` 932 : domain; 933 debugLog('Site domain info:', { domain, path, fullDomain }); 934 } else { 935 console.warn('MENU.JS: ContentInfo.Site is not available'); 936 debugLog('ContentInfo.Site not available - brand menu highlighting may not work'); 937 } 938 } catch (error) { 939 console.error('MENU.JS: Error accessing ContentInfo.Site:', error); 940 debugLog('Error accessing site info:', error.message); 941 } 942 943 // Initialize menu visibility 944 debugLog('Initializing menu visibility'); 945 toggleMenuVisibility(); 946 window.addEventListener("resize", debounce(toggleMenuVisibility, RESIZE_DEBOUNCE_TIME)); 947 948 // Initialize More menu (desktop overflow) 949 debugLog('Initializing More menu'); 950 initMoreMenu(fullDomain); 951 952 // Initialize Mobile brand menu 953 debugLog('Initializing Mobile brand menu'); 954 initMobileBrandMenu(); 955 956 // Highlight current brand menu item 957 debugLog('Highlighting current brand menu items'); 958 highlightCurrentNavItem(topBrandMenu, fullDomain); 959 highlightCurrentNavItem(stickyBrandMenu, fullDomain); 960 961 // Highlight current navigation item 962 debugLog('Highlighting current navigation item'); 963 const navItems = document.querySelectorAll(".header__mainMenu .primaryLink"); 964 const currentPath = window.location.pathname; 965 debugLog('Current path:', currentPath, 'Nav items found:', navItems.length); 966
967 navItems.forEach(item => { 968 const link = item.querySelector("a"); 969 if (link && link.getAttribute("href") === currentPath) { 970 item.classList.add("navCurrent"); 971 } 972 }); 973 974 // Setup event listeners 975 debugLog('Setting up event listeners'); 976 if (hlogo && !hlogo.classList.contains('rightMobNav') && typeof handleScroll === 'function') { 977 debugLog('Adding scroll event listener'); 978 window.addEventListener('scroll', handleScroll); 979 handleScroll(); 980 } else { 981 if (!hlogo) { 982 debugLog('hlogo element not found - scroll listener not added'); 983 } 984 } 985 986 debugLog('Adding resize event listener with debounce'); 987 window.addEventListener('resize', debounce(handleResize, RESIZE_DEBOUNCE_TIME)); 988 989 debugLog('Adding menu and search toggle listeners'); 990 if (menuToggle) { 991 menuToggle.addEventListener('click', () => isMobileView() && toggleMenu()); 992 } else { 993 debugLog('menuToggle not found - menu toggle listener not added'); 994 } 995 996 if (searchToggle) { 997 searchToggle.addEventListener('click', () => isMobileView() && toggleSearch()); 998 } else { 999 debugLog('searchToggle not found - search toggle listener not added'); 1000 } 1001 1002 // Initialize mobile features 1003 debugLog('Initializing mobile features'); 1004 initializeMobileDropdowns(); 1005 1006 if (isMobileView()) { 1007 if (siteMenu) { 1008 debugLog('Mobile view detected - hiding siteMenu'); 1009 siteMenu.style.display = "none"; 1010 } else { 1011 debugLog('siteMenu not found'); 1012 } 1013 } 1014 1015 debugLog('Creating action nav items'); 1016 createActionNavItem(); 1017 1018 debugLog('Positioning header wrapper'); 1019 positionHeaderWrapper(); 1020 1021 debugLog('=== MENU.JS: Initialization complete ==='); 1022}); 1023 1024 1025if (document.querySelector(".article--shorthand-header") && window.innerWidth > 767) { 1026 const mainMenu = document.querySelector(".header__mainMenu"); 1027 const trendingNav = document.querySelector(".header__trendingNav"); 1028 const headerInner = document.querySelector(".header__container--inner"); 1029 const logoWithNav = document.querySelector(".header__logoWithNav"); 1030 const brandLogo = document.querySelector(".header__brandLogo"); 1031 1032 if (mainMenu) { 1033 mainMenu.style.display = "none"; 1034 } 1035 1036 if (trendingNav) { 1037 trendingNav.style.display = "none"; 1038 } 1039 1040 if (headerInner) { 1041 headerInner.style.flexDirection = "row-reverse"; 1042 } 1043 1044 if (logoWithNav) { 1045 logoWithNav.style.margin = "10px 0"; 1046 } 1047 1048 if (brandLogo) { 1049 brandLogo.style.padding = "0"; 1050 } 1051}
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.