1/** 2 * File fronend.js 3 * 4 * Handles toggling the navigation menu for small screens and enables tab 5 * support for dropdown menus. 6 * 7 * @package Astra 8 */ 9 10/** 11 * Get all of an element's parent elements up the DOM tree 12 * 13 * @param {Node} elem The element. 14 * @param {String} selector Selector to match against [optional]. 15 * @return {Array} The parent elements. 16 */ 17var astraGetParents = function ( elem, selector ) { 18 19 // Setup parents array. 20 var parents = []; 21 22 // Get matching parent elements. 23 for ( ; elem && elem !== document; elem = elem.parentNode ) { 24 25 // Add matching parents to array. 26 if ( selector ) { 27 if ( elem.matches( selector ) ) { 28 parents.push( elem ); 29 } 30 } else { 31 parents.push( elem ); 32 } 33 } 34 return parents; 35}; 36 37 38/** 39 * Toggle Class funtion 40 * 41 * @param {Node} elem The element. 42 * @param {String} selector Selector to match against [optional]. 43 * @return {Array} The parent elements. 44 */ 45var astraToggleClass = function ( el, className ) { 46 if ( el.classList.contains( className ) ) { 47 el.classList.remove( className ); 48 } else { 49 el.classList.add( className ); 50 } 51}; 52 53 54/** 55 * Trigget custom JS Event. 56 * 57 * @since 1.4.6 58 * 59 * @link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent 60 * @param {Node} el Dom Node element on which the event is to be triggered. 61 * @param {Node} typeArg A DOMString representing the name of the event. 62 * @param {String} A CustomEventInit dictionary, having the following fields: 63 * "detail", optional and defaulting to null, of type any, that is an event-dependent value associated with the event. 64 */ 65var astraTriggerEvent = function astraTriggerEvent( el, typeArg ) { 66 var customEventInit = 67 arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 68 69 var event = new CustomEvent(typeArg, customEventInit); 70 el.dispatchEvent(event); 71}; 72 73/** 74 * Scroll to ID/Top with smooth scroll behavior. 75 * 76 * @since x.x.x 77 * 78 * @param {Event} e Event which is been fired. 79 * @param {String} top offset from top. 80 */ 81astraSmoothScroll = function astraSmoothScroll( e, top ) { 82 e.preventDefault(); 83 window.scrollTo({ 84 top: top, 85 left: 0, 86 behavior: 'smooth' 87 }); 88}; 89 90/** 91 * Scroll to Top trigger visibility adjustments. 92 * 93 * @since x.x.x 94 * 95 * @param {Node} masthead Page header. 96 * @param {Node} astScrollTop Scroll to Top selector. 97 */ 98astScrollToTopHandler = function ( masthead, astScrollTop ) { 99 100 var content = getComputedStyle(astScrollTop).content, 101 device = astScrollTop.dataset.onDevices; 102 content = content.replace( /[^0-9]/g, '' ); 103 104 if( 'both' == device || ( 'desktop' == device && '769' == content ) || ( 'mobile' == device && '' == content ) ) { 105 // Get current window / document scroll. 106 var scrollTop = window.pageYOffset || document.body.scrollTop; 107 // If masthead found. 108 if( masthead && masthead.length ) { 109 if (scrollTop > masthead.offsetHeight + 100) { 110 astScrollTop.style.display = "block"; 111 } else { 112 astScrollTop.style.display = "none"; 113 } 114 } else { 115 // If there is no masthead set default start scroll 116 if ( window.pageYOffset > 300 ) { 117 astScrollTop.style.display = "block"; 118 } else { 119 astScrollTop.style.display = "none"; 120 } 121 } 122 } else { 123 astScrollTop.style.display = "none"; 124 } 125}; 126 127( function() { 128 129 var menu_toggle_all = document.querySelectorAll( '#masthead .main-header-menu-toggle' ), 130 main_header_masthead = document.getElementById('masthead'), 131 menu_click_listeners_nav = {}, 132 mobileHeaderType = '', 133 body = document.body, 134 mobileHeader = ''; 135 136 if ( undefined !== main_header_masthead && null !== main_header_masthead ) { 137 138 mobileHeader = main_header_masthead.querySelector("#ast-mobile-header"); 139 } 140 141 if ( '' !== mobileHeader && null !== mobileHeader ) { 142 143 mobileHeaderType = mobileHeader.dataset.type; 144 } 145 146 document.addEventListener( 'astMobileHeaderTypeChange', updateHeaderType, false ); 147 148 /** 149 * Updates the header type. 150 */ 151 function updateHeaderType( e ) { 152 mobileHeaderType = e.detail.type; 153 var popupTrigger = document.querySelectorAll( '.menu-toggle' ); 154 155 if( 'dropdown' === mobileHeaderType ) { 156 157 document.getElementById( 'ast-mobile-popup' ).classList.remove( 'active', 'show' ); 158 updateTrigger('updateHeader'); 159 } 160 161 if ( 'off-canvas' === mobileHeaderType ) { 162 popupTrigger.forEach(function (trigger) { 163 if (trigger && trigger.classList.contains('toggled')) { 164 trigger.click(); 165 } 166 }); 167 } 168 169 init(mobileHeaderType); 170 } 171 172 function syncToggledClass() { 173 const buttons = document.querySelectorAll('.menu-toggle'); 174 const allToggled = Array.from(buttons).every(button => button.classList.contains('toggled')); 175 176 buttons.forEach(button => { 177 if (allToggled) { 178 button.classList.remove('toggled'); 179 button.setAttribute('aria-expanded', 'false'); 180 } else { 181 button.classList.add('toggled'); 182 button.setAttribute('aria-expanded', 'true'); 183 } 184 }); 185 } 186 187 document.addEventListener('click', function (e) { 188 const button = e.target.closest('.menu-toggle'); 189 if (button && mobileHeaderType === 'dropdown') { 190 if (typeof astraAddon === 'undefined') { 191 button.classList.toggle('toggled'); 192 syncToggledClass(); 193 } 194 const isToggled = button.classList.contains('toggled'); 195 button.setAttribute('aria-expanded', isToggled ? 'true' : 'false'); 196 } 197 }); 198 199 200 /** 201 * Opens the Popup when trigger is clicked. 202 */ 203 popupTriggerClick = function ( event ) { 204 205 var triggerType = event.currentTarget.trigger_type; 206 var popupWrap = document.getElementById( 'ast-mobile-popup' ); 207 208 if ( ! body.classList.contains( 'ast-popup-nav-open' ) ) { 209 body.classList.add( 'ast-popup-nav-open' ); 210 } 211 212 if ( ! body.classList.contains( 'ast-main-header-nav-open' ) && 'mobile' !== triggerType ) { 213 body.classList.add( 'ast-main-header-nav-open' ); 214 } 215 216 if ( ! document.documentElement.classList.contains( 'ast-off-canvas-active' ) ) { 217 document.documentElement.classList.add( 'ast-off-canvas-active' ); 218 } 219 220 if ( 'desktop' === triggerType ) { 221 222 popupWrap.querySelector( '.ast-mobile-popup-content' ).style.display = 'none'; 223 popupWrap.querySelector( '.ast-desktop-popup-content' ).style.display = 'block'; 224 } 225 if ( 'mobile' === triggerType ) { 226 227 popupWrap.querySelector( '.ast-desktop-popup-content' ).style.display = 'none'; 228 popupWrap.querySelector( '.ast-mobile-popup-content' ).style.display = 'block'; 229 } 230 if (event && event.currentTarget && event.currentTarget.style) { 231 event.currentTarget.style.display = 'none'; 232 } 233 234 popupWrap.classList.add( 'active', 'show' ); 235 236 const menuToggleClose = document.getElementById( 'menu-toggle-close' ); 237 menuToggleClose?.focus(); 238 } 239 240 /** 241 * Closes the Trigger when Popup is Closed. 242 */ 243 function updateTrigger(currentElement) { 244 mobileHeader = main_header_masthead.querySelector( "#ast-mobile-header" ); 245 var parent_li_sibling = ''; 246 247 if( undefined !== mobileHeader && null !== mobileHeader && 'dropdown' === mobileHeader.dataset.type && 'updateHeader' !== currentElement ) { 248 return; 249 } 250 if ( undefined !== currentElement && 'updateHeader' !== currentElement ) { 251 252 parent_li_sibling = currentElement.closest( '.ast-mobile-popup-inner' ).querySelectorAll('.menu-item-has-children'); 253 254 } else { 255 var popup = document.querySelector( '#ast-mobile-popup' ); 256 parent_li_sibling = popup.querySelectorAll('.menu-item-has-children'); 257 258 } 259 260 parent_li_sibling.forEach((li_sibling) => { 261 li_sibling.classList.remove('ast-submenu-expanded'); 262 263 const all_sub_menu = Array.from(li_sibling.querySelectorAll('.sub-menu')); 264 all_sub_menu.forEach((sub_menu) => { 265 if (!sub_menu.hasAttribute('data-initial-display')) { 266 sub_menu.setAttribute('data-initial-display', window.getComputedStyle(sub_menu).display); 267 } 268 269 if (sub_menu.getAttribute('data-initial-display') === 'block') { 270 sub_menu.style.display = 'block'; 271 } else { 272 sub_menu.style.display = 'none'; 273 } 274 }); 275 }); 276 277 var popupTrigger = document.querySelectorAll( '.menu-toggle' ); 278 279 document.body.classList.remove( 'ast-main-header-nav-open', 'ast-popup-nav-open' ); 280 document.documentElement.classList.remove( 'ast-off-canvas-active' ); 281 282 for ( var item = 0; item < popupTrigger.length; item++ ) { 283 284 popupTrigger[item].classList.remove( 'toggled' ); 285 popupTrigger[item].setAttribute('aria-expanded', 'false'); 286 287 popupTrigger[item].style.display = 'flex'; 288 } 289 } 290
291 /** 292 * Main Init Function. 293 */ 294 function init( mobileHeaderType ) { 295 296 var popupTriggerMobile = document.querySelectorAll( '#ast-mobile-header .menu-toggle' ); 297 var popupTriggerDesktop = document.querySelectorAll( '#ast-desktop-header .menu-toggle' ); 298 299 if ( undefined === mobileHeaderType && null !== main_header_masthead ) { 300 301 mobileHeader = main_header_masthead.querySelector("#ast-mobile-header"); 302 if( mobileHeader ) { 303 mobileHeaderType = mobileHeader.dataset.type; 304 } else { 305 var desktopHeader = main_header_masthead.querySelector("#ast-desktop-header"); 306 if ( desktopHeader ) { 307 308 mobileHeaderType = desktopHeader.dataset.toggleType; 309 } else { 310 return; 311 } 312 } 313 } 314 315 if ( 'off-canvas' === mobileHeaderType ) { 316 var popupClose = document.getElementById( 'menu-toggle-close' ), 317 popupInner = document.querySelector( '.ast-mobile-popup-inner' ); 318 319 if ( undefined === popupInner || null === popupInner ) { 320 return; // if toggel button component is not loaded. 321 } 322 popupLinks = popupInner.getElementsByTagName( 'a' ); 323 324 // --- Focus Trap Implementation Start --- 325 document.removeEventListener( 'keydown', astraOffcanvasTrapTabKey ); 326 327 function astraOffcanvasTrapTabKey( e ) { 328 let popup = document.getElementById( 'ast-mobile-popup' ); 329 if ( ! popup || ! popup.classList.contains( 'active' ) || e.key !== 'Tab' ) { 330 return; 331 } 332 let focusableElements = popupInner.querySelectorAll( 333 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' 334 ); 335 focusableElements = Array.prototype.filter.call( focusableElements, function ( element ) { 336 return ( 337 element.offsetWidth > 0 && element.offsetHeight > 0 && window.getComputedStyle( element ).visibility !== 'hidden' 338 ); 339 } ); 340 if ( focusableElements.length === 0 ) return; 341 let firstElement = focusableElements[ 0 ]; 342 let lastElement = focusableElements[ focusableElements.length - 1 ]; 343 if ( e.shiftKey && document.activeElement === firstElement ) { 344 e.preventDefault(); 345 lastElement.focus(); 346 } else if ( ! e.shiftKey && document.activeElement === lastElement ) { 347 e.preventDefault(); 348 firstElement.focus(); 349 } 350 } 351 document.addEventListener( 'keydown', astraOffcanvasTrapTabKey ); 352 353 // Remove focus trap when menu is closed 354 function removeAstraOffcanvasTrap() { 355 document.removeEventListener( 'keydown', astraOffcanvasTrapTabKey ); 356 } 357 if ( popupClose ) { 358 popupClose.addEventListener( 'click', removeAstraOffcanvasTrap ); 359 } 360 document.addEventListener( 'keyup', function ( event ) { 361 if ( event.key === 'Escape' ) { 362 removeAstraOffcanvasTrap(); 363 } 364 } ); 365 document.addEventListener( 'click', function ( event ) { 366 let target = event.target; 367 let modal = document.querySelector( '.ast-mobile-popup-drawer.active .ast-mobile-popup-overlay' ); 368 if ( target === modal ) { 369 removeAstraOffcanvasTrap(); 370 } 371 } ); 372 373 for ( var item = 0; item < popupTriggerMobile.length; item++ ) { 374 popupTriggerMobile[ item ].removeEventListener( 'click', astraNavMenuToggle, false ); 375 // Open the Popup when click on trigger 376 popupTriggerMobile[ item ].removeEventListener( 'click', popupTriggerClick ); 377 popupTriggerMobile[ item ].addEventListener( 'click', function(event) { 378 event.currentTarget.setAttribute('aria-expanded', 'true'); 379 popupTriggerClick(event); 380 const menu = document.querySelector('.ast-mobile-popup-drawer.active'); 381 if (!menu) { 382 removeAstraOffcanvasTrap(); 383 } 384 }, false ); 385 popupTriggerMobile[ item ].trigger_type = 'mobile'; 386 } 387 for ( var item = 0; item < popupTriggerDesktop.length; item++ ) { 388 popupTriggerDesktop[ item ].removeEventListener( 'click', astraNavMenuToggle, false ); 389 // Open the Popup when click on trigger 390 popupTriggerDesktop[ item ].removeEventListener( 'click', popupTriggerClick ); 391 popupTriggerDesktop[ item ].addEventListener( 'click', function(event) { 392 event.currentTarget.setAttribute('aria-expanded', 'true'); 393 popupTriggerClick(event); 394 }, false ); 395 popupTriggerDesktop[ item ].trigger_type = 'desktop'; 396 } 397 398 // Getting menu toggle button element. 399 const menuToggleButton = document.querySelector( '.ast-button-wrap .menu-toggle' ); 400 401 //Close Popup on CLose Button Click. 402 popupClose.addEventListener( 'click', function ( e ) { 403 document.getElementById( 'ast-mobile-popup' ).classList.remove( 'active', 'show' ); 404 updateTrigger( this ); 405 // Don't focus if we're in an iframe (e.g., Beaver Builder editor) 406 if ( window.self === window.top ) { 407 menuToggleButton?.focus(); 408 } 409 } ); 410 411 // Close Popup if esc is pressed. 412 document.addEventListener( 'keyup', function ( event ) { 413 if ( event.key === 'Escape' ) { 414 event.preventDefault(); 415 document.getElementById( 'ast-mobile-popup' ).classList.remove( 'active', 'show' ); 416 updateTrigger(); 417 menuToggleButton?.focus(); 418 } 419 } ); 420 421 // Close Popup on outside click. 422 document.addEventListener( 'click', function ( event ) { 423 var target = event.target; 424 var modal = document.querySelector( '.ast-mobile-popup-drawer.active .ast-mobile-popup-overlay' ); 425 if ( target === modal ) { 426 document.getElementById( 'ast-mobile-popup' ).classList.remove( 'active', 'show' ); 427 updateTrigger(); 428 menuToggleButton?.focus(); 429 } 430 } ); 431 432 // Close Popup on # link click inside Popup. 433 for ( let link = 0, len = popupLinks.length; link < len; link++ ) { 434 if ( 435 null !== popupLinks[ link ].getAttribute( 'href' ) && 436 ( popupLinks[ link ].getAttribute( 'href' ).startsWith( '#' ) || 437 -1 !== popupLinks[ link ].getAttribute( 'href' ).search( '#' ) ) && 438 ( ! popupLinks[ link ].parentElement.classList.contains( 'menu-item-has-children' ) || 439 ( popupLinks[ link ].parentElement.classList.contains( 'menu-item-has-children' ) && 440 document.querySelector( 'header.site-header' ).classList.contains( 'ast-builder
440-menu-toggle-icon' ) ) ) 441 ) { 442 popupLinks[ link ].addEventListener( 'click', triggerToggleClose, true ); 443 popupLinks[ link ].headerType = 'off-canvas'; 444 } 445 } 446 447 AstraToggleSetup(); 448 } else if ( 'dropdown' === mobileHeaderType ) { 449 450 var mobileDropdownContent = document.querySelectorAll( '.ast-mobile-header-content' ) || false, 451 desktopDropdownContent = document.querySelector( '.ast-desktop-header-content' ) || false; 452 453 // Close Popup on # link click inside Popup. 454 if ( mobileDropdownContent.length > 0 ) { 455 for ( let index = 0; index < mobileDropdownContent.length; index++ ) { 456 var mobileLinks = mobileDropdownContent[ index ].getElementsByTagName( 'a' ); 457 for ( link = 0, len = mobileLinks.length; link < len; link++ ) { 458 // Check if the link is not inside the tabs container 459 const isNotInsideTabsContainer = mobileLinks[ link ].closest( '.wp-block-uagb-tabs' ) === null; 460 461 if ( 462 null !== mobileLinks[ link ].getAttribute( 'href' ) && 463 ( mobileLinks[ link ].getAttribute( 'href' ).startsWith( '#' ) || 464 -1 !== mobileLinks[ link ].getAttribute( 'href' ).search( '#' ) ) && 465 ( ! mobileLinks[ link ].parentElement.classList.contains( 'menu-item-has-children' ) || 466 ( mobileLinks[ link ].parentElement.classList.contains( 'menu-item-has-children' ) && 467 document.querySelector( 'header.site-header' ).classList.contains( 'ast-builder-menu-toggle-icon' ) ) ) && 468 isNotInsideTabsContainer 469 ) { 470 mobileLinks[ link ].addEventListener( 'click', triggerToggleClose, true ); 471 mobileLinks[ link ].headerType = 'dropdown'; 472 } 473 } 474 } 475 } 476 477 // Close Popup on # link click inside Popup. 478 if ( desktopDropdownContent ) { 479 var desktopLinks = desktopDropdownContent.getElementsByTagName( 'a' ); 480 for ( link = 0, len = desktopLinks.length; link < len; link++ ) { 481 desktopLinks[ link ].addEventListener( 'click', triggerToggleClose, true ); 482 desktopLinks[ link ].headerType = 'dropdown'; 483 } 484 } 485 486 for ( var item = 0; item < popupTriggerMobile.length; item++ ) { 487 popupTriggerMobile[ item ].removeEventListener( 'click', popupTriggerClick, false ); 488 popupTriggerMobile[ item ].removeEventListener( 'click', astraNavMenuToggle ); 489 popupTriggerMobile[ item ].addEventListener( 'click', astraNavMenuToggle, false ); 490 popupTriggerMobile[ item ].trigger_type = 'mobile'; 491 } 492 for ( var item = 0; item < popupTriggerDesktop.length; item++ ) { 493 popupTriggerDesktop[ item ].removeEventListener( 'click', popupTriggerClick, false ); 494 popupTriggerDesktop[ item ].removeEventListener( 'click', astraNavMenuToggle ); 495 popupTriggerDesktop[ item ].addEventListener( 'click', astraNavMenuToggle, false ); 496 popupTriggerDesktop[ item ].trigger_type = 'desktop'; 497 } 498 499 AstraToggleSetup(); 500 } 501 502 } 503 504 function triggerToggleClose( event ) { 505 506 var headerType = event.currentTarget.headerType; 507 508 switch( headerType ) { 509 510 case 'dropdown': 511 512 var popupTrigger = document.querySelectorAll( '.menu-toggle.toggled' ); 513 514 for ( var item = 0; item < popupTrigger.length; item++ ) { 515 516 popupTrigger[item].click(); 517 } 518 break; 519 case 'off-canvas': 520 521 var popupClose = document.getElementById( 'menu-toggle-close' ); 522 523 popupClose.click(); 524 break; 525 default: 526 break; 527 } 528 } 529 530 window.addEventListener( 'load', function() { 531 init(); 532 } ); 533 document.addEventListener( 'astLayoutWidthChanged', function() { 534 init(); 535 } ); 536 537 document.addEventListener( 'astPartialContentRendered', function() { 538 539 menu_toggle_all = document.querySelectorAll( '.main-header-menu-toggle' ); 540 541 body.classList.remove("ast-main-header-nav-open"); 542 543 document.addEventListener( 'astMobileHeaderTypeChange', updateHeaderType, false ); 544 545 init(); 546 547 } ); 548 549 var mobile_width = ( null !== navigator.userAgent.match(/Android/i) && 'Android' === navigator.userAgent.match(/Android/i)[0] ) ? window.visualViewport.width : window.innerWidth; 550 551 function AstraHandleResizeEvent() { 552 553 var menu_offcanvas_close = document.getElementById('menu-toggle-close'); 554 var menu_dropdown_close = document.querySelector('.menu-toggle.toggled'); 555 var desktop_header_content = document.querySelector('#masthead > #ast-desktop-header .ast-desktop-header-content'); 556 var elementor_editor = document.querySelector('.elementor-editor-active'); 557 558 if ( desktop_header_content ) { 559 desktop_header_content.style.display = 'none'; 560 } 561 var mobileResizeWidth = ( null !== navigator.userAgent.match(/Android/i) && 'Android' === navigator.userAgent.match(/Android/i)[0] ) ? window.visualVie
561wport.width : window.innerWidth; 562 563 if ( mobileResizeWidth !== mobile_width ) { 564 if ( menu_dropdown_close && null === elementor_editor ) { 565 menu_dropdown_close.click(); 566 } 567 document.body.classList.remove( 'ast-main-header-nav-open', 'ast-popup-nav-open' ); 568 569 if( menu_offcanvas_close && null == elementor_editor ) { 570 menu_offcanvas_close.click(); 571 } 572 } 573 574 updateHeaderBreakPoint(); 575 576 AstraToggleSetup(); 577 578 } 579 580 window.addEventListener('resize', function(){ 581 // Skip resize event when keyboard display event triggers on devices. 582 if( 'INPUT' !== document.activeElement.tagName ) { 583 AstraHandleResizeEvent(); 584 } 585 } ); 586 587 document.addEventListener('DOMContentLoaded', function () { 588 AstraToggleSetup(); 589 /** 590 * Navigation Keyboard Navigation. 591 */ 592 var containerButton; 593 if ( body.classList.contains('ast-header-break-point') ) { 594 containerButton = document.getElementById( 'ast-mobile-header' ); 595 } else { 596 containerButton = document.getElementById( 'ast-desktop-header' ); 597 } 598 599 if( null !== containerButton ) { 600 var containerMenu = containerButton.querySelector( '.navigation-accessibility' ); 601 navigation_accessibility( containerMenu, containerButton ); 602 } 603 }); 604 605 var get_window_width = function () { 606 607 return document.documentElement.clientWidth; 608 } 609 610 /* Add break point Class and related trigger */ 611 var updateHeaderBreakPoint = function () { 612 613 // Use clientWidth directly. The overflow:hidden trick previously used here 614 // caused a visible content jump (scrollbar flash) after the breakpoint class 615 // was pre-applied by the early inline script in wp_body_open. Since 616 // document.documentElement.clientWidth is not affected by content overflow 617 // (unlike window.innerWidth), the overflow manipulation is not needed. 618 var ww = get_window_width(); 619 620 var break_point = astra.break_point; 621 622 /** 623 * This case is when one hits a URL one after the other via `Open in New Tab` option 624 * Chrome returns the value of outer width as 0 in this case. 625 * This mis-calculates the width of the window and header seems invisible. 626 * This could be fixed by using `0 === ww` condition below. 627 */ 628 if (ww > break_point || 0 === ww) { 629 //remove menu toggled class. 630 if ( menu_toggle_all.length > 0 ) { 631 632 for (var i = 0; i < menu_toggle_all.length; i++) { 633 634 if( null !== menu_toggle_all[i] ) { 635 menu_toggle_all[i].classList.remove('toggled'); 636 } 637 } 638 } 639 body.classList.remove("ast-header-break-point"); 640 body.classList.add("ast-desktop"); 641 astraTriggerEvent(body, "astra-header-responsive-enabled"); 642 643 } else { 644 645 body.classList.add("ast-header-break-point"); 646 body.classList.remove("ast-desktop"); 647 astraTriggerEvent(body, "astra-header-responsive-disabled") 648 } 649 } 650 651 updateHeaderBreakPoint(); 652 body.classList.add( 'ast-header-loaded' ); 653 654 AstraToggleSubMenu = function( event ) { 655 656 event.preventDefault(); 657 658 659 if ('false' === event.target.getAttribute('aria-expanded') || ! event.target.getAttribute('aria-expanded')) { 660 event.target.setAttribute('aria-expanded', 'true'); 661 } else { 662 event.target.setAttribute('aria-expanded', 'false'); 663 } 664 665 var parent_li = this.parentNode; 666 667 if ( parent_li.classList.contains('ast-submenu-expanded') && document.querySelector('header.site-header').classList.contains('ast-builder-menu-toggle-link') ) { 668 669 if (!this.classList.contains('ast-menu-toggle')) { 670 671 var link = parent_li.querySelector('a').getAttribute('href'); 672 if ( '' !== link && '#' !== link) { 673 window.location = link; 674 } 675 } 676 } 677 678 var parent_li_child = parent_li.querySelectorAll('.menu-item-has-children'); 679 for (var j = 0; j < parent_li_child.length; j++) { 680 681 parent_li_child[j].classList.remove('ast-submenu-expanded'); 682 var parent_li_child_sub_menu = parent_li_child[j].querySelector('.sub-menu, .children'); 683 if( null !== parent_li_child_sub_menu ) { 684 parent_li_child_sub_menu.style.display = 'none'; 685 } 686 } 687 688 var parent_li_sibling = parent_li.parentNode.querySelectorAll('.menu-item-has-children'); 689 for (var j = 0; j < parent_li_sibling.length; j++) { 690 691 if (parent_li_sibling[j] != parent_li) { 692 693 parent_li_sibling[j].classList.remove('ast-submenu-expanded'); 694 var all_sub_menu = parent_li_sibling[j].querySelectorAll('.sub-menu'); 695 for (var k = 0; k < all_sub_menu.length; k++) { 696 all_sub_menu[k].style.display = 'none'; 697 } 698 } 699 } 700 701 if (parent_li.classList.contains('menu-item-has-children') ) { 702 astraToggleClass(parent_li, 'ast-submenu-expanded'); 703 if (parent_li.classList.contains('ast-submenu-expanded')) { 704 parent_li.querySelector('.sub-menu').style.display = 'block'; 705 } else { 706 parent_li.querySelector('.sub-menu').style.display = 'none'; 707 } 708 } 709 }; 710 711 AstraToggleSetup = function () { 712 713 if( typeof astraAddon != 'undefined' && typeof astraToggleSetupPro === "function" ) { 714 astraToggleSetupPro( mobileHeaderType, body, menu_click_listeners_nav ); 715 } else { 716 var flag = false;
717 var menuToggleAllLength; 718 if ( 'off-canvas' === mobileHeaderType || 'full-width' === mobileHeaderType ) { 719 // comma separated selector added, if menu is outside of Off-Canvas then submenu is not clickable, it work only for Off-Canvas area with dropdown style. 720 var __main_header_all = document.querySelectorAll( '#ast-mobile-popup, #ast-mobile-header' ); 721 var menu_toggle_all = document.querySelectorAll('#ast-mobile-header .main-header-menu-toggle'); 722 723 menuToggleAllLength = menu_toggle_all.length; 724 } else { 725 var __main_header_all = document.querySelectorAll( '#ast-mobile-header' ), 726 menu_toggle_all = document.querySelectorAll('#ast-mobile-header .main-header-menu-toggle'); 727 menuToggleAllLength = menu_toggle_all.length; 728 flag = menuToggleAllLength > 0 ? false : true; 729 730 menuToggleAllLength = flag ? 1 : menuToggleAllLength; 731 732 } 733 734 if ( menuToggleAllLength > 0 || flag ) { 735 736 for (var i = 0; i < menuToggleAllLength; i++) { 737 738 if ( ! flag ) { 739 740 menu_toggle_all[i].setAttribute('data-index', i); 741 742 if ( ! menu_click_listeners_nav[i] ) { 743 menu_click_listeners_nav[i] = menu_toggle_all[i]; 744 menu_toggle_all[i].removeEventListener('click', astraNavMenuToggle); 745 menu_toggle_all[i].addEventListener('click', astraNavMenuToggle, false); 746 } 747 } 748 749 if ('undefined' !== typeof __main_header_all[i]) { 750 751 // To handle the comma seprated selector added above we need this loop. 752 for( var mainHeaderCount =0; mainHeaderCount < __main_header_all.length; mainHeaderCount++ ){ 753 754 if (document.querySelector('header.site-header').classList.contains('ast-builder-menu-toggle-link')) { 755 var astra_menu_toggle = __main_header_all[mainHeaderCount].querySelectorAll('ul.main-header-menu .menu-item-has-children > .menu-link, ul.main-header-menu .ast-menu-toggle'); 756 } else { 757 var astra_menu_toggle = __main_header_all[mainHeaderCount].querySelectorAll('ul.main-header-menu .ast-menu-toggle'); 758 } 759 // Add Eventlisteners for Submenu. 760 if (astra_menu_toggle.length > 0) { 761 762 for (var j = 0; j < astra_menu_toggle.length; j++) { 763 astra_menu_toggle[j].removeEventListener('click', AstraToggleSubMenu); 764 astra_menu_toggle[j].addEventListener('click', AstraToggleSubMenu, false); 765 } 766 } 767 } 768 } 769 } 770 } 771 } 772 }; 773 774 astraNavMenuToggle = function ( event ) { 775 776 if( typeof astraAddon != 'undefined' ) { 777 astraNavMenuTogglePro( event, body, mobileHeaderType, this ); 778 } else { 779 780 event.preventDefault(); 781 var __main_header_all = document.querySelectorAll('#masthead > #ast-mobile-header .main-header-bar-navigation'); 782 menu_toggle_all = document.querySelectorAll( '#masthead > #ast-mobile-header .main-header-menu-toggle' ) 783 var event_index = '0'; 784 785 if ( null !== this.closest( '#ast-fixed-header' ) ) { 786 787 __main_header_all = document.querySelectorAll('#ast-fixed-header > #ast-mobile-header .main-header-bar-navigation'); 788 menu_toggle_all = document.querySelectorAll( '#ast-fixed-header .main-header-menu-toggle' ) 789 790 event_index = '0'; 791 } 792 793 if ('undefined' === typeof __main_header_all[event_index]) { 794 return false; 795 } 796 var menuHasChildren = __main_header_all[event_index].querySelectorAll('.menu-item-has-children'); 797 for (var i = 0; i < menuHasChildren.length; i++) { 798 menuHasChildren[i].classList.remove('ast-submenu-expanded'); 799 var menuHasChildrenSubMenu = menuHasChildren[i].querySelectorAll('.sub-menu'); 800 for (var j = 0; j < menuHasChildrenSubMenu.length; j++) { 801 menuHasChildrenSubMenu[j].style.display = 'none'; 802 } 803 } 804 805 var menu_class = this.getAttribute('class') || ''; 806 807 if ( menu_class.indexOf('main-header-menu-toggle') !== -1 ) { 808 astraToggleClass(__main_header_all[event_index], 'toggle-on'); 809 astraToggleClass(menu_toggle_all[event_index], 'toggled'); 810 if (__main_header_all[event_index].classList.contains('toggle-on')) { 811 __main_header_all[event_index].style.display = 'block'; 812 body.classList.add("ast-main-header-nav-open"); 813 } else { 814 __main_header_all[event_index].style.display = ''; 815 body.classList.remove("ast-main-header-nav-open"); 816 } 817 } 818 } 819 }; 820 821 body.addEventListener("astra-header-responsive-enabled", function () { 822 823 var __main_header_all = document.querySelectorAll('.main-header-bar-navigation'); 824 825 if (__main_header_all.length > 0) { 826 827 for (var i = 0; i < __main_header_all.length; i++) { 828 if (null != __main_header_all[i]) { 829 __main_header_all[i].classList.remove('toggle-on'); 830 __main_header_all[i].style.display = ''; 831 } 832 833 var sub_menu = __main_header_all[i].getElementsByClassName('sub-menu'); 834 for (var j = 0; j < sub_menu.length; j++) { 835 sub_menu[j].style.display = ''; 836 } 837 var child_menu = __main_header_all[i].getElementsByClassName('children'); 838 for (var k = 0; k < child_menu.length; k++) { 839 child_menu[k].style.display = ''; 840 } 841 842 var searchIcons = __main_header_all[i].getElementsByClassName('ast-search-menu-icon'); 843 for (var l = 0; l < searchIcons.length; l++) { 844 searchIcons[l].classList.remove('ast-dropdown-active'); 845 searchIcons[l].style.display = ''; 846 } 847 } 848 } 849 }, false); 850 851 852 /* Search Script */ 853 var SearchIcons = document.getElementsByClassName( 'astra-search-icon' ); 854 for (var i = 0; i < SearchIcons.length; i++) { 855 856 SearchIcons[i].onclick = function(event) { 857 if ( this.classList.contains( 'slide-search' ) ) { 858 event.preventDefault(); 859 var sibling = this.parentNode.parentNode.parentNode.querySelector( '.ast-search-menu-icon' ); 860 if ( ! sibling.classList.contains( 'ast-dropdown-active' ) ) { 861 sibling.classList.add( 'ast-dropdown-active' ); 862 sibling.querySelector( '.search-field' ).setAttribute('autocomplete','off'); 863 setTimeout(function() { 864 sibling.querySelector( '.search-field' ).focus(); 865 },200); 866 } else { 867 var searchTerm = sibling.querySelector( '.search-field' ).value || ''; 868 if( '' !== searchTerm ) { 869 sibling.querySelector( '.search-form' ).submit(); 870 } 871 sibling.classList.remove( 'ast-dropdown-active' ); 872 } 873 } 874 } 875 } 876 var SearchInputs = document.querySelectorAll( '.search-field' );
877 SearchInputs.forEach(input => { 878 input.addEventListener('focus', function (e) { 879 var sibling = this.parentNode.parentNode.parentNode.querySelector( '.ast-search-menu-icon' ); 880 if ( sibling ) { 881 astraToggleClass( sibling, 'ast-dropdown-active' ); 882 } 883 }); 884 input.addEventListener('blur', function (e) { 885 var sibling = this.parentNode.parentNode.parentNode.querySelector( '.ast-search-menu-icon' ); 886 if ( sibling ) { 887 sibling.classList.remove( 'ast-dropdown-active' ); 888 astraToggleClass( sibling, 'ast-dropdown-active' ); 889 } 890 }); 891 }); 892 893 /* Hide Dropdown on body click*/ 894 body.onclick = function( event ) { 895 if ( typeof event.target.classList !== 'undefined' ) { 896 if ( ! event.target.classList.contains( 'ast-search-menu-icon' ) && ! event.target.closest( '.ast-search-menu-icon' ) && ! event.target.closest( '.ast-search-icon' ) ) { 897 var dropdownSearchWrap = document.getElementsByClassName( 'ast-search-menu-icon' ); 898 for (var i = 0; i < dropdownSearchWrap.length; i++) { 899 dropdownSearchWrap[i].classList.remove( 'ast-dropdown-active' ); 900 } 901 } 902 } 903 } 904 905 /** 906 * Navigation Keyboard Navigation. 907 */ 908 function navigation_accessibility(containerMenu, containerButton) { 909 if (!containerMenu || !containerButton) { 910 return; 911 } 912 var button = containerButton.getElementsByTagName('button')[0] || containerButton.getElementsByTagName('a')[0]; 913 if (!button || (button.classList.contains('astra-search-icon'))) { 914 return; 915 } 916 var menu = containerMenu.getElementsByTagName('ul')[0]; 917 918 // Hide menu toggle button if menu is empty and return early. 919 if (!menu) { 920 if (!button.classList.contains('custom-logo-link')) { 921 button.style.display = 'none'; 922 } 923 return; 924 } 925 926 if (!menu.className.includes('nav-menu')) { 927 menu.className += ' nav-menu'; 928 } 929 930 document.addEventListener('DOMContentLoaded', function () { 931 if ('off-canvas' === mobileHeaderType) { 932 var popupClose = document.getElementById('menu-toggle-close'); 933 if (popupClose) { 934 popupClose.onclick = function () { 935 var toggled = containerMenu.className.includes('toggled'); 936 containerMenu.className = toggled ? containerMenu.className.replace(' toggled', '') : containerMenu.className + ' toggled'; 937 button.setAttribute('aria-expanded', toggled ? 'false' : 'true'); 938 menu.setAttribute('aria-expanded', toggled ? 'false' : 'true'); 939 }; 940 } 941 } 942 }); 943 944 button.onclick = function () { 945 var toggled = containerMenu.className.includes('toggled'); 946 containerMenu.className = toggled ? containerMenu.className.replace(' toggled', '') : containerMenu.className + ' toggled'; 947 button.setAttribute('aria-expanded', toggled ? 'false' : 'true'); 948 menu.setAttribute('aria-expanded', toggled ? 'false' : 'true'); 949 }; 950 951 if (!astra.is_header_footer_builder_active) { 952 953 // Get all the link elements within the menu. 954 var links = menu.getElementsByTagName('a'); 955 var subMenus = menu.getElementsByTagName('ul'); 956 957 // Set menu items with submenus to aria-haspopup="true". 958 for (var i = 0, len = subMenus.length; i < len; i++) { 959 subMenus[i].parentNode.setAttribute('aria-haspopup', 'true'); 960 } 961 962 // Each time a menu link is focused or blurred, toggle focus. 963 for (var i = 0, len = links.length; i < len; i++) { 964 links[i].addEventListener('focus', toggleFocus, true); 965 links[i].addEventListener('blur', toggleFocus, true); 966 links[i].addEventListener('click', toggleClose, true); 967 } 968 } 969 970 if (astra.is_header_footer_builder_active) { 971 tabNavigation(); 972 } 973 } 974 975 // Tab navigation for accessibility. 976 function tabNavigation() { 977 const dropdownToggleLinks = document.querySelectorAll('nav.site-navigation .menu-item-has-children > a .ast-header-navigation-arrow'); 978 const siteNavigationSubMenu = document.querySelectorAll('nav.site-navigation .sub-menu'); 979 const menuLi = document.querySelectorAll('nav.site-navigation .menu-item-has-children'); 980 const megaMenuFullWidth = document.querySelectorAll('.astra-full-megamenu-wrapper'); 981 982 if (dropdownToggleLinks) { 983 dropdownToggleLinks.forEach(element => { 984 element.addEventListener('keydown', function (e) { 985 if ('Enter' === e.key || ' ' === e.key) { 986 // Check if the user is on a mobile device and prevent default and stop propagation if true. 987 if ( /Mobi|Android|iPad|iPhone/i.test( navigator.userAgent ) ) { 988 e.preventDefault(); 989 e.stopPropagation(); 990 } 991 992 const closestLi = e.target.closest('li'); 993 const subMenu = closestLi.querySelector('.sub-menu'); 994 const isMegaMenu = subMenu && subMenu.classList.contains('astra-megamenu'); 995 996 setTimeout(() => { 997 if (!isMegaMenu) { 998 subMenu.classList.toggle('toggled-on'); 999 closestLi.classList.toggle('ast-menu-hover'); 1000 } else { 1001 const fullMegaMenuWrapper = closestLi.querySelector('.astra-full-megamenu-wrapper'); 1002 if (subMenu) subMenu.classList.toggle('astra-megamenu-focus'); 1003 if (fullMegaMenuWrapper) fullMegaMenuWrapper.classList.toggle('astra-megamenu-wrapper-focus'); 1004 closestLi.classList.toggle('ast-menu-hover'); 1005 } 1006 1007 const ariaExpanded = e.target.getAttribute('aria-expanded'); 1008 e.target.setAttribute('aria-expanded', ariaExpanded === 'false' || !ariaExpanded ? 'true' : 'false'); 1009 }, 10); 1010 } 1011 }); 1012 }); 1013 1014 if (siteNavigationSubMenu || menuLi) { 1015 document.addEventListener('click', function (e) { 1016 closeNavigationMenu(siteNavigationSubMenu, dropdownToggleLinks, menuLi, megaMenuFullWidth); 1017 }, false); 1018 1019 document.addEventListener('keydown', function (e) { 1020 if ('Escape' === e.key) { 1021 closeNavigationMenu(siteNavigationSubMenu, dropdownToggleLinks, menuLi, megaMenuFullWidth); 1022 } 1023 }, false); 1024 } 1025 } 1026 1027 const allParentMenu = document.querySelectorAll('nav.site-navigation .ast-nav-menu > .menu-item-has-children > a .ast-header-navigation-arrow'); 1028 1029 if (allParentMenu) { 1030 allParentMenu.forEach(element => { 1031 element.addEventListener('keydown', function (e) { 1032 if (!e.target.closest('li').classList.contains('ast-menu-hover') && 'Enter' === e.key) { 1033 closeNavigationMenu(siteNavigationSubMenu, dropdownToggleLinks, menuLi, megaMenuFullWidth); 1034 } 1035 }, false); 1036 }); 1037 } 1038 1039 const desktopMenu = document.querySelectorAll( '#ast-desktop-header .ast-builder
1039-layout-element.ast-builder-menu' ); 1040 desktopMenu.forEach( menu => { 1041 const desktopMenuItems = menu.querySelectorAll( '.main-header-menu .menu-item > a' ); 1042 desktopMenuItems.forEach( ( item ) => { 1043 item.addEventListener( 'focusout', function( e ) { 1044 const nextFocus = e.relatedTarget; 1045 const nextFocusMenuItem = nextFocus ? nextFocus.closest( '.menu-item' ) : null; 1046 const currentFocus = e.target; 1047 const currentMenuItem = currentFocus.closest( '.menu-item' ); 1048 const subMenuOpened = currentMenuItem.classList.contains( 'ast-menu-hover' ); 1049 const subMenu = currentMenuItem.querySelector( '.sub-menu' ); 1050 const wrapperSubmenu = currentMenuItem.closest('.sub-menu') 1051 const parentMenuItem = currentMenuItem.closest('.sub-menu')?.closest( '.menu-item-has-children' ); 1052 const childMenuItem = currentMenuItem.querySelector( '.menu-item' ); 1053 1054 1055 // If the next focus is the same menu item or a child menu item, don't close the submenu. 1056 if ( 1057 currentMenuItem == nextFocusMenuItem || 1058 ( childMenuItem && childMenuItem == nextFocusMenuItem ) 1059 ) { 1060 return; 1061 } 1062 1063 // If there's no next focus, close all submenus. 1064 if( nextFocusMenuItem == null ) { 1065 if ( wrapperSubmenu ) 1066 recursiveMenuCloseOnblur( wrapperSubmenu ); 1067 if ( subMenu ) 1068 recursiveMenuCloseOnblur( subMenu ); 1069 return; 1070 } 1071 1072 // If the next focus is the next or previous sibling, don't close all the submenu. 1073 if ( 1074 currentMenuItem.nextElementSibling == nextFocusMenuItem || 1075 currentMenuItem.previousElementSibling == nextFocusMenuItem 1076 ) { 1077 // If the submenu is opened, close it and remove the 'ast-menu-hover' class. 1078 if( subMenuOpened ) { 1079 recursiveMenuCloseOnblur( subMenu, false ); 1080 currentMenuItem.classList.remove( 'ast-menu-hover' ); 1081 } 1082 return; 1083 } 1084 1085 // If the next focus is the parent menu item, close the submenu till the inner child menu item submenu 1086 if ( parentMenuItem && parentMenuItem == nextFocusMenuItem ) { 1087 childSubMenu = currentMenuItem.querySelector( '.sub-menu' ); 1088 recursiveMenuCloseOnblur( childSubMenu, false ); 1089 return; 1090 } 1091 1092 // Here we are setting a depth level point while traversing from lower to upper submenu parents. 1093 // The next focus is the next sibling of any of the parent elements in the tree, then close submenus till that level. 1094 let tempParent = parentMenuItem; 1095 let subMenuCloseEnd = null; 1096 while ( tempParent != null ) { 1097 if( tempParent.nextElementSibling == nextFocusMenuItem ) { 1098 subMenuCloseEnd = tempParent.querySelector( '.sub-menu' ); 1099 break; 1100 } 1101 tempParent = tempParent.closest('.sub-menu')?.closest( '.menu-item-has-children' ); 1102 } 1103 1104 // Closes all the menus. 1105 if( wrapperSubmenu ) 1106 recursiveMenuCloseOnblur( wrapperSubmenu, true, subMenuCloseEnd ); 1107 1108 }); 1109 }); 1110 }); 1111 } 1112 1113 // Recursively closes the submenu upwards 1114 function recursiveMenuCloseOnblur( submenu, recursive = true, bubblingEnd = null ) { 1115 /** 1116 * Close the submenu 1117 */ 1118 submenu.classList.remove( 'toggled-on' ); 1119 submenu.classList.remove( 'astra-megamenu-focus' ); 1120 const toggle = submenu.closest( '.menu-item-has-children' ).querySelector( '.ast-header-navigation-arrow' ); 1121 if ( toggle ) { 1122 toggle.setAttribute( 'aria-expanded', 'false' ); 1123 } 1124 1125 /** 1126 * If there's a bubbling end, set recursive to true. This recursive closing 1127 * the submenu upwards will end till this bubbleEnd element referenced at line 1168 1128 **/ 1129 if ( bubblingEnd ) { 1130 recursive = true; 1131 } 1132 1133 if( ! recursive ) { 1134 return; 1135 } 1136 1137 const parentSubmenu = submenu.parentElement.closest( '.sub-menu' ); 1138 1139 // If there's a parent submenu, close it and continue closing upwards. 1140 if( null !== parentSubmenu && submenu !== bubblingEnd ) { 1141 recursiveMenuCloseOnblur( parentSubmenu, true, bubblingEnd ); 1142 } 1143 } 1144 1145 function closeNavigationMenu(siteNavigationSubMenu, dropdownToggleLinks, menuLi, megaMenuFullWidth) { 1146 if (siteNavigationSubMenu) { 1147 siteNavigationSubMenu.forEach(element => { 1148 element.classList.remove('astra-megamenu-focus'); 1149 element.classList.remove('toggled-on'); 1150 }); 1151 } 1152 1153 if (menuLi) { 1154 menuLi.forEach(element => { 1155 element.classList.remove('ast-menu-hover'); 1156 }); 1157 } 1158 1159 if (megaMenuFullWidth) { 1160 megaMenuFullWidth.forEach(element => { 1161 element.classList.remove('astra-megamenu-wrapper-focus') 1162 }); 1163 } 1164 1165 1166 if (dropdownToggleLinks) { 1167 dropdownToggleLinks.forEach(element => { 1168 element.setAttribute('aria-expanded', 'false'); 1169 }); 1170 } 1171 } 1172
1173 /** 1174 * Close the Toggle Menu on Click on hash (#) link. 1175 * 1176 * @since 1.3.2 1177 * @return void 1178 */ 1179 function toggleClose( ) 1180 { 1181 var self = this || '', 1182 hash = '#'; 1183 1184 if( self && ! self.classList.contains('astra-search-icon') && null === self.closest('.ast-builder-menu') ) { 1185 var link = String( self ); 1186 if( link.indexOf( hash ) !== -1 ) { 1187 var link_parent = self.parentNode; 1188 if ( body.classList.contains('ast-header-break-point') ) { 1189 if( ! ( document.querySelector('header.site-header').classList.contains('ast-builder-menu-toggle-link') && link_parent.classList.contains('menu-item-has-children') ) ) { 1190 /* Close Builder Header Menu */ 1191 var builder_header_menu_toggle = document.querySelector( '.main-header-menu-toggle' ); 1192 builder_header_menu_toggle.classList.remove( 'toggled' ); 1193 1194 var main_header_bar_navigation = document.querySelector( '.main-header-bar-navigation' ); 1195 main_header_bar_navigation.classList.remove( 'toggle-on' ); 1196 1197 main_header_bar_navigation.style.display = 'none'; 1198 1199 astraTriggerEvent( document.querySelector('body'), 'astraMenuHashLinkClicked' ); 1200 } 1201 1202 } else { 1203 while ( -1 === self.className.indexOf( 'nav-menu' ) ) { 1204 // On li elements toggle the class .focus. 1205 if ( 'li' === self.tagName.toLowerCase() ) { 1206 if ( -1 !== self.className.indexOf( 'focus' ) ) { 1207 self.className = self.className.replace( ' focus', '' ); 1208 } 1209 } 1210 self = self.parentElement; 1211 } 1212 } 1213 } 1214 } 1215 } 1216 1217 /** 1218 * Sets or removes .focus class on an element on focus. 1219 */ 1220 function toggleFocus() { 1221 var self = this; 1222 // Move up through the ancestors of the current link until we hit .nav-menu. 1223 while ( -1 === self.className.indexOf( 'navigation-accessibility' ) ) { 1224 // On li elements toggle the class .focus. 1225 if ( 'li' === self.tagName.toLowerCase() ) { 1226 self.classList.toggle('focus'); 1227 } 1228 self = self.parentElement; 1229 } 1230 } 1231 1232 if( ! astra.is_header_footer_builder_active ) { 1233 1234 /* Add class if mouse clicked and remove if tab pressed */ 1235 if ( 'querySelector' in document && 'addEventListener' in window ) { 1236 body.addEventListener( 'mousedown', function() { 1237 body.classList.add( 'ast-mouse-clicked' ); 1238 } ); 1239 1240 body.addEventListener( 'keydown', function() { 1241 body.classList.remove( 'ast-mouse-clicked' ); 1242 } ); 1243 } 1244 } 1245 1246 /** 1247 * Scroll to specific hash link. 1248 * 1249 * @since x.x.x 1250 */ 1251 if ( astra.is_scroll_to_id ) { 1252 // Calculate the offset top of an element, accounting for nested elements. 1253 const getOffsetTop = (element) => { 1254 let offsetTop = 0; 1255 while (element) { 1256 offsetTop += element.offsetTop; 1257 element = element.offsetParent; 1258 } 1259 return offsetTop; 1260 } 1261 1262 const scrollToIDHandler = ( e, hash = null ) => { 1263 1264 let offset = 0; 1265 const siteHeader = document.querySelector('.site-header'); 1266 1267 if (siteHeader) { 1268 1269 // Check and add offset to scroll top if header is sticky. 1270 const stickyHeaders = siteHeader.querySelectorAll( 1271 'div[data-stick-support]' 1272 ); 1273 1274 if ( stickyHeaders.length > 0 ) { 1275 stickyHeaders.forEach( ( header ) => ( offset += header.clientHeight ) ); 1276 } else if ( typeof astraAddon !== 'undefined' && ! ( Number( astraAddon.sticky_hide_on_scroll ) && ! document?.querySelector( '.ast-header-sticked' ) ) ) { 1277 const fixedHeader = document.querySelector( '#ast-fixed-header' ); 1278 if ( fixedHeader ) { 1279 offset = fixedHeader?.clientHeight; 1280 if ( Number( astraAddon?.header_main_shrink ) ) { 1281 const headers = fixedHeader?.querySelectorAll( 1282 '.ast-above-header-wrap, .ast-below-header-wrap' 1283 ); 1284 headers?.forEach( () => ( offset -= 10 ) ); 1285 } 1286 } 1287 } 1288 1289 const href = hash ? hash : e.target?.closest( 'a' ).hash; 1290 if (href) { 1291 const scrollId = document.querySelector(href); 1292 if (scrollId) { 1293 const elementOffsetTop = getOffsetTop( scrollId ); 1294 if ( typeof astraAddon !== 'undefined' && Number( astraAddon.sticky_hide_on_scroll ) && window?.scrollY < elementOffsetTop ) { 1295 offset = 0; 1296 } 1297 1298 const scrollOffsetTop = elementOffsetTop - offset; 1299 if( scrollOffsetTop ) { 1300 astraSmoothScroll( e, scrollOffsetTop ); 1301 } 1302 } 1303 } 1304 } 1305 } 1306 1307 let hashLinks = []; 1308 const links = document.querySelectorAll( 1309 'a[href*="#"]:not([href="#"]):not([href="#0"]):not([href*="uagb-tab"]):not(.uagb-toc-link__trigger):not(.skip-link):not(.nav-links a):not([href*="tab-"])' 1310 ); 1311 if (links) { 1312 for (const link of links) { 1313 if (link.href.split("#")[0] !== location.href.split("#")[0]) { 1314 // Store the hash 1315 hashLinks.push({ 1316 hash: link.hash, 1317 url: link.href.split("#")[0], 1318 }); 1319 } else if (link.hash !== "") { 1320 link.addEventListener("click", scrollToIDHandler); 1321 } 1322 } 1323 } 1324 1325 window.addEventListener('DOMContentLoaded', (event) => { 1326 for (let link of hashLinks) { 1327 if (window.location.href.split('#')[0] === link.url) { 1328 const siteHeader = document.querySelector('.site-header'); 1329 let offset = 0; 1330 1331 // Check and add offset to scroll top if header is sticky. 1332 const headerHeight = siteHeader.querySelectorAll('div[data-stick-support]'); 1333 if (headerHeight) { 1334 headerHeight.forEach(single => { 1335 offset += single.clientHeight; 1336 }); 1337 } 1338 1339 const scrollId = document.querySelector(link.hash); 1340 if (scrollId) { 1341 const scrollOffsetTop = getOffsetTop(scrollId) - offset; 1342 if (scrollOffsetTop) { 1343 astraSmoothScroll(event, scrollOffsetTop); 1344 } 1345 } 1346 } 1347 } 1348 1349 // If there is a hash in the URL when the page loads, scroll to that element after a short delay. 1350 if ( location.hash ) { 1351 setTimeout( () => scrollToIDHandler( new Event( 'click' ), location.hash ), 750 ); 1352 } 1353 }); 1354 } 1355 1356 /** 1357 * Scroll to top. 1358 * 1359 * @since x.x.x 1360 */ 1361 if ( astra.is_scroll_to_top ) { 1362 var masthead = document.querySelector( '#page header' ); 1363 var astScrollTop = document.getElementById( 'ast-scroll-top' ); 1364 1365 astScrollToTopHandler(masthead, astScrollTop); 1366 1367 window.addEventListener('scroll', function () { 1368 astScrollToTopHandler(masthead, astScrollTop); 1369 }); 1370 1371 astScrollTop.onclick = function(e){ 1372 astraSmoothScroll( e, 0 ); 1373 }; 1374 1375 astScrollTop.addEventListener( 'keydown' , function(e) { 1376 if ( e.key === 'Enter') { 1377 astraSmoothScroll( e, 0 ); 1378 } 1379 }); 1380 } 1381
1382 if ( astra?.is_dark_palette ) { 1383 document.documentElement.classList.add("astra-dark-mode-enable"); 1384 } else { 1385 document.documentElement.classList.remove("astra-dark-mode-enable"); 1386 } 1387 1388 /** 1389 * To remove the blank space when the store notice gets dismissed. 1390 * To adjust the height of the store notice when hanged over top. 1391 * 1392 * @since x.x.x 1393 */ 1394 window.addEventListener('DOMContentLoaded', (event) => { 1395 const isHangOverTopNotice = document.querySelector('.ast-woocommerce-store-notice-hanged'); 1396 const adjustBodyHeight = () => { 1397 const storeNotice = document.querySelector('.woocommerce-store-notice[data-position="hang-over-top"]'); 1398 document.body.style.paddingTop = `${storeNotice?.clientHeight || 0}px`; 1399 } 1400 1401 if (isHangOverTopNotice) { 1402 window.addEventListener('resize', adjustBodyHeight); 1403 setTimeout(() => adjustBodyHeight(), 0); 1404 } 1405 1406 document 1407 .querySelector('.woocommerce-store-notice__dismiss-link') 1408 ?.addEventListener('click', () => { 1409 if ( typeof wp === 'undefined' || ! wp?.customize ) { 1410 document.body.classList.remove('ast-woocommerce-store-notice-hanged'); 1411 window.removeEventListener('resize', adjustBodyHeight); 1412 document.body.style.paddingTop = 0; 1413 } 1414 }); 1415 }); 1416 1417})(); 1418 1419// Accessibility improvement for menu items. 1420document.addEventListener('DOMContentLoaded', function () { 1421 const submenuToggles = document.querySelectorAll('.menu-link .dropdown-menu-toggle'); 1422 1423 const menuItemsWithSubmenu = document.querySelectorAll('.menu-item-has-children > a'); 1424 1425 // Ensuring the submenu toggle action is handled with appropriate CSS, with cross browser compatibility for Enter key press. 1426 menuItemsWithSubmenu.forEach(item => { 1427 item.addEventListener('keydown', function(event) { 1428 if (event.key === 'Enter') { 1429 const submenu = item.nextElementSibling; 1430 if (submenu && submenu.classList.contains('sub-menu')) { 1431 submenu.classList.toggle('ast-visible'); 1432 const ariaExpanded = item.getAttribute('aria-expanded') === 'false' ? 'true' : 'false'; 1433 item.setAttribute('aria-expanded', ariaExpanded); 1434 } 1435 } 1436 }); 1437 }); 1438 1439 // Add event listeners for focus, blur, and keydown events. 1440 submenuToggles.forEach(toggle => { 1441 toggle.addEventListener('focus', () => updateAriaExpanded(toggle)); 1442 toggle.addEventListener('blur', () => updateAriaExpanded(toggle)); 1443 toggle.addEventListener('keydown', event => { 1444 if (event.key === 'Enter' || event.key === ' ') { 1445 event.preventDefault(); 1446 toggleAriaExpanded(toggle); 1447 } 1448 }); 1449 }); 1450 1451 // Add event listener for Escape key press to close all submenus. 1452 document.addEventListener('keydown', event => { 1453 if (event.key === 'Escape') { 1454 closeAllSubmenus(); 1455 } 1456 }); 1457 1458 /** 1459 * Updates the `aria-expanded` attribute based on submenu visibility. 1460 * @param {HTMLElement} toggle - The toggle element. 1461 */ 1462 function updateAriaExpanded(toggle) { 1463 const menuItemLink = toggle.closest('.menu-link'); 1464 const submenu = menuItemLink.nextElementSibling; 1465 const isSubmenuVisible = submenu.classList.contains('toggled-on'); 1466 menuItemLink.setAttribute('aria-expanded', isSubmenuVisible ? 'true' : 'false'); 1467 } 1468 1469 /** 1470 * Toggles the `aria-expanded` attribute for a given toggle element. 1471 * @param {HTMLElement} toggle - The toggle element. 1472 */ 1473 function toggleAriaExpanded(toggle) { 1474 const menuItemLink = toggle.closest('.menu-link'); 1475 const currentState = menuItemLink.getAttribute('aria-expanded'); 1476 menuItemLink.setAttribute('aria-expanded', currentState === 'true' ? 'false' : 'true'); 1477 } 1478 1479 /** 1480 * Closes all submenus by updating the `aria-expanded` attribute. 1481 */ 1482 function closeAllSubmenus() { 1483 submenuToggles.forEach(toggle => updateAriaExpanded(toggle)); 1484 } 1485 1486 // This event listener is triggered when the device orientation changes, and it dispatches a 'resize' event to ensure layout adjustments are made. 1487 window.addEventListener( 'orientationchange', () => { 1488 setTimeout( () => window.dispatchEvent( new Event( 'resize' ) ), 50 ); 1489 } ); 1490}); 1491 1492// Accessibility improvement for product card quick view and add to cart buttons. 1493document.addEventListener('DOMContentLoaded', () => { 1494 const thumbnailWraps = document.querySelectorAll('.astra-shop-thumbn
1494ail-wrap'); 1495 1496 thumbnailWraps.forEach(wrap => { 1497 const focusableElements = wrap.querySelectorAll('a, span'); 1498 1499 focusableElements.forEach(el => { 1500 el.addEventListener('focus', () => { 1501 wrap.querySelectorAll('.ast-on-card-button, .ast-quick-view-trigger').forEach(btn => { 1502 btn.style.opacity = '1'; 1503 btn.style.visibility = 'visible'; 1504 btn.style.borderStyle = 'none'; 1505 }); 1506 }); 1507 1508 el.addEventListener('blur', () => { 1509 // Added Check to check if child elements are still focused. 1510 const isAnyFocused = Array.from(focusableElements).some(child => child === document.activeElement); 1511 if (!isAnyFocused) { 1512 wrap.querySelectorAll('.ast-on-card-button, .ast-quick-view-trigger').forEach(btn => { 1513 btn.style.opacity = ''; 1514 btn.style.visibility = ''; 1515 }); 1516 } 1517 }); 1518 }); 1519 }); 1520});
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.