PageSourceSearch

https://byoghavn.dk/havnen/wp-content/uploads/sites/13/bb-plugin/c…?ver=64d424d421b6d3461e23fcd59a11e3a4

js byoghavn.dk collected 2026-10-01 10:44:18 UTC 40,864 bytes, 1,538 lines download raw bytes

1var wpAjaxUrl = 'https://byoghavn.dk/havnen/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://byoghavn.dk/havnen/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = {
2	anchorLinkAnimations : {
3		duration 	: 1000,
4		easing		: 'swing',
5		offset 		: 100
6	},
7	paths : {
8		pluginUrl : 'https://byoghavn.dk/havnen/wp-content/plugins/bb-plugin/',
9		wpAjaxUrl : 'https://byoghavn.dk/havnen/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 row shape layer height.
52			FLBuilderLayout._initRowShapeLayerHeight();
53
54			// Only init if the builder isn't active.
55			if ( 0 === $('.fl-builder-edit').length ) {
56
57				// Init anchor links.
58				FLBuilderLayout._initAnchorLinks();
59
60				// Init the browser hash.
61				FLBuilderLayout._initHash();
62
63				// Init forms.
64				FLBuilderLayout._initForms();
65
66				FLBuilderLayout._reorderMenu();
67			}
68			else {
69				FLBuilderLayout._initNestedColsWidth();
70			}
71			$('body').removeClass( 'fl-no-js' );
72		},
73
74		/**
75		 * Public method for refreshing Wookmark or MosaicFlow galleries
76		 * within an element.
77		 *
78		 * @since 1.7.4
79		 * @method refreshGalleries
80		 */
81		refreshGalleries: function( element )
82		{
83			var $element  = 'undefined' == typeof element ? $( 'body' ) : $( element ),
84				mfContent = $element.find( '.fl-mosaicflow-content' ),
85				wmContent = $element.find( '.fl-gallery' ),
86				mfObject  = null;
87
88			if ( mfContent ) {
89
90				mfObject = mfContent.data( 'mosaicflow' );
91
92				if ( mfObject ) {
93					mfObject.columns = $( [] );
94					mfObject.columnsHeights = [];
95					mfContent.data( 'mosaicflow', mfObject );
96					mfContent.mosaicflow( 'refill' );
97				}
98			}
99			if ( wmContent ) {
100				wmContent.trigger( 'refreshWookmark' );
101			}
102		},
103
104		/**
105		 * Public method for refreshing Masonry within an element
106		 *
107		 * @since 1.8.1
108		 * @method refreshGridLayout
109		 */
110		refreshGridLayout: function( element )
111		{
112			var $element 		= 'undefined' == typeof element ? $( 'body' ) : $( element ),
113				msnryContent	= $element.find('.masonry');
114
115			if ( msnryContent.length )	{
116				msnryContent.masonry('layout');
117			}
118		},
119
120		/**
121		 * Public method for reloading BxSlider within an element
122		 *
123		 * @since 1.8.1
124		 * @method reloadSlider
125		 */
126		reloadSlider: function( content )
127		{
128			var $content = 'undefined' == typeof content ? $('body') : $(content);
129
130			// reload sliders.
131			if ($content.find('.bx-viewport > div').length > 0) {
132				$.each($content.find('.bx-viewport > div'), function (key, slider) {
133					setTimeout(function () {
134						$(slider).data('bxSlider').reloadSlider();
135					}, 100);
136				});
137			}
138		},
139
140		/**
141		 * Public method for resizing WP audio player
142		 *
143		 * @since 1.8.2
144		 * @method resizeAudio
145		 */
146		resizeAudio: function( element )
147		{
148			var $element 	 	= 'undefined' == typeof element ? $( 'body' ) : $( element ),
149				audioPlayers 	= $element.find('.wp-audio-shortcode.mejs-audio'),
150				player 		 	= null,
151				mejsPlayer 	 	= null,
152				rail 			= null,
153				railWidth 		= 400;
154
155			if ( audioPlayers.length && typeof mejs !== 'undefined' ) {
156            	audioPlayers.each(function(){
157	            	player 		= $(this);
158	            	mejsPlayer 	= mejs.players[player.attr('id')];
159	            	rail 		= player.find('.mejs-controls .mejs-time-rail');
160	            	var innerMejs = player.find('.mejs-inner'),
161	            		total 	  = player.find('.mejs-controls .mejs-time-total');
162
163	            	if ( typeof mejsPlayer !== 'undefined' ) {
164	            		railWidth = Math.ceil(player.width() * 0.8);
165
166	            		if ( innerMejs.length ) {
167
168		            		rail.css('width', railWidth +'px!important');
169		            		//total.width(rail.width() - 10);
170
171		            		mejsPlayer.options.autosizeProgress = true;
172
173		            		// webkit has trouble doing this without a delay
174							setTimeout(function () {
175								mejsPlayer.setControlsSize();
176							}, 50);
177
178			            	player.find('.mejs-inner').css({
179			            		visibility: 'visible',
180			            		height: 'inherit'
181			            	});
182		            	}
183		           	}
184	            });
185	        }
186		},
187
188		/**
189		 * Public method for preloading WP audio player when it's inside the hidden element
190		 *
191		 * @since 1.8.2
192		 * @method preloadAudio
193		 */
194		preloadAudio: function(element)
195		{
196			var $element 	 = 'undefined' == typeof element ? $( 'body' ) : $( element ),
197				contentWrap  = $element.closest('.fl-accordion-item'),
198				audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio');
199
200			if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) {
201				audioPlayers.find('.mejs-inner').css({
202					visibility : 'hidden',
203					height: 0
204				});
205			}
206		},
207
208		/**
209		 * Public method for resizing slideshow momdule within the tab
210		 *
211		 * @since 1.10.5
212		 * @method resizeSlideshow
213		 */
214		resizeSlideshow: function(){
215			if(typeof YUI !== 'undefined') {
216				YUI().use('node-event-simulate', function(Y) {
217					Y.one(window).simulate("resize");
218				});
219			}
220		},
221
222		/**
223		 * Public method for reloading an embedded Google Map within the tabs or hidden element.
224		 *
225		 * @since 2.2
226		 * @method reloadGoogleMap
227		 */
228		reloadGoogleMap: function(element){
229			var $element  = 'undefined' == typeof element ? $( 'body' ) : $( element ),
230			    googleMap = $element.find( 'iframe[src*="google.com/maps"]' );
231
232			if ( googleMap.length ) {
233			    googleMap.attr( 'src', function(i, val) {
234			        return val;
235			    });
236			}
237		},
238
239		/**
240		 * Unbinds builder layout events.
241		 *
242		 * @since 1.0
243		 * @access private
244		 * @method _destroy
245		 */
246		_destroy: function()
247		{
248			var win = $(window);
249
250			win.off('scroll.fl-bg-parallax');
251			win.off('resize.fl-bg-video');
252		},
253
254		/**
255		 * Checks to see if the current device has touch enabled.
256		 *
257		 * @since 1.0
258		 * @access private
259		 * @method _isTouch
260		 * @return {Boolean}
261		 */
262		_isTouch: function()
263		{
264			if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) {
265				return true;
266			}
267
268			return false;
269		},
270
271		/**
272		 * Checks to see if the current device is mobile.
273		 *
274		 * @since 1.7
275		 * @access private
276		 * @method _isMobile
277		 * @return {Boolean}
278		 */
279		_isMobile: function()
280		{
281			return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent );
282		},
283
284		/**
285		 * Initializes builder body classes.
286		 *
287		 * @since 1.0
288		 * @access private
289		 * @method _initClasses
290		 */
291		_initClasses: function()
292		{
293			var body = $( 'body' ),
294				ua   = navigator.userAgent;
295
296			// Add the builder body class.
297			if ( ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) {
298				body.addClass('fl-builder');
299			}
300
301			// Add the builder touch body class.
302			if(FLBuilderLayout._isTouch()) {
303				body.addClass('fl-builder-touch');
304			}
305
306			// Add the builder mobile body class.
307			if(FLBuilderLayout._isMobile()) {
308				body.addClass('fl-builder-mobile');
309			}
310
311			if ( $(window).width() < FLBuilderLayoutConfig.breakpoints.small ) {
312				body.addClass( 'fl-builder-breakpoint-small' );
313			}
314
315			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.small && $(window).width() < FLBuilderLayoutConfig.breakpoints.medium ) {
316				body.addClass( 'fl-builder-breakpoint-medium' );
317			}
318
319			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.medium && $(window).width() < FLBuilderLayoutConfig.breakpoints.large ) {
320				body.addClass( 'fl-builder-breakpoint-large' );
321			}
322
323			if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.large ) {
324				body.addClass( 'fl-builder-breakpoint-default' );
325			}
326
327			// IE11 body class.
328			if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) {
329				body.addClass( 'fl-builder-ie-11' );
330			}
331		},
332
333		/**
334		 * Initializes builder node backgrounds that require
335		 * additional JavaScript logic such as parallax.
336		 *
337		 * @since 1.1.4
338		 * @access private
339		 * @method _initBackgrounds
340		 */
341		_initBackgrounds: function()
342		{
343			var win = $(window);
344
345			// Init parallax backgrounds.
346			if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) {
347				FLBuilderLayout._scrollParallaxBackgrounds();
348				FLBuilderLayout._initParallaxBackgrounds();
349				win.on('resize.fl-bg-parallax', FLBuilderLayout._initParallaxBackgrounds);
350				win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds);
351			}
352
353			// Init video backgrounds.
354			if($('.fl-bg-video').length > 0) {
355				FLBuilderLayout._initBgVideos();
356				FLBuilderLayout._resizeBgVideos();
357
358				// Ensure FLBuilderLayout._resizeBgVideos() is only called once on window resize.
359				var resizeBGTimer = null;
360				win.on('resize.fl-bg-video', function(e){
361					clearTimeout( resizeBGTimer );
362					resizeBGTimer = setTimeout(function() {
363						FLBuilderLayout._resizeBgVideos(e);
364					}, 100 );
365				});
366			}
367		},
368
369		/**
370		 * Initializes all parallax backgrounds in a layout.
371		 *
372		 * @since 1.1.4
373		 * @access private
374		 * @method _initParallaxBackgrounds
375		 */
376		_initParallaxBackgrounds: function()
377		{
378			$('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground);
379		},
380
381		/**
382		 * Initializes a single parallax background.
383		 *
384		 * @since 1.1.4
385		 * @access private
386		 * @method _initParallaxBackgrounds
387		 */
388		_initParallaxBackground: function()
389		{
390			var row     = $(this),
391				content = row.find('> .fl-row-content-wrap'),
392				winWidth = $(window).width(),
393				screenSize = '',
394				imageSrc = {
395					default: '',
396					medium: '',
397					responsive: '',
398				};
399
400			imageSrc.default = row.data('parallax-image') || '';
401			imageSrc.medium = row.data('parallax-image-medium') || imageSrc.default;
402			imageSrc.responsive = row.data('parallax-image-responsive') || imageSrc.medium;
403
404			if (winWidth > FLBuilderLayoutConfig.breakpoints.medium) {
405				screenSize = 'default';
406			} else if (winWidth > FLBuilderLayoutConfig.breakpoints.small && winWidth <= FLBuilderLayoutConfig.breakpoints.medium ) {
407				screenSize = 'medium';
408			} else if (winWidth <= FLBuilderLayoutConfig.breakpoints.small) {
409				screenSize = 'responsive';
410			}
411
412			content.css('background-image', 'url(' + imageSrc[screenSize] + ')');
413			row.data('current-image-loaded', screenSize );
414
415		},
416
417		/**
418		 * Fires when the window is scrolled to adjust
419		 * parallax backgrounds.
420		 *
421		 * @since 1.1.4
422		 * @access private
423		 * @method _scrollParallaxBackgrounds
424		 */
425		_scrollParallaxBackgrounds: function()
426		{
427			$('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground);
428		},
429
430		/**
431		 * Fires when the window is scrolled to adjust
432		 * a single parallax background.
433		 *
434		 * @since 1.1.4
435		 * @access private
436		 * @method _scrollParallaxBackground
437		 */
438		_scrollParallaxBackground: function()
439		{
440			var win     	  = $(window),
441				row     	  = $(this),
442				content 	  = row.find('> .fl-row-content-wrap'),
443				speed   	  = row.data('parallax-speed'),
444				offset  	  = content.offset(),
445				yPos		  = -((win.scrollTop() - offset.top) / speed),
446				initialOffset = ( row.data('parallax-offset') != null ) ? row.data('parallax-offset') : 0,
447				totalOffset   = yPos - initialOffset;
448
449			content.css('background-position', 'center ' + totalOffset + 'px');
450		},
451
452		/**
453		 * Initializes all video backgrounds.
454		 *
455		 * @since 1.6.3.3
456		 * @access private
457		 * @method _initBgVideos
458		 */
459		_initBgVideos: function()
460		{
461			$('.fl-bg-video').each(FLBuilderLayout._initBgVideo);
462		},
463
464		/**
465		 * Initializes a video background.
466		 *
467		 * @since 1.6.3.3
468		 * @access private
469		 * @method _initBgVideo
470		 */
471		_initBgVideo: function()
472		{
473			var wrap   = $( this ),
474				width       = wrap.data( 'width' ),
475				height      = wrap.data( 'height' ),
476				mp4         = wrap.data( 'mp4' ),
477				youtube     = wrap.data( 'youtube'),
478				vimeo       = wrap.data( 'vimeo'),
479				mp4Type     = wrap.data( 'mp4-type' ),
480				webm        = wrap.data( 'webm' ),
481				webmType    = wrap.data( 'webm-type' ),
482				fallback    = wrap.data( 'fallback' ),
483				loaded      = wrap.data( 'loaded' ),
484				videoMobile = wrap.data( 'video-mobile' ),
485				fallbackTag = '',
486				videoTag    = null,
487				mp4Tag      = null,
488				webmTag     = null;
489
490			// Return if the video has been loaded for this row.
491			if ( loaded ) {
492				return;
493			}
494
495			videoTag  = $( '<video autoplay loop muted playsinline></video>' );
496
497			/**
498			 * Add poster image (fallback image)
499			 */
500			if( 'undefined' != typeof fallback && '' != fallback ) {
501				videoTag.attr( 'poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' )
502				videoTag.css({
503					backgroundImage: 'url("' + fallback + '")',
504					backgroundColor: 'transparent',
505					backgroundRepeat: 'no-repeat',
506					backgroundSize: 'cover',
507					backgroundPosition: 'center center',
508				})
509			}
510
511			// MP4 Source Tag
512			if ( 'undefined' != typeof mp4 && '' != mp4 ) {
513
514				mp4Tag = $( '<source />' );
515				mp4Tag.attr( 'src', mp4 );
516				mp4Tag.attr( 'type', mp4Type );
517
518				videoTag.append( mp4Tag );
519			}
520			// WebM Source Tag
521			if ( 'undefined' != typeof webm && '' != webm ) {
522
523				webmTag = $( '<source />' );
524				webmTag.attr( 'src', webm );
525				webmTag.attr( 'type', webmType );
526
527				videoTag.append( webmTag );
528			}
529
530			// This is either desktop, or mobile is enabled.
531			if ( ! FLBuilderLayout._isMobile() || ( FLBuilderLayout._isMobile() && "yes" == videoMobile ) ) {
532				if ( 'undefined' != typeof youtube ) {
533					FLBuilderLayout._initYoutubeBgVideo.apply( this );
534				}
535				else if ( 'undefined' != typeof vimeo ) {
536					FLBuilderLayout._initVimeoBgVideo.apply( this );
537				}
538				else {
539					wrap.append( videoTag );
540				}
541			}
542			else {
543				// if we are here, it means we are on mobile and NO is set so remove video src and use fallback
544				videoTag.attr('src', '')
545				wrap.append( videoTag );
546			}
547
548			// Mark this video as loaded.
549			wrap.data('loaded', true);
550		},
551
552		/**
553		 * Initializes Youtube video background
554		 *
555		 * @since 1.9
556		 * @access private
557		 * @method _initYoutubeBgVideo
558		 */
559		_initYoutubeBgVideo: function()
560		{
561			var playerWrap  = $(this),
562				videoId     = playerWrap.data('video-id'),
563				videoPlayer = playerWrap.find('.fl-bg-video-player'),
564				enableAudio = playerWrap.data('enable-audio'),
565				audioButton = playerWrap.find('.fl-bg-video-audio'),
566				startTime   = 'undefined' !== typeof playerWrap.data('start') ? playerWrap.data('start') : 0,
567				startTime   = 'undefined' !== typeof playerWrap.data('t') && startTime === 0 ? playerWrap.data('t') : startTime,
568				endTime     = 'undefined' !== typeof playerWrap.data('end') ? playerWrap.data('end') : 0,
569				loop        = 'undefined' !== typeof playerWrap.data('loop') ? playerWrap.data('loop') : 1,
570				stateCount  = 0,
571				player,fallback_showing;
572
573			if ( videoId ) {
574				fallback = playerWrap.data('fallback') || false
575				if( fallback ) {
576					playerWrap.find('iframe').remove()
577					fallbackTag = $( '<div></div>' );
578					fallbackTag.addClass( 'fl-bg-video-fallback' );
579					fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' );
580					fallbackTag.css( 'background-size', 'cover' );
581					fallbackTag.css( 'transition', 'background-image 1s')
582					playerWrap.append( fallbackTag );
583					fallback_showing = true;
584				}
585				FLBuilderLayout._onYoutubeApiReady( function( YT ) {
586					setTimeout( function() {
587
588						player = new YT.Player( videoPlayer[0], {
589							videoId: videoId,
590							events: {
591								onReady: function(event) {
592									if ( "no" === enableAudio || FLBuilderLayout._isMobile() ) {
593										event.target.mute();
594									}
595									else if ( "yes" === enableAudio && event.target.isMuted ) {
596										event.target.unMute();
597									}
598
599									// Store an instance to a parent
600									playerWrap.data('YTPlayer', player);
601									FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap);
602
603									// Queue the video.
604									event.target.playVideo();
605
606									if ( audioButton.length > 0 && ! FLBuilderLayout._isMobile() ) {
607										audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio );
608									}
609								},
610								onStateChange: function( event ) {
611
612									if ( event.data === 1 ) {
613										if ( fallback_showing ) {
614											$( '.fl-bg-video-fallback' ).css( 'background-image', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)' )
615										}
616									}
617									// Manual check if video is not playable in some browsers.
618									// StateChange order: [-1, 3, -1]
619									if ( stateCount < 4 ) {
620										stateCount++;
621									}
622
623									// Comply with the audio policy in some browsers like Chrome and Safari.
624									if ( stateCount > 1 && (-1 === event.data || 2 === event.data) && "yes" === enableAudio ) {
625										player.mute();
626										player.playVideo();
627										audioButton.show();
628									}
629
630									if ( event.data === YT.PlayerState.ENDED && 1 === loop ) {
631										if ( startTime > 0 ) {
632											player.seekTo( startTime );
633										}
634										else {
635											player.playVideo();
636										}
637									}
638								},
639								onError: function(event) {
640									console.info('YT Error: ' + event.data)
641									FLBuilderLayout._onErrorYoutubeVimeo(playerWrap)
642								}
643							},
644							playerVars: {
645								playsinline: FLBuilderLayout._isMobile() ? 1 : 0,
646								controls: 0,
647								showinfo: 0,
648								rel : 0,
649								start: startTime,
650								end: endTime,
651							}
652						} );
653					}, 1 );
654				} );
655			}
656		},
657
658		/**
659		 * On youtube or vimeo error show the fallback image if available.
660		 * @since 2.0.7
661		 */
662		_onErrorYoutubeVimeo: function(playerWrap) {
663
664			fallback = playerWrap.data('fallback') || false
665			if( ! fallback ) {
666				return false;
667			}
668			playerWrap.find('iframe').remove()
669			fallbackTag = $( '<div></div>' );
670			fallbackTag.addClass( 'fl-bg-video-fallback' );
671			fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' );
672			playerWrap.append( fallbackTag );
673		},
674
675		/**
676		 * Check if Youtube API has been downloaded
677		 *
678		 * @since 1.9
679		 * @access private
680		 * @method _onYoutubeApiReady
681		 * @param  {Function} callback Method to call when YT API has been loaded
682		 */
683		_onYoutubeApiReady: function( callback ) {
684			if ( window.YT && YT.loaded ) {
685				callback( YT );
686			} else {
687				// If not ready check again by timeout..
688				setTimeout( function() {
689					FLBuilderLayout._onYoutubeApiReady( callback );
690				}, 350 );
691			}
692		},
693
694		/**
695		 * Initializes Vimeo video background
696		 *
697		 * @since 1.9
698		 * @access private
699		 * @method _initVimeoBgVideo
700		 */
701		_initVimeoBgVideo: function()
702		{
703			var playerWrap	= $(this),
704				videoId 	= playerWrap.data('video-id'),
705				videoHash 	= playerWrap.data('video-hash'),
706				videoPlayer = playerWrap.find('.fl-bg-video-player'),
707				enableAudio = playerWrap.data('enable-audio'),
708				audioButton = playerWrap.find('.fl-bg-video-audio'),
709				player,
710				width = playerWrap.outerWidth(),
711				ua    = navigator.userAgent;
712
713			if ( typeof Vimeo !== 'undefined' && videoId )	{
714				
715				const vimOptions = {
716					loop       : true,
717					title      : false,
718					portrait   : false,
719					background : true,
720					autopause  : false,
721					muted      : true,
722				};
723
724				if ( videoHash.length ) {
725					vimOptions.url = `https://player.vimeo.com/video/${ videoId }?h=${ videoHash }`;
726				} else {
727					vimOptions.id = videoId;
728				}
729
730				player = new Vimeo.Player(videoPlayer[0], vimOptions );
731				playerWrap.data('VMPlayer', player);
732				if ( "no" === enableAudio ) {
733					player.setVolume(0);
734				}
735				else if ("yes" === enableAudio ) {
736					// Chrome, Safari, Firefox have audio policy restrictions for autoplay videos.
737					if ( ua.indexOf("Safari") > -1 || ua.indexOf("Chrome") > -1 || ua.indexOf("Firefox") > -1 ) {
738						player.setVolume(0);
739						audioButton.show();
740					}
741					else {
742						player.setVolume(1);
743					}
744				}
745
746				player.play().catch(function(error) {
747					FLBuilderLayout._onErrorYoutubeVimeo(playerWrap)
748				});
749
750				if ( audioButton.length > 0 ) {
751					audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio );
752				}
753			}
754		},
755
756		/**
757		 * Mute / unmute audio on row's video background.
758		 * It works for both Youtube and Vimeo.
759		 *
760		 * @since 2.1.3
761		 * @access private
762		 * @method _toggleBgVideoAudio
763		 * @param {Object} e Method arguments
764		 */
765		_toggleBgVideoAudio: function( e ) {
766			var player  = e.data.player,
767			    control = e.data.button.find('.fl-audio-control');
768
769			if ( control.hasClass( 'fa-volume-off' ) ) {
770				// Unmute
771				control
772					.removeClass( 'fa-volume-off' )
773					.addClass( 'fa-volume-up' );
774				e.data.button.find( '.fa-times' ).hide();
775
776				if ( 'function' === typeof player.unMute ) {
777					player.unMute();
778				}
779				else {
780					player.setVolume( 1 );
781				}
782			}
783			else {
784				// Mute
785				control
786					.removeClass( 'fa-volume-up' )
787					.addClass( 'fa-volume-off' );
788				e.data.button.find( '.fa-times' ).show();
789
790				if ( 'function' === typeof player.unMute ) {
791					player.mute();
792				}
793				else {
794					player.setVolume( 0 );
795				}
796			}
797		},
798
799		/**
800		 * Fires when there is an error loading a video
801		 * background source and shows the fallback.
802		 *
803		 * @since 1.6.3.3
804		 * @access private
805		 * @method _videoBgSourceError
806		 * @param {Object} e An event object
807		 * @deprecated 2.0.3
808		 */
809		_videoBgSourceError: function( e )
810		{
811			var source 		= $( e.target ),
812				wrap   		= source.closest( '.fl-bg-video' ),
813				vid		    = wrap.find( 'video' ),
814				fallback  	= wrap.data( 'fallback' ),
815				fallbackTag = '';
816			source.remove();
817
818			if ( vid.find( 'source' ).length ) {
819				// Don't show the fallback if we still have other sources to check.
820				return;
821			} else if ( '' !== fallback ) {
822				fallbackTag = $( '<div></div>' );
823				fallbackTag.addClass( 'fl-bg-video-fallback' );
824				fallbackTag.css( 'background-image', 'url(' + fallback + ')' );
825				wrap.append( fallbackTag );
826				vid.remove();
827			}
828		},
829
830		/**
831		 * Fires when the window is resized to resize
832		 * all video backgrounds.
833		 *
834		 * @since 1.1.4
835		 * @access private
836		 * @method _resizeBgVideos
837		 */
838		_resizeBgVideos: function()
839		{
840			$('.fl-bg-video').each( function() {
841
842				FLBuilderLayout._resizeBgVideo.apply( this );
843
844				if ( $( this ).parent().find( 'img' ).length > 0 ) {
845					$( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) );
846				}
847			} );
848		},
849
850		/**
851		 * Fires when the window is resized to resize
852		 * a single video background.
853		 *
854		 * @since 1.1.4
855		 * @access private
856		 * @method _resizeBgVideo
857		 */
858		_resizeBgVideo: function()
859		{
860			if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) {
861				return;
862			}
863
864			var wrap        = $(this),
865				wrapHeight  = wrap.outerHeight(),
866				wrapWidth   = wrap.outerWidth(),
867				vid         = wrap.find('video'),
868				vidHeight   = wrap.data('height'),
869				vidWidth    = wrap.data('width'),
870				newWidth    = wrapWidth,
871				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
872				newLeft     = 0,
873				newTop      = 0,
874				iframe 		= wrap.find('iframe'),
875				isRowFullHeight = $(this).closest('.fl-row-bg-video').hasClass('fl-row-full-height'),
876				vidCSS          = {
877					top:       '50%',
878					left:      '50%',
879					transform: 'translate(-50%,-50%)',
880				};
881
882			if ( vid.length ) {
883				if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') {
884					vid.css({
885						'left'      : '0px',
886						'top'       : '0px',
887						'width'     : newWidth + 'px'
888					});
889
890					// Try to set the actual video dimension on 'loadedmetadata' when using URL as video source
891					vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta);
892
893					return;
894				}
895
896				if ( ! isRowFullHeight ) {
897					if ( newHeight < wrapHeight ) {
898						newHeight = wrapHeight;
899						newLeft   = -((newWidth - wrapWidth) / 2);
900						newWidth  = vidHeight ? Math.round(vidWidth * wrapHeight/vidHeight) : newWidth;
901					}
902					else {
903						newTop = -((newHeight - wrapHeight)/2);
904					}
905					vidCSS = {
906						left   : newLeft + 'px',
907						top    : newTop + 'px',
908						height : newHeight + 'px',
909						width  : newWidth + 'px',
910					}
911				}
912
913				vid.css( vidCSS );
914
915			}
916			else if ( iframe.length ) {
917
918				// Resize Youtube video player within iframe tag
919				if ( typeof wrap.data('youtube') !== 'undefined' ) {
920					FLBuilderLayout._resizeYoutubeBgVideo.apply(this);
921				}
922			}
923		},
924
925		/**
926		 * Fires when video meta has been loaded.
927		 * This will be Triggered when width/height attributes were not specified during video background resizing.
928		 *
929		 * @since 1.8.5
930		 * @access private
931		 * @method _resizeOnLoadedMeta
932		 */
933		_resizeOnLoadedMeta: function(){
934			var video 		= $(this),
935				wrapHeight 	= video.parent().outerHeight(),
936				wrapWidth 	= video.parent().outerWidth(),
937				vidWidth 	= video[0].videoWidth,
938				vidHeight 	= video[0].videoHeight,
939				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
940				newWidth    = wrapWidth,
941				newLeft     = 0,
942				newTop 		= 0;
943
944			if(newHeight < wrapHeight) {
945				newHeight   = wrapHeight;
946				newWidth    = Math.round(vidWidth * wrapHeight/vidHeight);
947				newLeft     = -((newWidth - wrapWidth)/2);
948			}
949			else {
950				newTop      = -((newHeight - wrapHeight)/2);
951			}
952
953			video.parent().data('width', vidWidth);
954			video.parent().data('height', vidHeight);
955
956			video.css({
957				'left'      : newLeft + 'px',
958				'top'       : newTop + 'px',
959				'width'     : newWidth + 'px',
960				'height' 	: newHeight + 'px'
961			});
962		},
963
964		/**
965		 * Fires when the window is resized to resize
966		 * a single Youtube video background.
967		 *
968		 * @since 1.9
969		 * @access private
970		 * @method _resizeYoutubeBgVideo
971		 */
972		_resizeYoutubeBgVideo: function()
973		{
974			var wrap				= $(this),
975				wrapWidth 			= wrap.outerWidth(),
976				wrapHeight 			= wrap.outerHeight(),
977				player 				= wrap.data('YTPlayer'),
978				video 				= player ? player.getIframe() : null,
979				aspectRatioSetting 	= '16:9', // Medium
980				aspectRatioArray 	= aspectRatioSetting.split( ':' ),
981				aspectRatio 		= aspectRatioArray[0] / aspectRatioArray[1],
982				ratioWidth 			= wrapWidth / aspectRatio,
983				ratioHeight 		= wrapHeight * aspectRatio,
984				isWidthFixed 		= wrapWidth / wrapHeight > aspectRatio,
985				width 				= isWidthFixed ? wrapWidth : ratioHeight,
986				height 				= isWidthFixed ? ratioWidth : wrapHeight;
987
988			if ( video ) {
989				$(video).width( width ).height( height );
990			}
991		},
992
993		/**
994		 * Opens a tab or accordion item if the browser hash is set
995		 * to the ID of one on the page.
996		 *
997		 * @since 1.6.0
998		 * @access private
999		 * @method _initHash
1000		 */
1001		_initHash: function()
1002		{
1003			var hash 			= window.location.hash.replace( '#', '' ).split( '/' ).shift(),
1004				element 		= null,
1005				tabs			= null,
1006				responsiveLabel	= null,
1007				tabIndex		= null,
1008				label			= null;
1009
1010			if ( '' !== hash ) {
1011
1012				try {
1013
1014					element = $( '#' + hash );
1015
1016					if ( element.length > 0 ) {
1017
1018						if ( element.hasClass( 'fl-accordion-item' ) ) {
1019							setTimeout( function() {
1020								element.find( '.fl-accordion-button' ).trigger( 'click' );
1021							}, 100 );
1022						}
1023						if ( element.hasClass( 'fl-tabs-panel' ) ) {
1024							setTimeout( function() {
1025								tabs 			= element.closest( '.fl-tabs' );
1026								responsiveLabel = element.find( '.fl-tabs-panel-label' );
1027								tabIndex 		= responsiveLabel.data( 'index' );
1028								label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
1029
1030								label[0].click();
1031								FLBuilderLayout._scrollToElement(element);
1032							}, 100 );
1033						}
1034					}
1035				}
1036				catch( e ) {}
1037			}
1038		},
1039
1040		/**
1041		 * Initializes all anchor links on the page for smooth scrolling.
1042		 *
1043		 * @since 1.4.9
1044		 * @access private
1045		 * @method _initAnchorLinks
1046		 */
1047		_initAnchorLinks: function()
1048		{
1049			$( 'a' ).each( FLBuilderLayout._initAnchorLink );
1050		},
1051
1052		/**
1053		 * Initializes a single anchor link for smooth scrolling.
1054		 *
1055		 * @since 1.4.9
1056		 * @access private
1057		 * @method _initAnchorLink
1058		 */
1059		_initAnchorLink: function()
1060		{
1061			var link    = $( this ),
1062				href    = link.attr( 'href' ),
1063				loc     = window.location,
1064				id      = null,
1065				element = null,
1066				flNode  = false;
1067
1068			if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 && link.closest('svg').length < 1 ) {
1069
1070				if ( loc.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && loc.hostname == this.hostname ) {
1071
1072					try {
1073
1074						id      = href.split( '#' ).pop();
1075						// If there is no ID then we have nowhere to look
1076						// Fixes a quirk in jQuery and FireFox
1077						if( ! id ) {
1078							return;
1079						}
1080						element = $( '#' + id );
1081
1082						if ( element.length > 0 ) {
1083							flNode = element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' );
1084							if ( !element.hasClass( 'fl-no-scroll' ) && ( link.hasClass( 'fl-scroll-link' ) || flNode ) ) {
1085								$( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick );
1086							}
1087							if ( element.hasClass( 'fl-accordion-item' ) ) {
1088								$( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick );
1089							}
1090							if ( element.hasClass( 'fl-tabs-panel' ) ) {
1091								$( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick );
1092							}
1093						}
1094					}
1095					catch( e ) {}
1096				}
1097			}
1098		},
1099
1100		/**
1101		 * Scrolls to an element when an anchor link is clicked.
1102		 *
1103		 * @since 1.4.9
1104		 * @access private
1105		 * @method _scrollToElementOnLinkClick
1106		 * @param {Object} e An event object.
1107		 * @param {Function} callback A function to call when the scroll is complete.
1108		 */
1109		_scrollToElementOnLinkClick: function( e, callback )
1110		{
1111			var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() );
1112
1113			FLBuilderLayout._scrollToElement( element, callback );
1114
1115			e.preventDefault();
1116		},
1117
1118		/**
1119		 * Scrolls to an element.
1120		 *
1121		 * @since 1.6.4.5
1122		 * @access private
1123		 * @method _scrollToElement
1124		 * @param {Object} element The element to scroll to.
1125		 * @param {Function} callback A function to call when the scroll is complete.
1126		 */
1127		_scrollToElement: function( element, callback )
1128		{
1129			var config  = FLBuilderLayoutConfig.anchorLinkAnimations,
1130				dest    = 0,
1131				win     = $( window ),
1132				doc     = $( document );
1133
1134			if ( element.length > 0 ) {
1135
1136				if ( 'fixed' === element.css('position') || 'fixed' === element.parent().css('position') ) {
1137					dest = element.position().top;
1138				}
1139				else if ( element.offset().top > doc.height() - win.height() ) {
1140					dest = doc.height() - win.height();
1141				}
1142				else {
1143					dest = element.offset().top - config.offset;
1144				}
1145
1146				$( 'html, body' ).stop( true ).animate( { scrollTop: dest }, config.duration, config.easing, function() {
1147
1148					if ( 'undefined' != typeof callback ) {
1149						callback();
1150					}
1151
1152					if ( undefined != element.attr( 'id' ) && window.location.hash !== '#' + element.attr( 'id' ) ) {
1153
1154						var firefox_version = window.navigator.userAgent.match( /Firefox\/(\d+)\./ ),
1155							firefox_version = firefox_version ? parseInt( firefox_version[1], 10 ) : null;
1156
1157						if ( firefox_version !== null && firefox_version < 135 ) {
1158							window.location.hash = element.attr( 'id' );
1159						} else {
1160							if ( history.pushState ) {
1161								history.pushState( null, null, '#' + element.attr( 'id' ) );
1162							} else {
1163								window.location.hash = element.attr( 'id' );
1164							}
1165						}
1166					}
1167				} );
1168			}
1169		},
1170
1171		/**
1172		 * Scrolls to an accordion item when a link is clicked.
1173		 *
1174		 * @since 1.5.9
1175		 * @access private
1176		 * @method _scrollToAccordionOnLinkClick
1177		 * @param {Object} e An event object.
1178		 */
1179		_scrollToAccordionOnLinkClick: function( e )
1180		{
1181			var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() );
1182
1183			if ( element.length > 0 ) {
1184
1185				var callback = function() {
1186					if ( element ) {
1187						element.find( '.fl-accordion-button' ).trigger( 'click' );
1188						element = false;
1189					}
1190				};
1191
1192				FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1193			}
1194		},
1195
1196		/**
1197		 * Scrolls to a tab panel when a link is clicked.
1198		 *
1199		 * @since 1.5.9
1200		 * @access private
1201		 * @method _scrollToTabOnLinkClick
1202		 * @param {Object} e An event object.
1203		 */
1204		_scrollToTabOnLinkClick: function( e )
1205		{
1206			var element 		= $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ),
1207				tabs			= null,
1208				label   		= null,
1209				responsiveLabel = null;
1210
1211			if ( element.length > 0 ) {
1212
1213				tabs 			= element.closest( '.fl-tabs' );
1214				responsiveLabel = element.find( '.fl-tabs-panel-label' );
1215				tabIndex 		= responsiveLabel.data( 'index' );
1216				label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
1217
1218				if ( responsiveLabel.is( ':visible' ) ) {
1219
1220					var callback = function() {
1221						if ( element ) {
1222							responsiveLabel.trigger( $.Event( 'click', { which: 1 } ) );
1223						}
1224					};
1225
1226					FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1227				}
1228				else {
1229					label[0].click();
1230					FLBuilderLayout._scrollToElement( element );
1231				}
1232
1233				e.preventDefault();
1234			}
1235		},
1236
1237		/**
1238		 * Initializes all builder forms on a page.
1239		 *
1240		 * @since 1.5.4
1241		 * @access private
1242		 * @method _initForms
1243		 */
1244		_initForms: function()
1245		{
1246			if ( ! FLBuilderLayout._hasPlaceholderSupport ) {
1247				$( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback );
1248			}
1249
1250			$( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError );
1251		},
1252
1253		/**
1254		 * Checks to see if the current device has HTML5
1255		 * placeholder support.
1256		 *
1257		 * @since 1.5.4
1258		 * @access private
1259		 * @method _hasPlaceholderSupport
1260		 * @return {Boolean}
1261		 */
1262		_hasPlaceholderSupport: function()
1263		{
1264			var input = document.createElement( 'input' );
1265
1266			return 'undefined' != input.placeholder;
1267		},
1268
1269		/**
1270		 * Initializes the fallback for when placeholders aren't supported.
1271		 *
1272		 * @since 1.5.4
1273		 * @access private
1274		 * @method _initFormFieldPlaceholderFallback
1275		 */
1276		_initFormFieldPlaceholderFallback: function()
1277		{
1278			var field       = $( this ),
1279				val         = field.val(),
1280				placeholder = field.attr( 'placeholder' );
1281
1282			if ( 'undefined' != placeholder && '' === val ) {
1283				field.val( placeholder );
1284				field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback );
1285				field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback );
1286			}
1287		},
1288
1289		/**
1290		 * Hides a fallback placeholder on focus.
1291		 *
1292		 * @since 1.5.4
1293		 * @access private
1294		 * @method _hideFormFieldPlaceholderFallback
1295		 */
1296		_hideFormFieldPlaceholderFallback: function()
1297		{
1298			var field       = $( this ),
1299				val         = field.val(),
1300				placeholder = field.attr( 'placeholder' );
1301
1302			if ( val == placeholder ) {
1303				field.val( '' );
1304			}
1305		},
1306
1307		/**
1308		 * Shows a fallback placeholder on blur.
1309		 *
1310		 * @since 1.5.4
1311		 * @access private
1312		 * @method _showFormFieldPlaceholderFallback
1313		 */
1314		_showFormFieldPlaceholderFallback: function()
1315		{
1316			var field       = $( this ),
1317				val         = field.val(),
1318				placeholder = field.attr( 'placeholder' );
1319
1320			if ( '' === val ) {
1321				field.val( placeholder );
1322			}
1323		},
1324
1325		/**
1326		 * Clears a form field error message.
1327		 *
1328		 * @since 1.5.4
1329		 * @access private
1330		 * @method _clearFormFieldError
1331		 */
1332		_clearFormFieldError: function()
1333		{
1334			var field = $( this );
1335
1336			field.removeClass( 'fl-form-error' );
1337			field.siblings( '.fl-form-error-message' ).hide();
1338		},
1339
1340		/**
1341		 * Init Row Shape Layer's height.
1342		 *
1343		 * @since 2.5.3
1344		 * @access private
1345		 * @method _initRowShapeLayerHeight
1346		 */
1347		_initRowShapeLayerHeight: function () {
1348			FLBuilderLayout._adjustRowShapeLayerHeight();
1349			$( window ).on( 'resize', FLBuilderLayout._adjustRowShapeLayerHeight );
1350		},
1351
1352		/**
1353		 * Set parent column width of nested columns when it's zero or blank.
1354		 *
1355		 * @since 2.7.4
1356		 * @access private
1357		 * @method _initNestedColsWidth
1358		 */
1359		_initNestedColsWidth: function()
1360		{
1361			var nestedCols = $( '.fl-col-has-cols' );
1362
1363			if ( nestedCols.length <= 0 ) {
1364				return;
1365			}
1366
1367			$( nestedCols ).each( function(index, col ){
1368				if ( $( col ).width() <= 0 ) {
1369					$( col ).css( 'width', FLBuilderLayoutConfig.emptyColWidth );
1370				}
1371			});
1372		},
1373
1374		/**
1375		 * Adjust Row Shape Layer's height to fix to remove the fine line that appears on certain screen sizes.
1376		 *
1377		 * @since 2.5.3
1378		 * @access private
1379		 * @method _adjustRowShapeLayerHeight
1380		 */
1381		_adjustRowShapeLayerHeight: function() {
1382			var rowShapeLayers = $('.fl-builder-shape-layer');
1383
1384			$( rowShapeLayers ).each(function (index) {
1385				var rowShapeLayer = $(this),
1386					shape = $(rowShapeLayer).find('svg'),
1387					height = shape.height(),
1388					excludeShapes = '.fl-builder-shape-circle, .fl-builder-shape-dot-cluster, .fl-builder-shape-topography, .fl-builder-shape-rect';
1389
1390				if ( ! rowShapeLayer.is( excludeShapes ) ) {
1391					$(shape).css('height', Math.ceil( height ) );
1392				}
1393			});
1394		},
1395		_string_to_slug: function( str ) {
1396			str = str.replace(/^\s+|\s+$/g, ''); // trim
1397			if ( 'undefined' == typeof window._fl_string_to_slug_regex ) {
1398				regex = new RegExp('[^a-zA-Z0-9\'":() !.,-_|]', 'g');
1399			} else {
1400				regex = new RegExp('[^' + window._fl_string_to_slug_regex + '\'":\(\) !.,-_|\\\p{Letter}]', 'ug');
1401			}
1402			str = str.replace(regex, '') // remove invalid chars
1403				.replace(/\s+/g, ' '); // collapse whitespace and replace by a space
1404			return str;
1405		},
1406		_reorderMenu: function() {
1407			if ( $('#wp-admin-bar-fl-builder-frontend-edit-link-default li').length > 1 ) {
1408					$( '#wp-admin-bar-fl-builder-frontend-duplicate-link' )
1409					.appendTo('#wp-admin-bar-fl-builder-frontend-edit-link-default')
1410					.css( 'padding-top', '5px' )
1411					.css( 'border-top', '2px solid #1D2125' )
1412					.css( 'margin-top', '5px' )
1413				}
1414		}
1415	};
1416
1417	/* Initializes the builder layout. */
1418	$(function(){
1419		FLBuilderLayout.init();
1420	});
1421
1422})(jQuery);
1423(function($){
1424
1425	if(typeof FLBuilderLayoutModules !== 'undefined') {
1426		return;
1427	}
1428
1429	/**
1430	 * Helper class with generic logic for builder modules.
1431	 * If generic module code needs to work in both the block
1432	 * editor and builder, it should go here. Otherwise, it
1433	 * should go on FLBuilderLayout.
1434	 *
1435	 * @since 2.9
1436	 */
1437	FLBuilderLayoutModules = {
1438
1439		/**
1440		 * Initializes builder module logic.
1441		 *
1442		 * @since 2.9
1443		 * @method init
1444		 */
1445		init: function()
1446		{
1447			// Only init if the builder isn't active.
1448			if ( 0 === $('.fl-builder-edit').length ) {
1449
1450				// Init module animations.
1451				FLBuilderLayoutModules._initModuleAnimations();
1452			}
1453		},
1454
1455		/**
1456		 * Initializes module animations.
1457		 *
1458		 * @since 1.1.9
1459		 * @access private
1460		 * @method _initModuleAnimations
1461		 */
1462		_initModuleAnimations: function()
1463		{
1464			if(typeof jQuery.fn.waypoint !== 'undefined') {
1465				$('.fl-animation').each( function() {
1466					var node = $( this ),
1467						nodeTop = node.offset().top,
1468						winHeight = $( window ).height(),
1469						bodyHeight = $( 'body' ).height(),
1470						waypoint = FLBuilderLayoutConfig.waypoint,
1471						offset = '80%';
1472
1473					if ( typeof waypoint.offset !== undefined ) {
1474						offset = FLBuilderLayoutConfig.waypoint.offset + '%';
1475					}
1476
1477					if ( bodyHeight - nodeTop < winHeight * 0.2 ) {
1478						offset = '100%';
1479					}
1480
1481					node.waypoint({
1482						offset: offset,
1483						handler: FLBuilderLayoutModules._doModuleAnimation
1484					});
1485				} );
1486			}
1487		},
1488
1489		/**
1490		 * Runs a module animation.
1491		 *
1492		 * @since 1.1.9
1493		 * @access private
1494		 * @method _doModuleAnimation
1495		 */
1496		_doModuleAnimation: function()
1497		{
1498			var module = 'undefined' == typeof this.element ? $(this) : $(this.element),
1499				delay = parseFloat(module.data('animation-delay')),
1500				duration = parseFloat(module.data('animation-duration'));
1501
1502			if ( ! isNaN( duration ) ) {
1503				module.css( 'animation-duration', duration + 's' );
1504			}
1505
1506			if(!isNaN(delay) && delay > 0) {
1507				setTimeout(function(){
1508					module.addClass('fl-animated');
1509				}, delay * 1000);
1510			} else {
1511				setTimeout(function(){
1512					module.addClass('fl-animated');
1513				}, 1);
1514			}
1515		}
1516	};
1517
1518	/* Initializes builder module logic. */
1519	$(function(){
1520		FLBuilderLayoutModules.init();
1521	});
1522
1523})(jQuery);
1524
1525/* Start Global JS */
1526
1527/* End Global JS */
1528
1529
1530/* Start Global Node Custom JS */
1531
1532/* End Global Node Custom JS */
1533
1534
1535/* Start Layout Custom JS */
1536
1537/* End Layout Custom JS */
1538

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.