PageSourceSearch

https://www.printweek.in/HbmCoreTheme/js/menu.js?v=0doh5PH3XjHLka1muMT2CiW8Tdj-QHSqYh3fozUJ6sk

js printweek.in collected 2026-09-24 20:57:40 UTC 35,692 bytes, 1,051 lines download raw bytes

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.