PageSourceSearch

https://www.obdlink.com/wp-content/uploads/bb-plugin/cache/e53903b…ddf8077b1-layout-bundle.js?ver=2.11.0.3-1.6

js obdlink.com collected 2026-09-24 18:13:03 UTC 103,755 bytes, 3,612 lines download raw bytes

1var wpAjaxUrl = 'https://www.obdlink.com/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://www.obdlink.com/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = {
2	anchorLinkAnimations : {
3		duration 	: 1000,
4		easing		: 'swing',
5		offset 		: 100
6	},
7	paths : {
8		pluginUrl : 'https://www.obdlink.com/wp-content/plugins/bb-plugin/',
9		wpAjaxUrl : 'https://www.obdlink.com/wp-admin/admin-ajax.php'
10	},
11	breakpoints : {
12		small  : 768,
13		medium : 992,
14		large : 1200	},
15	waypoint: {
16		offset: 80
17	},
18	emptyColWidth: '0%'
19};
20(function($){
21
22	if(typeof FLBuilderLayout != 'undefined') {
23		return;
24	}
25
26	/**
27	 * Helper class with generic logic for a builder layout.
28	 *
29	 * @class FLBuilderLayout
30	 * @since 1.0
31	 */
32	FLBuilderLayout = {
33
34		/**
35		 * Initializes a builder layout.
36		 *
37		 * @since 1.0
38		 * @method init
39		 */
40		init: function()
41		{
42			// Destroy existing layout events.
43			FLBuilderLayout._destroy();
44
45			// Init CSS classes.
46			FLBuilderLayout._initClasses();
47
48			// Init backgrounds.
49			FLBuilderLayout._initBackgroun
49ds();
50
51			// Init buttons.
52			FLBuilderLayout._initButtons();
53
54			// Init row shape layer height.
55			FLBuilderLayout._initRowShapeLayerHeight();
56
57			// Only init if the builder isn't active.
58			if ( 0 === $('.fl-builder-edit').length ) {
59
60				// Init anchor links.
61				FLBuilderLayout._initAnchorLinks();
62
63				// Init the browser hash.
64				FLBuilderLayout._initHash();
65
66				// Init forms.
67				FLBuilderLayout._initForms();
68
69				FLBuilderLayout._reorderMenu();
70			}
71			else {
72				FLBuilderLayout._initNestedColsWidth();
73			}
74			$('body').removeClass( 'fl-no-js' );
75		},
76
77		/**
78		 * Public method for refreshing Wookmark or MosaicFlow galleries
79		 * within an element.
80		 *
81		 * @since 1.7.4
82		 * @method refreshGalleries
83		 */
84		refreshGalleries: function( element )
85		{
86			var $element  = 'undefined' == typeof element ? $( 'body' ) : $( element ),
87				mfContent = $element.find( '.fl-mosaicflow-content' ),
88				wmContent = $element.find( '.fl-gallery' ),
89				mfObject  = null;
90
91			if ( mfContent ) {
92
93				mfObject = mfContent.data( 'mosaicflow' );
94
95				if ( mfObject ) {
96					mfObject.columns = $( [] );
97					mfObject.columnsHeights = [];
98					mfContent.data( 'mosaicflow', mfObject );
99					mfContent.mosaicflow( 'refill' );
100				}
101			}
102			if ( wmContent ) {
103				wmContent.trigger( 'refreshWookmark' );
104			}
105		},
106
107		/**
108		 * Public method for refreshing Masonry within an element
109		 *
110		 * @since 1.8.1
111		 * @method refreshGridLayout
112		 */
113		refreshGridLayout: function( element )
114		{
115			var $element 		= 'undefined' == typeof element ? $( 'body' ) : $( element ),
116				msnryContent	= $element.find('.masonry');
117
118			if ( msnryContent.length )	{
119				msnryContent.masonry('layout');
120			}
121		},
122
123		/**
124		 * Public method for reloading BxSlider within an element
125		 *
126		 * @since 1.8.1
127		 * @method reloadSlider
128		 */
129		reloadSlider: function( content )
130		{
131			var $content = 'undefined' == typeof content ? $('body') : $(content);
132
133			// reload sliders.
134			if ($content.find('.bx-viewport > div').length > 0) {
135				$.each($content.find('.bx-viewport > div'), function (key, slider) {
136					setTimeout(function () {
137						$(slider).data('bxSlider').reloadSlider();
138					}, 100);
139				});
140			}
141		},
142
143		/**
144		 * Public method for resizing WP audio player
145		 *
146		 * @since 1.8.2
147		 * @method resizeAudio
148		 */
149		resizeAudio: function( element )
150		{
151			var $element 	 	= 'undefined' == typeof element ? $( 'body' ) : $( element ),
152				audioPlayers 	= $element.find('.wp-audio-shortcode.mejs-audio'),
153				player 		 	= null,
154				mejsPlayer 	 	= null,
155				rail 			= null,
156				railWidth 		= 400;
157
158			if ( audioPlayers.length && typeof mejs !== 'undefined' ) {
159            	audioPlayers.each(function(){
160	            	player 		= $(this);
161	            	mejsPlayer 	= mejs.players[player.attr('id')];
162	            	rail 		= player.find('.mejs-controls .mejs-time-rail');
163	            	var innerMejs = player.find('.mejs-inner'),
164	            		total 	  = player.find('.mejs-controls .mejs-time-total');
165
166	            	if ( typeof mejsPlayer !== 'undefined' ) {
167	            		railWidth = Math.ceil(player.width() * 0.8);
168
169	            		if ( innerMejs.length ) {
170
171		            		rail.css('width', railWidth +'px!important');
172		            		//total.width(rail.width() - 10);
173
174		            		mejsPlayer.options.autosizeProgress = true;
175
176		            		// webkit has trouble doing this without a delay
177							setTimeout(function () {
178								mejsPlayer.setControlsSize();
179							}, 50);
180
181			            	player.find('.mejs-inner').css({
182			            		visibility: 'visible',
183			            		height: 'inherit'
184			            	});
185		            	}
186		           	}
187	            });
188	        }
189		},
190
191		/**
192		 * Public method for preloading WP audio player when it's inside the hidden element
193		 *
194		 * @since 1.8.2
195		 * @method preloadAudio
196		 */
197		preloadAudio: function(element)
198		{
199			var $element 	 = 'undefined' == typeof element ? $( 'body' ) : $( element ),
200				contentWrap  = $element.closest('.fl-accordion-item'),
201				audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio');
202
203			if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) {
204				audioPlayers.find('.mejs-inner').css({
205					visibility : 'hidden',
206					height: 0
207				});
208			}
209		},
210
211		/**
212		 * Public method for resizing slideshow momdule within the tab
213		 *
214		 * @since 1.10.5
215		 * @method resizeSlideshow
216		 */
217		resizeSlideshow: function(){
218			if(typeof YUI !== 'undefined') {
219				YUI().use('node-event-simulate', function(Y) {
220					Y.one(window).simulate("resize");
221				});
222			}
223		},
224
225		/**
226		 * Public method for reloading an embedded Google Map within the tabs or hidden element.
227		 *
228		 * @since 2.2
229		 * @method reloadGoogleMap
230		 */
231		reloadGoogleMap: function(element){
232			var $element  = 'undefined' == typeof element ? $( 'body' ) : $( element ),
233			    googleMap = $element.find( 'iframe[src*="google.com/maps"]' );
234
235			if ( googleMap.length ) {
236			    googleMap.attr( 'src', function(i, val) {
237			        return val;
238			    });
239			}
240		},
241
242		/**
243		 * Unbinds builder layout events.
244		 *
245		 * @since 1.0
246		 * @access private
247		 * @method _destroy
248		 */
249		_destroy: function()
250		{
251			var win = $(window);
252
253			win.off('scroll.fl-bg-parallax');
254			win.off('resize.fl-bg-video');
255		},
256
257		/**
258		 * Checks to see if the current device has touch enabled.
259		 *
260		 * @since 1.0
261		 * @access private
262		 * @method _isTouch
263		 * @return {Boolean}
264		 */
265		_isTouch: function()
266		{
267			if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) {
268				return true;
269			}
270
271			return false;
272		},
273
274		/**
275		 * Checks to see if the current device is mobile.
276		 *
277		 * @since 1.7
278		 * @access private
279		 * @method _isMobile
280		 * @return {Boolean}
281		 */
282		_isMobile: function()
283		{
284			return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent );
285		},
286
287		/**
288		 * Initializes builder body classes.
289		 *
290		 * @since 1.0
291		 * @access private
292		 * @method _initClasses
293		 */
294		_initClasses: function()
295		{
296			var body = $( 'body' ),
297				ua   = navigator.userAgent;
298
299			// Add the builder body class (skip on block-only frontend to avoid layout break).
300			if ( ! body.hasClass( 'fl-builder-blocks-only' ) && ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) {
301				body.addClass('fl-builder');
302			}
303
304			// Add the builder touch body class.
305			if(FLBuilderLayout._isTouch()) {
306				body.addClass('fl-builder-touch');
307			}
308
309			// Add the builder mobile body class.
310			if(FLBuilderLayout._isMobile()) {
311				body.addClass('fl-builder-mobile');
312			}
313
314			if ( $(window).width() < FLBuilderLayoutConfig.breakpoints.small ) {
315				body.addClass( 'fl-builder-breakpoint-small' );
316			}
317
318			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.small && $(window).width() < FLBuilderLayoutConfig.breakpoints.medium ) {
319				body.addClass( 'fl-builder-breakpoint-medium' );
320			}
321
322			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.medium && $(window).width() < FLBuilderLayoutConfig.breakpoints.large ) {
323				body.addClass( 'fl-builder-breakpoint-large' );
324			}
325
326			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.large ) {
327				body.addClass( 'fl-builder-breakpoint-default' );
328			}
329
330			// IE11 body class.
331			if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) {
332				body.addClass( 'fl-builder-ie-11' );
333			}
334		},
335
336		/**
337		 * Initializes builder node backgrounds that require
338		 * additional JavaScript logic such as parallax.
339		 *
340		 * @since 1.1.4
341		 * @access private
342		 * @method _initBackgrounds
343		 */
344		_initBackgrounds: function()
345		{
346			var win = $(window);
347
348			// Init parallax backgrounds.
349			if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) {
350				FLBuilderLayout._scrollParallaxBackgrounds();
351				FLBuilderLayout._initParallaxBackgrounds();
352				win.on('resize.fl-bg-parallax', FLBuilderLayout._initParallaxBackgrounds);
353				win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds);
354			}
355
356			// Init video backgrounds.
357			if($('.fl-bg-video').length > 0) {
358				FLBuilderLayout._initBgVideos();
359				FLBuilderLayout._resizeBgVideos();
360
361				// Ensure FLBuilderLayout._resizeBgVideos() is only called once on window resize.
362				var resizeBGTimer = null;
363				win.on('resize.fl-bg-video', function(e){
364					clearTimeout( resizeBGTimer );
365					resizeBGTimer = setTimeout(function() {
366						FLBuilderLayout._resizeBgVideos(e);
367					}, 100 );
368				});
369			}
370		},
371
372		/**
373		 * Initializes all buttons in a layout.
374		 *
375		 * @since 2.10
376		 * @access private
377		 * @method _initButtons
378		 */
379		_initButtons: function()
380		{
381			// Trigger click event on Enter or Space key press for deprecated button markup.
382			$('a.fl-button[role="button"]').on('keydown', function(event) {
383				if (event.key === 'Enter' || event.key === ' ') {
384					// Necessary to prevent the default behavior of the space key from scrolling the page
385					event.preventDefault();
386					$(this).trigger('click');
387				}
388			});
389		},
390
391		/**
392		 * Initializes all parallax backgrounds in a layout.
393		 *
394		 * @since 1.1.4
395		 * @access private
396		 * @method _initParallaxBackgrounds
397		 */
398		_initParallaxBackgrounds: function()
399		{
400			$('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground);
401		},
402
403		/**
404		 * Initializes a single parallax background.
405		 *
406		 * @since 1.1.4
407		 * @access private
408		 * @method _initParallaxBackgrounds
409		 */
410		_initParallaxBackground: function()
411		{
412			var row     = $(this),
413				content = row.find('> .fl-row-content-wrap'),
414				winWidth = $(window).width(),
415				screenSize = '',
416				imageSrc = {
417					default: '',
418					medium: '',
419					responsive: '',
420				};
421
422			imageSrc.default = row.data('parallax-image') || '';
423			imageSrc.medium = row.data('parallax-image-medium') || imageSrc.default;
424			imageSrc.responsive = row.data('parallax-image-responsive') || imageSrc.medium;
425
426			if (winWidth > FLBuilderLayoutConfig.breakpoints.medium) {
427				screenSize = 'default';
428			} else if (winWidth > FLBuilderLayoutConfig.breakpoints.small && winWidth <= FLBuilderLayoutConfig.breakpoints.medium ) {
429				screenSize = 'medium';
430			} else if (winWidth <= FLBuilderLayoutConfig.breakpoints.small) {
431				screenSize = 'responsive';
432			}
433
434			content.css('background-image', 'url(' + imageSrc[screenSize] + ')');
435			row.data('current-image-loaded', screenSize );
436
437		},
438
439		/**
440		 * Fires when the window is scrolled to adjust
441		 * parallax backgrounds.
442		 *
443		 * @since 1.1.4
444		 * @access private
445		 * @method _scrollParallaxBackgrounds
446		 */
447		_scrollParallaxBackgrounds: function()
448		{
449			$('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground);
450		},
451
452		/**
453		 * Fires when the window is scrolled to adjust
454		 * a single parallax background.
455		 *
456		 * @since 1.1.4
457		 * @access private
458		 * @method _scrollParallaxBackground
459		 */
460		_scrollParallaxBackground: function()
461		{
462			var win     	  = $(window),
463				row     	  = $(this),
464				content 	  = row.find('> .fl-row-content-wrap'),
465				speed   	  = row.data('parallax-speed'),
466				offset  	  = content.offset(),
467				yPos		  = -((win.scrollTop() - offset.top) / speed),
468				initialOffset = ( row.data('parallax-offset') != null ) ? row.data('parallax-offset') : 0,
469				totalOffset   = yPos - initialOffset;
470
471			content.css('background-position', 'center ' + totalOffset + 'px');
472		},
473
474		/**
475		 * Initializes all video backgrounds.
476		 *
477		 * @since 1.6.3.3
478		 * @access private
479		 * @method _initBgVideos
480		 */
481		_initBgVideos: function()
482		{
483			$('.fl-bg-video').each(FLBuilderLayout._initBgVideo);
484		},
485
486		/**
487		 * Initializes a video background.
488		 *
489		 * @since 1.6.3.3
490		 * @access private
491		 * @method _initBgVideo
492		 */
493		_initBgVideo: function()
494		{
495			var wrap   = $( this ),
496				width       = wrap.data( 'width' ),
497				height      = wrap.data( 'height' ),
498				mp4         = wrap.data( 'mp4' ),
499				youtube     = wrap.data( 'youtube'),
500				vimeo       = wrap.data( 'vimeo'),
501				mp4Type     = wrap.data( 'mp4-type' ),
502				webm        = wrap.data( 'webm' ),
503				webmType    = wrap.data( 'webm-type' ),
504				fallback    = wrap.data( 'fallback' ),
505				loaded      = wrap.data( 'loaded' ),
506				videoMobile = wrap.data( 'video-mobile' ),
507				playPauseButton = wrap.find('.fl-bg-video-play-pause-control'),
508				fallbackTag = '',
509				videoTag    = null,
510				mp4Tag      = null,
511				webmTag     = null;
512
513			// Return if the video has been loaded for this row.
514			if ( loaded ) {
515				return;
516			}
517
518			videoTag  = $( '<video autoplay loop muted playsinline></video>' );
519
520			/**
521			 * Add poster image (fallback image)
522			 */
523			if( 'undefined' != typeof fallback && '' != fallback ) {
524				videoTag.attr( 'poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' )
525				videoTag.css({
526					backgroundImage: 'url("' + fallback + '")',
527					backgroundColor: 'transparent',
528					backgroundRepeat: 'no-repeat',
529					backgroundSize: 'cover',
530					backgroundPosition: 'center center',
531				})
532			}
533
534			// MP4 Source Tag
535			if ( 'undefined' != typeof mp4 && '' != mp4 ) {
536
537				mp4Tag = $( '<source />' );
538				mp4Tag.attr( 'src', mp4 );
539				mp4Tag.attr( 'type', mp4Type );
540
541				videoTag.append( mp4Tag );
542			}
543			// WebM Source Tag
544			if ( 'undefined' != typeof webm && '' != webm ) {
545
546				webmTag = $( '<source />' );
547				webmTag.attr( 'src', webm );
548				webmTag.attr( 'type', webmType );
549
550				videoTag.append( webmTag );
551			}
552
553			// This is either desktop, or mobile is enabled.
554			if ( ! FLBuilderLayout._isMobile() || ( FLBuilderLayout._isMobile() && "yes" == videoMobile ) ) {
555				if ( 'undefined' != typeof youtube ) {
556					FLBuilderLayout._initYoutubeBgVideo.apply( this );
557				}
558				else if ( 'undefined' != typeof vimeo ) {
559					FLBuilderLayout._initVimeoBgVideo.apply( this );
560				}
561				else {
562					wrap.append( videoTag );
563
564					if ( playPauseButton.length > 0 ) {
565						var video = videoTag[0];
566
567						playPauseButton.on( 'click', { video: video }, function(e) {
568							var video = e.data.video;
569
570							if ( video.paused ) {
571								video.play();
572							} else {
573								video.pause();
574							}
575						} );
576
577						$( video ).on( 'play playing', function () {
578							playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' );
579						} );
580						
581						$( video ).on( 'pause ended waiting', function () {
582							playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
583						} );
584					}
585				}
586			}
587			else {
588				// if we are here, it means we are on mobile and NO is set so remove video src and use fallback
589				videoTag.attr('src', '')
590				wrap.append( videoTag );
591			}
592
593			// Mark this video as loaded.
594			wrap.data('loaded', true);
595		},
596
597		/**
598		 * Initializes Youtube video background
599		 *
600		 * @since 1.9
601		 * @access private
602		 * @method _initYoutubeBgVideo
603		 */
604		_initYoutubeBgVideo: function()
605		{
606			var playerWrap  = $(this),
607				videoId     = playerWrap.data('video-id'),
608				videoPlayer = playerWrap.find('.fl-bg-video-player'),
609				enableAudio = playerWrap.data('enable-audio'),
610				audioButton = playerWrap.find('.fl-bg-video-audio'),
611				playPauseButton = playerWrap.find('.fl-bg-video-play-pause-control'),
612				startTime   = 'undefined' !== typeof playerWrap.data('start') ? playerWrap.data('start') : 0,
613				startTime   = 'undefined' !== typeof playerWrap.data('t') && startTime === 0 ? playerWrap.data('t') : startTime,
614				endTime     = 'undefined' !== typeof playerWrap.data('end') ? playerWrap.data('end') : 0,
615				loop        = 'undefined' !== typeof playerWrap.data('loop') ? playerWrap.data('loop') : 1,
616				stateCount  = 0,
617				player,fallback_showing;
618
619			if ( videoId ) {
620				fallback = playerWrap.data('fallback') || false
621				if( fallback ) {
622					playerWrap.find('iframe').remove()
623					fallbackTag = $( '<div></div>' );
624					fallbackTag.addClass( 'fl-bg-video-fallback' );
625					fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' );
626					fallbackTag.css( 'background-size', 'cover' );
627					fallbackTag.css( 'transition', 'background-image 1s')
628					playerWrap.append( fallbackTag );
629					fallback_showing = true;
630				}
631				FLBuilderLayout._onYoutubeApiReady( function( YT ) {
632					setTimeout( function() {
633
634						player = new YT.Player( videoPlayer[0], {
635							videoId: videoId,
636							events: {
637								onReady: function(event) {
638									if ( "no" === enableAudio || FLBuilderLayout._isMobile() ) {
639										event.target.mute();
640									}
641									else if ( "yes" === enableAudio && event.target.isMuted ) {
642										event.target.unMute();
643									}
644
645									// Store an instance to a parent
646									playerWrap.data('YTPlayer', player);
647									FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap);
648
649									// Queue the video.
650									event.target.playVideo();
651
652									if ( audioButton.length > 0 && ! FLBuilderLayout._isMobile() ) {
653										audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio );
654									}
655
656									if ( playPauseButton.length > 0 ) {
657										playPauseButton.on( 'click', {player: player}, function(e) {
658											var player = e.data.player;
659			
660											if ( 1 === player.getPlayerState() ) {
661												player.pauseVideo();
662											} else {
663												player.playVideo();
664											}
665										});
666									}
667								},
668								onStateChange: function( event ) {
669
670									if ( event.data === 1 ) {
671										if ( fallback_showing ) {
672											$( '.fl-bg-video-fallback' ).css( 'background-image', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)' )
673										}
674									}
675									// Manual check if video is not playable in some browsers.
676									// StateChange order: [-1, 3, -1]
677									if ( stateCount < 4 ) {
678										stateCount++;
679									}
680
681									// Comply with the audio policy in some browsers like Chrome and Safari.
682									if ( stateCount > 1 && -1 === event.data && "yes" === enableAudio ) {
683										player.mute();
684										player.playVideo();
685										audioButton.show();
686									}
687
688									if ( event.data === YT.PlayerState.ENDED && 1 === loop ) {
689										if ( startTime > 0 ) {
690											player.seekTo( startTime );
691										}
692										else {
693											player.playVideo();
694										}
695									}
696
697									if ( event.data === YT.PlayerState.PLAYING ) {
698										playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' );
699									} else if ( event.data === YT.PlayerState.PAUSED ) {
700										playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
701									} else if ( event.data === YT.PlayerState.BUFFERING ) {
702										playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' );
703									} else if ( event.data === YT.PlayerState.CUED ) {
704										playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
705									} else if ( event.data === YT.PlayerState.ENDED ) {
706										playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
707									}
708								},
709								onError: function(event) {
710									console.info('YT Error: ' + event.data)
711									FLBuilderLayout._onErrorYoutubeVimeo(playerWrap)
712								}
713							},
714							playerVars: {
715								playsinline: FLBuilderLayout._isMobile() ? 1 : 0,
716								controls: 0,
717								showinfo: 0,
718								rel : 0,
719								start: startTime,
720								end: endTime,
721							}
722						} );
723					}, 1 );
724				} );
725			}
726		},
727
728		/**
729		 * On youtube or vimeo error show the fallback image if available.
730		 * @since 2.0.7
731		 */
732		_onErrorYoutubeVimeo: function(playerWrap) {
733
734			fallback = playerWrap.data('fallback') || false
735			if( ! fallback ) {
736				return false;
737			}
738			playerWrap.find('iframe').remove()
739			fallbackTag = $( '<div></div>' );
740			fallbackTag.addClass( 'fl-bg-video-fallback' );
741			fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' );
742			playerWrap.append( fallbackTag );
743		},
744
745		/**
746		 * Check if Youtube API has been downloaded
747		 *
748		 * @since 1.9
749		 * @access private
750		 * @method _onYoutubeApiReady
751		 * @param  {Function} callback Method to call when YT API has been loaded
752		 */
753		_onYoutubeApiReady: function( callback ) {
754			if ( window.YT && YT.loaded ) {
755				callback( YT );
756			} else {
757				// If not ready check again by timeout..
758				setTimeout( function() {
759					FLBuilderLayout._onYoutubeApiReady( callback );
760				}, 350 );
761			}
762		},
763
764		/**
765		 * Initializes Vimeo video background
766		 *
767		 * @since 1.9
768		 * @access private
769		 * @method _initVimeoBgVideo
770		 */
771		_initVimeoBgVideo: function()
772		{
773			var playerWrap	= $(this),
774				videoId 	= playerWrap.data('video-id'),
775				videoHash 	= playerWrap.data('video-hash'),
776				videoPlayer = playerWrap.find('.fl-bg-video-player'),
777				enableAudio = playerWrap.data('enable-audio'),
778				audioButton = playerWrap.find('.fl-bg-video-audio'),
779				playPauseButton = playerWrap.find('.fl-bg-video-play-pause-control'),
780				playerState = '',
781				player,
782				width = playerWrap.outerWidth(),
783				ua    = navigator.userAgent;
784
785			if ( typeof Vimeo !== 'undefined' && videoId )	{
786				
787				const vimOptions = {
788					loop       : true,
789					title      : false,
790					portrait   : false,
791					background : true,
792					autopause  : false,
793					muted      : true,
794				};
795
796				if ( videoHash.length ) {
797					vimOptions.url = `https://player.vimeo.com/video/${ videoId }?h=${ videoHash }`;
798				} else {
799					vimOptions.id = videoId;
800				}
801
802				player = new Vimeo.Player(videoPlayer[0], vimOptions );
803				playerWrap.data('VMPlayer', player);
804				if ( "no" === enableAudio ) {
805					player.setVolume(0);
806				}
807				else if ("yes" === enableAudio ) {
808					// Chrome, Safari, Firefox have audio policy restrictions for autoplay videos.
809					if ( ua.indexOf("Safari") > -1 || ua.indexOf("Chrome") > -1 || ua.indexOf("Firefox") > -1 ) {
810						player.setVolume(0);
811						audioButton.show();
812					}
813					else {
814						player.setVolume(1);
815					}
816				}
817
818				player.play().catch(function(error) {
819					FLBuilderLayout._onErrorYoutubeVimeo(playerWrap)
820				});
821
822				if ( audioButton.length > 0 ) {
823					audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio );
824				}
825
826				player.on( 'play', function() {
827					playerState = 'play';
828					playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' );
829				} );
830				player.on( 'pause', function() {
831					playerState = 'pause';
832					playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
833				} );
834				player.on( 'ended', function() {
835					playerState = 'ended';
836					playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' );
837				} );
838				player.on( 'bufferstart', function() {
839					playerState = 'bufferstart';
840					playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' );
841				} );
842
843				if ( playPauseButton.length > 0 ) {
844					playPauseButton.on( 'click', { player: player }, function( e ) {
845						var player = e.data.player;
846
847						if ( playerState === 'play' ) {
848							player.pause();
849						} else {
850							player.play();
851						}
852					} );
853				}
854			}
855		},
856
857		/**
858		 * Mute / unmute audio on row's video background.
859		 * It works for both Youtube and Vimeo.
860		 *
861		 * @since 2.1.3
862		 * @access private
863		 * @method _toggleBgVideoAudio
864		 * @param {Object} e Method arguments
865		 */
866		_toggleBgVideoAudio: function( e ) {
867			var player  = e.data.player,
868			    control = e.data.button.find('.fl-audio-control');
869
870			if ( control.hasClass( 'fa-volume-off' ) ) {
871				// Unmute
872				control
873					.removeClass( 'fa-volume-off' )
874					.addClass( 'fa-volume-up' );
875				e.data.button.find( '.fa-times' ).hide();
876
877				if ( 'function' === typeof player.unMute ) {
878					player.unMute();
879				}
880				else {
881					player.setVolume( 1 );
882				}
883			}
884			else {
885				// Mute
886				control
887					.removeClass( 'fa-volume-up' )
888					.addClass( 'fa-volume-off' );
889				e.data.button.find( '.fa-times' ).show();
890
891				if ( 'function' === typeof player.unMute ) {
892					player.mute();
893				}
894				else {
895					player.setVolume( 0 );
896				}
897			}
898		},
899
900		/**
901		 * Fires when there is an error loading a video
902		 * background source and shows the fallback.
903		 *
904		 * @since 1.6.3.3
905		 * @access private
906		 * @method _videoBgSourceError
907		 * @param {Object} e An event object
908		 * @deprecated 2.0.3
909		 */
910		_videoBgSourceError: function( e )
911		{
912			var source 		= $( e.target ),
913				wrap   		= source.closest( '.fl-bg-video' ),
914				vid		    = wrap.find( 'video' ),
915				fallback  	= wrap.data( 'fallback' ),
916				fallbackTag = '';
917			source.remove();
918
919			if ( vid.find( 'source' ).length ) {
920				// Don't show the fallback if we still have other sources to check.
921				return;
922			} else if ( '' !== fallback ) {
923				fallbackTag = $( '<div></div>' );
924				fallbackTag.addClass( 'fl-bg-video-fallback' );
925				fallbackTag.css( 'background-image', 'url(' + fallback + ')' );
926				wrap.append( fallbackTag );
927				vid.remove();
928			}
929		},
930
931		/**
932		 * Fires when the window is resized to resize
933		 * all video backgrounds.
934		 *
935		 * @since 1.1.4
936		 * @access private
937		 * @method _resizeBgVideos
938		 */
939		_resizeBgVideos: function()
940		{
941			$('.fl-bg-video').each( function() {
942
943				FLBuilderLayout._resizeBgVideo.apply( this );
944
945				if ( $( this ).parent().find( 'img' ).length > 0 ) {
946					$( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) );
947				}
948			} );
949		},
950
951		/**
952		 * Fires when the window is resized to resize
953		 * a single video background.
954		 *
955		 * @since 1.1.4
956		 * @access private
957		 * @method _resizeBgVideo
958		 */
959		_resizeBgVideo: function()
960		{
961			if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) {
962				return;
963			}
964
965			var wrap        = $(this),
966				wrapHeight  = wrap.outerHeight(),
967				wrapWidth   = wrap.outerWidth(),
968				vid         = wrap.find('video'),
969				vidHeight   = wrap.data('height'),
970				vidWidth    = wrap.data('width'),
971				newWidth    = wrapWidth,
972				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
973				newLeft     = 0,
974				newTop      = 0,
975				iframe 		= wrap.find('iframe'),
976				isRowFullHeight = $(this).closest('.fl-row-bg-video').hasClass('fl-row-full-height'),
977				vidCSS          = {
978					top:       '50%',
979					left:      '50%',
980					transform: 'translate(-50%,-50%)',
981				};
982
983			if ( vid.length ) {
984				if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') {
985					vid.css({
986						'left'      : '0px',
987						'top'       : '0px',
988						'width'     : newWidth + 'px'
989					});
990
991					// Try to set the actual video dimension on 'loadedmetadata' when using URL as video source
992					vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta);
993
994					return;
995				}
996
997				if ( ! isRowFullHeight ) {
998					if ( newHeight < wrapHeight ) {
999						newHeight = wrapHeight;
1000						newLeft   = -((newWidth - wrapWidth) / 2);
1001						newWidth  = vidHeight ? Math.round(vidWidth * wrapHeight/vidHeight) : newWidth;
1002					}
1003					else {
1004						newTop = -((newHeight - wrapHeight)/2);
1005					}
1006					vidCSS = {
1007						left   : newLeft + 'px',
1008						top    : newTop + 'px',
1009						height : newHeight + 'px',
1010						width  : newWidth + 'px',
1011					}
1012				}
1013
1014				vid.css( vidCSS );
1015
1016			}
1017			else if ( iframe.length ) {
1018
1019				// Resize Youtube video player within iframe tag
1020				if ( typeof wrap.data('youtube') !== 'undefined' ) {
1021					FLBuilderLayout._resizeYoutubeBgVideo.apply(this);
1022				}
1023			}
1024		},
1025
1026		/**
1027		 * Fires when video meta has been loaded.
1028		 * This will be Triggered when width/height attributes were not specified during video background resizing.
1029		 *
1030		 * @since 1.8.5
1031		 * @access private
1032		 * @method _resizeOnLoadedMeta
1033		 */
1034		_resizeOnLoadedMeta: function(){
1035			var video 		= $(this),
1036				wrapHeight 	= video.parent().outerHeight(),
1037				wrapWidth 	= video.parent().outerWidth(),
1038				vidWidth 	= video[0].videoWidth,
1039				vidHeight 	= video[0].videoHeight,
1040				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
1041				newWidth    = wrapWidth,
1042				newLeft     = 0,
1043				newTop 		= 0;
1044
1045			if(newHeight < wrapHeight) {
1046				newHeight   = wrapHeight;
1047				newWidth    = Math.round(vidWidth * wrapHeight/vidHeight);
1048				newLeft     = -((newWidth - wrapWidth)/2);
1049			}
1050			else {
1051				newTop      = -((newHeight - wrapHeight)/2);
1052			}
1053
1054			video.parent().data('width', vidWidth);
1055			video.parent().data('height', vidHeight);
1056
1057			video.css({
1058				'left'      : newLeft + 'px',
1059				'top'       : newTop + 'px',
1060				'width'     : newWidth + 'px',
1061				'height' 	: newHeight + 'px'
1062			});
1063		},
1064
1065		/**
1066		 * Fires when the window is resized to resize
1067		 * a single Youtube video background.
1068		 *
1069		 * @since 1.9
1070		 * @access private
1071		 * @method _resizeYoutubeBgVideo
1072		 */
1073		_resizeYoutubeBgVideo: function()
1074		{
1075			var wrap				= $(this),
1076				wrapWidth 			= wrap.outerWidth(),
1077				wrapHeight 			= wrap.outerHeight(),
1078				player 				= wrap.data('YTPlayer'),
1079				video 				= player ? player.getIframe() : null,
1080				aspectRatioSetting 	= '16:9', // Medium
1081				aspectRatioArray 	= aspectRatioSetting.split( ':' ),
1082				aspectRatio 		= aspectRatioArray[0] / aspectRatioArray[1],
1083				ratioWidth 			= wrapWidth / aspectRatio,
1084				ratioHeight 		= wrapHeight * aspectRatio,
1085				isWidthFixed 		= wrapWidth / wrapHeight > aspectRatio,
1086				width 				= isWidthFixed ? wrapWidth : ratioHeight,
1087				height 				= isWidthFixed ? ratioWidth : wrapHeight;
1088
1089			if ( video ) {
1090				$(video).width( width ).height( height );
1091			}
1092		},
1093
1094		/**
1095		 * Opens a tab or accordion item if the browser hash is set
1096		 * to the ID of one on the page.
1097		 *
1098		 * @since 1.6.0
1099		 * @access private
1100		 * @method _initHash
1101		 */
1102		_initHash: function()
1103		{
1104			var hash 			= window.location.hash.replace( '#', '' ).split( '/' ).shift(),
1105				element 		= null,
1106				tabs			= null,
1107				responsiveLabel	= null,
1108				tabIndex		= null,
1109				label			= null;
1110
1111			if ( '' !== hash ) {
1112
1113				try {
1114
1115					element = $( '#' + hash );
1116
1117					if ( element.length > 0 ) {
1118
1119						if ( element.hasClass( 'fl-accordion-item' ) ) {
1120							setTimeout( function() {
1121								element.find( '.fl-accordion-button' ).trigger( 'click' );
1122							}, 100 );
1123						}
1124						if ( element.hasClass( 'fl-tabs-panel' ) ) {
1125							setTimeout( function() {
1126								tabs 			= element.closest( '.fl-tabs' );
1127								responsiveLabel = element.find( '.fl-tabs-panel-label' );
1128								tabIndex 		= responsiveLabel.data( 'index' );
1129								label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
1130
1131								label[0].click();
1132								FLBuilderLayout._scrollToElement(element);
1133							}, 100 );
1134						}
1135					}
1136				}
1137				catch( e ) {}
1138			}
1139		},
1140
1141		/**
1142		 * Initializes all anchor links on the page for smooth scrolling.
1143		 *
1144		 * @since 1.4.9
1145		 * @access private
1146		 * @method _initAnchorLinks
1147		 */
1148		_initAnchorLinks: function()
1149		{
1150			$( 'a, [role="link"]' ).each( FLBuilderLayout._initAnchorLink );
1151		},
1152
1153		/**
1154		 * Initializes a single anchor link for smooth scrolling.
1155		 *
1156		 * @since 1.4.9
1157		 * @access private
1158		 * @method _initAnchorLink
1159		 */
1160		_initAnchorLink: function()
1161		{
1162			var link    = $( this ),
1163				href    = link.data( 'url' ) ? link.data( 'url' ) : link.attr( 'href' ),
1164				target  = link.data( 'url' ) ? new URL( href, window.location.href ) : this,
1165				loc     = window.location,
1166				id      = null,
1167				element = null,
1168				flNode  = false;
1169
1170			if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 && link.closest('svg').length < 1 ) {
1171
1172				if ( loc.pathname.replace( /^\//, '' ) == target.pathname.replace( /^\//, '' ) && loc.hostname == target.hostname ) {
1173
1174					try {
1175
1176						id      = href.split( '#' ).pop();
1177						// If there is no ID then we have nowhere to look
1178						// Fixes a quirk in jQuery and FireFox
1179						if( ! id ) {
1180							return;
1181						}
1182						element = $( '#' + id );
1183
1184						if ( element.length > 0 ) {
1185							flNode = element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' );
1186							if ( !element.hasClass( 'fl-no-scroll' ) && ( link.hasClass( 'fl-scroll-link' ) || flNode ) ) {
1187								$( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick );
1188							}
1189							if ( element.hasClass( 'fl-accordion-item' ) ) {
1190								$( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick );
1191							}
1192							if ( element.hasClass( 'fl-tabs-panel' ) ) {
1193								$( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick );
1194							}
1195						}
1196					}
1197					catch( e ) {}
1198				}
1199			}
1200		},
1201
1202		/**
1203		 * Scrolls to an element when an anchor link is clicked.
1204		 *
1205		 * @since 1.4.9
1206		 * @access private
1207		 * @method _scrollToElementOnLinkClick
1208		 * @param {Object} e An event object.
1209		 * @param {Function} callback A function to call when the scroll is complete.
1210		 */
1211		_scrollToElementOnLinkClick: function( e, callback )
1212		{
1213			var attribute = $( this ).data( 'url' ) ? $( this ).data( 'url' ) : $( this ).attr( 'href' );
1214			var element = $( '#' + attribute.split( '#' ).pop() );
1215
1216			FLBuilderLayout._scrollToElement( element, callback );
1217
1218			e.preventDefault();
1219		},
1220
1221		/**
1222		 * Scrolls to an element.
1223		 *
1224		 * @since 1.6.4.5
1225		 * @access private
1226		 * @method _scrollToElement
1227		 * @param {Object} element The element to scroll to.
1228		 * @param {Function} callback A function to call when the scroll is complete.
1229		 */
1230		_scrollToElement: function( element, callback )
1231		{
1232			var config  = FLBuilderLayoutConfig.anchorLinkAnimations,
1233				dest    = 0,
1234				win     = $( window ),
1235				doc     = $( document );
1236
1237			if ( element.length > 0 ) {
1238
1239				if ( 'fixed' === element.css('position') || 'fixed' === element.parent().css('position') ) {
1240					dest = element.position().top;
1241				}
1242				else if ( element.offset().top > doc.height() - win.height() ) {
1243					dest = doc.height() - win.height();
1244				}
1245				else {
1246					dest = element.offset().top - config.offset;
1247				}
1248
1249				$( 'html, body' ).stop( true ).animate( { scrollTop: dest }, config.duration, config.easing, function() {
1250
1251					if ( 'undefined' != typeof callback ) {
1252						callback();
1253					}
1254
1255					if ( undefined != element.attr( 'id' ) && window.location.hash !== '#' + element.attr( 'id' ) ) {
1256
1257						var firefox_version = window.navigator.userAgent.match( /Firefox\/(\d+)\./ ),
1258							firefox_version = firefox_version ? parseInt( firefox_version[1], 10 ) : null;
1259
1260						if ( firefox_version !== null && firefox_version < 135 ) {
1261							window.location.hash = element.attr( 'id' );
1262						} else {
1263							if ( history.pushState ) {
1264								history.pushState( null, null, '#' + element.attr( 'id' ) );
1265							} else {
1266								window.location.hash = element.attr( 'id' );
1267							}
1268						}
1269					}
1270				} );
1271			}
1272		},
1273
1274		/**
1275		 * Scrolls to an accordion item when a link is clicked.
1276		 *
1277		 * @since 1.5.9
1278		 * @access private
1279		 * @method _scrollToAccordionOnLinkClick
1280		 * @param {Object} e An event object.
1281		 */
1282		_scrollToAccordionOnLinkClick: function( e )
1283		{
1284			var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() );
1285
1286			if ( element.length > 0 ) {
1287
1288				var callback = function() {
1289					if ( element ) {
1290						element.find( '.fl-accordion-button' ).trigger( 'click' );
1291						element = false;
1292					}
1293				};
1294
1295				FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1296			}
1297		},
1298
1299		/**
1300		 * Scrolls to a tab panel when a link is clicked.
1301		 *
1302		 * @since 1.5.9
1303		 * @access private
1304		 * @method _scrollToTabOnLinkClick
1305		 * @param {Object} e An event object.
1306		 */
1307		_scrollToTabOnLinkClick: function( e )
1308		{
1309			var element 		= $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ),
1310				tabs			= null,
1311				label   		= null,
1312				responsiveLabel = null;
1313
1314			if ( element.length > 0 ) {
1315
1316				tabs 			= element.closest( '.fl-tabs' );
1317				responsiveLabel = element.find( '.fl-tabs-panel-label' );
1318				tabIndex 		= responsiveLabel.data( 'index' );
1319				label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
1320
1321				if ( responsiveLabel.is( ':visible' ) ) {
1322
1323					var callback = function() {
1324						if ( element ) {
1325							responsiveLabel.trigger( $.Event( 'click', { which: 1 } ) );
1326						}
1327					};
1328
1329					FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1330				}
1331				else {
1332					label[0].click();
1333					FLBuilderLayout._scrollToElement( element );
1334				}
1335
1336				e.preventDefault();
1337			}
1338		},
1339
1340		/**
1341		 * Initializes all builder forms on a page.
1342		 *
1343		 * @since 1.5.4
1344		 * @access private
1345		 * @method _initForms
1346		 */
1347		_initForms: function()
1348		{
1349			if ( ! FLBuilderLayout._hasPlaceholderSupport ) {
1350				$( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback );
1351			}
1352
1353			$( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError );
1354		},
1355
1356		/**
1357		 * Checks to see if the current device has HTML5
1358		 * placeholder support.
1359		 *
1360		 * @since 1.5.4
1361		 * @access private
1362		 * @method _hasPlaceholderSupport
1363		 * @return {Boolean}
1364		 */
1365		_hasPlaceholderSupport: function()
1366		{
1367			var input = document.createElement( 'input' );
1368
1369			return 'undefined' != input.placeholder;
1370		},
1371
1372		/**
1373		 * Initializes the fallback for when placeholders aren't supported.
1374		 *
1375		 * @since 1.5.4
1376		 * @access private
1377		 * @method _initFormFieldPlaceholderFallback
1378		 */
1379		_initFormFieldPlaceholderFallback: function()
1380		{
1381			var field       = $( this ),
1382				val         = field.val(),
1383				placeholder = field.attr( 'placeholder' );
1384
1385			if ( 'undefined' != placeholder && '' === val ) {
1386				field.val( placeholder );
1387				field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback );
1388				field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback );
1389			}
1390		},
1391
1392		/**
1393		 * Hides a fallback placeholder on focus.
1394		 *
1395		 * @since 1.5.4
1396		 * @access private
1397		 * @method _hideFormFieldPlaceholderFallback
1398		 */
1399		_hideFormFieldPlaceholderFallback: function()
1400		{
1401			var field       = $( this ),
1402				val         = field.val(),
1403				placeholder = field.attr( 'placeholder' );
1404
1405			if ( val == placeholder ) {
1406				field.val( '' );
1407			}
1408		},
1409
1410		/**
1411		 * Shows a fallback placeholder on blur.
1412		 *
1413		 * @since 1.5.4
1414		 * @access private
1415		 * @method _showFormFieldPlaceholderFallback
1416		 */
1417		_showFormFieldPlaceholderFallback: function()
1418		{
1419			var field       = $( this ),
1420				val         = field.val(),
1421				placeholder = field.attr( 'placeholder' );
1422
1423			if ( '' === val ) {
1424				field.val( placeholder );
1425			}
1426		},
1427
1428		/**
1429		 * Clears a form field error message.
1430		 *
1431		 * @since 1.5.4
1432		 * @access private
1433		 * @method _clearFormFieldError
1434		 */
1435		_clearFormFieldError: function()
1436		{
1437			var field = $( this );
1438
1439			field.removeAttr( 'aria-invalid' );
1440			field.removeClass( 'fl-form-error' );
1441			const message = field.attr('aria-describedby');
1442			message ? $( '#' + message ).hide() : field.siblings( '.fl-form-error-message' ).hide();
1443		},
1444
1445		/**
1446		 * Init Row Shape Layer's height.
1447		 *
1448		 * @since 2.5.3
1449		 * @access private
1450		 * @method _initRowShapeLayerHeight
1451		 */
1452		_initRowShapeLayerHeight: function () {
1453			FLBuilderLayout._adjustRowShapeLayerHeight();
1454			$( window ).on( 'resize', FLBuilderLayout._adjustRowShapeLayerHeight );
1455		},
1456
1457		/**
1458		 * Set parent column width of nested columns when it's zero or blank.
1459		 *
1460		 * @since 2.7.4
1461		 * @access private
1462		 * @method _initNestedColsWidth
1463		 */
1464		_initNestedColsWidth: function()
1465		{
1466			var nestedCols = $( '.fl-col-has-cols' );
1467
1468			if ( nestedCols.length <= 0 ) {
1469				return;
1470			}
1471
1472			$( nestedCols ).each( function(index, col ){
1473				if ( $( col ).width() <= 0 ) {
1474					$( col ).css( 'width', FLBuilderLayoutConfig.emptyColWidth );
1475				}
1476			});
1477		},
1478
1479		/**
1480		 * Adjust Row Shape Layer's height to fix to remove the fine line that appears on certain screen sizes.
1481		 *
1482		 * @since 2.5.3
1483		 * @access private
1484		 * @method _adjustRowShapeLayerHeight
1485		 */
1486		_adjustRowShapeLayerHeight: function() {
1487			var rowShapeLayers = $('.fl-builder-shape-layer');
1488
1489			$( rowShapeLayers ).each(function (index) {
1490				var rowShapeLayer = $(this),
1491					shape = $(rowShapeLayer).find('svg'),
1492					height = shape.height(),
1493					excludeShapes = '.fl-builder-shape-circle, .fl-builder-shape-dot-cluster, .fl-builder-shape-topography, .fl-builder-shape-rect';
1494
1495				if ( ! rowShapeLayer.is( excludeShapes ) ) {
1496					$(shape).css('height', Math.ceil( height ) );
1497				}
1498			});
1499		},
1500		_string_to_slug: function( str ) {
1501			str = str.replace(/^\s+|\s+$/g, ''); // trim
1502			if ( 'undefined' == typeof window._fl_string_to_slug_regex ) {
1503				regex = new RegExp('[^a-zA-Z0-9\'":() !.,-_|]', 'g');
1504			} else {
1505				regex = new RegExp('[^' + window._fl_string_to_slug_regex + '\'":\(\) !.,-_|\\\p{Letter}]', 'ug');
1506			}
1507			str = str.replace(regex, '') // remove invalid chars
1508				.replace(/\s+/g, ' '); // collapse whitespace and replace by a space
1509			return str;
1510		},
1511		_reorderMenu: function() {
1512			if ( $('#wp-admin-bar-fl-builder-frontend-edit-link-default li').length > 1 ) {
1513					$( '#wp-admin-bar-fl-builder-frontend-duplicate-link' )
1514					.appendTo('#wp-admin-bar-fl-builder-frontend-edit-link-default')
1515					.css( 'padding-top', '5px' )
1516					.css( 'border-top', '2px solid #1D2125' )
1517					.css( 'margin-top', '5px' )
1518				}
1519		}
1520	};
1521
1522	/* Initializes the builder layout. */
1523	$(function(){
1524		FLBuilderLayout.init();
1525	});
1526
1527})(jQuery);
1528(function($){
1529
1530	if(typeof FLBuilderLayoutModules !== 'undefined') {
1531		return;
1532	}
1533
1534	/**
1535	 * Helper class with generic logic for builder modules.
1536	 * If generic module code needs to work in both the block
1537	 * editor and builder, it should go here. Otherwise, it
1538	 * should go on FLBuilderLayout.
1539	 *
1540	 * @since 2.9
1541	 */
1542	FLBuilderLayoutModules = {
1543
1544		/**
1545		 * Initializes builder module logic.
1546		 *
1547		 * @since 2.9
1548		 * @method init
1549		 */
1550		init: function()
1551		{
1552			// Only init if the builder isn't active.
1553			if ( 0 === $('.fl-builder-edit').length ) {
1554
1555				// Init module animations.
1556				FLBuilderLayoutModules._initModuleAnimations();
1557			}
1558		},
1559
1560		/**
1561		 * Initializes module animations.
1562		 *
1563		 * @since 1.1.9
1564		 * @access private
1565		 * @method _initModuleAnimations
1566		 */
1567		_initModuleAnimations: function()
1568		{
1569			if(typeof jQuery.fn.waypoint !== 'undefined') {
1570				$('.fl-animation').each( function() {
1571					var node = $( this ),
1572						nodeTop = node.offset().top,
1573						winHeight = $( window ).height(),
1574						bodyHeight = $( 'body' ).height(),
1575						waypoint = FLBuilderLayoutConfig.waypoint,
1576						offset = '80%';
1577
1578					if ( typeof waypoint.offset !== undefined ) {
1579						offset = FLBuilderLayoutConfig.waypoint.offset + '%';
1580					}
1581
1582					if ( bodyHeight - nodeTop < winHeight * 0.2 ) {
1583						offset = '100%';
1584					}
1585
1586					node.waypoint({
1587						offset: offset,
1588						handler: FLBuilderLayoutModules._doModuleAnimation
1589					});
1590				} );
1591			}
1592		},
1593
1594		/**
1595		 * Runs a module animation.
1596		 *
1597		 * @since 1.1.9
1598		 * @access private
1599		 * @method _doModuleAnimation
1600		 */
1601		_doModuleAnimation: function()
1602		{
1603			var module = 'undefined' == typeof this.element ? $(this) : $(this.element),
1604				delay = parseFloat(module.data('animation-delay')),
1605				duration = parseFloat(module.data('animation-duration'));
1606
1607			if ( ! isNaN( duration ) ) {
1608				module.css( 'animation-duration', duration + 's' );
1609			}
1610
1611			if(!isNaN(delay) && delay > 0) {
1612				setTimeout(function(){
1613					module.addClass('fl-animated');
1614				}, delay * 1000);
1615			} else {
1616				setTimeout(function(){
1617					module.addClass('fl-animated');
1618				}, 1);
1619			}
1620		}
1621	};
1622
1623	/* Initializes builder module logic. */
1624	$(function(){
1625		FLBuilderLayoutModules.init();
1626	});
1627
1628})(jQuery);
1629
1630/* Start Global JS */
1631const addToCart = document.querySelector('#singleCartBTN .add_to_cart_button');
1632
1633if (addToCart) {
1634    addToCart.innerHTML = "buy now";
1635    addToCart.style.color = 'rgba(255, 255, 255, 1)';
1636    addToCart.addEventListener('mouseover', function(e) {
1637      e.target.style.color = '#ffca08';
1638    });
1639    addToCart.addEventListener('mouseout', function(e) {
1640      e.target.style.color = '#ffffff';
1641    });
1642}
1643/* End Global JS */
1644
1645
1646;/* eslint-disable no-undef */
1647(function($) {
1648
1649	/**
1650	 * Class for Menu Module
1651	 *
1652	 * @since 1.6.1
1653	 */
1654	FLBuilderMenu = function( settings ){
1655
1656		// set params
1657		this.nodeId              = settings.id;
1658		this.nodeClass           = '.fl-node-' + settings.id;
1659		this.wrapperClass        = this.nodeClass + ' .fl-menu';
1660		this.type				 				 = settings.type;
1661		this.mobileToggle		     = settings.mobile;
1662		this.mobileBelowRow		   = settings.mobileBelowRow;
1663		this.mobileFlyout		     = settings.mobileFlyout;
1664		this.breakPoints         = settings.breakPoints;
1665		this.mobileBreakpoint	 	 = settings.mobileBreakpoint;
1666		this.currentBrowserWidth = $( window ).width();
1667		this.postId              = settings.postId;
1668		this.mobileStacked       = settings.mobileStacked;
1669		this.submenuIcon         = settings.submenuIcon;
1670		this.flyoutWidth         = settings.flyoutWidth;
1671
1672		// initialize the menu
1673		this._initMenu();
1674
1675		// check if viewport is resizing
1676		$( window ).on( 'resize', $.proxy( function() {
1677
1678			var width = $( window ).width();
1679
1680			// if screen width is resized, reload the menu
1681		    if( width != this.currentBrowserWidth ){
1682
1683				this.currentBrowserWidth = width;
1684				this._initMenu( true );
1685 				this._clickOrHover( true );
1686			}
1687
1688			this._resizeFlyoutMenuPanel();
1689		}, this ) );
1690
1691		$( window ).on( 'scroll', $.proxy( function() {
1692			this._resizeFlyoutMenuPanel();
1693		}, this ) );
1694
1695		// Move focus to the first menu item if the layout is set to BelowRow
1696		$( this.wrapperClass ).on( 'keydown', '.fl-menu-mobile-toggle, .menu-item:first a:first', $.proxy( function ( event ) {
1697			// Make sure it is a tab key with both the menu toggle enabled & below row layout set
1698			if ( event.key !== 'Tab' || ! this._isMenuToggle() || ! this._isMobileBelowRowEnabled() ) {
1699				return;
1700			}
1701			// Trigger focus on the mobile toggle button if the user is shift tabbing from the first menu item
1702			if ( event.shiftKey && $( event.currentTarget ).is( 'a' ) ) {
1703				event.preventDefault();
1704				$( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'focus' );
1705			}
1706			// Trigger focus on the first menu item if the user is tabbing from the mobile toggle button
1707			else if ( ! event.shiftKey && $( event.currentTarget ).hasClass( 'fl-menu-mobile-toggle' ) && $( event.currentTarget ).hasClass( 'fl-active' )  ) {
1708				event.preventDefault();
1709				$( this.wrapperClass ).find( '.menu-item' ).first().find( 'a' ).first().trigger( 'focus' );
1710			}
1711		}, this ) );
1712
1713		// Close mobile menu or accordion when tabbing out from the first or last menu item
1714		$( this.wrapperClass ).on( 'focusout', $.proxy( function ( event ) {
1715			if ( $( this.wrapperClass + ' nav' ).has( $( event.relatedTarget ) ).length === 0 ) {
1716				if ( this.type === 'accordion' ) {
1717					this._toggleSubmenu( $( event.target ).parents( '.fl-has-submenu' ).last(), false );
1718				}
1719				else {
1720					this._clickOrHover( true );
1721				}
1722				const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' );
1723				if ( this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) && ! $( event.relatedTarget ).is( mobileToggle ) && 'expanded' !== this.mobileToggle ) {
1724					mobileToggle.trigger( 'click' );
1725				}
1726			}
1727		}, this ) );
1728
1729	};
1730
1731	FLBuilderMenu.prototype = {
1732		nodeClass		: '',
1733		wrapperClass: '',
1734		type				: '',
1735		breakPoints	: {},
1736		$submenus		: null,
1737
1738		/**
1739		 * Check if the screen size fits a mobile viewport.
1740		 *
1741		 * @since  1.6.1
1742		 * @return bool
1743		 */
1744		_isMobile: function(){
1745			return this.currentBrowserWidth <= this.breakPoints.small ? true : false;
1746		},
1747
1748		/**
1749		 * Check if the device is connected to a mouse.
1750		 * 
1751		 * @since  2.9.0
1752		 * @return bool
1753		 */
1754		_isMouseAvailable: function(){
1755			return window.matchMedia("(pointer: fine) and (hover: hover)").matches;
1756		},
1757
1758		/**
1759		 * Check if the screen size fits a medium viewport.
1760		 *
1761		 * @since  1.10.5
1762		 * @return bool
1763		 */
1764		_isMedium: function(){
1765			return this.currentBrowserWidth <= this.breakPoints.medium ? true : false;
1766		},
1767
1768		/**
1769		 * Check if the screen size fits a large viewport.
1770		 *
1771		 * @since  1.10.5
1772		 * @return bool
1773		 */
1774		_isLarge: function(){
1775			return this.currentBrowserWidth <= this.breakPoints.large ? true : false;
1776		},
1777
1778		/**
1779		 * Check if the menu should toggle for the current viewport base on the selected breakpoint.
1780		 *
1781		 * @see 	 this._isMobile()
1782		 * @see 	 this._isMedium()
1783		 * @since  1.10.5
1784		 * @return bool
1785		 */
1786		_isMenuToggle: function(){
1787			if ( ( 'always' == this.mobileBreakpoint
1788				|| ( this._isMobile() && 'mobile' == this.mobileBreakpoint )
1789				|| ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint )
1790				|| ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint )
1791			) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) {
1792				return true;
1793			}
1794
1795			return false;
1796		},
1797
1798		/**
1799		 * Initialize the toggle logic for the menu.
1800		 *
1801		 * @see    this._isMenuToggle()
1802		 * @see    this._menuOnCLick()
1803		 * @see    this._clickOrHover()
1804		 * @see    this._submenuOnRight()
1805		 * @see    this._submenuRowZindexFix()
1806		 * @see    this._toggleForMobile()
1807		 * @since  1.6.1
1808		 * @return void
1809		 */
1810		_initMenu: function( resized = false ){
1811			this._setupSubmenu();
1812			if ( ! resized ) {
1813				this._menuOnFocus();
1814				this._menuOnClick();
1815				this._menuOnEscape();
1816			}
1817			if ( $( this.nodeClass ).length && this.type == 'horizontal' ) {
1818				this._initMegaMenus();
1819			}
1820
1821			if( this._isMenuToggle() || this.type == 'accordion' ){
1822
1823				$( this.wrapperClass ).off( 'mouseenter mouseleave' );
1824				this._clickOrHover();
1825
1826			} else {
1827				this._submenuOnRight();
1828				this._submenuRowZindexFix();
1829			}
1830
1831			if( this.mobileToggle != 'expanded' ){
1832				this._toggleForMobile();
1833			}
1834
1835			if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){
1836				this._toggleMenuSearch();
1837			}
1838
1839			if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){
1840				this._wooUpdateParams();
1841			}
1842		},
1843
1844		/**
1845		 * Whether the toggle behavior for submenus is through hovering or not.
1846		 *
1847		 * @since  2.5
1848		 * @return void
1849		 */
1850		_setupSubmenu: function() {
1851			if ( ! this._isMouseAvailable() || this._isMenuToggle() || this.type === 'accordion' ) {
1852				$( this.wrapperClass ).addClass( 'no-hover' );
1853			}
1854			else {
1855				$( this.wrapperClass ).removeClass( 'no-hover' );
1856			}
1857		},
1858
1859		/**
1860		 * Logic for menu items when focused.
1861		 *
1862		 * @since  1.9.0
1863		 * @return void
1864		 */
1865		_menuOnFocus: function(){
1866			$( this.wrapperClass ).on( 'focus', 'a:not(.fl-button), .fl-menu-toggle', $.proxy( function( event ) {
1867				const focusedMenuItem = $( event.currentTarget ).closest( '.menu-item' );
1868				const blurredMenuItem = $( event.relatedTarget ).closest( '.menu-item' );
1869				// In case the blurred & focused items are siblings
1870				if ( focusedMenuItem.closest( 'ul' ).is( blurredMenuItem.closest( 'ul' ) ) )	{
1871					// Check if the focus event is not between the link & submenu icon of the same menu item
1872					if ( ! focusedMenuItem.is( blurredMenuItem ) ) {
1873						this._toggleSubmenu( blurredMenuItem, false );
1874					}
1875				}
1876				// In case neither items are child & parent nor vice versa
1877				else if ( focusedMenuItem.has( blurredMenuItem ).length === blurredMenuItem.has( focusedMenuItem ).length ) {
1878					// Get the blurred item parent & is the sibling of the focused item
1879					blurredMenuItem.parents( '.fl-has-submenu' ).each( ( _, parent ) => {
1880						if ( focusedMenuItem.closest( 'ul' ).is( $( parent ).closest( 'ul' ) ) ) {
1881							this._toggleSubmenu( $( parent ), false );
1882							return false;
1883						}
1884					} );
1885				}
1886				// In case the blurred item is a child of the focused item
1887				else if ( focusedMenuItem.has( blurredMenuItem ).length ) {
1888					if ( this.type !== 'accordion' && this.submenuIcon === 'none' ) {
1889						this._toggleSubmenu( blurredMenuItem, false );
1890					}
1891				}
1892			}, this ) );
1893		},
1894
1895		/**
1896		 * Logic for menu items when Escape key is pressed.
1897		 *
1898		 * @since  2.7.1
1899		 * @return void
1900		 */
1901		_menuOnEscape: function(){
1902			$( this.wrapperClass ).on( 'keydown', $.proxy( function( event ){
1903				if ( event.key !== 'Escape' ) return;
1904				const menuItem = $( event.target ).closest( '.menu-item' );
1905				const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' );
1906				// In case there is a focused menu item
1907				if ( menuItem.length || $( event.target ).hasClass( 'fl-menu-mobile-close' ) ) {
1908					// Close the search form if it is open
1909					if ( menuItem.hasClass( 'fl-menu-search-item' ) && $( this.wrapperClass ).find('.fl-search-form-input-wrap').is( ':visible' ) ) {
1910						$( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))').trigger( 'focus' );
1911					}
1912					// Close all the submenus of the focused menu item
1913					else if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.find( '.sub-menu' ).first().is( ':visible' ) ) {
1914						this._toggleSubmenu( menuItem, false );
1915					}
1916					else {
1917						// Shift focus to the parent while closing all its submenus
1918						const parentMenuItem = menuItem.parents( '.fl-has-submenu' ).not( '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading' ).first();
1919						// Close the mobile menu if there is no parent menu item and the mobile toggle is active
1920						if ( parentMenuItem.length === 0 && this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) ) {
1921							// Blur to trigger the focus-out event for closing the menu
1922							mobileToggle.trigger( 'blur' ).trigger( 'focus' );
1923						}
1924						// Close the parent submenu and shift focus to its link
1925						else if ( parentMenuItem.length !== 0 ) {
1926							this._toggleSubmenu( parentMenuItem, false );
1927							parentMenuItem.find( 'a' ).first().trigger( 'focus' );
1928						}
1929					}
1930				}
1931				// Close the mobile menu if the mobile toggle is active
1932				else if ( $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && mobileToggle.hasClass( 'fl-active' ) ) {
1933					// Blur to trigger the focus-out event for closing the menu
1934					mobileToggle.trigger( 'blur' ).trigger( 'focus' );
1935				}
1936			}, this ) );
1937		},
1938
1939		/**
1940		 * Logic for menu items when clicked.
1941		 *
1942		 * @since  1.6.1
1943		 * @return void
1944		 */
1945		_menuOnClick: function(){
1946			// Fallback for span elements and fake links to interact with the keyboard
1947			$( this.wrapperClass ).on( 'keydown', 'a:not(.fl-button, [href]), span.fl-menu-toggle', $.proxy( function( event ) {
1948				if ( event.key === 'Enter' || event.key === ' ' ) {
1949					event.preventDefault();
1950					$( event.currentTarget ).trigger( 'click' );
1951				}
1952			}, this ) );
1953			$( this.wrapperClass ).on( 'click', 'a, .fl-menu-toggle', $.proxy( function( event ) {
1954				// Only allow mouse clicks with accordion & mobile menus
1955				if ( this._isMouseAvailable() && ! this._isMenuToggle() && event.detail && this.type !== 'accordion' ) return;
1956				// Links only open & do not toggle submenus if there is either a submenu icon or an accordion layout
1957				if ( $( event.currentTarget ).is( 'a' ) && ( this.submenuIcon !== 'none' || this.type === 'accordion' ) ) return;
1958				const menuItem = $( event.currentTarget ).closest( '.menu-item, .fl-menu-logo' );
1959				const menuLink = menuItem.find( 'a' ).first().attr( 'href' );
1960				const submenuHidden = menuItem.find( '.sub-menu' ).first().is( ':hidden' );
1961				if ( typeof menuLink === 'undefined' || menuLink === '#' || submenuHidden ) {
1962					event.preventDefault();
1963				}
1964				if ( $( event.currentTarget ).hasClass( 'fl-menu-toggle' ) || submenuHidden ) {
1965					this._toggleSubmenu( menuItem, submenuHidden );
1966				}
1967			}, this ) );
1968		},
1969
1970		/**
1971		 * Controls toggling the visibility of all submenu items for desktop & mobile.
1972		 *
1973		 * @since  2.10
1974		 * @return void
1975		 */
1976		_toggleSubmenu: function ( menuItem, opened ) {
1977			const togglingClass = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus';
1978			const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle';
1979			const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading';
1980			if ( opened && menuItem.hasClass( 'fl-has-submenu' ) && ! menuItem.is( hiddenMenu ) ) {
1981				menuItem.addClass( togglingClass );
1982				menuItem.find( toggleElement ).first().attr( 'aria-expanded', true );
1983				if ( this._isMenuToggle() || this.type === 'accordion' ) {
1984					menuItem.find( '.sub-menu' ).first().filter( ':hidden' ).slideDown();
1985				}
1986			}
1987			else {
1988				menuItem.parent().find( '.menu-item' ).removeClass( togglingClass );
1989				menuItem.parent().find( '.fl-has-submenu' ).not( hiddenMenu ).find( toggleElement ).attr( 'aria-expanded', false );
1990				if ( this._isMenuToggle() || this.type === 'accordion' ) {
1991					menuItem.find( '.sub-menu' ).filter( ':visible' ).slideUp();
1992				}
1993			}
1994		},
1995
1996		/**
1997		 * Changes general styling and behavior of menus based on mobile / desktop viewport.
1998		 *
1999		 * @see    this._isMenuToggle()
2000		 * @since  1.6.1
2001		 * @return void
2002		 */
2003		_clickOrHover: function( clear = false ){
2004			const selector = this._isMobileBelowRowEnabled() ? this.nodeClass + '-clone' : this.nodeClass;
2005			this.$submenus = this.$submenus || $( selector ).find( '.sub-menu' );
2006
2007			const className = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus';
2008			const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle';
2009			const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading';
2010			$( selector ).find( '.fl-has-submenu' ).not( hiddenMenu ).each( function() {
2011				if( clear || ! $ ( this ).hasClass( className ) ){
2012					if ( clear ) $( this ).removeClass( className );
2013					$( this ).find( toggleElement ).first().attr( 'aria-expanded', false );
2014					if ( className === 'fl-active' ) {
2015						$( this ).find( '.sub-menu' ).fadeOut();
2016					} else if ( className === 'focus' ) {
2017						$( this ).find( '.sub-menu' ).css( {
2018							'display' : '',
2019							'opacity' : ''
2020						} );
2021					}
2022				}
2023			} );
2024		},
2025
2026		/**
2027		 * Logic to prevent submenus to go outside viewport boundaries.
2028		 *
2029		 * @since  1.6.1
2030		 * @return void
2031		 */
2032		_submenuOnRight: function(){
2033
2034			$( this.wrapperClass )
2035				.on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){
2036
2037					if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) {
2038						return;
2039					}
2040
2041					var $link           = $( e.currentTarget ),
2042						$parent         = $link.parent(),
2043						$subMenu        = $link.find( '.sub-menu' ),
2044						subMenuWidth    = $subMenu.width(),
2045						subMenuPos      = 0,
2046						bodyWidth       = $( 'body' ).width();
2047
2048					if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) {
2049
2050						$link.addClass( 'fl-menu-submenu-right' );
2051
2052					} else if( $( 'body' ).hasClass( 'rtl' ) ) {
2053
2054						subMenuPos = $parent.is( '.sub-menu' ) ?
2055									 $parent.offset().left - subMenuWidth:
2056									 $link.offset().left - $link.width() - subMenuWidth;
2057
2058						if( subMenuPos <= 0 ) {
2059							$link.addClass( 'fl-menu-submenu-right' );
2060						}
2061
2062					} else {
2063
2064						subMenuPos = $parent.is( '.sub-menu' ) ?
2065									 $parent.offset().left + $parent.width() + subMenuWidth :
2066									 $link.offset().left + $link.width() + subMenuWidth;
2067
2068						if( subMenuPos > bodyWidth ) {
2069							$link.addClass('fl-menu-submenu-right');
2070						}
2071					}
2072				}, this ) )
2073				.on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){
2074					$( e.currentTarget ).removeClass( 'fl-menu-submenu-right' );
2075				}, this ) );
2076
2077		},
2078
2079		/**
2080		 * Logic to prevent submenus to go behind the next overlay row.
2081		 *
2082		 * @since  1.10.9
2083		 * @return void
2084		 */
2085		_submenuRowZindexFix: function(){
2086
2087			$( this.wrapperClass )
2088				.on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){
2089
2090					if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) {
2091						return;
2092					}
2093
2094					$( this.nodeClass )
2095						.closest( '.fl-row' )
2096						.find( '.fl-row-content' )
2097						.css( 'z-index', '10' );
2098
2099				}, this ) )
2100				.on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function(){
2101
2102					$( this.nodeClass )
2103						.closest( '.fl-row' )
2104						.find( '.fl-row-content' )
2105						.css( 'z-index', '' );
2106
2107				}, this ) );
2108		},
2109
2110		/**
2111		 * Logic for the mobile menu button.
2112		 *
2113		 * @since  1.6.1
2114		 * @return void
2115		 */
2116		_toggleForMobile: function(){
2117
2118			var $wrapper = null,
2119				$menu    = null,
2120				self     = this;
2121
2122			$( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).attr('aria-controls', $( this.wrapperClass ).find( 'ul.menu' ).attr('id'));
2123
2124			if( this._isMenuToggle() ){
2125
2126				if ( this._isMobileBelowRowEnabled() ) {
2127					this._placeMobileMenuBelowRow();
2128					$wrapper = $( this.wrapperClass );
2129					$menu    = $( this.nodeClass + '-clone' );
2130					$menu.find( 'ul.menu' ).show();
2131				}
2132				else {
2133					$wrapper = $( this.wrapperClass );
2134					$menu    = $wrapper.find( '.menu' );
2135				}
2136
2137				if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){
2138					$menu.css({ display: 'none' });
2139				}
2140
2141				// Flayout Menu
2142				if ( self.mobileFlyout ) {
2143					this._initFlyoutMenu();
2144				}
2145
2146				$wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){
2147					e.stopImmediatePropagation();
2148
2149					$( this ).toggleClass( 'fl-active' );
2150
2151					if ( self.mobileFlyout ) {
2152						self._toggleFlyoutMenu();
2153						const flyoutWrapper = $( '.fl-menu-mobile-flyout' );
2154						if ( $( this ).hasClass( 'fl-active' ) ) {
2155							flyoutWrapper.attr( 'aria-hidden', false );
2156							flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex="-1"]' ).attr( 'tabindex', 0 );
2157						}
2158						else {
2159							flyoutWrapper.attr( 'aria-hidden', true );
2160							flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not
2160([tabindex="-1"])' ).attr( 'tabindex', -1 );
2161						}
2162					}
2163					else {
2164						var targetMenu = null;
2165
2166						if ( self.mobileBelowRow ) {
2167							var $closestCol = $( this ).parents( '.fl-col, .fl-module-box' ),
2168								$closestColGroup = $closestCol.length ? $closestCol.parent( '.fl-col-group' ) : null;
2169								targetMenu  = $closestCol.length ? $closestCol.last().next( '.fl-menu-mobile-clone' ) : null;
2170
2171							if ( $closestColGroup.length ) {
2172								if ( $closestColGroup.hasClass( 'fl-col-group-responsive-reversed' ) ) {
2173									$closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', -1 );
2174								} else if ( $closestColGroup ) {
2175									$closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', 2 );
2176								}
2177							}
2178						} else {
2179							targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' );
2180						}
2181						
2182						if ( targetMenu.length ) {
2183							$menu = $( targetMenu );
2184						}
2185
2186						$menu.slideToggle();
2187					}
2188
2189					e.stopPropagation();
2190				} );
2191
2192				// Hide active menu when click on anchor link ID that exists on a page
2193				$menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(){
2194					var $href = $(this).attr('href'),
2195						$targetID = $href.split('#')[1],
2196						element = $('#' + $targetID);
2197					if ( $('body').find(element).length > 0 ) {
2198						$( this ).toggleClass( 'fl-active' );
2199						FLBuilderLayout._scrollToElement( element );
2200						if ( ! self._isMenuToggle() ) {
2201							$menu.slideToggle();
2202						}
2203					}
2204				});
2205			}
2206			else {
2207
2208				if ( this._isMobileBelowRowEnabled() ) {
2209					this._removeMenuFromBelowRow();
2210				}
2211
2212				$wrapper = $( this.wrapperClass ),
2213				$menu    = $wrapper.find( 'ul.menu' );
2214				$wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' );
2215				$menu.css({ display: '' });
2216
2217				if ( ! this._isMobileBelowRowEnabled() ) {
2218					$menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' );
2219				}
2220
2221				if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) {
2222					$( 'body' ).css( 'margin', '' );
2223					$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' );
2224					$menu.unwrap();
2225					$wrapper.find( '.fl-menu-mobile-close' ).remove();
2226					$wrapper.find( '.fl-menu-mobile-opacity' ).remove();
2227				}
2228			}
2229		},
2230
2231		/**
2232		 * Init any mega menus that exist.
2233		 *
2234		 * @see 	 this._isMenuToggle()
2235		 * @since  1.10.4
2236		 * @return void
2237		 */
2238		_initMegaMenus: function(){
2239
2240			var module     = $( this.nodeClass ),
2241				rowContent = module.closest( '.fl-row-content' ),
2242				rowWidth   = rowContent.width(),
2243				megas      = module.find( '.mega-menu' ),
2244				disabled   = module.find( '.mega-menu-disabled' ),
2245				isToggle   = this._isMenuToggle();
2246
2247			if ( isToggle ) {
2248				megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' );
2249				module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' );
2250				rowContent.css( 'position', '' );
2251			} else {
2252				disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' );
2253				module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' );
2254				rowContent.css( 'position', 'relative' );
2255			}
2256		},
2257
2258		/**
2259		 * Check to see if Below Row should be enabled.
2260		 *
2261		 * @since  1.11
2262		 * @return boolean
2263		 */
2264		_isMobileBelowRowEnabled: function() {
2265			return this.mobileBelowRow && ( $( this.nodeClass ).parents( '.fl-col, .fl-module-box' ).length );
2266		},
2267
2268		/**
2269		 * Logic for putting the mobile menu below the menu's
2270		 * column so it spans the full width of the page.
2271		 *
2272		 * @since  1.10
2273		 * @return void
2274		 */
2275		_placeMobileMenuBelowRow: function(){
2276
2277			if ( $( this.nodeClass + '-clone' ).length ) {
2278				return;
2279			}
2280
2281			var module = $( this.nodeClass ),
2282				clone  = null,
2283				col    = module.parents( '.fl-col, .fl-module-box' ).last();
2284
2285			if ( module.length < 1 ) {
2286				return;
2287			}
2288
2289			clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone();
2290			module.find( 'ul.menu' ).remove();
2291			clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) );
2292			clone.addClass( 'fl-menu-mobile-clone' );
2293			clone.find( '.fl-menu-mobile-toggle' ).remove();
2294			col.after( clone );
2295
2296			// Removes animation when enabled
2297			if ( module.hasClass( 'fl-animation' ) ) {
2298				clone.removeClass( 'fl-animation' );
2299			}
2300
2301			this._menuOnFocus();
2302			this._menuOnClick();
2303			this._menuOnEscape();
2304		},
2305
2306		/**
2307		 * Logic for removing the mobile menu from below the menu's
2308		 * column and putting it back in the main wrapper.
2309		 *
2310		 * @since  1.10
2311		 * @return void
2312		 */
2313		_removeMenuFromBelowRow: function(){
2314
2315			if ( ! $( this.nodeClass + '-clone' ).length ) {
2316				return;
2317			}
2318
2319			var module = $( this.nodeClass ),
2320				clone  = $( this.nodeClass + '-clone' ),
2321				menu   = clone.find( 'ul.menu' ),
2322				nav    = module.find( 'nav' );
2323
2324			if ( nav.length ) {
2325				nav.append( menu );
2326			} else {
2327				module.find( '.fl-menu-mobile-toggle' ).after( menu );
2328			}
2329			clone.remove();
2330			menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink );
2331		},
2332
2333		/**
2334		 * Logic for Flyout responsive menu.
2335		 *
2336		 * @since  2.2
2337		 * @return void
2338		 */
2339		_initFlyoutMenu: function(){
2340			var wrapper = $( this.wrapperClass ),
2341				menu  	= wrapper.find( 'ul.menu' ),
2342				button	= wrapper.find( '.fl-menu-mobile-toggle' );
2343
2344			if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) {
2345				menu.wrap( '<div class="fl-menu-mobile-flyout" aria-hidden="true"></div>' );
2346			}
2347
2348			if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) {
2349				var close = window.fl_responsive_close || 'Close'
2350				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>' );
2351			}
2352
2353			// Push with opacity
2354			if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) {
2355				wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' );
2356			}
2357
2358			wrapper.off( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close' ).on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){
2359				button.trigger('focus').trigger( 'click' );
2360				e.stopPropagation();
2361			});
2362
2363			if ( 'undefined' !== typeof FLBuilder ) {
2364				FLBuilder.addHook('restartEditingSession', function(){
2365					$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' );
2366
2367					// Toggle active menu
2368					if ( button.hasClass( 'fl-active' ) ) {
2369						button.trigger( 'click' );
2370					}
2371				});
2372			}
2373			$( '.fl-menu-mobile-flyout' ).find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not([tabindex="-1"])' ).attr( 'tabindex', -1 );
2374		},
2375
2376		/**
2377		 * Logic to enable/disable the Flyout menu on button click.
2378		 *
2379		 * @since  2.2
2380		 * @return void
2381		 */
2382		_toggleFlyoutMenu: function(){
2383			var wrapper		= $( this.wrapperClass ),
2384				button		= wrapper.find( '.fl-menu-mobile-toggle' ),
2385				position 	= wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
2386				pushMenu 	= wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ),
2387				opacity		= wrapper.find( '.fl-menu-mobile-opacity' ),
2388				marginPos	= {},
2389				fixedPos 	= {},
2390				fixedHeader	= $('header, header > div');
2391
2392			this._resizeFlyoutMenuPanel();
2393
2394			// Fix the push menu when builder ui panel is pinned
2395			if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) {
2396				$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' );
2397			}
2398
2399			if ( pushMenu ) {
2400				marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px';
2401				$( 'body' ).animate( marginPos, 200);
2402
2403				// Fixed header
2404				if ( fixedHeader.length > 0 ) {
2405					fixedPos[ position] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px';
2406					fixedHeader.each(function(){
2407						if ( 'fixed' == $( this ).css( 'position' ) ) {
2408							$( this ).css({ 'transition' : 'none' });
2409							$( this ).animate( fixedPos, 200 );
2410						}
2411					});
2412				}
2413			}
2414
2415			if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) {
2416				opacity.show();
2417			}
2418			else {
2419				opacity.hide();
2420			}
2421		},
2422
2423		/**
2424		 * Resize or reposition the Flyout Menu Panel.
2425		 * 
2426		 * @since  2.8.1
2427		 * @return void
2428		 */
2429		_resizeFlyoutMenuPanel: function(){
2430			const wrapper    = $( this.wrapperClass );
2431			const wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' );
2432				
2433			if ( wrapFlyout.length > 0 ) {
2434				wrapFlyout.css( this._getFlyoutMenuPanelPosition() );
2435			}
2436		},
2437
2438		/**
2439		 * Compute the Flyout Menu Panel's position on the screen.
2440		 * 
2441		 * @since  2.8.1
2442		 * @return object
2443		 */
2444		_getFlyoutMenuPanelPosition: function() {
2445			var wrapper        = $( this.wrapperClass ),
2446				button         = wrapper.find( '.fl-menu-mobile-toggle' ),
2447				side           = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
2448				winHeight      = $(window).outerHeight(),
2449				winTop         = $(window).scrollTop(),
2450				adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).height() : 0,
2451				flyoutPosition = {};
2452
2453			flyoutPosition[ side ]  = '-' + ( parseInt( this.flyoutWidth ) + 15 ) + 'px';
2454			if ( ! button.hasClass( 'fl-active' ) ) {
2455				return flyoutPosition;
2456			}
2457
2458			flyoutPosition[ side ]  = '0px';
2459			flyoutPosition[ 'height' ]  = winHeight + 'px';
2460			flyoutPosition[ 'top' ] = '0px';
2461			
2462			if ( adminBarHeight > 0 ) {
2463				const diff = adminBarHeight - winTop;
2464				flyoutPosition[ 'top' ] = diff <= 0 ? '0px' : (diff) + 'px';
2465			}
2466
2467			return flyoutPosition;
2468		},
2469
2470		/**
2471		 * Shows or hides the nav search form.
2472		 *
2473		 * @since  2.5
2474		 * @method _toggleMenuSearch
2475		 */
2476		_toggleMenuSearch: function(){
2477			const form   = $( this.wrapperClass ).find('.fl-menu-search-item .fl-search-form-input-wrap'); 
2478			const button = $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))');
2479			form.on('submit', () => form.stop().fadeToggle('fast'));
2480			// Close the search form when focus is lost
2481			form.on('focusout', (event) => {
2482				if (form.is(':visible') && form.has($(event.relatedTarget)).length === 0) {
2483					button.trigger('click');
2484				}
2485			});
2486			button.attr('aria-expanded', false);
2487			// Close other open submenus when focusing on the search button
2488			button.on('focus', (event) => {
2489				const parentMenus = $(event.relatedTarget).parents('.menu-item.fl-has-submenu');
2490				if (event.relatedTarget && parentMenus.length) {
2491					this._toggleSubmenu(parentMenus, false);
2492				}
2493			});
2494			button.on('click', (event) => {
2495				// Prevent toggling when clicking with mouse while the form is already open
2496				if (event.detail && event.type === 'click' && form.is(':visible')) return;
2497				form.stop().fadeToggle('fast', () => {
2498					button.attr('aria-expanded', form.is(':visible'));
2499					if(form.is(':visible')) {
2500						form.find('.fl-search-text').focus();
2501					}
2502				});
2503			});
2504		},
2505
2506		/**
2507		 * Adds menu node and post ID to WooCommerce ajax URL requests.
2508		 *
2509		 * @since  2.5
2510		 * @return void
2511		 */
2512		_wooUpdateParams: function() {
2513			if ( 'undefined' !== typeof wc_cart_fragments_params ) {
2514				wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId;
2515			}
2516			if ( 'undefined' !== typeof wc_add_to_cart_params ) {
2517				wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId;
2518			}
2519		},
2520	};
2521
2522})(jQuery);
2523
2524(function($) {
2525
2526	$(function() {
2527
2528		new FLBuilderMenu({
2529			id: '5b4e4504e6e84',
2530			type: 'horizontal',
2531			mobile: 'expanded',
2532			mobileBelowRow: false,
2533			mobileFlyout: false,
2534			breakPoints: {
2535				large: 1200,
2536				medium: 992,
2537				small: 768			},
2538			mobileBreakpoint: 'mobile',
2539			postId : '793',
2540			mobileStacked: true,
2541			submenuIcon: 'none',
2542			flyoutWidth: '250',
2543		});
2544
2545	});
2546
2547})(jQuery);
2548
2549/* Start Global Node Custom JS */
2550
2551/* End Global Node Custom JS */
2552
2553
2554/* Start Layout Custom JS */
2555
2556/* End Layout Custom JS */
2557
2558
2559jQuery(function($) {
2560	
2561		$(function() {
2562		$( '.fl-node-5f8f08a94844b .fl-photo-img' )
2563			.on( 'mouseenter', function( e ) {
2564				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
2565			} )
2566			.on( 'mouseleave', function( e ){
2567				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
2568			} );
2569	});
2570		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
2571});
2572jQuery(function($) {
2573	
2574		$(function() {
2575		$( '.fl-node-5f8f088a0bbca .fl-photo-img' )
2576			.on( 'mouseenter', function( e ) {
2577				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
2578			} )
2579			.on( 'mouseleave', function( e ){
2580				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
2581			} );
2582	});
2583		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
2584});
2585jQuery(function($) {
2586	
2587		$(function() {
2588		$( '.fl-node-5f8f0872a5094 .fl-photo-img' )
2589			.on( 'mouseenter', function( e ) {
2590				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
2591			} )
2592			.on( 'mouseleave', function( e ){
2593				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
2594			} );
2595	});
2596		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
2597});
2598
2599;/* eslint-disable no-undef */
2600(function($) {
2601
2602	FLBuilderPostGrid = function(settings)
2603	{
2604		this.settings    = settings;
2605		this.nodeClass   = '.fl-node-' + settings.id;
2606		this.matchHeight = settings.matchHeight;
2607
2608		if ( 'columns' == this.settings.layout ) {
2609			this.wrapperClass = this.nodeClass + ' .fl-post-grid';
2610			this.postClass    = this.nodeClass + ' .fl-post-column';
2611		}
2612		else {
2613			this.wrapperClass = this.nodeClass + ' .fl-post-' + this.settings.layout;
2614			this.postClass    = this.wrapperClass + '-post';
2615		}
2616
2617		if(this._hasPosts()) {
2618			this._initLayout();
2619			this._initInfiniteScroll();
2620		}
2621	};
2622
2623	FLBuilderPostGrid.prototype = {
2624
2625		settings        : {},
2626		nodeClass       : '',
2627		wrapperClass    : '',
2628		postClass       : '',
2629		gallery         : null,
2630		currPage		: 1,
2631		totalPages		: 1,
2632
2633		_hasPosts: function()
2634		{
2635			return $(this.postClass).length > 0;
2636		},
2637
2638		_initLayout: function()
2639		{
2640			switch(this.settings.layout) {
2641
2642				case 'columns':
2643				this._columnsLayout();
2644				break;
2645
2646				case 'grid':
2647				this._gridLayout();
2648				break;
2649
2650				case 'gallery':
2651				this._galleryLayout();
2652				break;
2653			}
2654
2655			$(this.postClass).css('visibility', 'visible');
2656
2657			FLBuilderLayout._scrollToElement( $( this.nodeClass + ' .fl-paged-scroll-to' ) );
2658		},
2659
2660		_columnsLayout: function()
2661		{
2662			$(this.wrapperClass).imagesLoaded( $.proxy( function() {
2663				this._gridLayoutMatchHeight();
2664			}, this ) );
2665
2666			$( window ).on( 'resize', $.proxy( function(){
2667				$(this.wrapperClass).imagesLoaded( $.proxy( function() {
2668					this._gridLayoutMatchHeight();
2669				}, this ) );
2670			}, this ) );
2671		},
2672
2673		_gridLayout: function()
2674		{
2675			var wrap = $(this.wrapperClass);
2676
2677			wrap.masonry({
2678				columnWidth         : this.nodeClass + ' .fl-post-grid-sizer',
2679				gutter              : parseInt(this.settings.postSpacing),
2680				isFitWidth          : true,
2681				itemSelector        : this.postClass,
2682				transitionDuration  : 0,
2683				isRTL               : this.settings.isRTL
2684			});
2685
2686			wrap.imagesLoaded( $.proxy( function() {
2687				this._gridLayoutMatchHeight();
2688				wrap.masonry();
2689			}, this ) );
2690
2691			$(window).scroll($.debounce( 25, function(){
2692				wrap.masonry()
2693			}));
2694
2695		},
2696
2697		_gridLayoutMatchHeight: function()
2698		{
2699			var highestBox = 0;
2700
2701			if ( ! this._isMatchHeight() ) {
2702				$(this.nodeClass + ' .fl-post-grid-post').css('height', '');
2703				return;
2704			}
2705
2706            $(this.nodeClass + ' .fl-post-grid-post').css('height', '').each(function(){
2707
2708                if($(this).height() > highestBox) {
2709                	highestBox = $(this).height();
2710                }
2711            });
2712
2713            $(this.nodeClass + ' .fl-post-grid-post').height(highestBox);
2714		},
2715
2716		_isMatchHeight: function(){
2717			var width 		= $( window ).width(),
2718				breakpoints = FLBuilderLayoutConfig.breakpoints,
2719				matchLarge = '' != this.matchHeight.large ? this.matchHeight.large : this.matchHeight.default,
2720				matchMedium = '' != this.matchHeight.medium ? this.matchHeight.medium : this.matchHeight.default,
2721				matchSmall  = '' != this.matchHeight.responsive ? this.matchHeight.responsive : this.matchHeight.default;
2722
2723			return (width > breakpoints.medium && 1 == this.matchHeight.default) // Must check medium here for backwards compat
2724				   || (width > breakpoints.medium && width <= breakpoints.large && 1 == matchLarge)
2725				   || (width > breakpoints.small && width <= breakpoints.medium && 1 == matchMedium)
2726				   || (width <= breakpoints.small && 1 == matchSmall);
2727		},
2728
2729		_galleryLayout: function()
2730		{
2731			this.gallery = new FLBuilderGalleryGrid({
2732				'wrapSelector' : this.wrapperClass,
2733				'itemSelector' : '.fl-post-gallery-post',
2734				'isRTL'        : this.settings.isRTL
2735			});
2736		},
2737
2738		_initInfiniteScroll: function()
2739		{
2740			var isScroll = 'scroll' == this.settings.pagination || 'load_more' == this.settings.pagination,
2741				pages	 = $( this.nodeClass + ' .fl-builder-pagination' ).find( 'li .page-numbers:not(.next)' );
2742
2743			if( pages.length > 1) {
2744				total = pages.last().text().replace( /\D/g, '' )
2745				this.totalPages = parseInt( total );
2746			}
2747
2748			if( isScroll && this.totalPages > 1 && 'undefined' === typeof FLBuilder ) {
2749				this._infiniteScroll();
2750
2751				if( 'load_more' == this.settings.pagination ) {
2752					this._infiniteScrollLoadMore();
2753				}
2754			}
2755		},
2756
2757		_infiniteScroll: function()
2758		{
2759			var path 		= $(this.nodeClass + ' .fl-builder-pagination a.next').attr('href'),
2760				pagePattern = /(.*?(\/|&|\?)paged-[0-9]{1,}(\/|=))([0-9]{1,})+(.*)/,
2761				wpPattern   = /^(.*?\/?page\/?)(?:\d+)(.*?$)/,
2762				pageMatched = null,
2763				scrollData	= {
2764					navSelector     : this.nodeClass + ' .fl-builder-pagination',
2765					nextSelector    : this.nodeClass + ' .fl-builder-pagination a.next',
2766					itemSelector    : this.postClass,
2767					prefill         : true,
2768					bufferPx        : 200,
2769					loading         : {
2770						msgText         : this.settings.loadingText,
2771						finishedMsg     : '',
2772						img             : FLBuilderLayoutConfig.paths.pluginUrl + 'img/ajax-loader-grey.gif',
2773						speed           : 1
2774					}
2775				};
2776			// Define path since Infinitescroll incremented our custom pagination '/paged-2/2/' to '/paged-3/2/'.
2777			if ( pagePattern.test( path ) ) {
2778				scrollData.path = function( currPage ){
2779					pageMatched = path.match( pagePattern );
2780					path = pageMatched[1] + currPage + pageMatched[5];
2781					return path;
2782				}
2783			}
2784			else if ( wpPattern.test( path ) ) {
2785				scrollData.path = path.match( wpPattern ).slice( 1 );
2786			}
2787
2788			$(this.postClass).first().parent().infinitescroll( scrollData, $.proxy(this._infiniteScrollComplete, this) );
2789
2790			setTimeout(function(){
2791				$(window).trigger('resize');
2792			}, 100);
2793		},
2794
2795		_infiniteScrollComplete: function(elements)
2796		{
2797			var wrap = $(this.wrapperClass);
2798
2799			elements = $(elements);
2800
2801			if(this.settings.layout == 'columns') {
2802				wrap.imagesLoaded( $.proxy( function() {
2803					$( '#infscr-loading' ).remove();
2804					this._gridLayoutMatchHeight();
2805					elements.css('visibility', 'visible');
2806				}, this ) );
2807			}
2808			else if(this.settings.layout == 'grid') {
2809				wrap.imagesLoaded( $.proxy( function() {
2810					this._gridLayoutMatchHeight();
2811					wrap.masonry('appended', elements);
2812					wrap.masonry();
2813					elements.css('visibility', 'visible');
2814				}, this ) );
2815			}
2816			else if(this.settings.layout == 'gallery') {
2817				this.gallery.resize();
2818				elements.css('visibility', 'visible');
2819			}
2820
2821			if( 'load_more' == this.settings.pagination ) {
2822				$( this.wrapperClass + ' .fl-post-grid-sizer.masonry-brick' ).appendTo( this.wrapperClass );
2823				$( '#infscr-loading' ).appendTo( this.wrapperClass );
2824			}
2825
2826			this.currPage++;
2827
2828			this._removeLoadMoreButton();
2829
2830			// trigger an event
2831			node = $(wrap).closest('.fl-module-post-grid').data('node')
2832			$('.fl-node-' + node).trigger( 'gridScrollComplete', this );
2833		},
2834
2835		_infiniteScrollLoadMore: function()
2836		{
2837			var wrap = $( this.postClass ).first().parent();
2838
2839			$( window ).unbind( '.infscr' );
2840
2841			$(this.nodeClass + ' .fl-builder-pagination-load-more .fl-button').on( 'click', function(){
2842				if( $( '#infscr-loading' ).length ) {
2843					$( '#infscr-loading' ).remove();
2844				}
2845
2846				wrap.infinitescroll( 'retrieve' );
2847				return false;
2848			});
2849		},
2850
2851		_removeLoadMoreButton: function()
2852		{
2853			if ( 'load_more' == this.settings.pagination && this.totalPages == this.currPage ) {
2854				$( this.nodeClass + ' .fl-builder-pagination-load-more' ).remove();
2855			}
2856		}
2857	};
2858
2859})(jQuery);
2860(function($) {
2861
2862	$(function() {
2863
2864		new FLBuilderPostGrid({
2865			id: '5baa61fac7a35',
2866			layout: 'feed',
2867			pagination: 'numbers',
2868			postSpacing: '60',
2869			postWidth: '300',
2870			matchHeight: {
2871				default	   : '1',
2872				large 	   : '',
2873				medium 	   : '',
2874				responsive : ''
2875			},
2876			isRTL: false,
2877			loadingText: 'Loading...'
2878		});
2879
2880			});
2881
2882})(jQuery);
2883
2884/* Start Layout Custom JS */
2885
2886/* End Layout Custom JS */
2887
2888
2889jQuery(function($) {
2890	
2891		$(function() {
2892		$( '.fl-node-5da892bbc0b4e .fl-photo-img' )
2893			.on( 'mouseenter', function( e ) {
2894				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
2895			} )
2896			.on( 'mouseleave', function( e ){
2897				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
2898			} );
2899	});
2900		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
2901});
2902
2903(function($) {
2904
2905	$(function() {
2906
2907		new FLBuilderMenu({
2908			id: '5da892bbc0b4a',
2909			type: 'horizontal',
2910			mobile: 'hamburger',
2911			mobileBelowRow: true,
2912			mobileFlyout: false,
2913			breakPoints: {
2914				large: 1200,
2915				medium: 992,
2916				small: 768			},
2917			mobileBreakpoint: 'medium-mobile',
2918			postId : '15756',
2919			mobileStacked: true,
2920			submenuIcon: 'none',
2921			flyoutWidth: '250',
2922		});
2923
2924	});
2925
2926})(jQuery);
2927
2928/* Start Layout Custom JS */
2929
2930/* End Layout Custom JS */
2931
2932(function($){
2933
2934	/**
2935	 * Helper class for header layout logic.
2936	 *
2937	 * @since 1.0
2938	 * @class FLThemeBuilderHeaderLayout
2939	 */
2940	FLThemeBuilderHeaderLayout = {
2941
2942		/**
2943		 * A reference to the window object for this page.
2944		 *
2945		 * @since 1.0
2946		 * @property {Object} win
2947		 */
2948		win : null,
2949
2950		/**
2951		 * A reference to the body object for this page.
2952		 *
2953		 * @since 1.0
2954		 * @property {Object} body
2955		 */
2956		body : null,
2957
2958		/**
2959		 * A reference to the header object for this page.
2960		 *
2961		 * @since 1.0
2962		 * @property {Object} header
2963		 */
2964		header : null,
2965
2966		/**
2967		 * Whether this header overlays the content or not.
2968		 *
2969		 * @since 1.0
2970		 * @property {Boolean} overlay
2971		 */
2972		overlay : false,
2973
2974		/**
2975		 * Whether the page has the WP admin bar or not.
2976		 *
2977		 * @since 1.0
2978		 * @property {Boolean} hasAdminBar
2979		 */
2980		hasAdminBar : false,
2981
2982		/**
2983		 * Breakpoint for when the sticky header should apply.
2984		 *
2985		 * @since 1.4
2986		 * @property {String} stickyOn
2987		 */
2988		stickyOn: '',
2989
2990		/**
2991		 * A reference of the sticky and shrink header breakpoint.
2992		 *
2993		 * @since 1.2.5
2994		 * @property {Number} breakpointWidth
2995		 */
2996		breakpointWidth: 0,
2997
2998		/**
2999		 * Initializes header layout logic.
3000		 *
3001		 * @since 1.0
3002		 * @method init
3003		 */
3004		init: function()
3005		{
3006			var editing          = $( 'html.fl-builder-edit' ).length,
3007				header           = $( '.fl-builder-content[data-type=header]' ),
3008				menuModule       = header.find( '.fl-module-menu' ),
3009				breakpoint       = null;
3010
3011			if ( ! editing && header.length ) {
3012
3013				header.imagesLoaded( $.proxy( function() {
3014
3015					this.win         = $( window );
3016					this.body        = $( 'body' );
3017					this.header      = header.eq( 0 );
3018					this.overlay     = !! Number( header.attr( 'data-overlay' ) );
3019					this.hasAdminBar = !! $( 'body.admin-bar' ).length;
3020					this.stickyOn    = this.header.data( 'sticky-on' );
3021					breakpoint       = this.header.data( 'sticky-breakpoint' );
3022
3023					if ( '' == this.stickyOn ) {
3024						if ( typeof FLBuilderLayoutConfig.breakpoints[ breakpoint ] !== undefined ) {
3025							this.breakpointWidth = FLBuilderLayoutConfig.breakpoints[ breakpoint ];
3026						}
3027						else {
3028							this.breakpointWidth = FLBuilderLayoutConfig.breakpoints.medium;
3029						}
3030					}
3031
3032					if ( Number( header.attr( 'data-sticky' ) ) ) {
3033
3034						this.header.data( 'original-top', this.header.offset().top );
3035						this.win.on( 'resize', $.throttle( 500, $.proxy( this._initSticky, this ) ) );
3036						this._initSticky();
3037
3038					}
3039
3040				}, this ) );
3041			}
3042		},
3043
3044		/**
3045		 * Initializes sticky logic for a header.
3046		 *
3047		 * @since 1.0
3048		 * @access private
3049		 * @method _initSticky
3050		 */
3051		_initSticky: function( e )
3052		{
3053			var header     = $('.fl-builder-content[data-type=header]'),
3054				windowSize = this.win.width(),
3055				makeSticky = false;
3056
3057			makeSticky = this._makeWindowSticky( windowSize );
3058			if ( makeSticky || ( this.breakpointWidth > 0 && windowSize >= this.breakpointWidth ) ) {
3059				this.win.on( 'scroll.fl-theme-builder-header-sticky', $.proxy( this._doSticky, this ) );
3060				//
3061				// Check if Event Type is 'resize' then invoke this._doSticky()
3062				// only if the 'fl-theme-builder-header-sticky' class is already present.
3063				//
3064				if ( e && 'resize' === e.type ) {
3065					if ( this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
3066						this._doSticky( e );
3067					}
3068					this._adjustStickyHeaderWidth();
3069				}
3070
3071				if ( Number( header.attr( 'data-shrink' ) ) ) {
3072					this.header.data( 'original-height', this.header.outerHeight() );
3073					this.win.on( 'resize', $.throttle( 500, $.proxy( this._initShrink, this ) ) );
3074					this._initShrink();
3075				}
3076
3077				this._initFlyoutMenuFix( e );
3078			} else {
3079				this.win.off( 'scroll.fl-theme-builder-header-sticky' );
3080				this.win.off( 'resize.fl-theme-builder-header-sticky' );
3081
3082				this.header.removeClass( 'fl-theme-builder-header-sticky' );
3083				this.header.removeAttr( 'style' );
3084				this.header.parent().css( 'padding-top', '0' );
3085			}
3086		},
3087
3088		/**
3089		 * Check if Header should be sticky at a particular Window size.
3090		 *
3091		 * @since 1.4
3092		 * @access private
3093		 * @param  widowSize
3094		 * @method _makeWindowSticky
3095		 */
3096		_makeWindowSticky: function ( windowSize )
3097		{
3098			var makeSticky = false;
3099
3100			switch (this.stickyOn) {
3101				case 'xl':
3102					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['large'];
3103					break;
3104				case '': // Default
3105				case 'desktop':
3106					makeSticky = windowSize >= FLBuilderLayoutConfig.breakpoints['medium'];
3107					break;
3108				case 'desktop-medium':
3109					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'];
3110					break;
3111				case 'large':
3112					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['medium'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large'];
3113					break;
3114				case 'large-medium':
3115					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large'];
3116					break;
3117				case 'medium':
3118					makeSticky = ( windowSize <= FLBuilderLayoutConfig.breakpoints['medium'] && windowSize > FLBuilderLayoutConfig.breakpoints['small'] );
3119					break;
3120				case 'medium-mobile':
3121					makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['medium']);
3122					break;
3123				case 'mobile':
3124					makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['small']);
3125					break;
3126				case 'all':
3127					makeSticky = true;
3128					break;
3129			}
3130
3131			return makeSticky;
3132		},
3133
3134		/**
3135		 * Sticks the header when the page is scrolled.
3136		 *
3137		 * @since 1.0
3138		 * @access private
3139		 * @method _doSticky
3140		 */
3141		_doSticky: function( e )
3142		{
3143			var winTop    		  = Math.floor( this.win.scrollTop() ),
3144				headerTop 		  = Math.floor( this.header.data( 'original-top' ) ),
3145				hasStickyClass    = this.header.hasClass( 'fl-theme-builder-header-sticky' ),
3146				hasScrolledClass  = this.header.hasClass( 'fl-theme-builder-header-scrolled' ),
3147				beforeHeader      = this.header.prevAll( '.fl-builder-content' ),
3148				bodyTopPadding    = parseInt( jQuery('body').css('padding-top') ),
3149				winBarHeight      = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0,
3150				headerHeight      = 0;
3151
3152			if ( isNaN( bodyTopPadding ) ) {
3153				bodyTopPadding = 0;
3154			}
3155
3156			if ( this.hasAdminBar && this.win.width() > 600 ) {
3157				winTop += Math.floor( winBarHeight );
3158			}
3159
3160			if ( winTop > headerTop ) {
3161				if ( ! hasStickyClass ) {
3162					if ( e && ( 'scroll' === e.type || 'smartscroll' === e.type ) ) {
3163					 	this.header.addClass( 'fl-theme-builder-header-sticky' );
3164						if ( this.overlay && beforeHeader.length ) {
3165							this.header.css( 'top', winBarHeight);
3166						}
3167					}
3168
3169					if ( ! this.overlay ) {
3170						this._adjustHeaderHeight();
3171					}
3172				}
3173			}
3174			else if ( hasStickyClass ) {
3175				this.header.removeClass( 'fl-theme-builder-header-sticky' );
3176				this.header.removeAttr( 'style' );
3177				this.header.parent().css( 'padding-top', '0' );
3178			}
3179
3180			this._adjustStickyHeaderWidth();
3181
3182			if ( winTop > headerTop ) {
3183				if ( ! hasScrolledClass ) {
3184					this.header.addClass( 'fl-theme-builder-header-scrolled' );
3185				}
3186			} else if ( hasScrolledClass ) {
3187				this.header.removeClass( 'fl-theme-builder-header-scrolled' );
3188			}
3189
3190			this._flyoutMenuFix( e );
3191		},
3192
3193		/**
3194		 * Initializes flyout menu fixes on sticky header.
3195		 *
3196		 * @since 1.4.1
3197		 * @method _initFlyoutMenuFix
3198		 */
3199		_initFlyoutMenuFix: function( e ) {
3200			var header       = this.header,
3201				menuModule   = header.closest( '.fl-menu' ),
3202				flyoutMenu   = menuModule.find( '.fl-menu-mobile-flyout' ),
3203				isPushMenu   = menuModule.hasClass( 'fl-menu-responsive-flyout-push' ) || menuModule.hasClass( 'fl-menu-responsive-flyout-push-opacity' ),
3204				isOverlay    = menuModule.hasClass( 'fl-menu-responsive-flyout-overlay' ),
3205				flyoutPos    = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
3206				flyoutParent = header.parent().is( 'header' ) ? header.parent().parent() : header.parent();
3207				isFullWidth  = this.win.width() === header.width(),
3208				flyoutLayout = '',
3209				activePos    = 250,
3210				headerPos    = 0;
3211
3212			if ( ! flyoutMenu.length ) {
3213				return;
3214			}
3215
3216			if ( this.win.width() > header.parent().width() ) {
3217				headerPos = ( this.win.width() - header.width() ) / 2;
3218			}
3219
3220			if ( isOverlay ) {
3221				activePos = headerPos;
3222			}
3223			else if ( isPushMenu ) {
3224				activePos = activePos + headerPos;
3225			}
3226			flyoutMenu.data( 'activePos', activePos );
3227
3228			if ( isPushMenu ) {
3229				flyoutLayout = 'push-' + flyoutPos;
3230			}
3231			else if ( isOverlay ) {
3232				flyoutLayout = 'overlay-' + flyoutPos;
3233			}
3234
3235			if ( isPushMenu && ! $( 'html' ).hasClass( 'fl-theme-builder-has-flyout-menu' ) ) {
3236				$( 'html' ).addClass( 'fl-theme-builder-has-flyout-menu' );
3237			}
3238
3239			if ( ! flyoutParent.hasClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ) ) {
3240				flyoutParent.addClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout );
3241			}
3242
3243			if ( ! header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && isOverlay ) {
3244				header.addClass( 'fl-theme-builder-flyout-menu-overlay' );
3245			}
3246
3247			if ( ! header.hasClass( 'fl-theme-builder-header-full-width' ) && isFullWidth ) {
3248			   header.addClass( 'fl-theme-builder-header-full-width' );
3249		    }
3250			else if ( ! isFullWidth ) {
3251				header.removeClass( 'fl-theme-builder-header-full-width' );
3252			}
3253
3254			menuModule.on( 'click', '.fl-menu-mobile-toggle', $.proxy( function( event ){
3255				if ( menuModule.find( '.fl-menu-mobile-toggle.fl-active' ).length ) {
3256					$( 'html' ).addClass( 'fl-theme-builder-flyout-menu-active' );
3257					event.stopImmediatePropagation();
3258				}
3259				else {
3260					$( 'html' ).removeClass( 'fl-theme-builder-flyout-menu-active' );
3261				}
3262
3263				this._flyoutMenuFix( event );
3264			}, this ) );
3265		},
3266
3267		/**
3268		 * Fix flyout menu inside the sticky header.
3269		 *
3270		 * @since 1.4.1
3271		 * @method _flyoutMenuFix
3272		 */
3273		_flyoutMenuFix: function( e ){
3274			var header      = this.header,
3275			    menuModule  = $( e.target ).closest( '.fl-menu' ),
3276				flyoutMenu  = menuModule.find( '.fl-menu-mobile-flyout' ),
3277				flyoutPos   = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
3278				menuOpacity = menuModule.find( '.fl-menu-mobile-opacity' ),
3279				isScroll    = 'undefined' !== typeof e && 'scroll' === e.handleObj.type,
3280				activePos   = 'undefined' !== typeof flyoutMenu.data( 'activePos' ) ? flyoutMenu.data( 'activePos' ) : 0,
3281				headerPos   = ( this.win.width() - header.width() ) / 2,
3282				inactivePos = headerPos > 0 ? activePos + 4 : 254;
3283
3284			if ( ! flyoutMenu.length ) {
3285				return;
3286			}
3287
3288			if ( this.overlay ) {
3289				return;
3290			}
3291
3292			if( $( '.fl-theme-builder-flyout-menu-active' ).length ) {
3293
3294				if ( isScroll && ! flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) {
3295					flyoutMenu.addClass( 'fl-menu-disable-transition' );
3296				}
3297
3298				if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
3299					if ( ! isScroll ) {
3300						setTimeout( $.proxy( function(){
3301							flyoutMenu.css( flyoutPos, '-' + activePos + 'px' );
3302						}, this ), 1 );
3303					}
3304					else {
3305						flyoutMenu.css( flyoutPos, '-' + activePos + 'px' );
3306					}
3307				}
3308				else {
3309					flyoutMenu.css( flyoutPos, '0px' );
3310				}
3311			}
3312			else {
3313				if ( flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) {
3314					flyoutMenu.removeClass( 'fl-menu-disable-transition' );
3315				}
3316
3317				if ( header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && headerPos > 0 && headerPos < 250 ) {
3318					if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
3319						inactivePos = headerPos + 254;
3320					}
3321					else {
3322						inactivePos = 254;
3323					}
3324				}
3325
3326				if ( e && e.type === 'resize' ) {
3327					inactivePos = headerPos + 254;
3328				}
3329
3330				flyoutMenu.css( flyoutPos, '-' + inactivePos + 'px' );
3331			}
3332
3333			if ( e && menuModule.is('.fl-menu-responsive-flyout-overlay') && $.infinitescroll ) {
3334				e.stopImmediatePropagation();
3335			}
3336
3337			if( menuOpacity.length ) {
3338				if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
3339					if ( '0px' === menuOpacity.css( 'left' ) ) {
3340						menuOpacity.css( 'left', '-' + headerPos + 'px' );
3341					}
3342				}
3343				else {
3344					menuOpacity.css( 'left', '' );
3345				}
3346			}
3347		},
3348
3349		/**
3350		 * Adjust sticky header width if BB Theme Boxed Layout is used.
3351		 *
3352		 * @since 1.4
3353		 * @access private
3354		 * @method _adjustStickyHeaderWidth
3355		 */
3356		_adjustStickyHeaderWidth: function () {
3357			if ( $('body').hasClass( 'fl-fixed-width' ) ) {
3358				var parentWidth = this.header.parent().width();
3359
3360				// Better if this is set in the stylesheet file.
3361				if ( this.win.width() >= 992 ) {
3362					this.header.css({
3363						'margin': '0 auto',
3364						'max-width': parentWidth,
3365					});
3366				}
3367				else {
3368					this.header.css({
3369						'margin': '',
3370						'max-width': '',
3371					});
3372				}
3373			}
3374		},
3375
3376		/**
3377		 * Adjust Sticky Header Height
3378		 *
3379		 * @since 1.4
3380		 * @access private
3381		 * @method _adjustHeaderHeight
3382		 */
3383		_adjustHeaderHeight: function () {
3384			var beforeHeader = this.header.prevAll('.fl-builder-content'),
3385				beforeHeaderHeight = 0,
3386				beforeHeaderFix = 0,
3387				headerHeight = Math.floor( this.header.outerHeight() ),
3388				bodyTopPadding = parseInt( $( 'body' ).css( 'padding-top' ) ),
3389				wpAdminBarHeight = 0,
3390				totalHeaderHeight = 0;
3391
3392			if ( isNaN( bodyTopPadding ) ) {
3393				bodyTopPadding = 0;
3394			}
3395
3396			if ( beforeHeader.length ) {
3397				$.each( beforeHeader, function() {
3398					beforeHeaderHeight += Math.floor( $(this).outerHeight() );
3399				});
3400				// Subtract this value from the header parent's top padding.
3401				beforeHeaderFix = 2;
3402			}
3403
3404			if ( this.hasAdminBar && this.win.width() <= 600 ) {
3405				wpAdminBarHeight = Math.floor( $('#wpadminbar').outerHeight() );
3406			}
3407
3408			totalHeaderHeight = Math.floor( beforeHeaderHeight + headerHeight);
3409
3410			if ( headerHeight > 0 ) {
3411				var headerParent = this.header.parent(),
3412					headerParentTopPadding = 0;
3413
3414				// If the header's parent container is the BODY tag ignore its top padding.
3415				if ( $( headerParent ).is('body') ) {
3416					headerParentTopPadding = Math.floor( headerHeight - wpAdminBarHeight );
3417				} else {
3418					headerParentTopPadding = Math.floor( headerHeight - bodyTopPadding - wpAdminBarHeight );
3419				}
3420
3421				$( headerParent ).css( 'padding-top',  ( headerParentTopPadding - beforeHeaderFix ) + 'px' );
3422
3423				this.header.css({
3424					'-webkit-transform': 'translate(0px, -' + totalHeaderHeight + 'px)',
3425					'-ms-transform': 'translate(0px, -' + totalHeaderHeight + 'px)',
3426					'transform': 'translate(0px, -' + totalHeaderHeight + 'px)'
3427				});
3428
3429			}
3430
3431		},
3432
3433		/**
3434		 * Initializes shrink logic for a header.
3435		 *
3436		 * @since 1.0
3437		 * @access private
3438		 * @method _initShrink
3439		 */
3440		_initShrink: function( e )
3441		{
3442			if ( this.win.width() >= this.breakpointWidth ) {
3443				this.win.on( 'scroll.fl-theme-builder-header-shrink', $.proxy( this._doShrink, this ) );
3444				this._setImageMaxHeight();
3445
3446				if ( this.win.scrollTop() > 0 ){
3447					this._doShrink();
3448				}
3449
3450			} else {
3451				this.header.parent().css( 'padding-top', '0' );
3452				this.win.off( 'scroll.fl-theme-builder-header-shrink' );
3453				this._removeShrink();
3454				this._removeImageMaxHeight();
3455			}
3456		},
3457
3458		/**
3459		 * Shrinks the header when the page is scrolled.
3460		 *
3461		 * @since 1.0
3462		 * @access private
3463		 * @method _doShrink
3464		 */
3465		_doShrink: function( e )
3466		{
3467			var winTop 			  = this.win.scrollTop(),
3468				headerTop 		  = this.header.data('original-top'),
3469				headerHeight 	  = this.header.data('original-height'),
3470				shrinkImageHeight = this.header.data('shrink-image-height'),
3471				windowSize   	  = this.win.width(),
3472				makeSticky   	  = this._makeWindowSticky( windowSize ),
3473				hasClass     	  = this.header.hasClass( 'fl-theme-builder-header-shrink' );
3474
3475
3476			if ( this.hasAdminBar ) {
3477				winTop += 32;
3478			}
3479
3480			if ( makeSticky && ( winTop > headerTop + headerHeight ) ) {
3481				if ( ! hasClass ) {
3482
3483					this.header.addClass( 'fl-theme-builder-header-shrink' );
3484
3485					// Shrink images but don't include lightbox and menu images.
3486					this.header.find('img').each( function( i ) {
3487						var image           = $( this ),
3488							maxMegaMenu     = image.closest( '.max-mega-menu' ).length,
3489							imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length,
3490							imageInNavMenu  = image.closest( 'li.menu-item' ).length;
3491
3492						if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) {
3493							image.css( 'max-height', shrinkImageHeight );
3494						}
3495
3496					});
3497
3498					this.header.find( '.fl-row-content-wrap' ).each( function() {
3499
3500						var row = $( this );
3501
3502						if ( parseInt( row.css( 'padding-bottom' ) ) > 5 ) {
3503							row.addClass( 'fl-theme-builder-header-shrink-row-bottom' );
3504						}
3505
3506						if ( parseInt( row.css( 'padding-top' ) ) > 5 ) {
3507							row.addClass( 'fl-theme-builder-header-shrink-row-top' );
3508						}
3509					} );
3510
3511					this.header.find( '.fl-module' ).each( function() {
3512
3513						var module = $( this ).find( '.fl-module-content' ).length ? $( this ).find( '.fl-module-content' ) : $( this );
3514
3515						if ( parseInt( module.css( 'margin-bottom' ) ) > 5 ) {
3516							module.addClass( 'fl-theme-builder-header-shrink-module-bottom' );
3517						}
3518
3519						if ( parseInt( module.css( 'margin-top' ) ) > 5 ) {
3520							module.addClass( 'fl-theme-builder-header-shrink-module-top' );
3521						}
3522					} );
3523				}
3524			} else if (hasClass) {
3525				this.header.find( 'img' ).css( 'max-height', '' );
3526				this._removeShrink();
3527			}
3528
3529			// Fixes Shrink header issue with BB Theme when window is scrolled then resized and back.
3530			if ( 'undefined' === typeof( e ) && $('body').hasClass( 'fl-fixed-width' ) ) {
3531				if ( ! this.overlay ) {
3532					this._adjustHeaderHeight();
3533				}
3534			}
3535
3536		},
3537
3538		/**
3539		 * Removes the header shrink effect.
3540		 *
3541		 * @since 1.0
3542		 * @access private
3543		 * @method _removeShrink
3544		 */
3545		_removeShrink: function()
3546		{
3547			var rows    = this.header.find( '.fl-row-content-wrap' ),
3548				modules = this.header.find('.fl-module, .fl-module-content');
3549
3550			rows.removeClass( 'fl-theme-builder-header-shrink-row-bottom' );
3551			rows.removeClass( 'fl-theme-builder-header-shrink-row-top' );
3552			modules.removeClass( 'fl-theme-builder-header-shrink-module-bottom' );
3553			modules.removeClass( 'fl-theme-builder-header-shrink-module-top' );
3554			this.header.removeClass( 'fl-theme-builder-header-shrink' );
3555		},
3556
3557		/**
3558		 * Adds max height to images in modules for smooth scrolling.
3559		 *
3560		 * @since 1.1.1
3561		 * @access private
3562		 * @method _setImageMaxHeight
3563		 */
3564		_setImageMaxHeight: function()
3565		{
3566			var head = $( 'head' ),
3567				stylesId = 'fl-header-styles-' + this.header.data( 'post-id' ),
3568				styles = '',
3569				images = this.header.find( '.fl-module img' );
3570
3571			if ( $( '#' + stylesId ).length ) {
3572				return;
3573			}
3574
3575			images.each( function( i ) {
3576				var image           = $( this ),
3577					height          = image.height(),
3578					node            = image.closest( '.fl-module' ).data( 'node' ),
3579					className       = 'fl-node-' + node + '-img-' + i,
3580					maxMegaMenu     = image.closest( '.max-mega-menu' ).length,
3581					imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length,
3582					imageInNavMenu  = image.closest( 'li.menu-item' ).length;
3583
3584				if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu  ) ) {
3585					image.addClass( className );
3586					styles += '.' + className + ' { max-height: ' + ( height ? height : image[0].height )  + 'px }';
3587				}
3588
3589			} );
3590
3591			if ( '' !== styles ) {
3592				head.append( '<style id="' + stylesId + '">' + styles + '</style>' );
3593			}
3594		},
3595
3596		/**
3597		 * Removes max height on images in modules for smooth scrolling.
3598		 *
3599		 * @since 1.1.1
3600		 * @access private
3601		 * @method _removeImageMaxHeight
3602		 */
3603		_removeImageMaxHeight: function()
3604		{
3605			$( '#fl-header-styles-' + this.header.data( 'post-id' ) ).remove();
3606		},
3607	};
3608
3609	$( function() { FLThemeBuilderHeaderLayout.init(); } );
3610
3611})(jQuery);
3612

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.