OwlCyberSecurity - MANAGER
Edit File: navigation-lite.js
/* global kadenceConfig */ /** * File navigation.js. * * Handles toggling the navigation menu for small screens and enables TAB key * navigation support for dropdown menus. */ (function() { 'use strict'; window.kadence = { /** * Function to init different style of focused element on keyboard users and mouse users. */ initOutlineToggle: function() { document.body.addEventListener( 'keydown', function() { document.body.classList.remove( 'hide-focus-outline' ); }); document.body.addEventListener( 'mousedown', function() { document.body.classList.add( 'hide-focus-outline' ); }); }, /** * Get element's offset. */ getOffset: function( el ) { if ( el instanceof HTMLElement ) { var rect = el.getBoundingClientRect(); return { top: rect.top + window.pageYOffset, left: rect.left + window.pageXOffset } } return { top: null, left: null }; }, /** * traverses the DOM up to find elements matching the query * * @param {HTMLElement} target * @param {string} query * @return {NodeList} parents matching query */ findParents: function( target, query ) { var parents = []; // recursively go up the DOM adding matches to the parents array function traverse( item ) { var parent = item.parentNode; if ( parent instanceof HTMLElement ) { if ( parent.matches( query ) ) { parents.push( parent ); } traverse( parent ); } } traverse( target ); return parents; }, /** * Toggle an attribute. */ toggleAttribute: function( element, attribute, trueVal, falseVal ) { if ( trueVal === undefined ) { trueVal = true; } if ( falseVal === undefined ) { falseVal = false; } if ( element.getAttribute( attribute ) !== trueVal ) { element.setAttribute( attribute, trueVal ); } else { element.setAttribute( attribute, falseVal ); } }, /** * Initiate the script to process all * navigation menus with submenu toggle enabled. */ initNavToggleSubmenus: function() { var navTOGGLE = document.querySelectorAll( '.nav--toggle-sub' ); // No point if no navs. if ( ! navTOGGLE.length ) { return; } for ( let i = 0; i < navTOGGLE.length; i++ ) { window.kadence.initEachNavToggleSubmenu( navTOGGLE[ i ] ); } }, initEachNavToggleSubmenu: function( nav ) { // Get the submenus. var SUBMENUS = nav.querySelectorAll( '.menu ul' ); // No point if no submenus. if ( ! SUBMENUS.length ) { return; } for ( let i = 0; i < SUBMENUS.length; i++ ) { var parentMenuItem = SUBMENUS[ i ].parentNode; let dropdown = parentMenuItem.querySelector( '.dropdown-nav-toggle' ); // If dropdown. if ( dropdown ) { var dropdown_label = parentMenuItem.querySelector( '.nav-drop-title-wrap' ).firstChild.textContent.trim(); var dropdownBtn = document.createElement( 'BUTTON' ); // Create a <button> element dropdownBtn.setAttribute( 'aria-label', ( dropdown_label ? kadenceConfig.screenReader.expandOf + ' ' + dropdown_label : kadenceConfig.screenReader.expand ) ); dropdownBtn.classList.add( 'dropdown-nav-special-toggle' ); parentMenuItem.insertBefore( dropdownBtn, parentMenuItem.childNodes[1] ); // Toggle the submenu when we click the dropdown button. dropdownBtn.addEventListener( 'click', function( e ) { e.preventDefault(); window.kadence.toggleSubMenu( e.target.parentNode ); } ); // Clean up the toggle if a mouse takes over from keyboard. parentMenuItem.addEventListener( 'mouseleave', function( e ) { window.kadence.toggleSubMenu( e.target, false ); } ); // When we focus on a menu link, make sure all siblings are closed. parentMenuItem.querySelector( 'a' ).addEventListener( 'focus', function( e ) { var parentMenuItemsToggled = e.target.parentNode.parentNode.querySelectorAll( 'li.menu-item--toggled-on' ); for ( let j = 0; j < parentMenuItemsToggled.length; j++ ) { if ( parentMenuItem !== parentMenuItemsToggled[ j ] ) { window.kadence.toggleSubMenu( parentMenuItemsToggled[ j ], false ); } } } ); // Handle keyboard accessibility for traversing menu. SUBMENUS[ i ].addEventListener( 'keydown', function( e ) { // 9 is tab KeyMap if ( 9 === e.keyCode ) { var focusSelector = 'ul.toggle-show > li > a, ul.toggle-show > li > .dropdown-nav-special-toggle'; if ( SUBMENUS[ i ].parentNode.classList.contains('kadence-menu-mega-enabled') ) { focusSelector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]'; } if ( e.shiftKey ) { // Means we're tabbing out of the beginning of the submenu. if ( window.kadence.isfirstFocusableElement (SUBMENUS[ i ], document.activeElement, focusSelector ) ) { window.kadence.toggleSubMenu( SUBMENUS[ i ].parentNode, false ); } // Means we're tabbing out of the end of the submenu. } else if ( window.kadence.islastFocusableElement( SUBMENUS[ i ], document.activeElement, focusSelector ) ) { window.kadence.toggleSubMenu( SUBMENUS[ i ].parentNode, false ); } } // 27 is keymap for esc key. if ( e.keyCode === 27 ) { window.kadence.toggleSubMenu( SUBMENUS[ i ].parentNode, false ); // Move the focus back to the toggle. SUBMENUS[ i ].parentNode.querySelector('.dropdown-nav-special-toggle').focus(); } } ); SUBMENUS[ i ].parentNode.classList.add( 'menu-item--has-toggle' ); } } }, /** * Toggle submenus open and closed, and tell screen readers what's going on. * @param {Object} parentMenuItem Parent menu element. * @param {boolean} forceToggle Force the menu toggle. * @return {void} */ toggleSubMenu: function( parentMenuItem, forceToggle ) { var toggleButton = parentMenuItem.querySelector( '.dropdown-nav-special-toggle' ), subMenu = parentMenuItem.querySelector( 'ul' ); let parentMenuItemToggled = parentMenuItem.classList.contains( 'menu-item--toggled-on' ); var dropdown_label = parentMenuItem.querySelector( '.nav-drop-title-wrap' ).firstChild.textContent.trim(); // Will be true if we want to force the toggle on, false if force toggle close. if ( undefined !== forceToggle && 'boolean' === ( typeof forceToggle ) ) { parentMenuItemToggled = ! forceToggle; } // Toggle aria-expanded status. toggleButton.setAttribute( 'aria-expanded', ( ! parentMenuItemToggled ).toString() ); /* * Steps to handle during toggle: * - Let the parent menu item know we're toggled on/off. * - Toggle the ARIA label to let screen readers know will expand or collapse. */ if ( parentMenuItemToggled ) { // Toggle "off" the submenu. setTimeout(function () { parentMenuItem.classList.remove( 'menu-item--toggled-on' ); subMenu.classList.remove( 'toggle-show' ); toggleButton.setAttribute( 'aria-label', ( dropdown_label ? kadenceConfig.screenReader.expandOf + ' ' + dropdown_label : kadenceConfig.screenReader.expand ) ); }, 5); // Make sure all children are closed. var subMenuItemsToggled = parentMenuItem.querySelectorAll( '.menu-item--toggled-on' ); for ( let i = 0; i < subMenuItemsToggled.length; i++ ) { window.kadence.toggleSubMenu( subMenuItemsToggled[ i ], false ); } } else { // Make sure siblings are closed. var parentMenuItemsToggled = parentMenuItem.parentNode.querySelectorAll( 'li.menu-item--toggled-on' ); for ( let i = 0; i < parentMenuItemsToggled.length; i++ ) { window.kadence.toggleSubMenu( parentMenuItemsToggled[ i ], false ); } // Toggle "on" the submenu. parentMenuItem.classList.add( 'menu-item--toggled-on' ); subMenu.classList.add( 'toggle-show' ); toggleButton.setAttribute( 'aria-label', ( dropdown_label ? kadenceConfig.screenReader.collapseOf + ' ' + dropdown_label : kadenceConfig.screenReader.collapse ) ); } }, /** * Returns true if element is the * first focusable element in the container. * @param {Object} container * @param {Object} element * @param {string} focusSelector * @return {boolean} whether or not the element is the first focusable element in the container */ isfirstFocusableElement: function( container, element, focusSelector ) { var focusableElements = container.querySelectorAll( focusSelector ); if ( 0 < focusableElements.length ) { return element === focusableElements[ 0 ]; } return false; }, /** * Returns true if element is the * last focusable element in the container. * @param {Object} container * @param {Object} element * @param {string} focusSelector * @return {boolean} whether or not the element is the last focusable element in the container */ islastFocusableElement: function( container, element, focusSelector ) { var focusableElements = container.querySelectorAll( focusSelector ); //console.log( focusableElements ); if ( 0 < focusableElements.length ) { return element === focusableElements[ focusableElements.length - 1 ]; } return false; }, /** * Initiate the script to process all drawer toggles. */ toggleDrawer: function( element, changeFocus ) { changeFocus = (typeof changeFocus !== 'undefined') ? changeFocus : true; var toggle = element; var target = document.querySelector( toggle.dataset.toggleTarget ); var _doc = document; var scrollBar = window.innerWidth - document.documentElement.clientWidth; var duration = ( toggle.dataset.toggleDuration ? toggle.dataset.toggleDuration : 250 ); window.kadence.toggleAttribute( toggle, 'aria-expanded', 'true', 'false' ); if ( target.classList.contains('show-drawer') ) { if ( toggle.dataset.toggleBodyClass ) { _doc.body.classList.remove( toggle.dataset.toggleBodyClass ); } // Hide the drawer. target.classList.remove('active'); target.classList.remove('pop-animated'); _doc.body.classList.remove( 'kadence-scrollbar-fixer' ); setTimeout(function () { target.classList.remove('show-drawer'); if ( toggle.dataset.setFocus && changeFocus ) { var focusElement = document.querySelector(toggle.dataset.setFocus); if ( focusElement ) { focusElement.focus(); if ( focusElement.hasAttribute( 'aria-expanded') ) { window.kadence.toggleAttribute( focusElement, 'aria-expanded', 'true', 'false' ); } } } }, duration); } else { // Show the drawer. target.classList.add('show-drawer'); // Toggle body class if ( toggle.dataset.toggleBodyClass ) { _doc.body.classList.toggle( toggle.dataset.toggleBodyClass ); if ( toggle.dataset.toggleBodyClass.includes( 'showing-popup-drawer-' ) ) { _doc.body.style.setProperty('--scrollbar-offset', scrollBar + 'px' ); _doc.body.classList.add( 'kadence-scrollbar-fixer' ); } } setTimeout(function () { target.classList.add('active'); if ( toggle.dataset.setFocus, changeFocus ) { var focusElement = document.querySelector(toggle.dataset.setFocus); if ( focusElement ) { if ( focusElement.hasAttribute( 'aria-expanded') ) { window.kadence.toggleAttribute( focusElement, 'aria-expanded', 'true', 'false' ); } var searchTerm = focusElement.value; focusElement.value = ''; focusElement.focus(); focusElement.value = searchTerm; } } }, 10); setTimeout(function () { target.classList.add('pop-animated'); }, duration); // Keep Focus in Modal if ( target.classList.contains('popup-drawer') ) { // add all the elements inside modal which you want to make focusable var focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'; var focusableContent = target.querySelectorAll( focusableElements ); var firstFocusableElement = focusableContent[0]; // get first element to be focused inside modal var lastFocusableElement = focusableContent[ focusableContent.length - 1 ]; // get last element to be focused inside modal document.addEventListener( 'keydown', function(e) { let isTabPressed = e.key === 'Tab' || e.keyCode === 9; if ( ! isTabPressed ) { return; } if ( e.shiftKey ) { // if shift key pressed for shift + tab combination if ( document.activeElement === firstFocusableElement ) { lastFocusableElement.focus(); // add focus for the last focusable element e.preventDefault(); } } else { // if tab key is pressed if ( document.activeElement === lastFocusableElement ) { // if focused has reached to last focusable element then focus first focusable element after pressing tab firstFocusableElement.focus(); // add focus for the first focusable element e.preventDefault(); } } }); } } }, /** * Initiate the script to process all * navigation menus with small toggle enabled. */ initToggleDrawer: function() { var drawerTOGGLE = document.querySelectorAll( '.drawer-toggle' ); // No point if no drawers. if ( ! drawerTOGGLE.length ) { return; } for ( let i = 0; i < drawerTOGGLE.length; i++ ) { drawerTOGGLE[ i ].addEventListener('click', function( event ) { event.preventDefault(); window.kadence.toggleDrawer( drawerTOGGLE[ i ] ); } ); } // Close Drawer if esc is pressed. document.addEventListener( 'keyup', function (event) { // 27 is keymap for esc key. if ( event.keyCode === 27 ) { if ( document.querySelectorAll( '.popup-drawer.show-drawer.active' ) ) { event.preventDefault(); document.querySelectorAll( '.popup-drawer.show-drawer.active' ).forEach(function ( element ) { window.kadence.toggleDrawer( document.querySelector('*[data-toggle-target="' + element.dataset.drawerTargetString + '"]' ) ); } ); } } }); // Close modal on outside click. document.addEventListener( 'click', function (event) { var target = event.target; var modal = document.querySelector( '.show-drawer.active .drawer-overlay' ); if ( target === modal ) { window.kadence.toggleDrawer(document.querySelector('*[data-toggle-target="' + modal.dataset.drawerTargetString + '"]')); } } ); }, /** * Initiate the script to process all * navigation menus with small toggle enabled. */ initMobileToggleSub: function() { var modalMenus = document.querySelectorAll( '.has-collapse-sub-nav' ); modalMenus.forEach( function( modalMenu ) { var activeMenuItem = modalMenu.querySelector( '.current-menu-item' ); if ( activeMenuItem ) { window.kadence.findParents( activeMenuItem, 'li' ).forEach( function( element ) { var subMenuToggle = element.querySelector( '.drawer-sub-toggle' ); if ( subMenuToggle ) { window.kadence.toggleDrawer( subMenuToggle, true ); } } ); } } ); var drawerSubTOGGLE = document.querySelectorAll( '.drawer-sub-toggle' ); // No point if no drawers. if ( ! drawerSubTOGGLE.length ) { return; } for ( let i = 0; i < drawerSubTOGGLE.length; i++ ) { drawerSubTOGGLE[ i ].addEventListener('click', function (event) { event.preventDefault(); window.kadence.toggleDrawer( drawerSubTOGGLE[ i ] ); } ); } }, /** * Initiate the script to process all * navigation menus check to close mobile. */ initMobileToggleAnchor: function() { var mobileModal = document.getElementById( 'mobile-drawer' ); // No point if no drawers. if ( ! mobileModal ) { return; } var menuLink = mobileModal.querySelectorAll( 'a:not(.kt-tab-title)' ); // No point if no links. if ( ! menuLink.length ) { return; } for ( let i = 0; i < menuLink.length; i++ ) { menuLink[ i ].addEventListener('click', function (event) { window.kadence.toggleDrawer( mobileModal.querySelector( '.menu-toggle-close' ), false ); } ); } }, /** * Initiate setting the top padding for hero title when page is transparent. */ initTransHeaderPadding: function() { if ( document.body.classList.contains( 'no-header' ) ) { return; } if ( ! document.body.classList.contains( 'transparent-header' ) || ! document.body.classList.contains( 'mobile-transparent-header' ) ) { return; } var titleHero = document.querySelector( '.entry-hero-container-inner' ), header = document.querySelector( '#masthead' ); var updateHeroPadding = function( e ) { header if ( kadenceConfig.breakPoints.desktop <= window.innerWidth ) { if ( ! document.body.classList.contains( 'transparent-header' ) ) { titleHero.style.paddingTop = 0; } else { titleHero.style.paddingTop = header.offsetHeight + 'px'; } } else { if ( ! document.body.classList.contains( 'mobile-transparent-header' ) ) { titleHero.style.paddingTop = 0; } else { titleHero.style.paddingTop = header.offsetHeight + 'px'; } } } if ( titleHero ) { window.addEventListener( 'resize', updateHeroPadding, false ); window.addEventListener( 'scroll', updateHeroPadding, false ); window.addEventListener( 'load', updateHeroPadding, false ); updateHeroPadding(); } }, getTopOffset: function() { var activeScrollOffsetTop = 0, activeScrollAdminOffsetTop = 0; if ( kadenceConfig.breakPoints.desktop <= window.innerWidth ) { if ( document.body.classList.contains( 'admin-bar' ) ) { activeScrollAdminOffsetTop = 32; } } else { activeScrollAdminOffsetTop = 0; } return Math.floor( activeScrollOffsetTop + activeScrollAdminOffsetTop ); }, /** * Initiate the sticky sidebar. */ initStickySidebar: function() { if ( ! document.body.classList.contains( 'has-sticky-sidebar' ) ) { return; } var offsetSticky = window.kadence.getTopOffset(), sidebar = document.querySelector( '#secondary .sidebar-inner-wrap' ); sidebar.style.top = Math.floor( offsetSticky + 20 ) + 'px'; sidebar.style.maxHeight = 'calc( 100vh - ' + Math.floor( offsetSticky + 20 ) + 'px )'; }, initClickToOpen: function () { // Find all <li> elements with the `menu-item--has-toggle` class const toggleItems = document.querySelectorAll('li.menu-item--has-toggle'); toggleItems.forEach(function (item) { const anchor = item.querySelector('a'); // Find the first child anchor inside <li> const button = item.querySelector('button[class="dropdown-nav*"]'); // Find a button if it exists [anchor, button].forEach(function (clickableTarget) { if (clickableTarget) { clickableTarget.addEventListener('click', function (e) { e.preventDefault(); // Prevent default action for <a> or <button> // Toggle the 'opened' class on the first child `ul.sub-menu` const submenu = item.querySelector('ul.sub-menu'); if (submenu) { const isOpen = submenu.classList.contains('opened'); submenu.classList.toggle('opened', !isOpen); // Toggle the 'opened' class // Close other open submenus at the same level const siblings = Array.from(item.parentNode.children).filter(sibling => sibling !== item); siblings.forEach(function (sibling) { const siblingSubmenu = sibling.querySelector(':scope > ul.sub-menu'); if (siblingSubmenu) { siblingSubmenu.classList.remove('opened'); // Close sibling submenus } }); // Add a `click` listener on the document to close the menu when clicking outside if (!isOpen) { // If opening the menu, add the event listener const handleClickOutside = (event) => { if (!item.contains(event.target)) { submenu.classList.remove('opened'); // Close the submenu document.removeEventListener('click', handleClickOutside); // Remove the listener } }; document.addEventListener('click', handleClickOutside); } } }); } }); }); }, // Initiate the menus when the DOM loads. init: function() { window.kadence.initNavToggleSubmenus(); window.kadence.initToggleDrawer(); window.kadence.initMobileToggleAnchor(); window.kadence.initMobileToggleSub(); window.kadence.initOutlineToggle(); window.kadence.initStickySidebar(); window.kadence.initTransHeaderPadding(); window.kadence.initClickToOpen(); } } if ( 'loading' === document.readyState ) { // The DOM has not yet been loaded. document.addEventListener( 'DOMContentLoaded', window.kadence.init ); } else { // The DOM has already been loaded. window.kadence.init(); } })();