{"version":3,"file":"header.js","names":[],"sources":["../resources/javascript/header.js"],"sourcesContent":["import {\n    headerActiveClasses,\n    navigationActivatingClasses,\n    navigationActiveClasses,\n} from './features/header/constants';\nimport {\n    toggleClass,\n    addClass,\n    removeClass,\n    removeAllActiveClasses,\n} from './features/header/util';\nimport {\n    header,\n    submenus,\n    toggleSubmenuButtons,\n    resetHeaderMenus,\n} from './features/header/index';\nimport {\n    setQuickBasketCountFromCookie,\n    initQuickBasket,\n} from './features/basket/mini-basket';\nimport { initialiseSwiper } from './swiper/swiper';\nimport { initialiseLazySearch } from './features/autocomplete/lazy';\nimport {\n    getHeaderSearchInput,\n    setHeaderSearchOpen,\n} from './features/autocomplete/header';\nimport { trackNavigationMenu, trackNoticeBar } from './util/tracking';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n    // TODO move most of this into ../features/header/index.js\n\n    const mobileToggle = document.querySelector('[data-mobile-toggle]');\n    const secondLevelButtons = document.querySelectorAll(\n        '[data-toggle-second-level]'\n    );\n    const searchInput = getHeaderSearchInput();\n\n    /**\n     * Track all nav links\n     */\n    const initHeaderLinkTracking = () => {\n        const nav = header.querySelector('[data-navigation]');\n\n        nav.addEventListener('click', e => {\n            if (e.target.tagName.toLowerCase() === 'a') {\n                trackNavigationMenu(\n                    'Navigation Link Clicked',\n                    e.target.textContent.trim(),\n                    e.target.href.trim()\n                );\n            }\n        });\n    };\n\n    /**\n     * Track all notice bar links\n     */\n    const initNoticeBarLinkTracking = () => {\n        const noticeBar = document.querySelector('aside.notice-bar');\n\n        noticeBar.addEventListener('click', e => {\n            if (e.target.tagName.toLowerCase() === 'a') {\n                trackNoticeBar(\n                    'Notice Bar Link Clicked',\n                    e.target.textContent.trim(),\n                    e.target.href.trim()\n                );\n            }\n        });\n    };\n\n    /**\n     * Toggles the submenu based on the clicked button.\n     * @param {Element} clickedButton\n     */\n    const toggleSubmenu = clickedButton => {\n        const clickedSubmenu = clickedButton.nextElementSibling;\n        const isActive = clickedSubmenu?.classList.contains(\n            navigationActiveClasses.groups\n        );\n\n        resetHeaderMenus();\n        setHeaderSearchOpen(false);\n\n        // No fade on mobile\n        const timeout = window.matchMedia('(max-width: 1024px)').matches\n            ? 0\n            : 100;\n\n        if (!isActive) {\n            setTimeout(() => {\n                addClass(clickedSubmenu, navigationActiveClasses.groups);\n            }, timeout);\n            addClass(clickedSubmenu, navigationActivatingClasses.groups);\n            addClass(clickedButton, navigationActiveClasses.button);\n            addClass(header, headerActiveClasses.submenu);\n            clickedButton.setAttribute('aria-expanded', 'true');\n\n            trackNavigationMenu(\n                'Open Submenu',\n                clickedButton.textContent.trim()\n            );\n        } else {\n            setTimeout(() => {\n                removeClass(clickedSubmenu, navigationActivatingClasses.groups);\n                trackNavigationMenu(\n                    'Close Submenu',\n                    clickedButton.textContent.trim()\n                );\n            }, timeout);\n        }\n    };\n\n    /**\n     * Toggles the mobile menu.\n     */\n    const toggleMobileMenu = () => {\n        const isMobileActive = header?.classList.toggle(\n            headerActiveClasses.mobile\n        );\n\n        if (isMobileActive) {\n            document.documentElement.classList.add('lock-scroll');\n            closeSearch();\n        } else {\n            document.documentElement.classList.remove('lock-scroll');\n            removeAllActiveClasses(header);\n        }\n    };\n\n    /**\n     * Close the search\n     */\n    const closeSearch = () => {\n        const searchContainer = header.querySelector('.js-header-search');\n\n        searchContainer.classList.remove('header-search--active');\n    };\n\n    /**\n     * Toggles the second-level menu based on the clicked button.\n     * @param {Element} clickedButton\n     */\n    const toggleSecondLevel = clickedButton => {\n        toggleClass(clickedButton.parentElement, navigationActiveClasses.group);\n        toggleClass(header, headerActiveClasses.secondLevel);\n\n        if (\n            header.classList.contains(headerActiveClasses.secondLevel) &&\n            clickedButton.parentElement.classList.contains(\n                navigationActiveClasses.group\n            )\n        ) {\n            trackNavigationMenu(\n                'Open Second Level Menu',\n                clickedButton.textContent.trim()\n            );\n        } else {\n            trackNavigationMenu(\n                'Close Second Level Menu',\n                clickedButton.textContent.trim()\n            );\n        }\n\n        clickedButton.setAttribute('aria-expanded', 'false');\n    };\n\n    /**\n     * Initializes Intersection Observer to manage header position based on scrolling.\n     */\n    const initIntersectionObserver = () => {\n        const sentinel = document.querySelector('[data-sentinel]');\n        const observer = new IntersectionObserver(\n            entries => {\n                const position = entries[0].isIntersecting\n                    ? 'static'\n                    : 'sticky';\n                header.setAttribute('data-position', position);\n            },\n            { threshold: 1.0 }\n        );\n        observer.observe(sentinel);\n    };\n\n    /**\n     * Initializes a fallback scroll listener for browsers without IntersectionObserver support.\n     */\n    const initFallbackScrollListener = () => {\n        window.addEventListener('scroll', () => {\n            const position = window.scrollY > 0 ? 'static' : 'sticky';\n            header.setAttribute('data-position', position);\n        });\n    };\n\n    mobileToggle?.addEventListener('click', toggleMobileMenu);\n\n    toggleSubmenuButtons.forEach(button => {\n        button.addEventListener('click', e => toggleSubmenu(e.currentTarget));\n    });\n\n    secondLevelButtons.forEach(button => {\n        button.addEventListener('click', e =>\n            toggleSecondLevel(e.currentTarget)\n        );\n    });\n\n    searchInput.addEventListener('keydown', e => {\n        if (e.key === 'Escape') {\n            e.preventDefault();\n            setHeaderSearchOpen(false);\n        }\n    });\n\n    /**\n     * Initialize Observers and Event Listeners\n     */\n    if (window.IntersectionObserver) {\n        initIntersectionObserver();\n    } else {\n        initFallbackScrollListener();\n    }\n\n    /**\n     * Close header when clicking outside of the header.\n     */\n    document.addEventListener('click', e => {\n        if (header && !header.contains(e.target)) {\n            if (header.classList.toString().includes('active')) {\n                trackNavigationMenu(\n                    'Closed Navigation Menu',\n                    'Clicked Off Menu'\n                );\n            }\n\n            removeAllActiveClasses(header);\n        }\n    });\n\n    const initNoticeCarousel = () => {\n        const swiper = document.querySelector('[data-swiper]');\n\n        initialiseSwiper(swiper);\n\n        function manageMobileSlides(noticeSwiper, isMobile) {\n            const mobileOnlySlides = document.querySelectorAll(\n                '[data-mobile-only=\"true\"]'\n            );\n\n            if (isMobile) {\n                // Add mobile-only slides\n                mobileOnlySlides.forEach(slide => {\n                    // Check if the slide is already appended\n                    if (\n                        !noticeSwiper.swiper.slides.some(\n                            swiperSlide =>\n                                swiperSlide.outerHTML === slide.outerHTML\n                        )\n                    ) {\n                        noticeSwiper.swiper.appendSlide(slide.outerHTML);\n                    }\n                });\n            } else {\n                let slidesToRemove = [];\n                // Remove mobile-only slides\n                noticeSwiper.swiper.slides.forEach((slide, index) => {\n                    if (slide.dataset.mobileOnly === 'true') {\n                        slidesToRemove.push(index);\n                    }\n                });\n\n                noticeSwiper.swiper.removeSlide(slidesToRemove);\n            }\n\n            noticeSwiper.swiper.update();\n        }\n\n        function managePrivateSale(noticeSwiper, isMobile) {\n            const privateSaleSlides = noticeSwiper.querySelectorAll(\n                '[data-private-sale=\"true\"]'\n            );\n\n            if (privateSaleSlides.length) {\n                const slidesToRemove = [];\n\n                noticeSwiper.swiper.slides.forEach((slide, index) => {\n                    // On desktop we only want to show the private sale slides if there are any\n                    if (\n                        (isMobile && slide.dataset.privateSale !== 'true') ||\n                        (slide.dataset.mobileOnly !== 'true' &&\n                            slide.dataset.privateSale !== 'true')\n                    ) {\n                        slidesToRemove.push(index);\n                    }\n                });\n\n                noticeSwiper.swiper.removeSlide(slidesToRemove);\n            }\n\n            noticeSwiper.swiper.update();\n        }\n\n        manageMobileSlides(swiper, window.innerWidth <= 1120);\n        managePrivateSale(swiper, window.innerWidth <= 1120);\n\n        swiper.style.opacity = 1;\n    };\n\n    initQuickBasket();\n    initNoticeCarousel();\n    initialiseLazySearch();\n    initHeaderLinkTracking();\n    initNoticeBarLinkTracking();\n});\n\nsetQuickBasketCountFromCookie();\n"],"mappings":"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"}