1jQuery(function($) { 2 3 $(function() { 4 $( '.fl-node-sn64o9ya1mxj .fl-photo-img' ) 5 .on( 'mouseenter', function( e ) { 6 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 7 } ) 8 .on( 'mouseleave', function( e ){ 9 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 10 } ); 11 }); 12 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 13}); 14 15;/* eslint-disable no-undef */ 16(function($) { 17 18 /** 19 * Class for Menu Module 20 * 21 * @since 1.6.1 22 */ 23 FLBuilderMenu = function( settings ){ 24 25 // set params 26 this.nodeId = settings.id; 27 this.nodeClass = '.fl-node-' + settings.id; 28 this.wrapperClass = this.nodeClass + ' .fl-menu'; 29 this.type = settings.type; 30 this.mobileToggle = settings.mobile; 31 this.mobileBelowRow = settings.mobileBelowRow; 32 this.mobileFlyout = settings.mobileFlyout; 33 this.breakPoints = settings.breakPoints; 34 this.mobileBreakpoint = settings.mobileBreakpoint; 35 this.currentBrowserWidth = $( window ).width(); 36 this.postId = settings.postId; 37 this.mobileStacked = settings.mobileStacked; 38 this.submenuIcon = settings.submenuIcon; 39 this.flyoutWidth = settings.flyoutWidth; 40 41 // initialize the menu 42 this._initMenu(); 43 44 // check if viewport is resizing 45 $( window ).on( 'resize', $.proxy( function() { 46 47 var width = $( window ).width(); 48 49 // if screen width is resized, reload the menu 50 if( width != this.currentBrowserWidth ){ 51 52 this.currentBrowserWidth = width; 53 this._initMenu( true ); 54 this._clickOrHover( true ); 55 } 56 57 this._resizeFlyoutMenuPanel(); 58 }, this ) ); 59 60 $( window ).on( 'scroll', $.proxy( function() { 61 this._resizeFlyoutMenuPanel(); 62 }, this ) ); 63 64 // Move focus to the first menu item if the layout is set to BelowRow 65 $( this.wrapperClass ).on( 'keydown', '.fl-menu-mobile-toggle, .menu-item:first a:first', $.proxy( function ( event ) { 66 // Make sure it is a tab key with both the menu toggle enabled & below row layout set 67 if ( event.key !== 'Tab' || ! this._isMenuToggle() || ! this._isMobileBelowRowEnabled() ) { 68 return; 69 } 70 // Trigger focus on the mobile toggle button if the user is shift tabbing from the first menu item 71 if ( event.shiftKey && $( event.currentTarget ).is( 'a' ) ) { 72 event.preventDefault(); 73 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'focus' ); 74 } 75 // Trigger focus on the first menu item if the user is tabbing from the mobile toggle button 76 else if ( ! event.shiftKey && $( event.currentTarget ).hasClass( 'fl-menu-mobile-toggle' ) && $( event.currentTarget ).hasClass( 'fl-active' ) ) { 77 event.preventDefault(); 78 $( this.wrapperClass ).find( '.menu-item' ).first().find( 'a' ).first().trigger( 'focus' ); 79 } 80 }, this ) ); 81 82 // Close mobile menu or accordion when tabbing out from the first or last menu item 83 $( this.wrapperClass ).on( 'focusout', $.proxy( function ( event ) { 84 if ( $( this.wrapperClass + ' nav' ).has( $( event.relatedTarget ) ).length === 0 ) { 85 if ( this.type === 'accordion' ) { 86 this._toggleSubmenu( $( event.target ).parents( '.fl-has-submenu' ).last(), false ); 87 } 88 else { 89 this._clickOrHover( true ); 90 } 91 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 92 if ( this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) && ! $( event.relatedTarget ).is( mobileToggle ) && 'expanded' !== this.mobileToggle ) { 93 mobileToggle.trigger( 'click' ); 94 } 95 } 96 }, this ) ); 97 98 }; 99 100 FLBuilderMenu.prototype = { 101 nodeClass : '', 102 wrapperClass: '', 103 type : '', 104 breakPoints : {}, 105 $submenus : null, 106 107 /** 108 * Check if the screen size fits a mobile viewport. 109 * 110 * @since 1.6.1 111 * @return bool 112 */ 113 _isMobile: function(){ 114 return this.currentBrowserWidth <= this.breakPoints.small ? true : false; 115 }, 116 117 /** 118 * Check if the device is connected to a mouse. 119 * 120 * @since 2.9.0 121 * @return bool 122 */ 123 _isMouseAvailable: function(){ 124 return window.matchMedia("(pointer: fine) and (hover: hover)").matches; 125 }, 126 127 /** 128 * Check if the screen size fits a medium viewport. 129 * 130 * @since 1.10.5 131 * @return bool 132 */ 133 _isMedium: function(){ 134 return this.currentBrowserWidth <= this.breakPoints.medium ? true : false;
135 }, 136 137 /** 138 * Check if the screen size fits a large viewport. 139 * 140 * @since 1.10.5 141 * @return bool 142 */ 143 _isLarge: function(){ 144 return this.currentBrowserWidth <= this.breakPoints.large ? true : false; 145 }, 146 147 /** 148 * Check if the menu should toggle for the current viewport base on the selected breakpoint. 149 * 150 * @see this._isMobile() 151 * @see this._isMedium() 152 * @since 1.10.5 153 * @return bool 154 */ 155 _isMenuToggle: function(){ 156 if ( ( 'always' == this.mobileBreakpoint 157 || ( this._isMobile() && 'mobile' == this.mobileBreakpoint ) 158 || ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint ) 159 || ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint ) 160 ) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) { 161 return true; 162 } 163 164 return false; 165 }, 166 167 /** 168 * Initialize the toggle logic for the menu. 169 * 170 * @see this._isMenuToggle() 171 * @see this._menuOnCLick() 172 * @see this._clickOrHover() 173 * @see this._submenuOnRight() 174 * @see this._submenuRowZindexFix() 175 * @see this._toggleForMobile() 176 * @since 1.6.1 177 * @return void 178 */ 179 _initMenu: function( resized = false ){ 180 this._setupSubmenu(); 181 if ( ! resized ) { 182 this._menuOnFocus(); 183 this._menuOnClick(); 184 this._menuOnEscape(); 185 } 186 if ( $( this.nodeClass ).length && this.type == 'horizontal' ) { 187 this._initMegaMenus(); 188 } 189 190 if( this._isMenuToggle() || this.type == 'accordion' ){ 191 192 $( this.wrapperClass ).off( 'mouseenter mouseleave' ); 193 this._clickOrHover(); 194 195 } else { 196 this._submenuOnRight(); 197 this._submenuRowZindexFix(); 198 } 199 200 if( this.mobileToggle != 'expanded' ){ 201 this._toggleForMobile(); 202 } 203 204 if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){ 205 this._toggleMenuSearch(); 206 } 207 208 if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){ 209 this._wooUpdateParams(); 210 } 211 }, 212 213 /** 214 * Whether the toggle behavior for submenus is through hovering or not. 215 * 216 * @since 2.5 217 * @return void 218 */ 219 _setupSubmenu: function() { 220 if ( ! this._isMouseAvailable() || this._isMenuToggle() || this.type === 'accordion' ) { 221 $( this.wrapperClass ).addClass( 'no-hover' ); 222 } 223 else { 224 $( this.wrapperClass ).removeClass( 'no-hover' ); 225 } 226 }, 227 228 /** 229 * Logic for menu items when focused. 230 * 231 * @since 1.9.0 232 * @return void 233 */ 234 _menuOnFocus: function(){ 235 $( this.wrapperClass ).on( 'focus', 'a:not(.fl-button), .fl-menu-toggle', $.proxy( function( event ) { 236 const focusedMenuItem = $( event.currentTarget ).closest( '.menu-item' ); 237 const blurredMenuItem = $( event.relatedTarget ).closest( '.menu-item' ); 238 // In case the blurred & focused items are siblings 239 if ( focusedMenuItem.closest( 'ul' ).is( blurredMenuItem.closest( 'ul' ) ) ) { 240 // Check if the focus event is not between the link & submenu icon of the same menu item 241 if ( ! focusedMenuItem.is( blurredMenuItem ) ) { 242 this._toggleSubmenu( blurredMenuItem, false ); 243 } 244 } 245 // In case neither items are child & parent nor vice versa 246 else if ( focusedMenuItem.has( blurredMenuItem ).length === blurredMenuItem.has( focusedMenuItem ).length ) { 247 // Get the blurred item parent & is the sibling of the focused item 248 blurredMenuItem.parents( '.fl-has-submenu' ).each( ( _, parent ) => { 249 if ( focusedMenuItem.closest( 'ul' ).is( $( parent ).closest( 'ul' ) ) ) { 250 this._toggleSubmenu( $( parent ), false ); 251 return false; 252 } 253 } ); 254 } 255 // In case the blurred item is a child of the focused item 256 else if ( focusedMenuItem.has( blurredMenuItem ).length ) { 257 if ( this.type !== 'accordion' && this.submenuIcon === 'none' ) { 258 this._toggleSubmenu( blurredMenuItem, false ); 259 } 260 } 261 }, this ) ); 262 }, 263 264 /** 265 * Logic for menu items when Escape key is pressed. 266 * 267 * @since 2.7.1 268 * @return void 269 */ 270 _menuOnEscape: function(){ 271 $( this.wrapperClass ).on( 'keydown', $.proxy( function( event ){ 272 if ( event.key !== 'Escape' ) return; 273 const menuItem = $( event.target ).closest( '.menu-item' ); 274 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 275 // In case there is a focused menu item 276 if ( menuItem.length || $( event.target ).hasClass( 'fl-menu-mobile-close' ) ) { 277 // Close the search form if it is open 278 if ( menuItem.hasClass( 'fl-menu-search-item' ) && $( this.wrapperClass ).find('.fl-search-form-input-wrap').is( ':visible' ) ) { 279 $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))').trigger( 'focus' ); 280 } 281 // Close all the submenus of the focused menu item 282 else if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.find( '.sub-menu' ).first().is( ':visible' ) ) { 283 this._toggleSubmenu( menuItem, false ); 284 } 285 else { 286 // Shift focus to the parent while closing all its submenus 287 const parentMenuItem = menuItem.parents( '.fl-has-submenu' ).not( '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading' ).first(); 288 // Close the mobile menu if there is no parent menu item and the mobile toggle is active 289 if ( parentMenuItem.length === 0 && this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) ) { 290 // Blur to trigger the focus-out event for closing the menu 291 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 292 } 293 // Close the parent submenu and shift focus to its link 294 else if ( parentMenuItem.length !== 0 ) { 295 this._toggleSubmenu( parentMenuItem, false ); 296 parentMenuItem.find( 'a' ).first().trigger( 'focus' ); 297 } 298 } 299 } 300 // Close the mobile menu if the mobile toggle is active 301 else if ( $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && mobileToggle.hasClass( 'fl-active' ) ) { 302 // Blur to trigger the focus-out event for closing the menu 303 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 304 } 305 }, this ) ); 306 }, 307 308 /** 309 * Logic for menu items when clicked. 310 * 311 * @since 1.6.1 312 * @return void 313 */ 314 _menuOnClick: function(){ 315 // Fallback for span elements and fake links to interact with the keyboard 316 $( this.wrapperClass ).on( 'keydown', 'a:not(.fl-button, [href]), span.fl-menu-toggle', $.proxy( function( event ) { 317 if ( event.key === 'Enter' || event.key === ' ' ) { 318 event.preventDefault(); 319 $( event.currentTarget ).trigger( 'click' ); 320 } 321 }, this ) ); 322 $( this.wrapperClass ).on( 'click', 'a, .fl-menu-toggle', $.proxy( function( event ) { 323 // Only allow mouse clicks with accordion & mobile menus 324 if ( this._isMouseAvailable() && ! this._isMenuToggle() && event.detail && this.type !== 'accordion' ) return; 325 // Links only open & do not toggle submenus if there is either a submenu icon or an accordion layout 326 if ( $( event.currentTarget ).is( 'a' ) && ( this.submenuIcon !== 'none' || this.type === 'accordion' ) ) return; 327 const menuItem = $( event.currentTarget ).closest( '.menu-item, .fl-menu-logo' ); 328 const menuLink = menuItem.find( 'a' ).first().attr( 'href' ); 329 const submenuHidden = menuItem.find( '.sub-menu' ).first().is( ':hidden' ); 330 if ( typeof menuLink === 'undefined' || menuLink === '#' || submenuHidden ) { 331 event.preventDefault(); 332 } 333 if ( $( event.currentTarget ).hasClass( 'fl-menu-toggle' ) || submenuHidden ) { 334 this._toggleSubmenu( menuItem, submenuHidden ); 335 } 336 }, this ) ); 337 }, 338 339 /** 340 * Controls toggling the visibility of all submenu items for desktop & mobile. 341 * 342 * @since 2.10 343 * @return void 344 */ 345 _toggleSubmenu: function ( menuItem, opened ) { 346 const togglingClass = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 347 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 348 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 349 if ( opened && menuItem.hasClass( 'fl-has-submenu' ) && ! menuItem.is( hiddenMenu ) ) { 350 menuItem.addClass( togglingClass ); 351 menuItem.find( toggleElement ).first().attr( 'aria-expanded', true ); 352 if ( this._isMenuToggle() || this.type === 'accordion' ) { 353 menuItem.find( '.sub-menu' ).first().filter( ':hidden' ).slideDown(); 354 } 355 } 356 else { 357 menuItem.parent().find( '.menu-item' ).removeClass( togglingClass ); 358 menuItem.parent().find( '.fl-has-submenu' ).not( hiddenMenu ).find( toggleElement ).attr( 'aria-expanded', false ); 359 if ( this._isMenuToggle() || this.type === 'accordion' ) {
360 menuItem.find( '.sub-menu' ).filter( ':visible' ).slideUp(); 361 } 362 } 363 }, 364 365 /** 366 * Changes general styling and behavior of menus based on mobile / desktop viewport. 367 * 368 * @see this._isMenuToggle() 369 * @since 1.6.1 370 * @return void 371 */ 372 _clickOrHover: function( clear = false ){ 373 const selector = this._isMobileBelowRowEnabled() ? this.nodeClass + '-clone' : this.nodeClass; 374 this.$submenus = this.$submenus || $( selector ).find( '.sub-menu' ); 375 376 const className = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 377 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 378 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 379 $( selector ).find( '.fl-has-submenu' ).not( hiddenMenu ).each( function() { 380 if( clear || ! $ ( this ).hasClass( className ) ){ 381 if ( clear ) $( this ).removeClass( className ); 382 $( this ).find( toggleElement ).first().attr( 'aria-expanded', false ); 383 if ( className === 'fl-active' ) { 384 $( this ).find( '.sub-menu' ).fadeOut(); 385 } else if ( className === 'focus' ) { 386 $( this ).find( '.sub-menu' ).css( { 387 'display' : '', 388 'opacity' : '' 389 } ); 390 } 391 } 392 } ); 393 }, 394 395 /** 396 * Logic to prevent submenus to go outside viewport boundaries. 397 * 398 * @since 1.6.1 399 * @return void 400 */ 401 _submenuOnRight: function(){ 402 403 $( this.wrapperClass ) 404 .on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){ 405 406 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 407 return; 408 } 409 410 var $link = $( e.currentTarget ), 411 $parent = $link.parent(), 412 $subMenu = $link.find( '.sub-menu' ), 413 subMenuWidth = $subMenu.width(), 414 subMenuPos = 0, 415 bodyWidth = $( 'body' ).width(); 416 417 if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) { 418 419 $link.addClass( 'fl-menu-submenu-right' ); 420 421 } else if( $( 'body' ).hasClass( 'rtl' ) ) { 422 423 subMenuPos = $parent.is( '.sub-menu' ) ? 424 $parent.offset().left - subMenuWidth: 425 $link.offset().left - $link.width() - subMenuWidth; 426 427 if( subMenuPos <= 0 ) { 428 $link.addClass( 'fl-menu-submenu-right' ); 429 } 430 431 } else { 432 433 subMenuPos = $parent.is( '.sub-menu' ) ? 434 $parent.offset().left + $parent.width() + subMenuWidth : 435 $link.offset().left + $link.width() + subMenuWidth; 436 437 if( subMenuPos > bodyWidth ) { 438 $link.addClass('fl-menu-submenu-right'); 439 } 440 } 441 }, this ) ) 442 .on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){ 443 $( e.currentTarget ).removeClass( 'fl-menu-submenu-right' ); 444 }, this ) ); 445 446 }, 447 448 /** 449 * Logic to prevent submenus to go behind the next overlay row. 450 * 451 * @since 1.10.9 452 * @return void 453 */ 454 _submenuRowZindexFix: function(){ 455 456 $( this.wrapperClass ) 457 .on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){ 458 459 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 460 return; 461 } 462 463 $( this.nodeClass ) 464 .closest( '.fl-row' ) 465 .find( '.fl-row-content' ) 466 .css( 'z-index', '10' ); 467 468 }, this ) ) 469 .on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function(){ 470 471 $( this.nodeClass ) 472 .closest( '.fl-row' ) 473 .find( '.fl-row-content' ) 474 .css( 'z-index', '' ); 475 476 }, this ) ); 477 }, 478 479 /** 480 * Logic for the mobile menu button. 481 * 482 * @since 1.6.1 483 * @return void 484 */ 485 _toggleForMobile: function(){ 486 487 var $wrapper = null, 488 $menu = null, 489 self = this; 490 491 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).attr('aria-controls', $( this.wrapperClass ).find( 'ul.menu' ).attr('id')); 492 493 if( this._isMenuToggle() ){ 494 495 if ( this._isMobileBelowRowEnabled() ) { 496 this._placeMobileMenuBelowRow(); 497 $wrapper = $( this.wrapperClass ); 498 $menu = $( this.nodeClass + '-clone' ); 499 $menu.find( 'ul.menu' ).show(); 500 } 501 else { 502 $wrapper = $( this.wrapperClass ); 503 $menu = $wrapper.find( '.menu' ); 504 } 505 506 if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){ 507 $menu.css({ display: 'none' }); 508 } 509 510 // Flayout Menu 511 if ( self.mobileFlyout ) { 512 this._initFlyoutMenu(); 513 } 514 515 $wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){ 516 e.stopImmediatePropagation(); 517 518 $( this ).toggleClass( 'fl-active' ); 519 520 if ( self.mobileFlyout ) { 521 self._toggleFlyoutMenu(); 522 const flyoutWrapper = $( '.fl-menu-mobile-flyout' ); 523 if ( $( this ).hasClass( 'fl-active' ) ) { 524 flyoutWrapper.attr( 'aria-hidden', false ); 525 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex="-1"]' ).attr( 'tabindex', 0 ); 526 } 527 else { 528 flyoutWrapper.attr( 'aria-hidden', true ); 529 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not
529([tabindex="-1"])' ).attr( 'tabindex', -1 ); 530 } 531 } 532 else { 533 var targetMenu = null; 534 535 if ( self.mobileBelowRow ) { 536 var $closestCol = $( this ).parents( '.fl-col, .fl-module-box' ), 537 $closestColGroup = $closestCol.length ? $closestCol.parent( '.fl-col-group' ) : null; 538 targetMenu = $closestCol.length ? $closestCol.last().next( '.fl-menu-mobile-clone' ) : null; 539 540 if ( $closestColGroup.length ) { 541 if ( $closestColGroup.hasClass( 'fl-col-group-responsive-reversed' ) ) { 542 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', -1 ); 543 } else if ( $closestColGroup ) { 544 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', 2 ); 545 } 546 } 547 } else { 548 targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' ); 549 } 550 551 if ( targetMenu.length ) { 552 $menu = $( targetMenu ); 553 } 554 555 $menu.slideToggle(); 556 } 557 558 e.stopPropagation(); 559 } ); 560 561 // Hide active menu when click on anchor link ID that exists on a page 562 $menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(){ 563 var $href = $(this).attr('href'), 564 $targetID = $href.split('#')[1], 565 element = $('#' + $targetID); 566 if ( $('body').find(element).length > 0 ) { 567 $( this ).toggleClass( 'fl-active' ); 568 FLBuilderLayout._scrollToElement( element ); 569 if ( ! self._isMenuToggle() ) { 570 $menu.slideToggle(); 571 } 572 } 573 }); 574 } 575 else { 576 577 if ( this._isMobileBelowRowEnabled() ) { 578 this._removeMenuFromBelowRow(); 579 } 580 581 $wrapper = $( this.wrapperClass ), 582 $menu = $wrapper.find( 'ul.menu' ); 583 $wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' ); 584 $menu.css({ display: '' }); 585 586 if ( ! this._isMobileBelowRowEnabled() ) { 587 $menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' ); 588 } 589 590 if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) { 591 $( 'body' ).css( 'margin', '' ); 592 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 593 $menu.unwrap(); 594 $wrapper.find( '.fl-menu-mobile-close' ).remove(); 595 $wrapper.find( '.fl-menu-mobile-opacity' ).remove(); 596 } 597 } 598 }, 599 600 /** 601 * Init any mega menus that exist. 602 * 603 * @see this._isMenuToggle() 604 * @since 1.10.4 605 * @return void 606 */ 607 _initMegaMenus: function(){ 608 609 var module = $( this.nodeClass ), 610 rowContent = module.closest( '.fl-row-content' ), 611 rowWidth = rowContent.width(), 612 megas = module.find( '.mega-menu' ), 613 disabled = module.find( '.mega-menu-disabled' ), 614 isToggle = this._isMenuToggle(); 615 616 if ( isToggle ) { 617 megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' ); 618 module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' ); 619 rowContent.css( 'position', '' ); 620 } else { 621 disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' ); 622 module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' ); 623 rowContent.css( 'position', 'relative' ); 624 } 625 }, 626 627 /** 628 * Check to see if Below Row should be enabled. 629 * 630 * @since 1.11 631 * @return boolean 632 */ 633 _isMobileBelowRowEnabled: function() { 634 return this.mobileBelowRow && ( $( this.nodeClass ).parents( '.fl-col, .fl-module-box' ).length ); 635 }, 636 637 /** 638 * Logic for putting the mobile menu below the menu's 639 * column so it spans the full width of the page. 640 * 641 * @since 1.10 642 * @return void 643 */ 644 _placeMobileMenuBelowRow: function(){ 645 646 if ( $( this.nodeClass + '-clone' ).length ) { 647 return; 648 } 649 650 var module = $( this.nodeClass ), 651 clone = null, 652 col = module.parents( '.fl-col, .fl-module-box' ).last(); 653 654 if ( module.length < 1 ) { 655 return; 656 } 657 658 clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone(); 659 module.find( 'ul.menu' ).remove(); 660 clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) ); 661 clone.addClass( 'fl-menu-mobile-clone' ); 662 clone.find( '.fl-menu-mobile-toggle' ).remove(); 663 col.after( clone ); 664 665 // Removes animation when enabled 666 if ( module.hasClass( 'fl-animation' ) ) { 667 clone.removeClass( 'fl-animation' ); 668 } 669 670 this._menuOnFocus(); 671 this._menuOnClick(); 672 this._menuOnEscape(); 673 }, 674 675 /** 676 * Logic for removing the mobile menu from below the menu's 677 * column and putting it back in the main wrapper. 678 * 679 * @since 1.10 680 * @return void 681 */ 682 _removeMenuFromBelowRow: function(){ 683 684 if ( ! $( this.nodeClass + '-clone' ).length ) { 685 return; 686 } 687 688 var module = $( this.nodeClass ), 689 clone = $( this.nodeClass + '-clone' ), 690 menu = clone.find( 'ul.menu' ), 691 nav = module.find( 'nav' ); 692
693 if ( nav.length ) { 694 nav.append( menu ); 695 } else { 696 module.find( '.fl-menu-mobile-toggle' ).after( menu ); 697 } 698 clone.remove(); 699 menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink ); 700 }, 701 702 /** 703 * Logic for Flyout responsive menu. 704 * 705 * @since 2.2 706 * @return void 707 */ 708 _initFlyoutMenu: function(){ 709 var wrapper = $( this.wrapperClass ), 710 menu = wrapper.find( 'ul.menu' ), 711 button = wrapper.find( '.fl-menu-mobile-toggle' ); 712 713 if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) { 714 menu.wrap( '<div class="fl-menu-mobile-flyout" aria-hidden="true"></div>' ); 715 } 716 717 if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) { 718 var close = window.fl_responsive_close || 'Close' 719 wrapper.find( '.fl-menu-mobile-flyout' ).prepend( '<button class="fl-menu-mobile-close fl-content-ui-button" aria-label="' + close + '"><i class="fas fa-times"></i></button>' ); 720 } 721 722 // Push with opacity 723 if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) { 724 wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' ); 725 } 726 727 wrapper.off( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close' ).on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){ 728 button.trigger('focus').trigger( 'click' ); 729 e.stopPropagation(); 730 }); 731 732 if ( 'undefined' !== typeof FLBuilder ) { 733 FLBuilder.addHook('restartEditingSession', function(){ 734 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 735 736 // Toggle active menu 737 if ( button.hasClass( 'fl-active' ) ) { 738 button.trigger( 'click' ); 739 } 740 }); 741 } 742 $( '.fl-menu-mobile-flyout' ).find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not([tabindex="-1"])' ).attr( 'tabindex', -1 ); 743 }, 744 745 /** 746 * Logic to enable/disable the Flyout menu on button click. 747 * 748 * @since 2.2 749 * @return void 750 */ 751 _toggleFlyoutMenu: function(){ 752 var wrapper = $( this.wrapperClass ), 753 button = wrapper.find( '.fl-menu-mobile-toggle' ), 754 position = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 755 pushMenu = wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 756 opacity = wrapper.find( '.fl-menu-mobile-opacity' ), 757 marginPos = {}, 758 fixedPos = {}, 759 fixedHeader = $('header, header > div'); 760 761 this._resizeFlyoutMenuPanel(); 762 763 // Fix the push menu when builder ui panel is pinned 764 if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) { 765 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' ); 766 } 767 768 if ( pushMenu ) { 769 marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 770 $( 'body' ).animate( marginPos, 200); 771 772 // Fixed header 773 if ( fixedHeader.length > 0 ) { 774 fixedPos[ position] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 775 fixedHeader.each(function(){ 776 if ( 'fixed' == $( this ).css( 'position' ) ) { 777 $( this ).css({ 'transition' : 'none' }); 778 $( this ).animate( fixedPos, 200 ); 779 } 780 }); 781 } 782 } 783 784 if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) { 785 opacity.show(); 786 } 787 else { 788 opacity.hide(); 789 } 790 }, 791 792 /** 793 * Resize or reposition the Flyout Menu Panel. 794 * 795 * @since 2.8.1 796 * @return void 797 */ 798 _resizeFlyoutMenuPanel: function(){ 799 const wrapper = $( this.wrapperClass ); 800 const wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' ); 801 802 if ( wrapFlyout.length > 0 ) { 803 wrapFlyout.css( this._getFlyoutMenuPanelPosition() ); 804 } 805 }, 806 807 /** 808 * Compute the Flyout Menu Panel's position on the screen. 809 * 810 * @since 2.8.1 811 * @return object 812 */ 813 _getFlyoutMenuPanelPosition: function() { 814 var wrapper = $( this.wrapperClass ), 815 button = wrapper.find( '.fl-menu-mobile-toggle' ), 816 side = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 817 winHeight = $(window).outerHeight(), 818 winTop = $(window).scrollTop(), 819 adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).height() : 0, 820 flyoutPosition = {}; 821 822 flyoutPosition[ side ] = '-' + ( parseInt( this.flyoutWidth ) + 15 ) + 'px'; 823 if ( ! button.hasClass( 'fl-active' ) ) { 824 return flyoutPosition; 825 } 826 827 flyoutPosition[ side ] = '0px'; 828 flyoutPosition[ 'height' ] = winHeight + 'px'; 829 flyoutPosition[ 'top' ] = '0px'; 830 831 if ( adminBarHeight > 0 ) { 832 const diff = adminBarHeight - winTop; 833 flyoutPosition[ 'top' ] = diff <= 0 ? '0px' : (diff) + 'px'; 834 } 835 836 return flyoutPosition; 837 }, 838 839 /** 840 * Shows or hides the nav search form. 841 * 842 * @since 2.5 843 * @method _toggleMenuSearch 844 */ 845 _toggleMenuSearch: function(){ 846 const form = $( this.wrapperClass ).find('.fl-menu-search-item .fl-search-form-input-wrap');
847 const button = $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))'); 848 form.on('submit', () => form.stop().fadeToggle('fast')); 849 // Close the search form when focus is lost 850 form.on('focusout', (event) => { 851 if (form.is(':visible') && form.has($(event.relatedTarget)).length === 0) { 852 button.trigger('click'); 853 } 854 }); 855 button.attr('aria-expanded', false); 856 // Close other open submenus when focusing on the search button 857 button.on('focus', (event) => { 858 const parentMenus = $(event.relatedTarget).parents('.menu-item.fl-has-submenu'); 859 if (event.relatedTarget && parentMenus.length) { 860 this._toggleSubmenu(parentMenus, false); 861 } 862 }); 863 button.on('click', (event) => { 864 // Prevent toggling when clicking with mouse while the form is already open 865 if (event.detail && event.type === 'click' && form.is(':visible')) return; 866 form.stop().fadeToggle('fast', () => { 867 button.attr('aria-expanded', form.is(':visible')); 868 if(form.is(':visible')) { 869 form.find('.fl-search-text').focus(); 870 } 871 }); 872 }); 873 }, 874 875 /** 876 * Adds menu node and post ID to WooCommerce ajax URL requests. 877 * 878 * @since 2.5 879 * @return void 880 */ 881 _wooUpdateParams: function() { 882 if ( 'undefined' !== typeof wc_cart_fragments_params ) { 883 wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 884 } 885 if ( 'undefined' !== typeof wc_add_to_cart_params ) { 886 wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 887 } 888 }, 889 }; 890 891})(jQuery); 892 893(function($) { 894 895 $(function() { 896 897 new FLBuilderMenu({ 898 id: 'z8vsayhod7fk', 899 type: 'horizontal', 900 mobile: 'expanded', 901 mobileBelowRow: false, 902 mobileFlyout: false, 903 breakPoints: { 904 large: 1200, 905 medium: 978, 906 small: 768 }, 907 mobileBreakpoint: 'mobile', 908 postId : '10661', 909 mobileStacked: false, 910 submenuIcon: 'none', 911 flyoutWidth: '250', 912 }); 913 914 }); 915 916})(jQuery); 917 918/* Start Layout Custom JS */ 919 920/* End Layout Custom JS */ 921 922
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.