Newer
Older
pre-www / src / assets / js / site.js
import './blocks/cb.js';
import './blocks/accordion.js';
import './blocks/carousel.js';
import './blocks/cards-grid.js';
import './blocks/featured-tabs.js';
import './blocks/inputs.js';
import './blocks/marquee.js';
import './blocks/home-scroll-banner.js';
import './blocks/page-title-banner.js';
import './blocks/paragraph.js';
import './blocks/secondary-nav.js';
import './blocks/tabs.js';
import './blocks/tease.js';

/**
 * Global scripts
 */

window.addEventListener('load', (event) => {

    /**
     * Vars
     */

    //functional
    let vh = '100vh'
    let currentScrollPos = 0
    let prevScrollPos = 0
    let menuToggledScrollPos
    let menuIsOpen = false
    let desktopMenuIsOpen = false
    let mobileMenuIsOpen = false

    //media query
    const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
    const isDesktop = window.matchMedia('(min-width: 80rem)')

    // DOM elements
    const body = document.body
    const header = document.querySelector('.site-header')
    const logo = document.querySelector('.site-logo')
    const a11y_ariaexpanded = document.querySelectorAll('[aria-expanded="false"]')
    const mainNav = document.getElementById('site-header-main-nav')
    const menuItems = document.querySelectorAll('#site-header-main-nav > ul > .menu-item-has-children > a')
    const menuBtn = document.getElementById('menu-btn')
    const overlay = document.getElementById('overlay')
    const menuMobile = document.getElementById('menu-mobile') 
    const pageWrapper = document.getElementById('site-content-wrapper')
    const accordionMenuItems = document.querySelectorAll('[data-toggle-menu-items]')
    const footer = document.getElementById('site-footer')

    /**
     * Throttle
     */
    function throttle(mainFunction, delay) {
        let timerFlag = null
        return (...args) => {
            if (timerFlag === null) { 
                mainFunction(...args)
                timerFlag = setTimeout(() => {
                    timerFlag = null
                }, delay)
            }
        }
    }

    /**
     * Check if iOS, then set --vh
     */
    if (isIOS && window.matchMedia("(max-width: 1024px)").matches) {
        document.documentElement.classList.add('is-ios')
    }
    
    function set100vh() {
        // If window size is iPad or smaller, then use JS to set screen height.
        if (isIOS && window.matchMedia("(max-width: 1024px)").matches) {
            vh = `${window.innerHeight}px`
            document.documentElement.style.setProperty("--vh", vh)
        }
    }
    set100vh()

    /**
     * WAI-ARIA toggle aria-expanded
     */
    function updateAriaExpanded(item){
        const ariaexpanded = item.getAttribute('aria-expanded')
        if (ariaexpanded == 'true') {
            item.setAttribute('aria-expanded', 'false')
        } else {
            item.setAttribute('aria-expanded', 'true')
        }
    }
    a11y_ariaexpanded.forEach((item) => {
        item.addEventListener('click', function () {
            updateAriaExpanded(this)
        })
    })

 
    /**
     * Get header height
     */
    let headerHeight
    function getHeaderHeight(){
        headerHeight = header.clientHeight
        return `${headerHeight}px`
    }
        
    function setHeaderHeightVar(){
        document.documentElement.style.setProperty("--header-height", getHeaderHeight())
    }

    setHeaderHeightVar()

    /**
     * Hide header if scrolling down, show if scrolling up
     */

    window.addEventListener('scroll', () => {
        
        currentScrollPos = window.scrollY

        // const currentScrollPos = window.scrollY

        //if you start scrolling add class
        if (currentScrollPos > headerHeight && !menuIsOpen) {
            body.classList.add('is-scrolled')
        } else{
            body.classList.remove('is-scrolled')
        }
        
        // if scrolling down, hide header and position logo to the left
        // if scrolling up, show header and logo in initial position
        if (prevScrollPos > headerHeight && prevScrollPos < currentScrollPos && !menuIsOpen) {
            header.classList.add('is-hidden')
            logo.classList.add('is-visible')
            overlay.classList.remove('is-active')
        } else if (prevScrollPos >= currentScrollPos && !menuIsOpen) {
            header.classList.remove('is-hidden')
            logo.classList.remove('is-visible')
        }
        
        prevScrollPos = currentScrollPos

    })

    /**
     * Menu
     */

    function toggleMenuSharedElements(toggle = true){
               
        if (!menuIsOpen) {
            body.classList.add('has-menu-toggled')
            menuBtn.classList.add('is-active')
            menuBtn.classList.add('is-toggled')
            overlay.classList.add('is-active')
            menuIsOpen = true
        } else if (toggle) {
            body.classList.remove('has-menu-toggled')
            menuBtn.classList.remove('is-active')
            menuBtn.classList.remove('is-toggled')
            overlay.classList.remove('is-active')
            menuIsOpen = false
        }

    }

    // when menu is toggled, set margin top based
    // on scrolled px and restore scroll after menu is closed
    function setScrolledMarginContent(scrolled){
        if (mobileMenuIsOpen || desktopMenuIsOpen) {
            pageWrapper.style.marginTop = 0
            document.body.scrollTop = menuToggledScrollPos
            document.body.scrollTop = menuToggledScrollPos
            document.documentElement.scrollTop = menuToggledScrollPos
        } else {
            pageWrapper.style.marginTop = `-${scrolled}px`
        }
        menuToggledScrollPos = scrolled
    }
    
    function toggleMobileMenu(forceClosing = null){
        toggleMenuSharedElements()
        if (forceClosing) {
            menuMobile.classList.remove('is-toggled')
        } else {
            menuMobile.classList.toggle('is-toggled')
            // if (menuIsOpen) {                
            //     menuMobile.animate(
            //         [
            //             { height: '0px' },
            //             { height: `${menuMobile.clientHeight}px` }
            //         ],
            //         {
            //             duration: 500,
            //             easing: 'ease-out'
            //         }
            //     )
            // } else {
            //     menuMobile.animate(
            //         [
            //             { height: '0px' },
            //             { height: `${menuMobile.clientHeight}px` }
            //         ],
            //         {
            //             duration: 500,
            //             easing: 'ease-out'
            //         }
            //     )
            // }
        }
        closeAllAccordionMenuItems()
        // set margin on page wapper 
        // and restore scrolled position when you close menu
        setScrolledMarginContent(currentScrollPos)
        menuIsOpen ? mobileMenuIsOpen = true : mobileMenuIsOpen = false    
    }

    let previousClickedItem
    function toggleDesktopMenu(clickedItem = null){

        if (clickedItem == null) {
            toggleMenuSharedElements()
            openSubMenu()

        } else if (clickedItem == previousClickedItem || previousClickedItem == null || !desktopMenuIsOpen) {
            // if desktop menu is not toggled or you are toggling menu item
            toggleMenuSharedElements()
            openSubMenu(clickedItem)
        } else if (clickedItem != previousClickedItem && clickedItem != null){
            // if you are swapping submenu
            openSubMenu(clickedItem, false)
        }
        // assign previous clicked item to currently clicked item
        previousClickedItem = clickedItem
        
        // toggle/remove class on all menu items
        menuItems.forEach((item) => { 
            const itemListItem = item.parentElement
            if (itemListItem != clickedItem) {
                itemListItem.classList.remove('is-toggled')
            } else {
                itemListItem.classList.toggle('is-toggled')
            }
        })
        // set margin on page wapper  
        // and restore scrolled position when you close menu
        setScrolledMarginContent(currentScrollPos)
        menuIsOpen ? desktopMenuIsOpen = true : desktopMenuIsOpen = false
    }

    function toggleMenuWhenResized(){
        // if mobile menu is open and window resized to desktop
        if (mobileMenuIsOpen && isDesktop.matches){
            toggleMenuSharedElements()
            toggleMobileMenu(true)
            menuIsOpen = false
        }
        // if desktop menu is open and window resized to mobile
        if (desktopMenuIsOpen && !isDesktop.matches){
            toggleMenuSharedElements()
            toggleDesktopMenu()
            menuIsOpen = false
        }
    }

    // animate desktop dropdown and toggle 
    function openSubMenu(clickedItem, animate = true){
        let submenu
        if (clickedItem) {
            //if there's a clicked item get submenu descendante 
            submenu = clickedItem.querySelector('.site-header-navbar-submenu-0')
        } else {
            // if there isn't a clicked item (eg: X button), select visible menus 
            submenu = document.querySelector('.site-header-navbar-submenu-0.is-visible')
            clickedItem = document.querySelector('#site-header-main-nav .menu-item-has-children.is-toggled')
            console.log(clickedItem)
        }
        if (clickedItem.classList.contains('is-toggled')) {
            // if desktop menu is already open and click on already toggled item
            // remove classes and animate submenu to 0px height
            mainNav.classList.remove('is-toggled')
            submenu.classList.add('is-closing')
            submenu.animate(
                [
                    { height: `${submenu.clientHeight}px` },
                    { height: 0 }
                ],
                {
                    duration: 250,
                    delay: 250,
                    easing: 'ease-out'
                }
            )
            // timeout animation
            setTimeout(() => {
                submenu.classList.remove('is-visible')
                submenu.classList.remove('is-closing')
            }, 500);
        } else if (!animate){
            // if desktop menu is open and click on item not yet toggled
            // swap submenu container without animations
            [...document.querySelectorAll('.site-header-navbar-submenu-0')].forEach(s=>{
                if(submenu != s){
                    s.classList.remove('is-visible')
                } else {
                    submenu.classList.add('is-visible')
                }
            })
        } else {
            // if desktop menu is not open and click on item
            // show and animate submenu
            submenu.classList.add('is-visible')
            submenu.animate(
                [
                    { height: 0 },
                    { height: `${submenu.clientHeight}px` }
                ],
                {
                    duration: 250,
                    easing: 'ease-out'
                }
            )
            setTimeout(() => {
                mainNav.classList.add('is-toggled')
            }, 500);
        }
    }
    
    function cbToggleDesktopMenu(event){
        const item = event.target.parentElement
        toggleDesktopMenu(item)
    }
      
    // Throttle the fetchData function with a delay of 5000 ms
    const throttledtoggleDesktopMenu = throttle(cbToggleDesktopMenu, 500)

    menuItems.forEach(item => {
        item.addEventListener('click', throttledtoggleDesktopMenu)
    })
    
    menuBtn.addEventListener('click', function(){
        if (isDesktop.matches) {
            console.log('test')
            toggleDesktopMenu()
        } else {
            toggleMobileMenu()
        }
    })
  
    //close all accordion menu items
    function closeAllAccordionMenuItems(){
        accordionMenuItems.forEach(item => {
            item.parentElement.parentElement.classList.remove('is-toggled')
            item.parentElement.parentElement.setAttribute('aria-expanded', 'false')
        })
    }

    accordionMenuItems.forEach(button => {
        button.addEventListener('click', function(){
            // get <li>
            const clickedItem = this.parentElement.parentElement
            // get nesting of clicked item (from button)
            const nesting = this.getAttribute('data-toggle-menu-items')

            if (nesting == 0 && clickedItem.classList.contains('is-toggled')) {
                // if is first level and already opened, 
                // when clicked close all items
                closeAllAccordionMenuItems()
            } else {
                // when you click on item, close other items on same nesting level
                // [...document.querySelectorAll(`[data-toggle-menu-items="${nesting}"]`)].forEach(i=>{if(this != i){i.parentElement.parentElement.classList.remove('is-toggled')}})
                // toggle clicked item
                clickedItem.classList.toggle('is-toggled')
            }
        })
    })

    // if click on overlay close menu
    overlay.addEventListener('click', function(){
        // toggleMenuSharedElements()
        if (isDesktop.matches) {
            toggleDesktopMenu()
        } else {
            toggleMobileMenu()
        }
    })

    /**
     * Filters
     */
    const filters = document.querySelectorAll('.block-filters')
    filters.forEach(filter => {
        const trigger = filter.querySelector('.block-filters__header')
        const content = filter.querySelector('.block-filters__inner')
        trigger.addEventListener('click', function(){
            trigger.classList.toggle('is-toggled')
            content.classList.toggle('is-visible')
        })
    })

    /**
     * Back to top
     */
    document.getElementById('backToTop').addEventListener('click', function(){
        window.scrollTo({
            top: 0,
            behavior: 'smooth'
        })
    })

    /**
     * Footer observer
     */
    //when footer is in viewport, restore logo position
    let footerObserver = new IntersectionObserver((entries) => { 
        
        entries.forEach(entry => {
            if(entry.isIntersecting){
                body.classList.add('footer-in-viewport')
            } else {
                body.classList.remove('footer-in-viewport')
            }
        })

    }, 
    {
        rootMargin: '0px'
    })
    footerObserver.observe(footer)

    /**
     * Window resize function callbacks
     */
    const resizeHandler = function(){
        // set vh
        set100vh()
        // get header height
        setHeaderHeightVar()
        // when resizing disable menu if toggled
        toggleMenuWhenResized()
    }
    window.addEventListener('resize', resizeHandler)

    /**
     * Keyboard related functions and events
     */
    document.onkeydown = function(evt) {
        evt = evt || window.event;
        var isEscape = false;
        if ('key' in evt) {
            isEscape = (evt.key === 'Escape' || evt.key === 'Esc');
        } else {
            isEscape = (evt.keyCode === 27);
        }
        // if menu is open and press escape, toggle desktop or mobile menu
        // based on media query
        if (isEscape && menuIsOpen) {
            toggleMenuSharedElements(false)
            if (isDesktop.matches) {
                toggleDesktopMenu()
            } else {
                toggleMobileMenu()
            }
        }
    }

})