PageSourceSearch

https://starsapphire-oto.org/wp-content/uploads/bb-plugin/cache/10…?ver=687ea46c195f71140f5085eebe1547f2

js starsapphire-oto.org collected 2026-10-06 20:04:10 UTC 29,339 bytes, 1,166 lines download raw bytes

1var wpAjaxUrl = 'https://starsapphire-oto.org/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://starsapphire-oto.org/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = {
2	anchorLinkAnimations : {
3		duration 	: 1000,
4		easing		: 'swing',
5		offset 		: 100
6	},
7	paths : {
8		pluginUrl : 'https://starsapphire-oto.org/wp-content/plugins/bb-plugin/',
9		wpAjaxUrl : 'https://starsapphire-oto.org/wp-admin/admin-ajax.php'
10	},
11	breakpoints : {
12		small  : 768,
13		medium : 992	},
14	waypoint: {
15		offset: 80
16	}
17};(function($){
18
19	if(typeof FLBuilderLayout != 'undefined') {
20		return;
21	}
22	
23	/**
24	 * Helper class with generic logic for a builder layout.
25	 *
26	 * @class FLBuilderLayout
27	 * @since 1.0
28	 */
29	FLBuilderLayout = {
30		
31		/**
32		 * Initializes a builder layout.
33		 *
34		 * @since 1.0
35		 * @method init
36		 */ 
37		init: function()
38		{
39			// Destroy existing layout events.
40			FLBuilderLayout._destroy();
41			
42			// Init CSS classes.
43			FLBuilderLayout._initClasses();
44			
45			// Init backgrounds.
46			FLBuilderLayout._initBackgrounds();
47			
48			// Only init if the builder isn't active. 
49			if ( 0 === $('.fl-builder-edit').length ) {
50				
51				// Init anchor links.
52				FLBuilderLayout._initAnchorLinks();
53				
54				// Init the browser hash.
55				FLBuilderLayout._initHash();
56			
57				// Init module animations.
58				FLBuilderLayout._initModuleAnimations();
59				
60				// Init forms.
61				FLBuilderLayout._initForms();
62			}
63		},
64		
65		/**
66		 * Public method for refreshing Wookmark or MosaicFlow galleries
67		 * within an element.
68		 *
69		 * @since 1.7.4
70		 * @method refreshGalleries
71		 */ 
72		refreshGalleries: function( element )
73		{
74			var $element  = 'undefined' == typeof element ? $( 'body' ) : $( element ),
75				mfContent = $element.find( '.fl-mosaicflow-content' ),
76				wmContent = $element.find( '.fl-gallery' ),
77				mfObject  = null;
78			
79			if ( mfContent ) {
80				
81				mfObject = mfContent.data( 'mosaicflow' );
82				
83				if ( mfObject ) {
84					mfObject.columns = $( [] );
85					mfObject.columnsHeights = [];
86					mfContent.data( 'mosaicflow', mfObject );
87					mfContent.mosaicflow( 'refill' );
88				}
89			}
90			if ( wmContent ) {
91				wmContent.trigger( 'refreshWookmark' );
92			}
93		},
94
95		/**
96		 * Public method for refreshing Masonry within an element
97		 *
98		 * @since 1.8.1
99		 * @method refreshGridLayout
100		 */
101		refreshGridLayout: function( element )
102		{
103			var $element 		= 'undefined' == typeof element ? $( 'body' ) : $( element ),
104				msnryContent	= $element.find('.masonry');
105
106			if ( msnryContent.length )	{
107				msnryContent.masonry('layout');
108			}
109		},
110
111		/**
112		 * Public method for reloading BxSlider within an element
113		 *
114		 * @since 1.8.1
115		 * @method reloadSlider
116		 */
117		reloadSlider: function( element )
118		{
119			var $element 	= 'undefined' == typeof element ? $( 'body' ) : $( element ),
120				bxContent	= $element.find('.bx-viewport .fl-post-carousel-wrapper'),
121				bxObject   	= null;
122				
123			if ( bxContent.length ) {
124				bxContent.each(function(){
125					bxObject = $(this).data( 'bxSlider');
126					if ( bxObject ) {
127						bxObject.reloadSlider();
128					}					
129				})
130				
131			}
132		},
133
134		/**
135		 * Public method for resizing WP audio player
136		 *
137		 * @since 1.8.2
138		 * @method resizeAudio
139		 */
140		resizeAudio: function( element )
141		{
142			var $element 	 	= 'undefined' == typeof element ? $( 'body' ) : $( element ),
143				audioPlayers 	= $element.find('.wp-audio-shortcode.mejs-audio'),
144				player 		 	= null,
145				mejsPlayer 	 	= null,
146				rail 			= null,
147				railWidth 		= 400;
148				
149			if ( audioPlayers.length && typeof mejs !== 'undefined' ) {
150            	audioPlayers.each(function(){
151	            	player 		= $(this);
152	            	mejsPlayer 	= mejs.players[player.attr('id')];
153	            	rail 		= player.find('.mejs-controls .mejs-time-rail');
154	            	var innerMejs = player.find('.mejs-inner'),
155	            		total 	  = player.find('.mejs-controls .mejs-time-total');
156	            	
157	            	if ( typeof mejsPlayer !== 'undefined' ) {
158	            		railWidth = Math.ceil(player.width() * 0.8);
159
160	            		if ( innerMejs.length ) {
161
162		            		rail.css('width', railWidth +'px!important');
163		            		//total.width(rail.width() - 10);
164		            		
165		            		mejsPlayer.options.autosizeProgress = true;
166
167		            		// webkit has trouble doing this without a delay
168							setTimeout(function () {
169								mejsPlayer.setControlsSize();
170							}, 50);
171
172			            	player.find('.mejs-inner').css({
173			            		visibility: 'visible',
174			            		height: 'inherit'
175			            	});
176		            	} 
177		           	}
178	            });
179	        }
180		},
181
182		/**
183		 * Public method for preloading WP audio player when it's inside the hidden element
184		 *
185		 * @since 1.8.2
186		 * @method preloadAudio
187		 */
188		preloadAudio: function(element)
189		{
190			var $element 	 = 'undefined' == typeof element ? $( 'body' ) : $( element ),
191				contentWrap  = $element.closest('.fl-accordion-item'),
192				audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio');
193			
194			if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) {
195				audioPlayers.find('.mejs-inner').css({
196					visibility : 'hidden',
197					height: 0
198				});	
199			}			
200		},
201
202		/**
203		 * Unbinds builder layout events.
204		 *
205		 * @since 1.0
206		 * @access private
207		 * @method _destroy
208		 */ 
209		_destroy: function()
210		{
211			var win = $(window);
212			
213			win.off('scroll.fl-bg-parallax');
214			win.off('resize.fl-bg-video');
215		},
216		
217		/**
218		 * Checks to see if the current device has touch enabled.
219		 *
220		 * @since 1.0
221		 * @access private
222		 * @method _isTouch
223		 * @return {Boolean}
224		 */ 
225		_isTouch: function()
226		{
227			if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) {
228				return true;
229			}
230			
231			return false;
232		},
233		
234		/**
235		 * Checks to see if the current device is mobile.
236		 *
237		 * @since 1.7
238		 * @access private
239		 * @method _isMobile
240		 * @return {Boolean}
241		 */ 
242		_isMobile: function()
243		{
244			return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent );
245		},
246		
247		/**
248		 * Initializes builder body classes.
249		 *
250		 * @since 1.0
251		 * @access private
252		 * @method _initClasses
253		 */ 
254		_initClasses: function()
255		{
256			var body = $( 'body' ),
257				ua   = navigator.userAgent;
258			
259			// Add the builder body class.
260			if ( ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) {
261				body.addClass('fl-builder');
262			}
263			
264			// Add the builder touch body class.
265			if(FLBuilderLayout._isTouch()) {
266				body.addClass('fl-builder-touch');
267			}
268			
269			// Add the builder mobile body class.
270			if(FLBuilderLayout._isMobile()) {
271				body.addClass('fl-builder-mobile');
272			}
273			
274			// IE11 body class.
275			if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) {
276				body.addClass( 'fl-builder-ie-11' );
277			}
278		},
279		
280		/**
281		 * Initializes builder node backgrounds that require
282		 * additional JavaScript logic such as parallax.
283		 *
284		 * @since 1.1.4
285		 * @access private
286		 * @method _initBackgrounds
287		 */ 
288		_initBackgrounds: function()
289		{
290			var win = $(window);
291			
292			// Init parallax backgrounds.
293			if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) {
294				FLBuilderLayout._scrollParallaxBackgrounds();
295				FLBuilderLayout._initParallaxBackgrounds();
296				win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds);
297			}
298			
299			// Init video backgrounds.
300			if($('.fl-bg-video').length > 0) {
301				FLBuilderLayout._initBgVideos();
302				FLBuilderLayout._resizeBgVideos();
303				win.on('resize.fl-bg-video', FLBuilderLayout._resizeBgVideos);
304			}
305		},
306		
307		/**
308		 * Initializes all parallax backgrounds in a layout.
309		 *
310		 * @since 1.1.4
311		 * @access private
312		 * @method _initParallaxBackgrounds
313		 */ 
314		_initParallaxBackgrounds: function()
315		{
316			$('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground);
317		},
318		
319		/**
320		 * Initializes a single parallax background.
321		 *
322		 * @since 1.1.4
323		 * @access private
324		 * @method _initParallaxBackgrounds
325		 */ 
326		_initParallaxBackground: function()
327		{
328			var row     = $(this),
329				content = row.find('> .fl-row-content-wrap'),
330				src     = row.data('parallax-image'),
331				loaded  = row.data('parallax-loaded'),
332				img     = new Image();
333			
334			if(loaded) {
335				return;
336			}
337			else if(typeof src != 'undefined') {
338			 
339				$(img).on('load', function() {
340					content.css('background-image', 'url(' + src + ')');
341					row.data('parallax-loaded', true);
342				});
343				
344				img.src = src;
345			}
346		},
347		
348		/**
349		 * Fires when the window is scrolled to adjust
350		 * parallax backgrounds.
351		 *
352		 * @since 1.1.4
353		 * @access private
354		 * @method _scrollParallaxBackgrounds
355		 */ 
356		_scrollParallaxBackgrounds: function()
357		{
358			$('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground);
359		},
360		
361		/**
362		 * Fires when the window is scrolled to adjust
363		 * a single parallax background.
364		 *
365		 * @since 1.1.4
366		 * @access private
367		 * @method _scrollParallaxBackground
368		 */ 
369		_scrollParallaxBackground: function()
370		{
371			var win     = $(window),
372				row     = $(this),
373				content = row.find('> .fl-row-content-wrap'),
374				speed   = row.data('parallax-speed'),
375				offset  = content.offset(),
376				yPos    = -((win.scrollTop() - offset.top) / speed);
377				
378			content.css('background-position', 'center ' + yPos + 'px');
379		},
380		
381		/**
382		 * Initializes all video backgrounds.
383		 *
384		 * @since 1.6.3.3
385		 * @access private
386		 * @method _initBgVideos
387		 */ 
388		_initBgVideos: function()
389		{
390			$('.fl-bg-video').each(FLBuilderLayout._initBgVideo);
391		},
392		
393		/**
394		 * Initializes a video background.
395		 *
396		 * @since 1.6.3.3
397		 * @access private
398		 * @method _initBgVideo
399		 */ 
400		_initBgVideo: function()
401		{
402			var wrap 		= $( this ),
403				width  		= wrap.data( 'width' ),
404				height  	= wrap.data( 'height' ),
405				mp4  		= wrap.data( 'mp4' ),
406				youtube 	= wrap.data( 'youtube'),	
407				vimeo 		= wrap.data( 'vimeo'),
408				mp4Type  	= wrap.data( 'mp4-type' ),
409				webm  		= wrap.data( 'webm' ),
410				webmType  	= wrap.data( 'webm-type' ),
411				fallback  	= wrap.data( 'fallback' ),
412				loaded  	= wrap.data( 'loaded' ),
413				fallbackTag = '',
414				videoTag	= null,
415				mp4Tag    	= null,
416				webmTag    	= null;	
417				
418			// Return if the video has been loaded for this row.
419			if ( loaded ) {
420				return;
421			}
422			// Append the video tag for non-mobile.
423			else if ( ! FLBuilderLayout._isMobile() ) {
424				
425				videoTag  = $( '<video autoplay loop muted preload></video>' );
426				
427				// MP4 Source Tag
428				if ( 'undefined' != typeof mp4 ) {
429					
430					mp4Tag = $( '<source />' );
431					mp4Tag.attr( 'src', mp4 );
432					mp4Tag.attr( 'type', mp4Type );
433					
434					if ( 'undefined' == typeof webm ) {
435						mp4Tag.on( 'error', FLBuilderLayout._videoBgSourceError );
436					}
437					
438					videoTag.append( mp4Tag );
439				}
440				
441				// WebM Source Tag
442				if ( 'undefined' != typeof webm ) {
443					
444					webmTag = $( '<source />' );
445					webmTag.attr( 'src', webm );
446					webmTag.attr( 'type', webmType );
447					
448					if ( 'undefined' != typeof mp4 ) {
449						webmTag.on( 'error', FLBuilderLayout._videoBgSourceError );
450					}
451					
452					videoTag.append( webmTag );
453				}
454				
455				// Check what video player we are going to load in a row
456				if ( 'undefined' != typeof youtube ) {
457					FLBuilderLayout._initYoutubeBgVideo.apply( this );	
458				} 
459				else if ( 'undefined' != typeof vimeo ) {
460					FLBuilderLayout._initVimeoBgVideo.apply( this );
461				}
462				else {
463					wrap.append( videoTag );
464				}
465			}
466			// Append the fallback tag for mobile.
467			else if ( '' !== fallback ) {
468				fallbackTag = $( '<div></div>' );
469				fallbackTag.addClass( 'fl-bg-video-fallback' );
470				fallbackTag.css( 'background-image', 'url(' + fallback + ')' );
471				wrap.append( fallbackTag );
472			}
473			
474			// Mark this video as loaded.
475			wrap.data('loaded', true);
476		},
477
478		/**
479		 * Initializes Youtube video background
480		 *
481		 * @since 1.9
482		 * @access private
483		 * @method _initYoutubeBgVideo
484		 */
485		_initYoutubeBgVideo: function()
486		{
487			var playerWrap	= $(this),
488				videoId 	= playerWrap.data('video-id'),
489				videoPlayer = playerWrap.find('.fl-bg-video-player'),
490				enableAudio = playerWrap.data('enable-audio'),
491				player;
492
493			if ( videoId ) {
494
495				FLBuilderLayout._onYoutubeApiReady( function( YT ) {
496					setTimeout( function() {
497
498						player = new YT.Player( videoPlayer[0], {
499							videoId: videoId,
500							events: {
501								onReady: function(event) {
502									if ( "no" === enableAudio ) {
503										event.target.mute();
504									}
505									else if ("yes" === enableAudio && event.target.isMuted ) {
506										event.target.unMute();	
507									}
508									
509									// Store an instance to a parent
510									playerWrap.data('YTPlayer', player);
511									FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap);
512
513									event.target.playVideo();									
514								},
515								onStateChange: function( event ) {
516									if ( event.data === YT.PlayerState.ENDED ) {
517										player.seekTo( 0 );
518									}
519								}
520							},
521							playerVars: {
522								controls: 0,
523								showinfo: 0
524							}
525						} );
526					}, 1 );
527				} );
528			}
529		},
530
531		/**
532		 * Check if Youtube API has been downloaded
533		 *
534		 * @since 1.9
535		 * @access private
536		 * @method _onYoutubeApiReady
537		 * @param  {Function} callback Method to call when YT API has been loaded
538		 */
539		_onYoutubeApiReady: function( callback ) {
540			if ( window.YT && YT.loaded ) {
541				callback( YT );
542			} else {
543				// If not ready check again by timeout..
544				setTimeout( function() {
545					FLBuilderLayout._onYoutubeApiReady( callback );
546				}, 350 );
547			}
548		},
549
550		/**
551		 * Initializes Vimeo video background
552		 *
553		 * @since 1.9
554		 * @access private
555		 * @method _initVimeoBgVideo
556		 */
557		_initVimeoBgVideo: function()
558		{
559			var playerWrap	= $(this),
560				videoId 	= playerWrap.data('video-id'),
561				videoPlayer = playerWrap.find('.fl-bg-video-player'),
562				enableAudio = playerWrap.data('enable-audio'),
563				player,
564				width = playerWrap.outerWidth();
565
566			if ( typeof Vimeo !== 'undefined' && videoId )	{
567				player = new Vimeo.Player(videoPlayer[0], {
568					id: videoId,
569			        loop: true,
570			        title: false,
571			        portrait: false
572				});
573
574				playerWrap.data('VMPlayer', player);
575				if ( "no" === enableAudio ) {
576					player.setVolume(0);
577				}
578				else if ("yes" === enableAudio ) {
579					player.setVolume(1);
580				}
581				
582				player.play();
583			}
584		},
585		
586		/**
587		 * Fires when there is an error loading a video 
588		 * background source and shows the fallback.
589		 *
590		 * @since 1.6.3.3
591		 * @access private
592		 * @method _videoBgSourceError
593		 * @param {Object} e An event object.
594		 */ 
595		_videoBgSourceError: function( e )
596		{
597			var source 		= $( e.target ),
598				wrap   		= source.closest( '.fl-bg-video' ),
599				vid		    = wrap.find( 'video' ),
600				fallback  	= wrap.data( 'fallback' ),
601				fallbackTag = '';
602				
603			if ( '' !== fallback ) {
604				fallbackTag = $( '<div></div>' );
605				fallbackTag.addClass( 'fl-bg-video-fallback' );
606				fallbackTag.css( 'background-image', 'url(' + fallback + ')' );
607				wrap.append( fallbackTag );
608				vid.remove();
609			}
610		},
611		
612		/**
613		 * Fires when the window is resized to resize
614		 * all video backgrounds.
615		 *
616		 * @since 1.1.4
617		 * @access private
618		 * @method _resizeBgVideos
619		 */ 
620		_resizeBgVideos: function()
621		{
622			$('.fl-bg-video').each( function() {
623				
624				FLBuilderLayout._resizeBgVideo.apply( this );
625				
626				if ( $( this ).parent().find( 'img' ).length > 0 ) {
627					$( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) );
628				}
629			} );
630		},
631		
632		/**
633		 * Fires when the window is resized to resize
634		 * a single video background.
635		 *
636		 * @since 1.1.4
637		 * @access private
638		 * @method _resizeBgVideo
639		 */ 
640		_resizeBgVideo: function()
641		{
642			if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) {
643				return;
644			}
645			
646			var wrap        = $(this),
647				wrapHeight  = wrap.outerHeight(),
648				wrapWidth   = wrap.outerWidth(),
649				vid         = wrap.find('video'),
650				vidHeight   = wrap.data('height'),
651				vidWidth    = wrap.data('width'),
652				newWidth    = wrapWidth,
653				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
654				newLeft     = 0,
655				newTop      = 0,
656				iframe 		= wrap.find('iframe');
657			
658			if ( vid.length ) {
659				if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') {
660					vid.css({
661						'left'      : '0px',
662						'top'       : '0px',
663						'width'     : newWidth + 'px'
664					});
665
666					// Try to set the actual video dimension on 'loadedmetadata' when using URL as video source
667					vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta);
668
669				}
670				else {
671					
672					if(newHeight < wrapHeight) {
673						newHeight   = wrapHeight;
674						newWidth    = Math.round(vidWidth * wrapHeight/vidHeight);  
675						newLeft     = -((newWidth - wrapWidth)/2);
676					}
677					else {
678						newTop      = -((newHeight - wrapHeight)/2);
679					}
680					
681					vid.css({
682						'left'      : newLeft + 'px',
683						'top'       : newTop + 'px',
684						'height'    : newHeight + 'px',
685						'width'     : newWidth + 'px'
686					});
687				}
688			}
689			else if ( iframe.length ) {
690
691				// Resize Youtube video player within iframe tag
692				if ( typeof wrap.data('youtube') !== 'undefined' ) {
693					FLBuilderLayout._resizeYoutubeBgVideo.apply(this);	
694				}				
695			}
696		},
697
698		/**
699		 * Fires when video meta has been loaded. 
700		 * This will be Triggered when width/height attributes were not specified during video background resizing.
701		 *
702		 * @since 1.8.5
703		 * @access private
704		 * @method _resizeOnLoadedMeta
705		 */
706		_resizeOnLoadedMeta: function(){
707			var video 		= $(this),
708				wrapHeight 	= video.parent().outerHeight(),
709				wrapWidth 	= video.parent().outerWidth(),
710				vidWidth 	= video[0].videoWidth,
711				vidHeight 	= video[0].videoHeight,
712				newHeight   = Math.round(vidHeight * wrapWidth/vidWidth),
713				newTop 		= 0;
714
715			if(newHeight < wrapHeight) {
716				newHeight   = wrapHeight;
717				newWidth    = Math.round(vidWidth * wrapHeight/vidHeight);  
718				newLeft     = -((newWidth - wrapWidth)/2);
719			}
720			else {
721				newTop      = -((newHeight - wrapHeight)/2);
722			}
723
724			video.parent().data('width', vidWidth);
725			video.parent().data('height', vidHeight);
726
727			video.css({
728				'left'      : newLeft + 'px',
729				'top'       : newTop + 'px',
730				'width'     : newWidth + 'px',
731				'height' 	: newHeight + 'px'
732			});
733		},
734
735		/**
736		 * Fires when the window is resized to resize
737		 * a single Youtube video background.
738		 *
739		 * @since 1.9
740		 * @access private
741		 * @method _resizeYoutubeBgVideo
742		 */
743		_resizeYoutubeBgVideo: function()
744		{
745			var wrap				= $(this),
746				wrapWidth 			= wrap.outerWidth(),
747				wrapHeight 			= wrap.outerHeight(),
748				player 				= wrap.data('YTPlayer'),
749				video 				= player ? player.getIframe() : null,
750				aspectRatioSetting 	= '16:9', // Medium
751				aspectRatioArray 	= aspectRatioSetting.split( ':' ),
752				aspectRatio 		= aspectRatioArray[0] / aspectRatioArray[1],
753				ratioWidth 			= wrapWidth / aspectRatio,
754				ratioHeight 		= wrapHeight * aspectRatio,
755				isWidthFixed 		= wrapWidth / wrapHeight > aspectRatio,
756				width 				= isWidthFixed ? wrapWidth : ratioHeight,
757				height 				= isWidthFixed ? ratioWidth : wrapHeight;
758
759			if ( video ) {
760				$(video).width( width ).height( height );
761			}
762		},
763
764		/**
765		 * Initializes module animations.
766		 *
767		 * @since 1.1.9
768		 * @access private
769		 * @method _initModuleAnimations
770		 */ 
771		_initModuleAnimations: function()
772		{
773			if(typeof jQuery.fn.waypoint !== 'undefined' && !FLBuilderLayout._isMobile()) {
774				$('.fl-animation').each( function() {
775					var node = $( this ),
776						nodeTop = node.offset().top,
777						winHeight = $( window ).height(),
778						bodyHeight = $( 'body' ).height(),
779						offset = '80%';
780						
781					if ( bodyHeight - nodeTop < winHeight * 0.2 ) {
782						offset = '100%';
783					}
784					
785					node.waypoint({
786						offset: offset,
787						handler: FLBuilderLayout._doModuleAnimation
788					});
789				} );
790			}
791		},
792		
793		/**
794		 * Runs a module animation.
795		 *
796		 * @since 1.1.9
797		 * @access private
798		 * @method _doModuleAnimation
799		 */ 
800		_doModuleAnimation: function()
801		{
802			var module = 'undefined' == typeof this.element ? $(this) : $(this.element),
803				delay  = parseFloat(module.data('animation-delay'));
804			
805			if(!isNaN(delay) && delay > 0) {
806				setTimeout(function(){
807					module.addClass('fl-animated');
808				}, delay * 1000);
809			}
810			else {
811				module.addClass('fl-animated');
812			}
813		},
814		
815		/**
816		 * Opens a tab or accordion item if the browser hash is set
817		 * to the ID of one on the page.
818		 *
819		 * @since 1.6.0
820		 * @access private
821		 * @method _initHash
822		 */ 
823		_initHash: function()
824		{
825			var hash 			= window.location.hash.replace( '#', '' ).split( '/' ).shift(),
826				element 		= null,
827				tabs			= null,
828				responsiveLabel	= null,
829				tabIndex		= null,
830				label			= null;
831			
832			if ( '' !== hash ) {
833				
834				try {
835				
836					element = $( '#' + hash );
837						
838					if ( element.length > 0 ) {
839						
840						if ( element.hasClass( 'fl-accordion-item' ) ) {
841							setTimeout( function() {
842								element.find( '.fl-accordion-button' ).trigger( 'click' );
843							}, 100 );
844						}
845						if ( element.hasClass( 'fl-tabs-panel' ) ) {
846							
847							setTimeout( function() {
848								
849								tabs 			= element.closest( '.fl-tabs' );
850								responsiveLabel = element.find( '.fl-tabs-panel-label' );
851								tabIndex 		= responsiveLabel.data( 'index' );
852								label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
853							
854								if ( responsiveLabel.is( ':visible' ) ) {
855									responsiveLabel.trigger( 'click' );	
856								}
857								else {									
858									label[0].click();
859									FLBuilderLayout._scrollToElement( element );
860								}
861								
862							}, 100 );
863						}
864					}
865				}
866				catch( e ) {}
867			}
868		},
869		
870		/**
871		 * Initializes all anchor links on the page for smooth scrolling.
872		 *
873		 * @since 1.4.9
874		 * @access private
875		 * @method _doModuleAnimation
876		 */ 
877		_initAnchorLinks: function()
878		{
879			$( 'a' ).each( FLBuilderLayout._initAnchorLink );
880		},
881		
882		/**
883		 * Initializes a single anchor link for smooth scrolling.
884		 *
885		 * @since 1.4.9
886		 * @access private
887		 * @method _doModuleAnimation
888		 */ 
889		_initAnchorLink: function()
890		{
891			var link    = $( this ),
892				href    = link.attr( 'href' ),
893				loc     = window.location,
894				id      = null,
895				element = null;
896
897			if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 ) {
898
899				if ( loc.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && loc.hostname == this.hostname ) {
900
901					try {
902
903						id      = href.split( '#' ).pop();
904						// If there is no ID then we have nowhere to look
905						// Fixes a quirk in jQuery and FireFox
906						if( ! id ) {
907							return;
908						}
909						element = $( '#' + id );
910
911						if ( element.length > 0 ) {
912							if ( link.hasClass( 'fl-scroll-link' ) || element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' ) ) {
913								$( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick );
914							}
915							if ( element.hasClass( 'fl-accordion-item' ) ) {
916								$( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick );
917							}
918							if ( element.hasClass( 'fl-tabs-panel' ) ) {
919								$( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick );
920							}
921						}
922					}
923					catch( e ) {}
924				}
925			}
926		},
927		
928		/**
929		 * Scrolls to an element when an anchor link is clicked.
930		 *
931		 * @since 1.4.9
932		 * @access private
933		 * @method _scrollToElementOnLinkClick
934		 * @param {Object} e An event object.
935		 * @param {Function} callback A function to call when the scroll is complete.
936		 */ 
937		_scrollToElementOnLinkClick: function( e, callback )
938		{
939			var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() );
940				
941			FLBuilderLayout._scrollToElement( element, callback );
942				
943			e.preventDefault();
944		},
945		
946		/**
947		 * Scrolls to an element.
948		 *
949		 * @since 1.6.4.5
950		 * @access private
951		 * @method _scrollToElement
952		 * @param {Object} element The element to scroll to.
953		 * @param {Function} callback A function to call when the scroll is complete.
954		 */ 
955		_scrollToElement: function( element, callback )
956		{
957			var config  = FLBuilderLayoutConfig.anchorLinkAnimations,
958				dest    = 0,
959				win     = $( window ),
960				doc     = $( document );
961				
962			if ( element.length > 0 ) {
963			
964				if ( element.offset().top > doc.height() - win.height() ) {
965					dest = doc.height() - win.height();
966				} 
967				else {
968					dest = element.offset().top - config.offset;
969				}
970	
971				$( 'html, body' ).animate( { scrollTop: dest }, config.duration, config.easing, function() {
972					
973					if ( 'undefined' != typeof callback ) {
974						callback();
975					}
976					
977					if ( undefined != element.attr( 'id' ) ) {
978						
979						if ( history.pushState ) {
980							history.pushState( null, null, '#' + element.attr( 'id' ) );
981						}
982						else {
983							window.location.hash = element.attr( 'id' );
984						}
985					}
986				} );
987			}
988		},
989		
990		/**
991		 * Scrolls to an accordion item when a link is clicked.
992		 *
993		 * @since 1.5.9
994		 * @access private
995		 * @method _scrollToAccordionOnLinkClick
996		 * @param {Object} e An event object.
997		 */ 
998		_scrollToAccordionOnLinkClick: function( e )
999		{
1000			var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() );
1001				
1002			if ( element.length > 0 ) {
1003			
1004				var callback = function() {
1005					if ( element ) {
1006						element.find( '.fl-accordion-button' ).trigger( 'click' );	
1007						element = false;
1008					}
1009				};
1010				
1011				FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1012			}
1013		},
1014		
1015		/**
1016		 * Scrolls to a tab panel when a link is clicked.
1017		 *
1018		 * @since 1.5.9
1019		 * @access private
1020		 * @method _scrollToTabOnLinkClick
1021		 * @param {Object} e An event object.
1022		 */ 
1023		_scrollToTabOnLinkClick: function( e )
1024		{
1025			var element 		= $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ),
1026				tabs			= null,
1027				label   		= null,
1028				responsiveLabel = null;
1029				
1030			if ( element.length > 0 ) {
1031				
1032				tabs 			= element.closest( '.fl-tabs' );
1033				responsiveLabel = element.find( '.fl-tabs-panel-label' );
1034				tabIndex 		= responsiveLabel.data( 'index' );
1035				label 			= tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' );
1036			
1037				if ( responsiveLabel.is( ':visible' ) ) {
1038					
1039					var callback = function() {
1040						if ( element ) {
1041							responsiveLabel.trigger( 'click' );	
1042							element = false;
1043						}
1044					};
1045					
1046					FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback );
1047				}
1048				else {
1049					label[0].click();
1050					FLBuilderLayout._scrollToElement( element );
1051				}
1052				
1053				e.preventDefault();
1054			}
1055		},
1056		
1057		/**
1058		 * Initializes all builder forms on a page.
1059		 *
1060		 * @since 1.5.4
1061		 * @access private
1062		 * @method _initForms
1063		 */ 
1064		_initForms: function()
1065		{
1066			if ( ! FLBuilderLayout._hasPlaceholderSupport ) {
1067				$( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback );
1068			}
1069			
1070			$( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError );
1071		},
1072		
1073		/**
1074		 * Checks to see if the current device has HTML5
1075		 * placeholder support.
1076		 *
1077		 * @since 1.5.4
1078		 * @access private
1079		 * @method _hasPlaceholderSupport
1080		 * @return {Boolean}
1081		 */ 
1082		_hasPlaceholderSupport: function()
1083		{
1084			var input = document.createElement( 'input' );
1085			
1086			return 'undefined' != input.placeholder;
1087		},
1088		
1089		/**
1090		 * Initializes the fallback for when placeholders aren't supported.
1091		 *
1092		 * @since 1.5.4
1093		 * @access private
1094		 * @method _initFormFieldPlaceholderFallback
1095		 */ 
1096		_initFormFieldPlaceholderFallback: function()
1097		{
1098			var field       = $( this ),
1099				val         = field.val(),
1100				placeholder = field.attr( 'placeholder' );
1101			
1102			if ( 'undefined' != placeholder && '' === val ) {
1103				field.val( placeholder );
1104				field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback );
1105				field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback );
1106			}
1107		},
1108		
1109		/**
1110		 * Hides a fallback placeholder on focus.
1111		 *
1112		 * @since 1.5.4
1113		 * @access private
1114		 * @method _hideFormFieldPlaceholderFallback
1115		 */ 
1116		_hideFormFieldPlaceholderFallback: function()
1117		{
1118			var field       = $( this ),
1119				val         = field.val(),
1120				placeholder = field.attr( 'placeholder' );
1121			
1122			if ( val == placeholder ) {
1123				field.val( '' );
1124			}
1125		},
1126		
1127		/**
1128		 * Shows a fallback placeholder on blur.
1129		 *
1130		 * @since 1.5.4
1131		 * @access private
1132		 * @method _showFormFieldPlaceholderFallback
1133		 */ 
1134		_showFormFieldPlaceholderFallback: function()
1135		{
1136			var field       = $( this ),
1137				val         = field.val(),
1138				placeholder = field.attr( 'placeholder' );
1139			
1140			if ( '' === val ) {
1141				field.val( placeholder );
1142			}
1143		},
1144		
1145		/**
1146		 * Clears a form field error message.
1147		 *
1148		 * @since 1.5.4
1149		 * @access private
1150		 * @method _clearFormFieldError
1151		 */ 
1152		_clearFormFieldError: function()
1153		{
1154			var field = $( this );
1155			
1156			field.removeClass( 'fl-form-error' );
1157			field.siblings( '.fl-form-error-message' ).hide();
1158		}
1159	};
1160
1161	/* Initializes the builder layout. */
1162	$(function(){
1163		FLBuilderLayout.init();
1164	});
1165
1166})(jQuery);

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.