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 * Whether this header can be pinned from page load. 1040 * 1041 * @since 1.6.1 1042 * @property {Boolean} pinnable 1043 */ 1044 pinnable : false, 1045 1046 /** 1047 * Initializes header layout logic. 1048 * 1049 * @since 1.0 1050 * @method init 1051 */ 1052 init: function() 1053 {
1054 var editing = $( 'html.fl-builder-edit' ).length, 1055 header = $( '.fl-builder-content[data-type=header]' ), 1056 menuModule = header.find( '.fl-module-menu' ), 1057 breakpoint = null, 1058 adminBarHeight = 0; 1059 1060 if ( ! editing && header.length ) { 1061 1062 header.imagesLoaded( $.proxy( function() { 1063 1064 this.win = $( window ); 1065 this.body = $( 'body' ); 1066 this.header = header.eq( 0 ); 1067 this.overlay = !! Number( header.attr( 'data-overlay' ) ); 1068 this.hasAdminBar = !! $( 'body.admin-bar' ).length; 1069 this.stickyOn = this.header.data( 'sticky-on' ); 1070 breakpoint = this.header.data( 'sticky-breakpoint' ); 1071 1072 if ( '' == this.stickyOn ) { 1073 if ( typeof FLBuilderLayoutConfig.breakpoints[ breakpoint ] !== undefined ) { 1074 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints[ breakpoint ]; 1075 } 1076 else { 1077 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints.medium; 1078 } 1079 } 1080 1081 if ( Number( header.attr( 'data-sticky' ) ) ) { 1082 1083 this.header.data( 'original-top', this.header.offset().top ); 1084 1085 // The pin decision is made once here, while the header offset and the admin bar height are read from the same layout. 1086 adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).outerHeight() : 0; 1087 this.pinnable = this.overlay && this.header.data( 'original-top' ) <= adminBarHeight; 1088 1089 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initSticky, this ) ) ); 1090 this._initSticky(); 1091 1092 } 1093 1094 }, this ) ); 1095 } 1096 }, 1097 1098 /** 1099 * Initializes sticky logic for a header. 1100 * 1101 * @since 1.0 1102 * @access private 1103 * @method _initSticky 1104 */ 1105 _initSticky: function( e ) 1106 { 1107 var header = $('.fl-builder-content[data-type=header]'), 1108 windowSize = this.win.width(), 1109 makeSticky = false; 1110 1111 makeSticky = this._makeWindowSticky( windowSize ); 1112 if ( makeSticky || ( this.breakpointWidth > 0 && windowSize >= this.breakpointWidth ) ) { 1113 this.win.on( 'scroll.fl-theme-builder-header-sticky', $.proxy( this._doSticky, this ) ); 1114 this._initPin(); 1115
1116 // Apply the sticky state on initial load when the page is 1117 // already scrolled past the header — e.g. when the browser 1118 // restores the scroll position on refresh. Overlay headers are 1119 // out of scope here; this mirrors the shrink-on-load behavior 1120 // in _initShrink(). 1121 if ( ! e && ! this.overlay && ! this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1122 var loadWinTop = this.win.scrollTop(), 1123 loadHeaderTop = Math.floor( this.header.data( 'original-top' ) ); 1124 1125 if ( this.hasAdminBar && windowSize > 600 ) { 1126 loadWinTop += Math.floor( $( '#wpadminbar' ).outerHeight() ); 1127 } 1128 1129 if ( loadWinTop > loadHeaderTop ) { 1130 this.header.addClass( 'fl-theme-builder-header-sticky' ); 1131 this.header.addClass( 'fl-theme-builder-header-scrolled' ); 1132 this._adjustHeaderHeight(); 1133 this._adjustStickyHeaderWidth(); 1134 } 1135 } 1136 1137 // 1138 // Check if Event Type is 'resize' then invoke this._doSticky() 1139 // only if the 'fl-theme-builder-header-sticky' class is already present. 1140 // 1141 if ( e && 'resize' === e.type ) { 1142 if ( this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1143 this._doSticky( e ); 1144 } 1145 this._adjustStickyHeaderWidth(); 1146 } 1147 1148 if ( Number( header.attr( 'data-shrink' ) ) ) { 1149 this.header.data( 'original-height', this.header.outerHeight() ); 1150 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initShrink, this ) ) ); 1151 this._initShrink(); 1152 } 1153 1154 this._initFlyoutMenuFix( e ); 1155 } else { 1156 this.win.off( 'scroll.fl-theme-builder-header-sticky' ); 1157 this.win.off( 'resize.fl-theme-builder-header-sticky' ); 1158 1159 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 1160 this.header.removeClass( 'fl-theme-builder-header-pinned' ); 1161 this.header.removeAttr( 'style' ); 1162 this.header.parent().css( 'padding-top', '0' ); 1163 } 1164 }, 1165 1166 /** 1167 * Pins an overlay header with fixed positioning from page load, avoiding a position change that a scroll handler cannot apply before the compositor paints. 1168 * 1169 * @since 1.6.1 1170 * @access private 1171 * @method _initPin 1172 */ 1173 _initPin: function() 1174 { 1175 this.header.toggleClass( 'fl-theme-builder-header-pinned', this.pinnable ); 1176 1177 if ( ! this.pinnable ) { 1178 return; 1179 } 1180 1181 // Fixed positioning resolves the width against the viewport, so boxed layouts require their maximum width immediately. 1182 this._adjustStickyHeaderWidth(); 1183 1184 // The header is visible from the first paint, so the scrolled state must reflect any restored scroll position. 1185 if ( this.win.scrollTop() > Math.floor( this.header.data( 'original-top' ) ) ) { 1186 this.header.addClass( 'fl-theme-builder-header-scrolled' ); 1187 } 1188 }, 1189 1190 /** 1191 * Check if Header should be sticky at a particular Window size. 1192 * 1193 * @since 1.4 1194 * @access private 1195 * @param widowSize 1196 * @method _makeWindowSticky 1197 */ 1198 _makeWindowSticky: function ( windowSize ) 1199 { 1200 var makeSticky = false; 1201 1202 switch (this.stickyOn) { 1203 case 'xl': 1204 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['large']; 1205 break; 1206 case '': // Default 1207 case 'desktop': 1208 makeSticky = windowSize >= FLBuilderLayoutConfig.breakpoints['medium']; 1209 break; 1210 case 'desktop-medium': 1211 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small']; 1212 break; 1213 case 'large': 1214 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['medium'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 1215 break; 1216 case 'large-medium': 1217 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 1218 break; 1219 case 'medium': 1220 makeSticky = ( windowSize <= FLBuilderLayoutConfig.breakpoints['medium'] && windowSize > FLBuilderLayoutConfig.breakpoints['small'] ); 1221 break; 1222 case 'medium-mobile': 1223 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['medium']); 1224 break; 1225 case 'mobile': 1226 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['small']); 1227 break; 1228 case 'all':
1229 makeSticky = true; 1230 break; 1231 } 1232 1233 return makeSticky; 1234 }, 1235 1236 /** 1237 * Sticks the header when the page is scrolled. 1238 * 1239 * @since 1.0 1240 * @access private 1241 * @method _doSticky 1242 */ 1243 _doSticky: function( e ) 1244 { 1245 var winTop = Math.floor( this.win.scrollTop() ), 1246 headerTop = Math.floor( this.header.data( 'original-top' ) ), 1247 hasStickyClass = this.header.hasClass( 'fl-theme-builder-header-sticky' ), 1248 hasScrolledClass = this.header.hasClass( 'fl-theme-builder-header-scrolled' ), 1249 beforeHeader = this.header.prevAll( '.fl-builder-content' ), 1250 bodyTopPadding = parseInt( jQuery('body').css('padding-top') ), 1251 winBarHeight = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0, 1252 headerHeight = 0; 1253 1254 if ( isNaN( bodyTopPadding ) ) { 1255 bodyTopPadding = 0; 1256 } 1257 1258 if ( this.hasAdminBar && this.win.width() > 600 ) { 1259 winTop += Math.floor( winBarHeight ); 1260 } 1261 1262 if ( winTop > headerTop ) { 1263 if ( ! hasStickyClass ) { 1264 if ( e && ( 'scroll' === e.type || 'smartscroll' === e.type ) ) { 1265 this.header.addClass( 'fl-theme-builder-header-sticky' ); 1266 if ( this.overlay && beforeHeader.length ) { 1267 this.header.css( 'top', winBarHeight); 1268 } 1269 } 1270 1271 if ( ! this.overlay ) { 1272 this._adjustHeaderHeight(); 1273 } 1274 } 1275 } 1276 else if ( hasStickyClass ) { 1277 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 1278 this.header.removeAttr( 'style' ); 1279 this.header.parent().css( 'padding-top', '0' ); 1280 } 1281 1282 this._adjustStickyHeaderWidth(); 1283 1284 if ( winTop > headerTop ) { 1285 if ( ! hasScrolledClass ) { 1286 this.header.addClass( 'fl-theme-builder-header-scrolled' ); 1287 } 1288 } else if ( hasScrolledClass ) { 1289 this.header.removeClass( 'fl-theme-builder-header-scrolled' ); 1290 } 1291 1292 this._flyoutMenuFix( e ); 1293 }, 1294 1295 /** 1296 * Initializes flyout menu fixes on sticky header. 1297 * 1298 * @since 1.4.1 1299 * @method _initFlyoutMenuFix 1300 */ 1301 _initFlyoutMenuFix: function( e ) { 1302 var header = this.header, 1303 menuModule = header.closest( '.fl-menu' ), 1304 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 1305 isPushMenu = menuModule.hasClass( 'fl-menu-responsive-flyout-push' ) || menuModule.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 1306 isOverlay = menuModule.hasClass( 'fl-menu-responsive-flyout-overlay' ), 1307 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 1308 flyoutParent = header.parent().is( 'header' ) ? header.parent().parent() : header.parent(); 1309 isFullWidth = this.win.width() === header.width(), 1310 flyoutLayout = '', 1311 activePos = 250, 1312 headerPos = 0; 1313 1314 if ( ! flyoutMenu.length ) { 1315 return; 1316 } 1317 1318 if ( this.win.width() > header.parent().width() ) { 1319 headerPos = ( this.win.width() - header.width() ) / 2; 1320 } 1321 1322 if ( isOverlay ) { 1323 activePos = headerPos; 1324 } 1325 else if ( isPushMenu ) { 1326 activePos = activePos + headerPos; 1327 } 1328 flyoutMenu.data( 'activePos', activePos ); 1329 1330 if ( isPushMenu ) { 1331 flyoutLayout = 'push-' + flyoutPos; 1332 } 1333 else if ( isOverlay ) { 1334 flyoutLayout = 'overlay-' + flyoutPos; 1335 } 1336 1337 if ( isPushMenu && ! $( 'html' ).hasClass( 'fl-theme-builder-has-flyout-menu' ) ) { 1338 $( 'html' ).addClass( 'fl-theme-builder-has-flyout-menu' ); 1339 } 1340 1341 if ( ! flyoutParent.hasClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ) ) { 1342 flyoutParent.addClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ); 1343 } 1344 1345 if ( ! header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && isOverlay ) { 1346 header.addClass( 'fl-theme-builder-flyout-menu-overlay' ); 1347 } 1348 1349 if ( ! header.hasClass( 'fl-theme-builder-header-full-width' ) && isFullWidth ) { 1350 header.addClass( 'fl-theme-builder-header-full-width' ); 1351 } 1352 else if ( ! isFullWidth ) { 1353 header.removeClass( 'fl-theme-builder-header-full-width' ); 1354 } 1355 1356 menuModule.on( 'click', '.fl-menu-mobile-toggle', $.proxy( function( event ){ 1357 if ( menuModule.find( '.fl-menu-mobile-toggle.fl-active' ).length ) {
1358 $( 'html' ).addClass( 'fl-theme-builder-flyout-menu-active' ); 1359 event.stopImmediatePropagation(); 1360 } 1361 else { 1362 $( 'html' ).removeClass( 'fl-theme-builder-flyout-menu-active' ); 1363 } 1364 1365 this._flyoutMenuFix( event ); 1366 }, this ) ); 1367 }, 1368 1369 /** 1370 * Fix flyout menu inside the sticky header. 1371 * 1372 * @since 1.4.1 1373 * @method _flyoutMenuFix 1374 */ 1375 _flyoutMenuFix: function( e ){ 1376 var header = this.header, 1377 menuModule = $( e.target ).closest( '.fl-menu' ), 1378 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 1379 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 1380 menuOpacity = menuModule.find( '.fl-menu-mobile-opacity' ), 1381 isScroll = 'undefined' !== typeof e && 'scroll' === e.handleObj.type, 1382 activePos = 'undefined' !== typeof flyoutMenu.data( 'activePos' ) ? flyoutMenu.data( 'activePos' ) : 0, 1383 headerPos = ( this.win.width() - header.width() ) / 2, 1384 inactivePos = headerPos > 0 ? activePos + 4 : 254; 1385 1386 if ( ! flyoutMenu.length ) { 1387 return; 1388 } 1389 1390 if ( this.overlay ) { 1391 return; 1392 } 1393 1394 if( $( '.fl-theme-builder-flyout-menu-active' ).length ) { 1395 1396 if ( isScroll && ! flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 1397 flyoutMenu.addClass( 'fl-menu-disable-transition' ); 1398 } 1399 1400 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1401 if ( ! isScroll ) { 1402 setTimeout( $.proxy( function(){ 1403 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 1404 }, this ), 1 ); 1405 } 1406 else { 1407 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 1408 } 1409 } 1410 else { 1411 flyoutMenu.css( flyoutPos, '0px' ); 1412 } 1413 } 1414 else { 1415 if ( flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 1416 flyoutMenu.removeClass( 'fl-menu-disable-transition' ); 1417 } 1418 1419 if ( header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && headerPos > 0 && headerPos < 250 ) { 1420 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1421 inactivePos = headerPos + 254; 1422 } 1423 else { 1424 inactivePos = 254; 1425 } 1426 } 1427 1428 if ( e && e.type === 'resize' ) { 1429 inactivePos = headerPos + 254; 1430 } 1431 1432 flyoutMenu.css( flyoutPos, '-' + inactivePos + 'px' ); 1433 } 1434 1435 if ( e && menuModule.is('.fl-menu-responsive-flyout-overlay') && $.infinitescroll ) { 1436 e.stopImmediatePropagation(); 1437 } 1438 1439 if( menuOpacity.length ) { 1440 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 1441 if ( '0px' === menuOpacity.css( 'left' ) ) { 1442 menuOpacity.css( 'left', '-' + headerPos + 'px' ); 1443 } 1444 } 1445 else { 1446 menuOpacity.css( 'left', '' ); 1447 } 1448 } 1449 }, 1450 1451 /** 1452 * Adjust sticky header width if BB Theme Boxed Layout is used. 1453 * 1454 * @since 1.4 1455 * @access private 1456 * @method _adjustStickyHeaderWidth 1457 */ 1458 _adjustStickyHeaderWidth: function () { 1459 if ( $('body').hasClass( 'fl-fixed-width' ) ) { 1460 var parentWidth = this.header.parent().width(); 1461 1462 // Better if this is set in the stylesheet file. 1463 if ( this.win.width() >= 992 ) { 1464 this.header.css({ 1465 'margin': '0 auto', 1466 'max-width': parentWidth, 1467 }); 1468 } 1469 else { 1470 this.header.css({ 1471 'margin': '', 1472 'max-width': '', 1473 }); 1474 } 1475 } 1476 }, 1477 1478 /** 1479 * Adjust Sticky Header Height 1480 * 1481 * @since 1.4 1482 * @access private 1483 * @method _adjustHeaderHeight 1484 */ 1485 _adjustHeaderHeight: function () { 1486 var beforeHeader = this.header.prevAll('.fl-builder-content'), 1487 beforeHeaderHeight = 0, 1488 beforeHeaderFix = 0, 1489 headerHeight = Math.floor( this.header.outerHeight() ), 1490 bodyTopPadding = parseInt( $( 'body' ).css( 'padding-top' ) ), 1491 wpAdminBarHeight = 0, 1492 totalHeaderHeight = 0; 1493 1494 if ( isNaN( bodyTopPadding ) ) { 1495 bodyTopPadding = 0; 1496 } 1497 1498 if ( beforeHeader.length ) { 1499 $.each( beforeHeader, function() { 1500 beforeHeaderHeight += Math.floor( $(this).outerHeight() ); 1501 }); 1502 // Subtract this value from the header parent's top padding. 1503 beforeHeaderFix = 2; 1504 } 1505 1506 if ( this.hasAdminBar && this.win.width() <= 600 ) { 1507 wpAdminBarHeight = Math.floor( $('#wpadminbar').outerHeight() ); 1508 } 1509 1510 totalHeaderHeight = Math.floor( beforeHeaderHeight + headerHeight); 1511 1512 if ( headerHeight > 0 ) { 1513 var headerParent = this.header.parent(), 1514 headerParentTopPadding = 0; 1515 1516 // If the header's parent container is the BODY tag ignore its top padding. 1517 if ( $( headerParent ).is('body') ) { 1518 headerParentTopPadding = Math.floor( headerHeight - wpAdminBarHeight ); 1519 } else { 1520 headerParentTopPadding = Math.floor( headerHeight - bodyTopPadding - wpAdminBarHeight ); 1521 } 1522 1523 $( headerParent ).css( 'padding-top', ( headerParentTopPadding - beforeHeaderFix ) + 'px' ); 1524 1525 this.header.css({ 1526 '-webkit-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 1527 '-ms-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 1528 'transform': 'translate(0px, -' + totalHeaderHeight + 'px)' 1529 }); 1530 1531 } 1532 1533 }, 1534 1535 /** 1536 * Initializes shrink logic for a header. 1537 * 1538 * @since 1.0 1539 * @access private 1540 * @method _initShrink 1541 */ 1542 _initShrink: function( e ) 1543 { 1544 if ( this.win.width() >= this.breakpointWidth ) {
1545 this.win.on( 'scroll.fl-theme-builder-header-shrink', $.proxy( this._doShrink, this ) ); 1546 this._setImageMaxHeight(); 1547 1548 if ( this.win.scrollTop() > 0 ){ 1549 this._doShrink(); 1550 } 1551 1552 } else { 1553 this.header.parent().css( 'padding-top', '0' ); 1554 this.win.off( 'scroll.fl-theme-builder-header-shrink' ); 1555 this._removeShrink(); 1556 this._removeImageMaxHeight(); 1557 } 1558 }, 1559 1560 /** 1561 * Shrinks the header when the page is scrolled. 1562 * 1563 * @since 1.0 1564 * @access private 1565 * @method _doShrink 1566 */ 1567 _doShrink: function( e ) 1568 { 1569 var winTop = this.win.scrollTop(), 1570 headerTop = this.header.data('original-top'), 1571 headerHeight = this.header.data('original-height'), 1572 shrinkImageHeight = this.header.data('shrink-image-height'), 1573 windowSize = this.win.width(), 1574 makeSticky = this._makeWindowSticky( windowSize ), 1575 hasClass = this.header.hasClass( 'fl-theme-builder-header-shrink' ); 1576 1577 1578 if ( this.hasAdminBar ) { 1579 winTop += 32; 1580 } 1581 1582 if ( makeSticky && ( winTop > headerTop + headerHeight ) ) { 1583 if ( ! hasClass ) { 1584 1585 this.header.addClass( 'fl-theme-builder-header-shrink' ); 1586 1587 // Shrink images but don't include lightbox and menu images. 1588 this.header.find('img').each( function( i ) { 1589 var image = $( this ), 1590 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 1591 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 1592 imageInNavMenu = image.closest( 'li.menu-item' ).length; 1593 1594 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 1595 image.css( 'max-height', shrinkImageHeight ); 1596 } 1597 1598 }); 1599 1600 this.header.find( '.fl-row-content-wrap' ).each( function() { 1601 1602 var row = $( this ); 1603 1604 if ( parseInt( row.css( 'padding-bottom' ) ) > 5 ) { 1605 row.addClass( 'fl-theme-builder-header-shrink-row-bottom' ); 1606 } 1607 1608 if ( parseInt( row.css( 'padding-top' ) ) > 5 ) { 1609 row.addClass( 'fl-theme-builder-header-shrink-row-top' ); 1610 } 1611 } ); 1612 1613 this.header.find( '.fl-module' ).each( function() { 1614 1615 var module = $( this ).find( '.fl-module-content' ).length ? $( this ).find( '.fl-module-content' ) : $( this ); 1616 1617 if ( parseInt( module.css( 'margin-bottom' ) ) > 5 ) { 1618 module.addClass( 'fl-theme-builder-header-shrink-module-bottom' ); 1619 } 1620 1621 if ( parseInt( module.css( 'margin-top' ) ) > 5 ) { 1622 module.addClass( 'fl-theme-builder-header-shrink-module-top' ); 1623 } 1624 } ); 1625 } 1626 } else if (hasClass) { 1627 this.header.find( 'img' ).css( 'max-height', '' ); 1628 this._removeShrink(); 1629 } 1630 1631 // Fixes Shrink header issue with BB Theme when window is scrolled then resized and back. 1632 if ( 'undefined' === typeof( e ) && $('body').hasClass( 'fl-fixed-width' ) ) { 1633 if ( ! this.overlay ) { 1634 this._adjustHeaderHeight(); 1635 } 1636 } 1637 1638 }, 1639 1640 /** 1641 * Removes the header shrink effect. 1642 * 1643 * @since 1.0 1644 * @access private 1645 * @method _removeShrink 1646 */ 1647 _removeShrink: function() 1648 { 1649 var rows = this.header.find( '.fl-row-content-wrap' ), 1650 modules = this.header.find('.fl-module, .fl-module-content'); 1651 1652 rows.removeClass( 'fl-theme-builder-header-shrink-row-bottom' ); 1653 rows.removeClass( 'fl-theme-builder-header-shrink-row-top' ); 1654 modules.removeClass( 'fl-theme-builder-header-shrink-module-bottom' ); 1655 modules.removeClass( 'fl-theme-builder-header-shrink-module-top' ); 1656 this.header.removeClass( 'fl-theme-builder-header-shrink' ); 1657 }, 1658 1659 /** 1660 * Adds max height to images in modules for smooth scrolling. 1661 * 1662 * @since 1.1.1 1663 * @access private 1664 * @method _setImageMaxHeight 1665 */ 1666 _setImageMaxHeight: function() 1667 { 1668 var head = $( 'head' ), 1669 stylesId = 'fl-header-styles-' + this.header.data( 'post-id' ), 1670 styles = '', 1671 images = this.header.find( '.fl-module img' ); 1672 1673 if ( $( '#' + stylesId ).length ) { 1674 return; 1675 } 1676 1677 images.each( function( i ) { 1678 var image = $( this ), 1679 height = image.height(), 1680 node = image.closest( '.fl-module' ).data( 'node' ), 1681 className = 'fl-node-' + node + '-img-' + i, 1682 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 1683 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 1684 imageInNavMenu = image.closest( 'li.menu-item' ).length; 1685 1686 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 1687 image.addClass( className ); 1688 styles += '.' + className + ' { max-height: ' + ( height ? height : image[0].height ) + 'px }'; 1689 } 1690 1691 } ); 1692
1693 if ( '' !== styles ) { 1694 head.append( '<style id="' + stylesId + '">' + styles + '</style>' ); 1695 } 1696 }, 1697 1698 /** 1699 * Removes max height on images in modules for smooth scrolling. 1700 * 1701 * @since 1.1.1 1702 * @access private 1703 * @method _removeImageMaxHeight 1704 */ 1705 _removeImageMaxHeight: function() 1706 { 1707 $( '#fl-header-styles-' + this.header.data( 'post-id' ) ).remove(); 1708 }, 1709 }; 1710 1711 $( function() { FLThemeBuilderHeaderLayout.init(); } ); 1712 1713})(jQuery); 1714
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.