1 2;(function($) { 3 $(function() { 4 5 // FitVids 6 if ( 'undefined' !== typeof $.fn.fitVids ) { 7 $('.fl-module-fl-post-content').fitVids( { 8 ignore: '.wp-block-embed *' 9 } ); 10 } 11 12 }); 13})(jQuery); 14 15/* Start Layout Custom JS */ 16 17/* End Layout Custom JS */ 18 19 20 21;/* eslint-disable no-undef */ 22(function($) { 23 24 /** 25 * Class for Menu Module 26 * 27 * @since 1.6.1 28 */ 29 FLBuilderMenu = function( settings ){ 30 31 // set params 32 this.nodeId = settings.id; 33 this.nodeClass = '.fl-node-' + settings.id; 34 this.wrapperClass = this.nodeClass + ' .fl-menu'; 35 this.type = settings.type; 36 this.mobileToggle = settings.mobile; 37 this.mobileBelowRow = settings.mobileBelowRow; 38 this.mobileFlyout = settings.mobileFlyout; 39 this.breakPoints = settings.breakPoints; 40 this.mobileBreakpoint = settings.mobileBreakpoint; 41 this.currentBrowserWidth = $( window ).width(); 42 this.postId = settings.postId; 43 this.mobileStacked = settings.mobileStacked; 44 this.submenuIcon = settings.submenuIcon; 45 this.flyoutWidth = settings.flyoutWidth; 46 47 // initialize the menu 48 this._initMenu(); 49 50 // check if viewport is resizing 51 $( window ).on( 'resize', $.proxy( function() { 52 53 var width = $( window ).width(); 54 55 // if screen width is resized, reload the menu 56 if( width != this.currentBrowserWidth ){ 57 58 this.currentBrowserWidth = width; 59 this._initMenu( true ); 60 this._clickOrHover( true ); 61 } 62 63 this._resizeFlyoutMenuPanel(); 64 }, this ) ); 65 66 $( window ).on( 'scroll', $.proxy( function() { 67 this._resizeFlyoutMenuPanel(); 68 }, this ) ); 69 70 // Move focus to the first menu item if the layout is set to BelowRow 71 $( this.wrapperClass ).on( 'keydown', '.fl-menu-mobile-toggle, .menu-item:first a:first', $.proxy( function ( event ) { 72 // Make sure it is a tab key with both the menu toggle enabled & below row layout set 73 if ( event.key !== 'Tab' || ! this._isMenuToggle() || ! this._isMobileBelowRowEnabled() ) { 74 return; 75 } 76 // Trigger focus on the mobile toggle button if the user is shift tabbing from the first menu item 77 if ( event.shiftKey && $( event.currentTarget ).is( 'a' ) ) { 78 event.preventDefault(); 79 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'focus' ); 80 } 81 // Trigger focus on the first menu item if the user is tabbing from the mobile toggle button 82 else if ( ! event.shiftKey && $( event.currentTarget ).hasClass( 'fl-menu-mobile-toggle' ) && $( event.currentTarget ).hasClass( 'fl-active' ) ) { 83 event.preventDefault(); 84 $( this.wrapperClass ).find( '.menu-item' ).first().find( 'a' ).first().trigger( 'focus' ); 85 } 86 }, this ) ); 87 88 // Close mobile menu or accordion when tabbing out from the first or last menu item 89 $( this.wrapperClass ).on( 'focusout', $.proxy( function ( event ) { 90 if ( $( this.wrapperClass + ' nav' ).has( $( event.relatedTarget ) ).length === 0 ) { 91 if ( this.type === 'accordion' ) { 92 this._toggleSubmenu( $( event.target ).parents( '.fl-has-submenu' ).last(), false ); 93 } 94 else { 95 this._clickOrHover( true ); 96 } 97 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 98 if ( this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) && ! $( event.relatedTarget ).is( mobileToggle ) && 'expanded' !== this.mobileToggle ) { 99 mobileToggle.trigger( 'click' ); 100 } 101 } 102 }, this ) ); 103 104 }; 105 106 FLBuilderMenu.prototype = { 107 nodeClass : '', 108 wrapperClass: '', 109 type : '', 110 breakPoints : {}, 111 $submenus : null, 112 113 /** 114 * Check if the screen size fits a mobile viewport. 115 * 116 * @since 1.6.1 117 * @return bool 118 */ 119 _isMobile: function(){ 120 return this.currentBrowserWidth <= this.breakPoints.small ? true : false; 121 }, 122 123 /** 124 * Check if the device is connected to a mouse. 125 * 126 * @since 2.9.0 127 * @return bool 128 */ 129 _isMouseAvailable: function(){ 130 return window.matchMedia("(pointer: fine) and (hover: hover)").matches; 131 }, 132 133 /** 134 * Check if the screen size fits a medium viewport. 135 * 136 * @since 1.10.5 137 * @return bool 138 */ 139 _isMedium: function(){ 140 return this.currentBrowserWidth <= this.breakPoints.medium ? true : false;
141 }, 142 143 /** 144 * Check if the screen size fits a large viewport. 145 * 146 * @since 1.10.5 147 * @return bool 148 */ 149 _isLarge: function(){ 150 return this.currentBrowserWidth <= this.breakPoints.large ? true : false; 151 }, 152 153 /** 154 * Check if the menu should toggle for the current viewport base on the selected breakpoint. 155 * 156 * @see this._isMobile() 157 * @see this._isMedium() 158 * @since 1.10.5 159 * @return bool 160 */ 161 _isMenuToggle: function(){ 162 if ( ( 'always' == this.mobileBreakpoint 163 || ( this._isMobile() && 'mobile' == this.mobileBreakpoint ) 164 || ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint ) 165 || ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint ) 166 ) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) { 167 return true; 168 } 169 170 return false; 171 }, 172 173 /** 174 * Initialize the toggle logic for the menu. 175 * 176 * @see this._isMenuToggle() 177 * @see this._menuOnCLick() 178 * @see this._clickOrHover() 179 * @see this._submenuOnRight() 180 * @see this._submenuRowZindexFix() 181 * @see this._toggleForMobile() 182 * @since 1.6.1 183 * @return void 184 */ 185 _initMenu: function( resized = false ){ 186 this._setupSubmenu(); 187 if ( ! resized ) { 188 this._menuOnFocus(); 189 this._menuOnClick(); 190 this._menuOnEscape(); 191 } 192 if ( $( this.nodeClass ).length && this.type == 'horizontal' ) { 193 this._initMegaMenus(); 194 } 195 196 if( this._isMenuToggle() || this.type == 'accordion' ){ 197 198 $( this.wrapperClass ).off( 'mouseenter mouseleave' ); 199 this._clickOrHover(); 200 201 } else { 202 this._submenuOnRight(); 203 this._submenuRowZindexFix(); 204 } 205 206 if( this.mobileToggle != 'expanded' ){ 207 this._toggleForMobile(); 208 } 209 210 if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){ 211 this._toggleMenuSearch(); 212 } 213 214 if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){ 215 this._wooUpdateParams(); 216 } 217 }, 218 219 /** 220 * Whether the toggle behavior for submenus is through hovering or not. 221 * 222 * @since 2.5 223 * @return void 224 */ 225 _setupSubmenu: function() { 226 if ( ! this._isMouseAvailable() || this._isMenuToggle() || this.type === 'accordion' ) { 227 $( this.wrapperClass ).addClass( 'no-hover' ); 228 } 229 else { 230 $( this.wrapperClass ).removeClass( 'no-hover' ); 231 } 232 }, 233 234 /** 235 * Logic for menu items when focused. 236 * 237 * @since 1.9.0 238 * @return void 239 */ 240 _menuOnFocus: function(){ 241 $( this.wrapperClass ).on( 'focus', 'a:not(.fl-button), .fl-menu-toggle', $.proxy( function( event ) { 242 const focusedMenuItem = $( event.currentTarget ).closest( '.menu-item' ); 243 const blurredMenuItem = $( event.relatedTarget ).closest( '.menu-item' ); 244 // In case the blurred & focused items are siblings 245 if ( focusedMenuItem.closest( 'ul' ).is( blurredMenuItem.closest( 'ul' ) ) ) { 246 // Check if the focus event is not between the link & submenu icon of the same menu item 247 if ( ! focusedMenuItem.is( blurredMenuItem ) ) { 248 this._toggleSubmenu( blurredMenuItem, false ); 249 } 250 } 251 // In case neither items are child & parent nor vice versa 252 else if ( focusedMenuItem.has( blurredMenuItem ).length === blurredMenuItem.has( focusedMenuItem ).length ) { 253 // Get the blurred item parent & is the sibling of the focused item 254 blurredMenuItem.parents( '.fl-has-submenu' ).each( ( _, parent ) => { 255 if ( focusedMenuItem.closest( 'ul' ).is( $( parent ).closest( 'ul' ) ) ) { 256 this._toggleSubmenu( $( parent ), false ); 257 return false; 258 } 259 } ); 260 } 261 // In case the blurred item is a child of the focused item 262 else if ( focusedMenuItem.has( blurredMenuItem ).length ) { 263 if ( this.type !== 'accordion' && this.submenuIcon === 'none' ) { 264 this._toggleSubmenu( blurredMenuItem, false ); 265 } 266 } 267 }, this ) ); 268 }, 269 270 /** 271 * Logic for menu items when Escape key is pressed. 272 * 273 * @since 2.7.1 274 * @return void 275 */ 276 _menuOnEscape: function(){ 277 $( this.wrapperClass ).on( 'keydown', $.proxy( function( event ){ 278 if ( event.key !== 'Escape' ) return; 279 const menuItem = $( event.target ).closest( '.menu-item' ); 280 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 281 // In case there is a focused menu item 282 if ( menuItem.length || $( event.target ).hasClass( 'fl-menu-mobile-close' ) ) { 283 // Close the search form if it is open 284 if ( menuItem.hasClass( 'fl-menu-search-item' ) && $( this.wrapperClass ).find('.fl-search-form-input-wrap').is( ':visible' ) ) { 285 $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))').trigger( 'focus' ); 286 } 287 // Close all the submenus of the focused menu item 288 else if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.find( '.sub-menu' ).first().is( ':visible' ) ) { 289 this._toggleSubmenu( menuItem, false ); 290 } 291 else { 292 // Shift focus to the parent while closing all its submenus 293 const parentMenuItem = menuItem.parents( '.fl-has-submenu' ).not( '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading' ).first(); 294 // Close the mobile menu if there is no parent menu item and the mobile toggle is active 295 if ( parentMenuItem.length === 0 && this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) ) { 296 // Blur to trigger the focus-out event for closing the menu 297 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 298 } 299 // Close the parent submenu and shift focus to its link 300 else if ( parentMenuItem.length !== 0 ) { 301 this._toggleSubmenu( parentMenuItem, false ); 302 parentMenuItem.find( 'a' ).first().trigger( 'focus' ); 303 } 304 } 305 } 306 // Close the mobile menu if the mobile toggle is active 307 else if ( $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && mobileToggle.hasClass( 'fl-active' ) ) { 308 // Blur to trigger the focus-out event for closing the menu 309 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 310 } 311 }, this ) ); 312 }, 313 314 /** 315 * Logic for menu items when clicked. 316 * 317 * @since 1.6.1 318 * @return void 319 */ 320 _menuOnClick: function(){ 321 // Fallback for span elements and fake links to interact with the keyboard 322 $( this.wrapperClass ).on( 'keydown', 'a:not(.fl-button, [href]), span.fl-menu-toggle', $.proxy( function( event ) { 323 if ( event.key === 'Enter' || event.key === ' ' ) { 324 event.preventDefault(); 325 $( event.currentTarget ).trigger( 'click' ); 326 } 327 }, this ) ); 328 $( this.wrapperClass ).on( 'click', 'a, .fl-menu-toggle', $.proxy( function( event ) { 329 // Only allow mouse clicks with accordion & mobile menus 330 if ( this._isMouseAvailable() && ! this._isMenuToggle() && event.detail && this.type !== 'accordion' ) return; 331 // Links only open & do not toggle submenus if there is either a submenu icon or an accordion layout 332 if ( $( event.currentTarget ).is( 'a' ) && ( this.submenuIcon !== 'none' || this.type === 'accordion' ) ) return; 333 const menuItem = $( event.currentTarget ).closest( '.menu-item, .fl-menu-logo' ); 334 const menuLink = menuItem.find( 'a' ).first().attr( 'href' ); 335 const submenuHidden = menuItem.find( '.sub-menu' ).first().is( ':hidden' ); 336 if ( typeof menuLink === 'undefined' || menuLink === '#' || submenuHidden ) { 337 event.preventDefault(); 338 } 339 if ( $( event.currentTarget ).hasClass( 'fl-menu-toggle' ) || submenuHidden ) { 340 this._toggleSubmenu( menuItem, submenuHidden ); 341 } 342 }, this ) ); 343 }, 344 345 /** 346 * Controls toggling the visibility of all submenu items for desktop & mobile. 347 * 348 * @since 2.10 349 * @return void 350 */ 351 _toggleSubmenu: function ( menuItem, opened ) { 352 const togglingClass = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 353 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 354 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 355 if ( opened && menuItem.hasClass( 'fl-has-submenu' ) && ! menuItem.is( hiddenMenu ) ) { 356 menuItem.addClass( togglingClass ); 357 menuItem.find( toggleElement ).first().attr( 'aria-expanded', true ); 358 if ( this._isMenuToggle() || this.type === 'accordion' ) { 359 menuItem.find( '.sub-menu' ).first().filter( ':hidden' ).slideDown(); 360 } 361 } 362 else { 363 menuItem.parent().find( '.menu-item' ).removeClass( togglingClass ); 364 menuItem.parent().find( '.fl-has-submenu' ).not( hiddenMenu ).find( toggleElement ).attr( 'aria-expanded', false ); 365 if ( this._isMenuToggle() || this.type === 'accordion' ) {
366 menuItem.find( '.sub-menu' ).filter( ':visible' ).slideUp(); 367 } 368 } 369 }, 370 371 /** 372 * Changes general styling and behavior of menus based on mobile / desktop viewport. 373 * 374 * @see this._isMenuToggle() 375 * @since 1.6.1 376 * @return void 377 */ 378 _clickOrHover: function( clear = false ){ 379 const selector = this._isMobileBelowRowEnabled() ? this.nodeClass + '-clone' : this.nodeClass; 380 this.$submenus = this.$submenus || $( selector ).find( '.sub-menu' ); 381 382 const className = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 383 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 384 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 385 $( selector ).find( '.fl-has-submenu' ).not( hiddenMenu ).each( function() { 386 if( clear || ! $ ( this ).hasClass( className ) ){ 387 if ( clear ) $( this ).removeClass( className ); 388 $( this ).find( toggleElement ).first().attr( 'aria-expanded', false ); 389 if ( className === 'fl-active' ) { 390 $( this ).find( '.sub-menu' ).fadeOut(); 391 } else if ( className === 'focus' ) { 392 $( this ).find( '.sub-menu' ).css( { 393 'display' : '', 394 'opacity' : '' 395 } ); 396 } 397 } 398 } ); 399 }, 400 401 /** 402 * Logic to prevent submenus to go outside viewport boundaries. 403 * 404 * @since 1.6.1 405 * @return void 406 */ 407 _submenuOnRight: function(){ 408 409 $( this.wrapperClass ) 410 .on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){ 411 412 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 413 return; 414 } 415 416 var $link = $( e.currentTarget ), 417 $parent = $link.parent(), 418 $subMenu = $link.find( '.sub-menu' ), 419 subMenuWidth = $subMenu.width(), 420 subMenuPos = 0, 421 bodyWidth = $( 'body' ).width(); 422 423 if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) { 424 425 $link.addClass( 'fl-menu-submenu-right' ); 426 427 } else if( $( 'body' ).hasClass( 'rtl' ) ) { 428 429 subMenuPos = $parent.is( '.sub-menu' ) ? 430 $parent.offset().left - subMenuWidth: 431 $link.offset().left - $link.width() - subMenuWidth; 432 433 if( subMenuPos <= 0 ) { 434 $link.addClass( 'fl-menu-submenu-right' ); 435 } 436 437 } else { 438 439 subMenuPos = $parent.is( '.sub-menu' ) ? 440 $parent.offset().left + $parent.width() + subMenuWidth : 441 $link.offset().left + $link.width() + subMenuWidth; 442 443 if( subMenuPos > bodyWidth ) { 444 $link.addClass('fl-menu-submenu-right'); 445 } 446 } 447 }, this ) ) 448 .on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){ 449 $( e.currentTarget ).removeClass( 'fl-menu-submenu-right' ); 450 }, this ) ); 451 452 }, 453 454 /** 455 * Logic to prevent submenus to go behind the next overlay row. 456 * 457 * @since 1.10.9 458 * @return void 459 */ 460 _submenuRowZindexFix: function(){ 461 462 $( this.wrapperClass ) 463 .on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){ 464 465 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 466 return; 467 } 468 469 $( this.nodeClass ) 470 .closest( '.fl-row' ) 471 .find( '.fl-row-content' ) 472 .css( 'z-index', '10' ); 473 474 }, this ) ) 475 .on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function(){ 476 477 $( this.nodeClass ) 478 .closest( '.fl-row' ) 479 .find( '.fl-row-content' ) 480 .css( 'z-index', '' ); 481 482 }, this ) ); 483 }, 484 485 /** 486 * Logic for the mobile menu button. 487 * 488 * @since 1.6.1 489 * @return void 490 */ 491 _toggleForMobile: function(){ 492 493 var $wrapper = null, 494 $menu = null, 495 self = this; 496 497 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).attr('aria-controls', $( this.wrapperClass ).find( 'ul.menu' ).attr('id')); 498 499 if( this._isMenuToggle() ){ 500 501 if ( this._isMobileBelowRowEnabled() ) { 502 this._placeMobileMenuBelowRow(); 503 $wrapper = $( this.wrapperClass ); 504 $menu = $( this.nodeClass + '-clone' ); 505 $menu.find( 'ul.menu' ).show(); 506 } 507 else { 508 $wrapper = $( this.wrapperClass ); 509 $menu = $wrapper.find( '.menu' ); 510 } 511 512 if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){ 513 $menu.css({ display: 'none' }); 514 } 515 516 // Flayout Menu 517 if ( self.mobileFlyout ) { 518 this._initFlyoutMenu(); 519 } 520 521 $wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){ 522 e.stopImmediatePropagation(); 523 524 $( this ).toggleClass( 'fl-active' ); 525 526 if ( self.mobileFlyout ) { 527 self._toggleFlyoutMenu(); 528 const flyoutWrapper = $( '.fl-menu-mobile-flyout' ); 529 if ( $( this ).hasClass( 'fl-active' ) ) { 530 flyoutWrapper.attr( 'aria-hidden', false ); 531 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex="-1"]' ).attr( 'tabindex', 0 ); 532 } 533 else { 534 flyoutWrapper.attr( 'aria-hidden', true ); 535 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not
535([tabindex="-1"])' ).attr( 'tabindex', -1 ); 536 } 537 } 538 else { 539 var targetMenu = null; 540 541 if ( self.mobileBelowRow ) { 542 var $closestCol = $( this ).parents( '.fl-col, .fl-module-box' ), 543 $closestColGroup = $closestCol.length ? $closestCol.parent( '.fl-col-group' ) : null; 544 targetMenu = $closestCol.length ? $closestCol.last().next( '.fl-menu-mobile-clone' ) : null; 545 546 if ( $closestColGroup.length ) { 547 if ( $closestColGroup.hasClass( 'fl-col-group-responsive-reversed' ) ) { 548 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', -1 ); 549 } else if ( $closestColGroup ) { 550 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', 2 ); 551 } 552 } 553 } else { 554 targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' ); 555 } 556 557 if ( targetMenu.length ) { 558 $menu = $( targetMenu ); 559 } 560 561 $menu.slideToggle(); 562 } 563 564 e.stopPropagation(); 565 } ); 566 567 // Hide active menu when click on anchor link ID that exists on a page 568 $menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(){ 569 var $href = $(this).attr('href'), 570 $targetID = $href.split('#')[1], 571 element = $('#' + $targetID); 572 if ( $('body').find(element).length > 0 ) { 573 $( this ).toggleClass( 'fl-active' ); 574 FLBuilderLayout._scrollToElement( element ); 575 if ( ! self._isMenuToggle() ) { 576 $menu.slideToggle(); 577 } 578 } 579 }); 580 } 581 else { 582 583 if ( this._isMobileBelowRowEnabled() ) { 584 this._removeMenuFromBelowRow(); 585 } 586 587 $wrapper = $( this.wrapperClass ), 588 $menu = $wrapper.find( 'ul.menu' ); 589 $wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' ); 590 $menu.css({ display: '' }); 591 592 if ( ! this._isMobileBelowRowEnabled() ) { 593 $menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' ); 594 } 595 596 if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) { 597 $( 'body' ).css( 'margin', '' ); 598 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 599 $menu.unwrap(); 600 $wrapper.find( '.fl-menu-mobile-close' ).remove(); 601 $wrapper.find( '.fl-menu-mobile-opacity' ).remove(); 602 } 603 } 604 }, 605 606 /** 607 * Init any mega menus that exist. 608 * 609 * @see this._isMenuToggle() 610 * @since 1.10.4 611 * @return void 612 */ 613 _initMegaMenus: function(){ 614 615 var module = $( this.nodeClass ), 616 rowContent = module.closest( '.fl-row-content' ), 617 rowWidth = rowContent.width(), 618 megas = module.find( '.mega-menu' ), 619 disabled = module.find( '.mega-menu-disabled' ), 620 isToggle = this._isMenuToggle(); 621 622 if ( isToggle ) { 623 megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' ); 624 module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' ); 625 rowContent.css( 'position', '' ); 626 } else { 627 disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' ); 628 module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' ); 629 rowContent.css( 'position', 'relative' ); 630 } 631 }, 632 633 /** 634 * Check to see if Below Row should be enabled. 635 * 636 * @since 1.11 637 * @return boolean 638 */ 639 _isMobileBelowRowEnabled: function() { 640 return this.mobileBelowRow && ( $( this.nodeClass ).parents( '.fl-col, .fl-module-box' ).length ); 641 }, 642 643 /** 644 * Logic for putting the mobile menu below the menu's 645 * column so it spans the full width of the page. 646 * 647 * @since 1.10 648 * @return void 649 */ 650 _placeMobileMenuBelowRow: function(){ 651 652 if ( $( this.nodeClass + '-clone' ).length ) { 653 return; 654 } 655 656 var module = $( this.nodeClass ), 657 clone = null, 658 col = module.parents( '.fl-col, .fl-module-box' ).last(); 659 660 if ( module.length < 1 ) { 661 return; 662 } 663 664 clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone(); 665 module.find( 'ul.menu' ).remove(); 666 clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) ); 667 clone.addClass( 'fl-menu-mobile-clone' ); 668 clone.find( '.fl-menu-mobile-toggle' ).remove(); 669 col.after( clone ); 670 671 // Removes animation when enabled 672 if ( module.hasClass( 'fl-animation' ) ) { 673 clone.removeClass( 'fl-animation' ); 674 } 675 676 this._menuOnFocus(); 677 this._menuOnClick(); 678 this._menuOnEscape(); 679 }, 680 681 /** 682 * Logic for removing the mobile menu from below the menu's 683 * column and putting it back in the main wrapper. 684 * 685 * @since 1.10 686 * @return void 687 */ 688 _removeMenuFromBelowRow: function(){ 689 690 if ( ! $( this.nodeClass + '-clone' ).length ) { 691 return; 692 } 693 694 var module = $( this.nodeClass ), 695 clone = $( this.nodeClass + '-clone' ), 696 menu = clone.find( 'ul.menu' ), 697 nav = module.find( 'nav' ); 698
699 if ( nav.length ) { 700 nav.append( menu ); 701 } else { 702 module.find( '.fl-menu-mobile-toggle' ).after( menu ); 703 } 704 clone.remove(); 705 menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink ); 706 }, 707 708 /** 709 * Logic for Flyout responsive menu. 710 * 711 * @since 2.2 712 * @return void 713 */ 714 _initFlyoutMenu: function(){ 715 var wrapper = $( this.wrapperClass ), 716 menu = wrapper.find( 'ul.menu' ), 717 button = wrapper.find( '.fl-menu-mobile-toggle' ); 718 719 if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) { 720 menu.wrap( '<div class="fl-menu-mobile-flyout" aria-hidden="true"></div>' ); 721 } 722 723 if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) { 724 var close = window.fl_responsive_close || 'Close' 725 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>' ); 726 } 727 728 // Push with opacity 729 if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) { 730 wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' ); 731 } 732 733 wrapper.off( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close' ).on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){ 734 button.trigger('focus').trigger( 'click' ); 735 e.stopPropagation(); 736 }); 737 738 if ( 'undefined' !== typeof FLBuilder ) { 739 FLBuilder.addHook('restartEditingSession', function(){ 740 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 741 742 // Toggle active menu 743 if ( button.hasClass( 'fl-active' ) ) { 744 button.trigger( 'click' ); 745 } 746 }); 747 } 748 $( '.fl-menu-mobile-flyout' ).find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not([tabindex="-1"])' ).attr( 'tabindex', -1 ); 749 }, 750 751 /** 752 * Logic to enable/disable the Flyout menu on button click. 753 * 754 * @since 2.2 755 * @return void 756 */ 757 _toggleFlyoutMenu: function(){ 758 var wrapper = $( this.wrapperClass ), 759 button = wrapper.find( '.fl-menu-mobile-toggle' ), 760 position = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 761 pushMenu = wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 762 opacity = wrapper.find( '.fl-menu-mobile-opacity' ), 763 marginPos = {}, 764 fixedPos = {}, 765 fixedHeader = $('header, header > div'); 766 767 this._resizeFlyoutMenuPanel(); 768 769 // Fix the push menu when builder ui panel is pinned 770 if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) { 771 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' ); 772 } 773 774 if ( pushMenu ) { 775 marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 776 $( 'body' ).animate( marginPos, 200); 777 778 // Fixed header 779 if ( fixedHeader.length > 0 ) { 780 fixedPos[ position] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 781 fixedHeader.each(function(){ 782 if ( 'fixed' == $( this ).css( 'position' ) ) { 783 $( this ).css({ 'transition' : 'none' }); 784 $( this ).animate( fixedPos, 200 ); 785 } 786 }); 787 } 788 } 789 790 if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) { 791 opacity.show(); 792 } 793 else { 794 opacity.hide(); 795 } 796 }, 797 798 /** 799 * Resize or reposition the Flyout Menu Panel. 800 * 801 * @since 2.8.1 802 * @return void 803 */ 804 _resizeFlyoutMenuPanel: function(){ 805 const wrapper = $( this.wrapperClass ); 806 const wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' ); 807 808 if ( wrapFlyout.length > 0 ) { 809 wrapFlyout.css( this._getFlyoutMenuPanelPosition() ); 810 } 811 }, 812 813 /** 814 * Compute the Flyout Menu Panel's position on the screen. 815 * 816 * @since 2.8.1 817 * @return object 818 */ 819 _getFlyoutMenuPanelPosition: function() { 820 var wrapper = $( this.wrapperClass ), 821 button = wrapper.find( '.fl-menu-mobile-toggle' ), 822 side = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 823 winHeight = $(window).outerHeight(), 824 winTop = $(window).scrollTop(), 825 adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).height() : 0, 826 flyoutPosition = {}; 827 828 flyoutPosition[ side ] = '-' + ( parseInt( this.flyoutWidth ) + 15 ) + 'px'; 829 if ( ! button.hasClass( 'fl-active' ) ) { 830 return flyoutPosition; 831 } 832 833 flyoutPosition[ side ] = '0px'; 834 flyoutPosition[ 'height' ] = winHeight + 'px'; 835 flyoutPosition[ 'top' ] = '0px'; 836 837 if ( adminBarHeight > 0 ) { 838 const diff = adminBarHeight - winTop; 839 flyoutPosition[ 'top' ] = diff <= 0 ? '0px' : (diff) + 'px'; 840 } 841 842 return flyoutPosition; 843 }, 844 845 /** 846 * Shows or hides the nav search form. 847 * 848 * @since 2.5 849 * @method _toggleMenuSearch 850 */ 851 _toggleMenuSearch: function(){ 852 const form = $( this.wrapperClass ).find('.fl-menu-search-item .fl-search-form-input-wrap');
853 const button = $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))'); 854 form.on('submit', () => form.stop().fadeToggle('fast')); 855 // Close the search form when focus is lost 856 form.on('focusout', (event) => { 857 if (form.is(':visible') && form.has($(event.relatedTarget)).length === 0) { 858 button.trigger('click'); 859 } 860 }); 861 button.attr('aria-expanded', false); 862 // Close other open submenus when focusing on the search button 863 button.on('focus', (event) => { 864 const parentMenus = $(event.relatedTarget).parents('.menu-item.fl-has-submenu'); 865 if (event.relatedTarget && parentMenus.length) { 866 this._toggleSubmenu(parentMenus, false); 867 } 868 }); 869 button.on('click', (event) => { 870 // Prevent toggling when clicking with mouse while the form is already open 871 if (event.detail && event.type === 'click' && form.is(':visible')) return; 872 form.stop().fadeToggle('fast', () => { 873 button.attr('aria-expanded', form.is(':visible')); 874 if(form.is(':visible')) { 875 form.find('.fl-search-text').focus(); 876 } 877 }); 878 }); 879 }, 880 881 /** 882 * Adds menu node and post ID to WooCommerce ajax URL requests. 883 * 884 * @since 2.5 885 * @return void 886 */ 887 _wooUpdateParams: function() { 888 if ( 'undefined' !== typeof wc_cart_fragments_params ) { 889 wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 890 } 891 if ( 'undefined' !== typeof wc_add_to_cart_params ) { 892 wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 893 } 894 }, 895 }; 896 897})(jQuery); 898 899(function($) { 900 901 $(function() { 902 903 new FLBuilderMenu({ 904 id: '5b4e4504e6e84', 905 type: 'horizontal', 906 mobile: 'expanded', 907 mobileBelowRow: false, 908 mobileFlyout: false, 909 breakPoints: { 910 large: 1200, 911 medium: 992, 912 small: 768 }, 913 mobileBreakpoint: 'mobile', 914 postId : '793', 915 mobileStacked: true, 916 submenuIcon: 'none', 917 flyoutWidth: '250', 918 }); 919 920 }); 921 922})(jQuery); 923 924/* Start Layout Custom JS */ 925 926/* End Layout Custom JS */ 927 928 929jQuery(function($) { 930 931 $(function() { 932 $( '.fl-node-5da892bbc0b4e .fl-photo-img' ) 933 .on( 'mouseenter', function( e ) { 934 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 935 } ) 936 .on( 'mouseleave', function( e ){ 937 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 938 } ); 939 }); 940 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 941}); 942 943(function($) { 944 945 $(function() { 946 947 new FLBuilderMenu({ 948 id: '5da892bbc0b4a', 949 type: 'horizontal', 950 mobile: 'hamburger', 951 mobileBelowRow: true, 952 mobileFlyout: false, 953 breakPoints: { 954 large: 1200, 955 medium: 992, 956 small: 768 }, 957 mobileBreakpoint: 'medium-mobile', 958 postId : '15756', 959 mobileStacked: true, 960 submenuIcon: 'none', 961 flyoutWidth: '250', 962 }); 963 964 }); 965 966})(jQuery); 967 968/* Start Layout Custom JS */ 969 970/* End Layout Custom JS */ 971 972(function($){ 973 974 /** 975 * Helper class for header layout logic. 976 * 977 * @since 1.0 978 * @class FLThemeBuilderHeaderLayout 979 */ 980 FLThemeBuilderHeaderLayout = { 981 982 /** 983 * A reference to the window object for this page. 984 * 985 * @since 1.0 986 * @property {Object} win 987 */ 988 win : null, 989 990 /** 991 * A reference to the body object for this page. 992 * 993 * @since 1.0 994 * @property {Object} body 995 */ 996 body : null, 997 998 /** 999 * A reference to the header object for this page. 1000 * 1001 * @since 1.0 1002 * @property {Object} header 1003 */ 1004 header : null, 1005 1006 /** 1007 * Whether this header overlays the content or not. 1008 * 1009 * @since 1.0 1010 * @property {Boolean} overlay 1011 */ 1012 overlay : false, 1013 1014 /** 1015 * Whether the page has the WP admin bar or not. 1016 * 1017 * @since 1.0 1018 * @property {Boolean} hasAdminBar 1019 */ 1020 hasAdminBar : false, 1021 1022 /** 1023 * Breakpoint for when the sticky header should apply. 1024 * 1025 * @since 1.4 1026 * @property {String} stickyOn 1027 */ 1028 stickyOn: '', 1029 1030 /** 1031 * A reference of the sticky and shrink header breakpoint. 1032 * 1033 * @since 1.2.5 1034 * @property {Number} breakpointWidth 1035 */ 1036 breakpointWidth: 0, 1037 1038 /** 1039 * Initializes header layout logic. 1040 * 1041 * @since 1.0 1042 * @method init 1043 */ 1044 init: function() 1045 {
1046 var editing = $( 'html.fl-builder-edit' ).length, 1047 header = $( '.fl-builder-content[data-type=header]' ), 1048 menuModule = header.find( '.fl-module-menu' ), 1049 breakpoint = null; 1050 1051 if ( ! editing && header.length ) { 1052 1053 header.imagesLoaded( $.proxy( function() { 1054 1055 this.win = $( window ); 1056 this.body = $( 'body' ); 1057 this.header = header.eq( 0 ); 1058 this.overlay = !! Number( header.attr( 'data-overlay' ) ); 1059 this.hasAdminBar = !! $( 'body.admin-bar' ).length; 1060 this.stickyOn = this.header.data( 'sticky-on' ); 1061 breakpoint = this.header.data( 'sticky-breakpoint' ); 1062 1063 if ( '' == this.stickyOn ) { 1064 if ( typeof FLBuilderLayoutConfig.breakpoints[ breakpoint ] !== undefined ) { 1065 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints[ breakpoint ]; 1066 } 1067 else { 1068 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints.medium; 1069 } 1070 } 1071 1072 if ( Number( header.attr( 'data-sticky' ) ) ) { 1073 1074 this.header.data( 'original-top', this.header.offset().top ); 1075 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initSticky, this ) ) ); 1076 this._initSticky(); 1077 1078 } 1079 1080 }, this ) ); 1081 } 1082 }, 1083 1084 /** 1085 * Initializes sticky logic for a header. 1086 * 1087 * @since 1.0 1088 * @access private 1089 * @method _initSticky 1090 */ 1091 _initSticky: function( e ) 1092 { 1093 var header = $('.fl-builder-content[data-type=header]'), 1094 windowSize = this.win.width(), 1095 makeSticky = false; 1096 1097 makeSticky = this._makeWindowSticky( windowSize ); 1098 if ( makeSticky || ( this.breakpointWidth > 0 && windowSize >= this.breakpointWidth ) ) { 1099 this.win.on( 'scroll.fl-theme-builder-header-sticky', $.proxy( this._doSticky, this ) ); 1100 // 1101 // Check if Event Type is 'resize' then invoke this._doSticky() 1102 // only if the 'fl-theme-builder-header-sticky' class is already present. 1103 // 1104 if ( e && 'resize' === e.type ) { 1105 if ( this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1106 this._doSticky( e ); 1107 } 1108 this._adjustStickyHeaderWidth(); 1109 } 1110 1111 if ( Number( header.attr( 'data-shrink' ) ) ) { 1112 this.header.data( 'original-height', this.header.outerHeight() ); 1113 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initShrink, this ) ) ); 1114 this._initShrink(); 1115 } 1116 1117 this._initFlyoutMenuFix( e ); 1118 } else { 1119 this.win.off( 'scroll.fl-theme-builder-header-sticky' ); 1120 this.win.off( 'resize.fl-theme-builder-header-sticky' ); 1121 1122 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 1123 this.header.removeAttr( 'style' ); 1124 this.header.parent().css( 'padding-top', '0' ); 1125 } 1126 }, 1127 1128 /** 1129 * Check if Header should be sticky at a particular Window size. 1130 * 1131 * @since 1.4 1132 * @access private 1133 * @param widowSize 1134 * @method _makeWindowSticky 1135 */ 1136 _makeWindowSticky: function ( windowSize ) 1137 { 1138 var makeSticky = false; 1139 1140 switch (this.stickyOn) { 1141 case 'xl': 1142 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['large']; 1143 break; 1144 case '': // Default 1145 case 'desktop': 1146 makeSticky = windowSize >= FLBuilderLayoutConfig.breakpoints['medium']; 1147 break; 1148 case 'desktop-medium': 1149 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small']; 1150 break; 1151 case 'large': 1152 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['medium'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 1153 break; 1154 case 'large-medium': 1155 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 1156 break; 1157 case 'medium': 1158 makeSticky = ( windowSize <= FLBuilderLayoutConfig.breakpoints['medium'] && windowSize > FLBuilderLayoutConfig.breakpoints['small'] ); 1159 break; 1160 case 'medium-mobile': 1161 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['medium']); 1162 break; 1163 case 'mobile': 1164 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['small']); 1165 break; 1166 case 'all': 1167 makeSticky = true; 1168 break; 1169 } 1170 1171 return makeSticky; 1172 }, 1173 1174 /** 1175 * Sticks the header when the page is scrolled. 1176 * 1177 * @since 1.0 1178 * @access private 1179 * @method _doSticky 1180 */ 1181 _doSticky: function( e ) 1182 { 1183 var winTop = Math.floor( this.win.scrollTop() ), 1184 headerTop = Math.floor( this.header.data( 'original-top' ) ),
1185 hasStickyClass = this.header.hasClass( 'fl-theme-builder-header-sticky' ), 1186 hasScrolledClass = this.header.hasClass( 'fl-theme-builder-header-scrolled' ), 1187 beforeHeader = this.header.prevAll( '.fl-builder-content' ), 1188 bodyTopPadding = parseInt( jQuery('body').css('padding-top') ), 1189 winBarHeight = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0, 1190 headerHeight = 0; 1191 1192 if ( isNaN( bodyTopPadding ) ) { 1193 bodyTopPadding = 0; 1194 } 1195 1196 if ( this.hasAdminBar && this.win.width() > 600 ) { 1197 winTop += Math.floor( winBarHeight ); 1198 } 1199 1200 if ( winTop > headerTop ) { 1201 if ( ! hasStickyClass ) { 1202 if ( e && ( 'scroll' === e.type || 'smartscroll' === e.type ) ) { 1203 this.header.addClass( 'fl-theme-builder-header-sticky' ); 1204 if ( this.overlay && beforeHeader.length ) { 1205 this.header.css( 'top', winBarHeight); 1206 } 1207 } 1208 1209 if ( ! this.overlay ) { 1210 this._adjustHeaderHeight(); 1211 } 1212 } 1213 } 1214 else if ( hasStickyClass ) { 1215 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 1216 this.header.removeAttr( 'style' ); 1217 this.header.parent().css( 'padding-top', '0' ); 1218 } 1219 1220 this._adjustStickyHeaderWidth(); 1221 1222 if ( winTop > headerTop ) { 1223 if ( ! hasScrolledClass ) { 1224 this.header.addClass( 'fl-theme-builder-header-scrolled' ); 1225 } 1226 } else if ( hasScrolledClass ) { 1227 this.header.removeClass( 'fl-theme-builder-header-scrolled' ); 1228 } 1229 1230 this._flyoutMenuFix( e ); 1231 }, 1232 1233 /** 1234 * Initializes flyout menu fixes on sticky header. 1235 * 1236 * @since 1.4.1 1237 * @method _initFlyoutMenuFix 1238 */ 1239 _initFlyoutMenuFix: function( e ) { 1240 var header = this.header, 1241 menuModule = header.closest( '.fl-menu' ), 1242 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 1243 isPushMenu = menuModule.hasClass( 'fl-menu-responsive-flyout-push' ) || menuModule.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 1244 isOverlay = menuModule.hasClass( 'fl-menu-responsive-flyout-overlay' ), 1245 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 1246 flyoutParent = header.parent().is( 'header' ) ? header.parent().parent() : header.parent(); 1247 isFullWidth = this.win.width() === header.width(), 1248 flyoutLayout = '', 1249 activePos = 250, 1250 headerPos = 0; 1251 1252 if ( ! flyoutMenu.length ) { 1253 return; 1254 } 1255 1256 if ( this.win.width() > header.parent().width() ) { 1257 headerPos = ( this.win.width() - header.width() ) / 2; 1258 } 1259 1260 if ( isOverlay ) { 1261 activePos = headerPos; 1262 } 1263 else if ( isPushMenu ) { 1264 activePos = activePos + headerPos; 1265 } 1266 flyoutMenu.data( 'activePos', activePos ); 1267 1268 if ( isPushMenu ) { 1269 flyoutLayout = 'push-' + flyoutPos; 1270 } 1271 else if ( isOverlay ) { 1272 flyoutLayout = 'overlay-' + flyoutPos; 1273 } 1274 1275 if ( isPushMenu && ! $( 'html' ).hasClass( 'fl-theme-builder-has-flyout-menu' ) ) { 1276 $( 'html' ).addClass( 'fl-theme-builder-has-flyout-menu' ); 1277 } 1278 1279 if ( ! flyoutParent.hasClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ) ) { 1280 flyoutParent.addClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ); 1281 } 1282 1283 if ( ! header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && isOverlay ) { 1284 header.addClass( 'fl-theme-builder-flyout-menu-overlay' ); 1285 } 1286 1287 if ( ! header.hasClass( 'fl-theme-builder-header-full-width' ) && isFullWidth ) { 1288 header.addClass( 'fl-theme-builder-header-full-width' ); 1289 } 1290 else if ( ! isFullWidth ) { 1291 header.removeClass( 'fl-theme-builder-header-full-width' ); 1292 } 1293 1294 menuModule.on( 'click', '.fl-menu-mobile-toggle', $.proxy( function( event ){ 1295 if ( menuModule.find( '.fl-menu-mobile-toggle.fl-active' ).length ) { 1296 $( 'html' ).addClass( 'fl-theme-builder-flyout-menu-active' ); 1297 event.stopImmediatePropagation(); 1298 } 1299 else { 1300 $( 'html' ).removeClass( 'fl-theme-builder-flyout-menu-active' ); 1301 } 1302 1303 this._flyoutMenuFix( event ); 1304 }, this ) ); 1305 }, 1306 1307 /** 1308 * Fix flyout menu inside the sticky header. 1309 * 1310 * @since 1.4.1 1311 * @method _flyoutMenuFix 1312 */ 1313 _flyoutMenuFix: function( e ){ 1314 var header = this.header, 1315 menuModule = $( e.target ).closest( '.fl-menu' ), 1316 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 1317 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 1318 menuOpacity = menuModule.find( '.fl-menu-mobile-opacity' ), 1319 isScroll = 'undefined' !== typeof e && 'scroll' === e.handleObj.type, 1320 activePos = 'undefined' !== typeof flyoutMenu.data( 'activePos' ) ? flyoutMenu.data( 'activePos' ) : 0, 1321 headerPos = ( this.win.width() - header.width() ) / 2, 1322 inactivePos = headerPos > 0 ? activePos + 4 : 254; 1323 1324 if ( ! flyoutMenu.length ) { 1325 return; 1326 } 1327 1328 if ( this.overlay ) { 1329 return; 1330 } 1331
1332 if( $( '.fl-theme-builder-flyout-menu-active' ).length ) { 1333 1334 if ( isScroll && ! flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 1335 flyoutMenu.addClass( 'fl-menu-disable-transition' ); 1336 } 1337 1338 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1339 if ( ! isScroll ) { 1340 setTimeout( $.proxy( function(){ 1341 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 1342 }, this ), 1 ); 1343 } 1344 else { 1345 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 1346 } 1347 } 1348 else { 1349 flyoutMenu.css( flyoutPos, '0px' ); 1350 } 1351 } 1352 else { 1353 if ( flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 1354 flyoutMenu.removeClass( 'fl-menu-disable-transition' ); 1355 } 1356 1357 if ( header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && headerPos > 0 && headerPos < 250 ) { 1358 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1359 inactivePos = headerPos + 254; 1360 } 1361 else { 1362 inactivePos = 254; 1363 } 1364 } 1365 1366 if ( e && e.type === 'resize' ) { 1367 inactivePos = headerPos + 254; 1368 } 1369 1370 flyoutMenu.css( flyoutPos, '-' + inactivePos + 'px' ); 1371 } 1372 1373 if ( e && menuModule.is('.fl-menu-responsive-flyout-overlay') && $.infinitescroll ) { 1374 e.stopImmediatePropagation(); 1375 } 1376 1377 if( menuOpacity.length ) { 1378 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1379 if ( '0px' === menuOpacity.css( 'left' ) ) { 1380 menuOpacity.css( 'left', '-' + headerPos + 'px' ); 1381 } 1382 } 1383 else { 1384 menuOpacity.css( 'left', '' ); 1385 } 1386 } 1387 }, 1388 1389 /** 1390 * Adjust sticky header width if BB Theme Boxed Layout is used. 1391 * 1392 * @since 1.4 1393 * @access private 1394 * @method _adjustStickyHeaderWidth 1395 */ 1396 _adjustStickyHeaderWidth: function () { 1397 if ( $('body').hasClass( 'fl-fixed-width' ) ) { 1398 var parentWidth = this.header.parent().width(); 1399 1400 // Better if this is set in the stylesheet file. 1401 if ( this.win.width() >= 992 ) { 1402 this.header.css({ 1403 'margin': '0 auto', 1404 'max-width': parentWidth, 1405 }); 1406 } 1407 else { 1408 this.header.css({ 1409 'margin': '', 1410 'max-width': '', 1411 }); 1412 } 1413 } 1414 }, 1415 1416 /** 1417 * Adjust Sticky Header Height 1418 * 1419 * @since 1.4 1420 * @access private 1421 * @method _adjustHeaderHeight 1422 */ 1423 _adjustHeaderHeight: function () { 1424 var beforeHeader = this.header.prevAll('.fl-builder-content'), 1425 beforeHeaderHeight = 0, 1426 beforeHeaderFix = 0, 1427 headerHeight = Math.floor( this.header.outerHeight() ), 1428 bodyTopPadding = parseInt( $( 'body' ).css( 'padding-top' ) ), 1429 wpAdminBarHeight = 0, 1430 totalHeaderHeight = 0; 1431 1432 if ( isNaN( bodyTopPadding ) ) { 1433 bodyTopPadding = 0; 1434 } 1435 1436 if ( beforeHeader.length ) { 1437 $.each( beforeHeader, function() { 1438 beforeHeaderHeight += Math.floor( $(this).outerHeight() ); 1439 }); 1440 // Subtract this value from the header parent's top padding. 1441 beforeHeaderFix = 2; 1442 } 1443 1444 if ( this.hasAdminBar && this.win.width() <= 600 ) { 1445 wpAdminBarHeight = Math.floor( $('#wpadminbar').outerHeight() ); 1446 } 1447 1448 totalHeaderHeight = Math.floor( beforeHeaderHeight + headerHeight); 1449 1450 if ( headerHeight > 0 ) { 1451 var headerParent = this.header.parent(), 1452 headerParentTopPadding = 0; 1453 1454 // If the header's parent container is the BODY tag ignore its top padding. 1455 if ( $( headerParent ).is('body') ) { 1456 headerParentTopPadding = Math.floor( headerHeight - wpAdminBarHeight ); 1457 } else { 1458 headerParentTopPadding = Math.floor( headerHeight - bodyTopPadding - wpAdminBarHeight ); 1459 } 1460 1461 $( headerParent ).css( 'padding-top', ( headerParentTopPadding - beforeHeaderFix ) + 'px' ); 1462 1463 this.header.css({ 1464 '-webkit-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 1465 '-ms-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 1466 'transform': 'translate(0px, -' + totalHeaderHeight + 'px)' 1467 }); 1468 1469 } 1470 1471 }, 1472 1473 /** 1474 * Initializes shrink logic for a header. 1475 * 1476 * @since 1.0 1477 * @access private 1478 * @method _initShrink 1479 */ 1480 _initShrink: function( e ) 1481 { 1482 if ( this.win.width() >= this.breakpointWidth ) {
1483 this.win.on( 'scroll.fl-theme-builder-header-shrink', $.proxy( this._doShrink, this ) ); 1484 this._setImageMaxHeight(); 1485 1486 if ( this.win.scrollTop() > 0 ){ 1487 this._doShrink(); 1488 } 1489 1490 } else { 1491 this.header.parent().css( 'padding-top', '0' ); 1492 this.win.off( 'scroll.fl-theme-builder-header-shrink' ); 1493 this._removeShrink(); 1494 this._removeImageMaxHeight(); 1495 } 1496 }, 1497 1498 /** 1499 * Shrinks the header when the page is scrolled. 1500 * 1501 * @since 1.0 1502 * @access private 1503 * @method _doShrink 1504 */ 1505 _doShrink: function( e ) 1506 { 1507 var winTop = this.win.scrollTop(), 1508 headerTop = this.header.data('original-top'), 1509 headerHeight = this.header.data('original-height'), 1510 shrinkImageHeight = this.header.data('shrink-image-height'), 1511 windowSize = this.win.width(), 1512 makeSticky = this._makeWindowSticky( windowSize ), 1513 hasClass = this.header.hasClass( 'fl-theme-builder-header-shrink' ); 1514 1515 1516 if ( this.hasAdminBar ) { 1517 winTop += 32; 1518 } 1519 1520 if ( makeSticky && ( winTop > headerTop + headerHeight ) ) { 1521 if ( ! hasClass ) { 1522 1523 this.header.addClass( 'fl-theme-builder-header-shrink' ); 1524 1525 // Shrink images but don't include lightbox and menu images. 1526 this.header.find('img').each( function( i ) { 1527 var image = $( this ), 1528 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 1529 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 1530 imageInNavMenu = image.closest( 'li.menu-item' ).length; 1531 1532 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 1533 image.css( 'max-height', shrinkImageHeight ); 1534 } 1535 1536 }); 1537 1538 this.header.find( '.fl-row-content-wrap' ).each( function() { 1539 1540 var row = $( this ); 1541 1542 if ( parseInt( row.css( 'padding-bottom' ) ) > 5 ) { 1543 row.addClass( 'fl-theme-builder-header-shrink-row-bottom' ); 1544 } 1545 1546 if ( parseInt( row.css( 'padding-top' ) ) > 5 ) { 1547 row.addClass( 'fl-theme-builder-header-shrink-row-top' ); 1548 } 1549 } ); 1550 1551 this.header.find( '.fl-module' ).each( function() { 1552 1553 var module = $( this ).find( '.fl-module-content' ).length ? $( this ).find( '.fl-module-content' ) : $( this ); 1554 1555 if ( parseInt( module.css( 'margin-bottom' ) ) > 5 ) { 1556 module.addClass( 'fl-theme-builder-header-shrink-module-bottom' ); 1557 } 1558 1559 if ( parseInt( module.css( 'margin-top' ) ) > 5 ) { 1560 module.addClass( 'fl-theme-builder-header-shrink-module-top' ); 1561 } 1562 } ); 1563 } 1564 } else if (hasClass) { 1565 this.header.find( 'img' ).css( 'max-height', '' ); 1566 this._removeShrink(); 1567 } 1568 1569 // Fixes Shrink header issue with BB Theme when window is scrolled then resized and back. 1570 if ( 'undefined' === typeof( e ) && $('body').hasClass( 'fl-fixed-width' ) ) { 1571 if ( ! this.overlay ) { 1572 this._adjustHeaderHeight(); 1573 } 1574 } 1575 1576 }, 1577 1578 /** 1579 * Removes the header shrink effect. 1580 * 1581 * @since 1.0 1582 * @access private 1583 * @method _removeShrink 1584 */ 1585 _removeShrink: function() 1586 { 1587 var rows = this.header.find( '.fl-row-content-wrap' ), 1588 modules = this.header.find('.fl-module, .fl-module-content'); 1589 1590 rows.removeClass( 'fl-theme-builder-header-shrink-row-bottom' ); 1591 rows.removeClass( 'fl-theme-builder-header-shrink-row-top' ); 1592 modules.removeClass( 'fl-theme-builder-header-shrink-module-bottom' ); 1593 modules.removeClass( 'fl-theme-builder-header-shrink-module-top' ); 1594 this.header.removeClass( 'fl-theme-builder-header-shrink' ); 1595 }, 1596 1597 /** 1598 * Adds max height to images in modules for smooth scrolling. 1599 * 1600 * @since 1.1.1 1601 * @access private 1602 * @method _setImageMaxHeight 1603 */ 1604 _setImageMaxHeight: function() 1605 { 1606 var head = $( 'head' ), 1607 stylesId = 'fl-header-styles-' + this.header.data( 'post-id' ), 1608 styles = '', 1609 images = this.header.find( '.fl-module img' ); 1610 1611 if ( $( '#' + stylesId ).length ) { 1612 return; 1613 } 1614 1615 images.each( function( i ) { 1616 var image = $( this ), 1617 height = image.height(), 1618 node = image.closest( '.fl-module' ).data( 'node' ), 1619 className = 'fl-node-' + node + '-img-' + i, 1620 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 1621 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 1622 imageInNavMenu = image.closest( 'li.menu-item' ).length; 1623 1624 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 1625 image.addClass( className ); 1626 styles += '.' + className + ' { max-height: ' + ( height ? height : image[0].height ) + 'px }'; 1627 } 1628 1629 } ); 1630
1631 if ( '' !== styles ) { 1632 head.append( '<style id="' + stylesId + '">' + styles + '</style>' ); 1633 } 1634 }, 1635 1636 /** 1637 * Removes max height on images in modules for smooth scrolling. 1638 * 1639 * @since 1.1.1 1640 * @access private 1641 * @method _removeImageMaxHeight 1642 */ 1643 _removeImageMaxHeight: function() 1644 { 1645 $( '#fl-header-styles-' + this.header.data( 'post-id' ) ).remove(); 1646 }, 1647 }; 1648 1649 $( function() { FLThemeBuilderHeaderLayout.init(); } ); 1650 1651})(jQuery); 1652
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.