PageSourceSearch

https://www.obdlink.com/wp-content/uploads/bb-plugin/cache/15e6522…e2fe434-layout-bundle.js?ver=2.11.1.1-1.6.1

js obdlink.com collected 2026-10-02 03:52:01 UTC 52,439 bytes, 1,714 lines download raw bytes

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.