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