PageSourceSearch

http://www.aytorasines.org/wp-content/plugins/jet-elements/assets/js/jet-elements.js?ver=1.15.4

js aytorasines.org collected 2026-10-02 20:24:59 UTC 79,940 bytes, 2,926 lines download raw bytes

1( function( $, elementor ) {
2
3	"use strict";
4
5	var JetElements = {
6
7		init: function() {
8
9			var widgets = {
10				'jet-carousel.default' : JetElements.widgetCarousel,
11				'jet-circle-progress.default' : JetElements.widgetProgress,
12				'jet-map.default' : JetElements.widgetMap,
13				'jet-countdown-timer.default' : JetElements.widgetCountdown,
14				'jet-posts.default' : JetElements.widgetPosts,
15				'jet-animated-text.default' : JetElements.widgetAnimatedText,
16				'jet-animated-box.default' : JetElements.widgetAnimatedBox,
17				'jet-images-layout.default' : JetElements.widgetImagesLayout,
18				'jet-slider.default' : JetElements.widgetSlider,
19				'jet-testimonials.default' : JetElements.widgetTestimonials,
20				'jet-image-comparison.default' : JetElements.widgetImageComparison,
21				'jet-instagram-gallery.default' : JetElements.widgetInstagramGallery,
22				'jet-scroll-navigation.default' : JetElements.widgetScrollNavigation,
23				'jet-subscribe-form.default' : JetElements.widgetSubscribeForm,
24				'jet-progress-bar.default' : JetElements.widgetProgressBar,
25				'jet-portfolio.default' : JetElements.widgetPortfolio,
26				'jet-timeline.default': JetElements.widgetTimeLine,
27				'jet-table.default': JetElements.widgetTable,
28				'jet-dropbar.default': JetElements.widgetDropbar,
29				'jet-video.default': JetElements.widgetVideo,
30				'jet-audio.default': JetElements.widgetAudio,
31				'jet-horizontal-timeline.default': JetElements.widgetHorizontalTimeline,
32				'mp-timetable.default': JetElements.widgetTimeTable,
33				'jet-pie-chart.default': JetElements.widgetPieChart
34			};
35
36			$.each( widgets, function( widget, callback ) {
37				elementor.hooks.addAction( 'frontend/element_ready/' + widget, callback );
38			});
39
40			elementor.hooks.addAction( 'frontend/element_ready/section', JetElements.elementorSection );
41		},
42
43		widgetCountdown: function( $scope ) {
44
45			var timeInterval,
46				$coutdown = $scope.find( '[data-due-date]' ),
47				endTime = new Date( $coutdown.data( 'due-date' ) * 1000 ),
48				elements = {
49					days: $coutdown.find( '[data-value="days"]' ),
50					hours: $coutdown.find( '[data-value="hours"]' ),
51					minutes: $coutdown.find( '[data-value="minutes"]' ),
52					seconds: $coutdown.find( '[data-value="seconds"]' )
53				};
54
55			JetElements.widgetCountdown.updateClock = function() {
56
57				var timeRemaining = JetElements.widgetCountdown.getTimeRemaining( endTime );
58
59				$.each( timeRemaining.parts, function( timePart ) {
60
61					var $element = elements[ timePart ];
62
63					if ( $element.length ) {
64						$element.html( this );
65					}
66
67				} );
68
69				if ( timeRemaining.total <= 0 ) {
70					clearInterval( timeInterval );
71				}
72			};
73
74			JetElements.widgetCountdown.initClock = function() {
75				JetElements.widgetCountdown.updateClock();
76				timeInterval = setInterval( JetElements.widgetCountdown.updateClock, 1000 );
77			};
78
79			JetElements.widgetCountdown.splitNum = function( num ) {
80
81				var num   = num.toString(),
82					arr   = [],
83					reult = '';
84
85				if ( 1 === num.length ) {
86					num = 0 + num;
87				}
88
89				arr = num.match(/\d{1}/g);
90
91				$.each( arr, function( index, val ) {
92					reult += '<span class="jet-countdown-timer__digit">' + val + '</span>';
93				});
94
95				return reult;
96			};
97
98			JetElements.widgetCountdown.getTimeRemaining = function( endTime ) {
99
100				var timeRemaining = endTime - new Date(),
101					seconds = Math.floor( ( timeRemaining / 1000 ) % 60 ),
102					minutes = Math.floor( ( timeRemaining / 1000 / 60 ) % 60 ),
103					hours = Math.floor( ( timeRemaining / ( 1000 * 60 * 60 ) ) % 24 ),
104					days = Math.floor( timeRemaining / ( 1000 * 60 * 60 * 24 ) );
105
106				if ( days < 0 || hours < 0 || minutes < 0 ) {
107					seconds = minutes = hours = days = 0;
108				}
109
110				return {
111					total: timeRemaining,
112					parts: {
113						days: JetElements.widgetCountdown.splitNum( days ),
114						hours: JetElements.widgetCountdown.splitNum( hours ),
115						minutes: JetElements.widgetCountdown.splitNum( minutes ),
116						seconds: JetElements.widgetCountdown.splitNum( seconds )
117					}
118				};
119			};
120
121			JetElements.widgetCountdown.initClock();
122
123		},
124
125		widgetMap: function( $scope ) {
126
127			var $container = $scope.find( '.jet-map' ),
128				map,
129				init,
130				pins;
131
132			if ( ! window.google || ! $container.length ) {
133				return;
134			}
135
136			init = $container.data( 'init' );
137			pins = $container.data( 'pins' );
138			map  = new google.maps.Map( $container[0], init );
139
140			if ( pins ) {
141				$.each( pins, function( index, pin ) {
142
143					var marker,
144						infowindow,
145						pinData = {
146							position: pin.position,
147							map: map
148						};
149
150					if ( '' !== pin.image ) {
151						pinData.icon = pin.image;
152					}
153
154					marker = new google.maps.Marker( pinData );
155
156					if ( '' !== pin.desc ) {
157						infowindow = new google.maps.InfoWindow({
158							content: pin.desc,
159							disableAutoPan: true
160						});
161					}
162
163					marker.addListener( 'click', function() {
164						infowindow.setOptions({ disableAutoPan: false });
165						infowindow.open( map, marker );
166					});
167
168					if ( 'visible' === pin.state && '' !== pin.desc ) {
169						infowindow.open( map, marker );
170					}
171
172				});
173			}
174
175		},
176
177		widgetProgress: function( $scope ) {
178
179			var $progress = $scope.find( '.circle-progress' );
180
181			if ( ! $progress.length ) {
182				return;
183			}
184
185			var $value            = $progress.find( '.circle-progress__value' ),
186				$meter            = $progress.find( '.circle-progress__meter' ),
187				percent           = parseInt( $value.data( 'value' ) ),
188				progress          = percent / 100,
189				duration          = $scope.find( '.circle-progress-wrap' ).data( 'duration' ),
190				responsiveSizes   = $progress.data( 'responsive-sizes' ),
191				desktopSizes      = responsiveSizes.desktop,
192				tabletSizes       = responsiveSizes.tablet,
193				mobileSizes       = responsiveSizes.mobile,
194				currentDeviceMode = elementorFrontend.getCurrentDeviceMode(),
195				prevDeviceMode    = currentDeviceMode,
196				isAnimatedCircle  = false;
197
198			if ( 'tablet' === currentDeviceMode ) {
199				updateSvgSizes( tabletSizes.size, tabletSizes.viewBox, tabletSizes.center, tabletSizes.radius, tabletSizes.valStroke, tabletSizes.bgStroke, tabletSizes.circumference );
200			}
201
202			if ( 'mobile' === currentDeviceMode ) {
203				updateSvgSizes( mobileSizes.size, mobileSizes.viewBox, mobileSizes.center, mobileSizes.radius, mobileSizes.valStroke, mobileSizes.bgStroke, mobileSizes.circumference );
204			}
205
206			elementorFrontend.waypoint( $scope, function() {
207
208				// animate counter
209				var $number = $scope.find( '.circle-counter__number' ),
210					data = $number.data();
211
212				var decimalDigits = data.toValue.toString().match( /\.(.*)/ );
213
214				if ( decimalDigits ) {
215					data.rounding = decimalDigits[1].length;
216				}
217
218				data.duration = duration;
219
220				$number.numerator( data );
221
222				// animate progress
223				var circumference = parseInt( $progress.data( 'circumference' ) ),
224					dashoffset    = circumference * (1 - progress);
225
226				$value.css({
227					'transitionDuration': duration + 'ms',
228					'strokeDashoffset': dashoffset
229				});
230
231				isAnimatedCircle = true;
232
233			}, {
234				offset: 'bottom-in-view'
235			} );
236
237			$( window ).on( 'resize.jetCircleProgress orientationchange.jetCircleProgress', circleResizeHandler );
238
239			function circleResizeHandler( event ) {
240				currentDeviceMode = elementorFrontend.getCurrentDeviceMode();
241
242				if ( 'desktop' === currentDeviceMode && 'desktop' !== prevDeviceMode ) {
243					updateSvgSizes( desktopSizes.size, desktopSizes.viewBox, desktopSizes.center, desktopSizes.radius, desktopSizes.valStroke, desktopSizes.bgStroke, desktopSizes.circumference );
244					prevDeviceMode = 'desktop';
245				}
246
247				if ( 'tablet' === currentDeviceMode && 'tablet' !== prevDeviceMode ) {
248					updateSvgSizes( tabletSizes.size, tabletSizes.viewBox, tabletSizes.center, tabletSizes.radius, tabletSizes.valStroke, tabletSizes.bgStroke, tabletSizes.circumference );
249					prevDeviceMode = 'tablet';
250				}
251
252				if ( 'mobile' === currentDeviceMode && 'mobile' !== prevDeviceMode ) {
253					updateSvgSizes( mobileSizes.size, mobileSizes.viewBox, mobileSizes.center, mobileSizes.radius, mobileSizes.valStroke, mobileSizes.bgStroke, mobileSizes.circumference );
254					prevDeviceMode = 'mobile';
255				}
256			}
257
258			function updateSvgSizes( size, viewBox, center, radius, valStroke, bgStroke, circumference ) {
259				var dashoffset = circumference * (1 - progress);
260
261				$progress.attr( {
262					'width': size,
263					'height': size,
264					'data-radius': radius,
265					'data-circumference': circumference
266				} );
267
268				$progress[0].setAttribute( 'viewBox', viewBox );
269
270				$meter.attr( {
271					'cx': center,
272					'cy': center,
273					'r': radius,
274					'stroke-width': bgStroke
275				} );
276
277				if ( isAnimatedCircle ) {
278					$value.css( {
279						'transitionDuration': ''
280					} );
281				}
282
283				$value.attr( {
284					'cx': center,
285					'cy': center,
286					'r': radius,
287					'stroke-width': valStroke
288				} );
289
290				$value.css( {
291					'strokeDasharray': circumference,
292					'strokeDashoffset': isAnimatedCircle ? dashoffset : circumference
293				} );
294			}
295		},
296
297		widgetCarousel: function( $scope ) {
298
299			var $carousel = $scope.find( '.jet-carousel' );
300
301			if ( ! $carousel.length ) {
302				return;
303			}
304
305			JetElements.initCarousel( $carousel, $carousel.data( 'slider_options' ) );
306
307		},
308
309		widgetPosts: function ( $scope ) {
310
311			var $target = $scope.find( '.jet-carousel' );
312
313			if ( ! $target.length ) {
314				return;
315			}
316
317			JetElements.initCarousel( $target.find( '.jet-posts' ), $target.data( 'slider_options' ) );
318
319		},
320
321		widgetAnimatedText: function( $scope ) {
322			var $target = $scope.find( '.jet-animated-text' ),
323				instance = null,
324				settings = {};
325
326			if ( ! $target.length ) {
327				return;
328			}
329
330			settings = $target.data( 'settings' );
331			instance = new jetAnimatedText( $target, settings );
332			instance.init();
333		},
334
335		widgetAnimatedBox: function( $scope ) {
336
337			JetElements.onAnimatedBoxSectionActivated( $scope );
338
339			var $target      = $scope.find( '.jet-animated-box' ),
340				toogleEvents = 'mouseenter mouseleave',
341				scrollOffset = $( window ).scrollTop(),
342				firstMouseEvent = true;
343
344			if ( ! $target.length ) {
345				return;
346			}
347
348			if ( 'ontouchend' in window || 'ontouchstart' in window ) {
349				$target.on( 'touchstart', function( event ) {
350					scrollOffset = $( window ).scrollTop();
351				} );
352
353				$target.on( 'touchend', function( event ) {
354
355					if ( scrollOffset !== $( window ).scrollTop() ) {
356						return false;
357					}
358
359					if ( ! $( this ).hasClass( 'flipped-stop' ) ) {
360						$( this ).toggleClass( 'flipped' );
361					}
362				} );
363
364			} else {
365				$target.on( toogleEvents, function( event ) {
366
367					if ( firstMouseEvent && 'mouseleave' === event.type ) {
368						return;
369					}
370
371					if ( firstMouseEvent && 'mouseenter' === event.type ) {
372						firstMouseEvent = false;
373					}
374
375					if ( ! $( this ).hasClass( 'flipped-stop' ) ) {
376						$( this ).toggleClass( 'flipped' );
377					}
378				} );
379			}
380		},
381
382		onAnimatedBoxSectionActivated: function( $scope ) {
383			if ( ! window.elementor ) {
384				return;
385			}
386
387			if ( ! window.JetElementsEditor ) {
388				return;
389			}
390
391			if ( ! window.JetElementsEditor.activeSection ) {
392				return;
393			}
394
395			var section = window.JetElementsEditor.activeSection;
396			var isBackSide = -1 !== [ 'section_back_content', 'section_action_button_style' ].indexOf( section );
397
398			if ( isBackSide ) {
399				$scope.find( '.jet-animated-box' ).addClass( 'flipped' );
400				$scope.find( '.jet-animated-box' ).addClass( 'flipped-stop' );
401			} else {
402				$scope.find( '.jet-animated-box' ).removeClass( 'flipped' );
403				$scope.find( '.jet-animated-box' ).removeClass( 'flipped-stop' );
404			}
405		},
406
407		widgetImagesLayout: function( $scope ) {
408			var $target = $scope.find( '.jet-images-layout' ),
409				instance = null,
410				settings = {};
411
412			if ( ! $target.length ) {
413				return;
414			}
415
416			settings = $target.data( 'settings' );
417			instance = new jetImagesLayout( $target, settings );
418			instance.init();
419		},
420
421		widgetPortfolio: function( $scope ) {
422			var $target = $scope.find( '.jet-portfolio' ),
423				instance = null,
424				settings = {};
425
426			if ( ! $target.length ) {
427				return;
428			}
429
430			settings = $target.data( 'settings' );
431			instance = new jetPortfolio( $target, settings );
432			instance.init();
433		},
434
435		widgetInstagramGallery: function( $scope ) {
436			var $target         = $scope.find( '.jet-instagram-gallery__instance' ),
437				instance        = null,
438				defaultSettings = {},
439				settings        = {};
440
441			if ( ! $target.length ) {
442				return;
443			}
444
445			settings = $target.data( 'settings' ),
446
447			/*
448			 * Default Settings
449			 */
450			defaultSettings = {
451				layoutType: 'masonry',
452				columns: 3,
453				columnsTablet: 2,
454				columnsMobile: 1,
455			}
456
457			/**
458			 * Checking options, settings and options merging
459			 */
460			$.extend( defaultSettings, settings );
461
462			if ( 'masonry' === settings.layoutType ) {
463				salvattore.init();
464			}
465
466		},
467
468		widgetScrollNavigation: function( $scope ) {
469			var $target         = $scope.find( '.jet-scroll-navigation' ),
470				instance        = null,
471				settings        = $target.data( 'settings' );
472
473			instance = new jetScrollNavigation( $target, settings );
474			instance.init();
475		},
476
477		widgetSubscribeForm: function( $scope ) {
478			var $target               = $scope.find( '.jet-subscribe-form' ),
479				scoreId               = $scope.data( 'id' ),
480				settings              = $target.data( 'settings' ),
481				jetSubscribeFormAjax  = null,
482				subscribeFormAjaxId   = 'jet_subscribe_form_ajax',
483				$subscribeForm        = $( '.jet-subscribe-form__form', $target ),
484				$fields               = $( '.jet-subscribe-form__fields', $target ),
485				$mailField            = $( '.jet-subscribe-form__mail-field', $target ),
486				$inputData            = $mailField.data( 'instance-data' ),
487				$submitButton         = $( '.jet-subscribe-form__submit', $target ),
488				$subscribeFormMessage = $( '.jet-subscribe-form__message', $target ),
489				timeout               = null,
490				invalidMailMessage    = window.jetElements.messages.invalidMail || 'Please specify a valid email';
491
492			jetSubscribeFormAjax = new CherryJsCore.CherryAjaxHandler({
493				handlerId: subscribeFormAjaxId,
494
495				successCallback: function( data ) {
496					var successType   = data.type,
497						message       = data.message || '',
498						responceClass = 'jet-subscribe-form--response-' + successType;
499
500					$submitButton.removeClass( 'loading' );
501
502					$target.removeClass( 'jet-subscribe-form--response-error' );
503					$target.addClass( responceClass );
504
505					$( 'span', $subscribeFormMessage ).html( message );
506					$subscribeFormMessage.css( { 'visibility': 'visible' } );
507
508					timeout = setTimeout( function() {
509						$subscribeFormMessage.css( { 'visibility': 'hidden' } );
510						$target.removeClass( responceClass );
511					}, 20000 );
512
513					if ( settings['redirect'] ) {
514						window.location.href = settings['redirect_url'];
515					}
516
517					$( window ).trigger( {
518						type: 'jet-elements/subscribe',
519						elementId: scoreId,
520						successType: successType,
521						inputData: $inputData
522					} );
523				}
524			});
525
526			$mailField.on( 'focus', function() {
527				$mailField.removeClass( 'mail-invalid' );
528			} );
529
530			$( document ).keydown( function( event ) {
531
532				if ( 13 === event.keyCode && $mailField.is( ':focus' ) ) {
533					subscribeHandle();
534
535					return false;
536				}
537			} );
538
539			$submitButton.on( 'click', function() {
540				subscribeHandle();
541
542				return false;
543			} );
544
545			function subscribeHandle() {
546				var inputValue     = $mailField.val(),
547					sendData       = {
548						'email': inputValue,
549						'use_target_list_id': settings['use_target_list_id'] || false,
550						'target_list_id': settings['target_list_id'] || '',
551						'data': $inputData
552					},
553					serializeArray = $subscribeForm.serializeArray(),
554					additionalFields = {};
555
556				if ( JetElementsTools.validateEmail( inputValue ) ) {
557
558					$.each( serializeArray, function( key, fieldData ) {
559
560						if ( 'email' === fieldData.name ) {
561							sendData[ fieldData.name ] = fieldData.value;
562						} else {
563							additionalFields[ fieldData.name ] = fieldData.value;
564						}
565					} );
566
567					sendData['additional'] = additionalFields;
568
569					jetSubscribeFormAjax.sendData( sendData );
570
571					$submitButton.addClass( 'loading' );
572				} else {
573					$mailField.addClass( 'mail-invalid' );
574
575					$target.addClass( 'jet-subscribe-form--response-error' );
576					$( 'span', $subscribeFormMessage ).html( invalidMailMessage );
577					$subscribeFormMessage.css( { 'visibility': 'visible' } );
578
579					timeout = setTimeout( function() {
580						$target.removeClass( 'jet-subscribe-form--response-error' );
581						$subscribeFormMessage.css( { 'visibility': 'hidden' } );
582						$mailField.removeClass( 'mail-invalid' );
583					}, 20000 );
584				}
585			}
586		},
587
588		widgetProgressBar: function( $scope ) {
589			var $target      = $scope.find( '.jet-progress-bar' ),
590				percent      = $target.data( 'percent' ),
591				type         = $target.data( 'type' ),
592				deltaPercent = percent * 0.01;
593
594			elementorFrontend.waypoint( $target, function( direction ) {
595				var $this       = $( this ),
596					animeObject = { charged: 0 },
597					$statusBar  = $( '.jet-progress-bar__status-bar', $this ),
598					$percent    = $( '.jet-progress-bar__percent-value', $this ),
599					animeProgress,
600					animePercent;
601
602				if ( 'type-7' == type ) {
603					$statusBar.css( {
604						'height': percent + '%'
605					} );
606				} else {
607					$statusBar.css( {
608						'width': percent + '%'
609					} );
610				}
611
612				animePercent = anime({
613					targets: animeObject,
614					charged: percent,
615					round: 1,
616					duration: 1000,
617					easing: 'easeInOutQuad',
618					update: function() {
619						$percent.html( animeObject.charged );
620					}
621				});
622
623			} );
624		},
625
626		widgetSlider: function( $scope ) {
627			var $target        = $scope.find( '.jet-slider' ),
628				$imagesTagList = $( '.sp-image', $target ),
629				instance       = null,
630				defaultSettings = {
631					imageScaleMode: 'cover',
632					slideDistance: { size: 10, unit: 'px' },
633					slideDuration: 500,
634					sliderAutoplay: true,
635					sliderAutoplayDelay: 2000,
636					sliderAutoplayOnHover: 'pause',
637					sliderFadeMode: false,
638					sliderFullScreen: true,
639					sliderFullscreenIcon: 'fa fa-arrows-alt',
640					sliderHeight: { size: 600, unit: 'px' },
641					sliderHeightTablet: { size: 400, unit: 'px' },
642					sliderHeightMobile: { size: 300, unit: 'px' },
643					sliderLoop: true,
644					sliderNaviOnHover: false,
645					sliderNavigation: true,
646					sliderNavigationIcon: 'fa fa-angle-left',
647					sliderPagination: false,
648					sliderShuffle: false,
649					sliderWidth: { size: 100, unit: '%' },
650					thumbnailWidth: 120,
651					thumbnailHeight: 80,
652					thumbnails: true,
653					rightToLeft: false,
654				},
655				instanceSettings = $target.data( 'settings' ) || {},
656				settings        = $.extend( {}, defaultSettings, instanceSettings );
657
658			if ( ! $target.length ) {
659				return;
660			}
661
662			$target.imagesLoaded().progress( function( instance, image ) {
663				var loadedImages = null,
664					progressBarWidth = null;
665
666				if ( image.isLoaded ) {
667
668					if ( $( image.img ).hasClass( 'sp-image' ) ) {
669						$( image.img ).addClass( 'image-loaded' );
670					}
671
672					loadedImages = $( '.image-loaded', $target );
673					progressBarWidth = 100 * ( loadedImages.length / $imagesTagList.length ) + '%';
674
675					$( '.jet-slider-loader', $target ).css( { width: progressBarWidth } );
676				}
677
678			} ).done( function( instance ) {
679
680				$( '.slider-pro', $target ).addClass( 'slider-loaded' );
681				$( '.jet-slider-loader', $target ).css( { 'display': 'none' } );
682			} );
683
684			var tabletHeight = '' !== settings['sliderHeightTablet']['size'] ? settings['sliderHeightTablet']['size'] + settings['sliderHeightTablet']['unit'] : settings['sliderHeight']['size'] + settings['sliderHeight']['unit'];
685			var mobileHeight = '' !== settings['sliderHeightMobile']['size'] ? settings['sliderHeightMobile']['size'] + settings['sliderHeightMobile']['unit'] : settings['sliderHeight']['size'] + settings['sliderHeight']['unit'];
686
687			$( '.slider-pro', $target ).sliderPro( {
688				width: settings['sliderWidth']['size'] + settings['sliderWidth']['unit'],
689				height: settings['sliderHeight']['size'] + settings['sliderHeight']['unit'],
690				arrows: settings['sliderNavigation'],
691				fadeArrows: settings['sliderNaviOnHover'],
692				buttons: settings['sliderPagination'],
693				autoplay: settings['sliderAutoplay'],
694				autoplayDelay: settings['sliderAutoplayDelay'],
695				autoplayOnHover: settings['sliderAutoplayOnHover'],
696				fullScreen: settings['sliderFullScreen'],
697				shuffle: settings['sliderShuffle'],
698				loop: settings['sliderLoop'],
699				fade: settings['sliderFadeMode'],
700				slideDistance: ( 'string' !== typeof settings['slideDistance']['size'] ) ? settings['slideDistance']['size'] : 0,
701				slideAnimationDuration: +settings['slideDuration'],
702				//imageScaleMode: settings['imageScaleMode'],
703				imageScaleMode: 'exact',
704				waitForLayers: false,
705				grabCursor: false,
706				thumbnailWidth: settings['thumbnailWidth'],
707				thumbnailHeight: settings['thumbnailHeight'],
708				rightToLeft: settings['rightToLeft'],
709				init: function() {
710					this.resize();
711
712					$( '.sp-previous-arrow', $target ).append( '<i class="' + settings['sliderNavigationIcon'] + '"></i>' );
713					$( '.sp-next-arrow', $target ).append( '<i class="' + settings['sliderNavigationIcon'] + '"></i>' );
714
715					$( '.sp-full-screen-button', $target ).append( '<i class="' + settings['sliderFullscreenIcon'] + '"></i>' );
716				},
717				breakpoints: {
718					1023: {
719						height: tabletHeight
720					},
721					767: {
722						height: mobileHeight
723					}
724				}
725			} );
726		},
727
728		widgetTestimonials: function( $scope ) {
729			var $target        = $scope.find( '.jet-testimonials__instance' ),
730				$imagesTagList = $( '.jet-testimonials__figure', $target ),
731				instance       = null,
732				settings       = $target.data( 'settings' );
733
734			if ( ! $target.length ) {
735				return;
736			}
737
738			settings.adaptiveHeight = settings['adaptiveHeight'];
739
740			JetElements.initCarousel( $target, settings );
741		},
742
743		widgetImageComparison: function( $scope ) {
744			var $target              = $scope.find( '.jet-image-comparison__instance' ),
745				instance             = null,
746				imageComparisonItems = $( '.jet-image-comparison__container', $target ),
747				settings             = $target.data( 'settings' ),
748				elementId            = $scope.data( 'id' );
749
750			if ( ! $target.length ) {
751				return;
752			}
753
754			window.juxtapose.scanPage( '.jet-juxtapose' );
755
756			settings.draggable = false;
757			settings.infinite = false;
758			//settings.adaptiveHeight = true;
759			JetElements.initCarousel( $target, settings );
760		},
761
762		widgetTimeTable: function( $scope ) {
763
764			var $mptt_shortcode_wrapper = $scope.find( '.mptt-shortcode-wrapper' );
765
766			if ( ( typeof typenow ) !== 'undefined' ) {
767				if ( pagenow === typenow ) {
768					switch ( typenow ) {
769
770						case 'mp-event':
771							Registry._get( 'Event' ).init();
772							break;
773
774						case 'mp-column':
775							Registry._get( 'Event' ).initDatePicker();
776							Registry._get( 'Event' ).columnRadioBox();
777							break;
778
779						default:
780							break;
781					}
782				}
783			}
784
785			if ( $mptt_shortcode_wrapper.length ) {
786
787				Registry._get( 'Event' ).initTableData();
788				Registry._get( 'Event' ).filterShortcodeEvents();
789				Registry._get( 'Event' ).getFilterByHash();
790
791				$mptt_shortcode_wrapper.show();
792			}
793
794			if ( $( '.upcoming-events-widget' ).length || $mptt_shortcode_wrapper.length ) {
795				Registry._get( 'Event' ).setColorSettings();
796			}
797		},
798
799		elementorSection: function( $scope ) {
800			var $target   = $scope,
801				instance  = null,
802				editMode  = Boolean( elementor.isEditMode() );
803
804			instance = new jetSectionParallax( $target );
805			instance.init();
806		},
807
808		initCarousel: function( $target, options ) {
809
810			var tabletSlides, mobileSlides, defaultOptions, slickOptions;
811
812			if ( options.slidesToShow.tablet ) {
813				tabletSlides = options.slidesToShow.tablet;
814			} else {
815				tabletSlides = 1 === options.slidesToShow.desktop ? 1 : 2;
816			}
817
818			if ( options.slidesToShow.mobile ) {
819				mobileSlides = options.slidesToShow.mobile;
820			} else {
821				mobileSlides = 1;
822			}
823
824			options.slidesToShow = options.slidesToShow.desktop;
825
826			defaultOptions = {
827				customPaging: function(slider, i) {
828					return $( '<span />' ).text( i + 1 );
829				},
830				dotsClass: 'jet-slick-dots',
831				responsive: [
832					{
833						breakpoint: 1025,
834						settings: {
835							slidesToShow: tabletSlides,
836						}
837					},
838					{
839						breakpoint: 768,
840						settings: {
841							slidesToShow: mobileSlides,
842							slidesToScroll: 1
843						}
844					}
845				]
846			};
847
848			slickOptions = $.extend( {}, defaultOptions, options );
849
850			$target.slick( slickOptions );
851		},
852
853		widgetTimeLine : function ( $scope ){
854			var $target = $scope.find( '.jet-timeline' ),
855				instance = null;
856
857			if ( ! $target.length ) {
858				return;
859			}
860
861			instance = new jetTimeLine( $target );
862			instance.init();
863		},
864
865		widgetTable: function( $scope ) {
866			var $target = $scope.find( '.jet-table' ),
867				options = {
868					cssHeader: 'jet-table-header-sort',
869					cssAsc: 'jet-table-header-sort--up',
870					cssDesc: 'jet-table-header-sort--down',
871					initWidgets: false
872				};
873
874			if ( ! $target.length ) {
875				return;
876			}
877
878			if ( $target.hasClass( 'jet-table--sorting' ) ) {
879				$target.tablesorter( options );
880			}
881		},
882
883		widgetDropbar: function( $scope ) {
884			var $dropbar       = $scope.find( '.jet-dropbar' ),
885				$dropbar_inner = $dropbar.find( '.jet-dropbar__inner' ),
886				$btn           = $dropbar.find( '.jet-dropbar__button' ),
887				$content       = $dropbar.find( '.jet-dropbar__content' ),
888				settings       = $dropbar.data( 'settings' ) || {},
889				mode           = settings['mode'] || 'hover',
890				hide_delay     = +settings['hide_delay'] || 0,
891				activeClass    = 'jet-dropbar-open',
892				scrollOffset,
893				timer;
894
895			if ( 'click' === mode ) {
896				$btn.on( 'click.jetDropbar', function( event ) {
897					$dropbar.toggleClass( activeClass );
898				} );
899			} else {
900				if ( 'ontouchstart' in window || 'ontouchend' in window ) {
901					$btn.on( 'touchend.jetDropbar', function( event ) {
902						if ( $( window ).scrollTop() !== scrollOffset ) {
903							return;
904						}
905
906						$dropbar.toggleClass( activeClass );
907					} );
908				} else {
909					$dropbar_inner.on( 'mouseenter.jetDropbar', function( event ) {
910						clearTimeout( timer );
911						$dropbar.addClass( activeClass );
912					} );
913
914					$dropbar_inner.on( 'mouseleave.jetDropbar', function( event ) {
915						timer = setTimeout( function() {
916							$dropbar.removeClass( activeClass );
917						}, hide_delay );
918					} );
919				}
920			}
921
922			$( document ).on( 'touchstart.jetDropbar', function( event ) {
923				scrollOffset = $( window ).scrollTop();
924			} );
925
926			$( document ).on( 'click.jetDropbar touchend.jetDropbar', function( event ) {
927
928				if ( 'touchend' === event.type && $( window ).scrollTop() !== scrollOffset ) {
929					return;
930				}
931
932				if ( $( event.target ).closest( $btn ).length || $( event.target ).closest( $content ).length ) {
933					return;
934				}
935
936				if ( ! $dropbar.hasClass( activeClass ) ) {
937					return;
938				}
939
940				$dropbar.removeClass( activeClass );
941			} );
942		},
943
944		widgetVideo: function( $scope ) {
945			var $video = $scope.find( '.jet-video' ),
946				$iframe = $scope.find( '.jet-video-iframe' ),
947				$videoPlaer = $scope.find( '.jet-video-player' ),
948				$mejsPlaer = $scope.find( '.jet-video-mejs-player' ),
949				mejsPlaerControls = $mejsPlaer.data( 'controls' ) || ['playpause', 'current', 'progress', 'duration', 'volume', 'fullscreen'],
950				$overlay = $scope.find( '.jet-video__overlay' ),
951				hasOverlay = $overlay.length > 0,
952				settings = $video.data( 'settings' ) || {},
953				autoplay = settings.autoplay || false;
954
955			if ( $overlay[0] ) {
956				$overlay.on( 'click.jetVideo', function( event ) {
957
958					if ( $videoPlaer[0] ) {
959						$videoPlaer[0].play();
960
961						$overlay.remove();
962						hasOverlay = false;
963
964						return;
965					}
966
967					if ( $iframe[0] ) {
968						iframeStartPlay();
969					}
970				} );
971			}
972
973			if ( autoplay && $iframe[0] && $overlay[0] ) {
974				iframeStartPlay();
975			}
976
977			function iframeStartPlay() {
978				var lazyLoad = $iframe.data( 'lazy-load' );
979
980				if ( lazyLoad ) {
981					$iframe.attr( 'src', lazyLoad );
982				}
983
984				if ( ! autoplay ) {
985					$iframe[0].src = $iframe[0].src.replace( '&autoplay=0', '&autoplay=1' );
986				}
987
988				$overlay.remove();
989				hasOverlay = false;
990			}
991
992			if ( $videoPlaer[0] ) {
993				$videoPlaer.on( 'play.jetVideo', function( event ) {
994					if ( hasOverlay ) {
995						$overlay.remove();
996						hasOverlay = false;
997					}
998				} );
999			}
1000
1001			if ( $mejsPlaer[0] ) {
1002				$mejsPlaer.mediaelementplayer( {
1003					videoVolume: 'horizontal',
1004					hideVolumeOnTouchDevices: false,
1005					enableProgressTooltip: false,
1006					features: mejsPlaerControls,
1007					success: function( media ) {
1008						media.addEventListener( 'timeupdate', function( event ) {
1009							var $currentTime = $scope.find( '.mejs-time-current' ),
1010								inlineStyle  = $currentTime.attr( 'style' );
1011
1012							if ( inlineStyle ) {
1013								var scaleX = inlineStyle.match(/scaleX\([0-9.]*\)/gi)[0].replace( 'scaleX(', '' ).replace( ')', '' );
1014
1015								if ( scaleX ) {
1016									$currentTime.css( 'width', scaleX * 100 + '%' );
1017								}
1018							}
1019						}, false );
1020					}
1021				} );
1022			}
1023		},
1024
1025		widgetAudio: function( $scope ) {
1026			var $wrapper = $scope.find( '.jet-audio' ),
1027				$player  = $scope.find( '.jet-audio-player' ),
1028				settings = $wrapper.data( 'settings' );
1029
1030			if ( ! $player[0] ) {
1031				return;
1032			}
1033
1034			$player.mediaelementplayer( {
1035				features: settings['controls'] || ['playpause', 'current', 'progress', 'duration', 'volume'],
1036				audioVolume: settings['audioVolume'] || 'horizontal',
1037				startVolume: settings['startVolume'] || 0.8,
1038				hideVolumeOnTouchDevices: settings['hideVolumeOnTouchDevices'],
1039				enableProgressTooltip: false,
1040				success: function( media ) {
1041					media.addEventListener( 'timeupdate', function( event ) {
1042						var $currentTime = $scope.find( '.mejs-time-current' ),
1043							inlineStyle  = $currentTime.attr( 'style' );
1044
1045						if ( inlineStyle ) {
1046							var scaleX = inlineStyle.match(/scaleX\([0-9.]*\)/gi)[0].replace( 'scaleX(', '' ).replace( ')', '' );
1047
1048							if ( scaleX ) {
1049								$currentTime.css( 'width', scaleX * 100 + '%' );
1050							}
1051						}
1052					}, false );
1053				}
1054			} );
1055		},
1056
1057		widgetHorizontalTimeline: function( $scope ) {
1058			var $timeline         = $scope.find( '.jet-hor-timeline' ),
1059				$timelineTrack    = $scope.find( '.jet-hor-timeline-track' ),
1060				$items            = $scope.find( '.jet-hor-timeline-item' ),
1061				$arrows           = $scope.find( '.jet-arrow' ),
1062				$nextArrow        = $scope.find( '.jet-next-arrow' ),
1063				$prevArrow        = $scope.find( '.jet-prev-arrow' ),
1064				columns           = $timeline.data( 'columns' ) || {},
1065				desktopColumns    = columns.desktop || 3,
1066				tabletColumns     = columns.tablet || desktopColumns,
1067				mobileColumns     = columns.mobile || tabletColumns,
1068				firstMouseEvent   = true,
1069				currentDeviceMode = elementorFrontend.getCurrentDeviceMode(),
1070				prevDeviceMode    = currentDeviceMode,
1071				itemsCount        = $scope.find( '.jet-hor-timeline-list--middle .jet-hor-timeline-item' ).length,
1072				currentTransform  = 0,
1073				currentPosition   = 0,
1074				transform = {
1075					desktop: 100 / desktopColumns,
1076					tablet:  100 / tabletColumns,
1077					mobile:  100 / mobileColumns
1078				},
1079				maxPosition = {
1080					desktop: Math.max( 0, (itemsCount - desktopColumns) ),
1081					tablet:  Math.max( 0, (itemsCount - tabletColumns) ),
1082					mobile:  Math.max( 0, (itemsCount - mobileColumns) )
1083				};
1084
1085			if ( 'ontouchstart' in window || 'ontouchend' in window ) {
1086				$items.on( 'touchend.jetHorTimeline', function( event ) {
1087					var itemId = $( this ).data( 'item-id' );
1088
1089					$scope.find( '.elementor-repeater-item-' + itemId ).toggleClass( 'is-hover' );
1090				} );
1091			} else {
1092				$items.on( 'mouseenter.jetHorTimeline mouseleave.jetHorTimeline', function( event ) {
1093
1094					if ( firstMouseEvent && 'mouseleave' === event.type ) {
1095						return;
1096					}
1097
1098					if ( firstMouseEvent && 'mouseenter' === event.type ) {
1099						firstMouseEvent = false;
1100					}
1101
1102					var itemId = $( this ).data( 'item-id' );
1103
1104					$scope.find( '.elementor-repeater-item-' + itemId ).toggleClass( 'is-hover' );
1105				} );
1106			}
1107
1108			// Set Line Position
1109			setLinePosition();
1110			$( window ).on( 'resize.jetHorTimeline orientationchange.jetHorTimeline', setLinePosition );
1111
1112			function setLinePosition() {
1113				var $line             = $scope.find( '.jet-hor-timeline__line' ),
1114					$firstPoint       = $scope.find( '.jet-hor-timeline-item__point-content:first' ),
1115					$lastPoint        = $scope.find( '.jet-hor-timeline-item__point-content:last' ),
1116					firstPointLeftPos = $firstPoint.position().left + parseInt( $firstPoint.css( 'marginLeft' ) ),
1117					lastPointLeftPos  = $lastPoint.position().left + parseInt( $lastPoint.css( 'marginLeft' ) ),
1118					pointWidth        = $firstPoint.outerWidth();
1119
1120				$line.css( {
1121					'left': firstPointLeftPos + pointWidth/2,
1122					'width': lastPointLeftPos - firstPointLeftPos
1123				} );
1124
1125				// var $progressLine   = $scope.find( '.jet-hor-timeline__line-progress' ),
1126				// 	$lastActiveItem = $scope.find( '.jet-hor-timeline-list--middle .jet-hor-timeline-item.is-active:last' );
1127				//
1128				// if ( $lastActiveItem[0] ) {
1129				// 	var $lastActiveItemPointWrap = $lastActiveItem.find( '.jet-hor-timeline-item__point' ),
1130				// 		progressLineWidth        = $lastActiveItemPointWrap.position().left + $lastActiveItemPointWrap.outerWidth() - firstPointLeftPos - pointWidth / 2;
1131				//
1132				// 	$progressLine.css( {
1133				// 		'width': progressLineWidth
1134				// 	} );
1135				// }
1136			}
1137
1138			// Arrows Navigation Type
1139			if ( $nextArrow[0] && maxPosition[ currentDeviceMode ] === 0 ) {
1140				$nextArrow.addClass( 'jet-arrow-disabled' );
1141			}
1142
1143			if ( $arrows[0] ) {
1144				$arrows.on( 'click.jetHorTimeline', function( event ){
1145					var $this = $( this ),
1146						direction = $this.hasClass( 'jet-next-arrow' ) ? 'next' : 'prev',
1147						currentDeviceMode = elementorFrontend.getCurrentDeviceMode();
1148
1149					if ( 'next' === direction && currentPosition < maxPosition[ currentDeviceMode ] ) {
1150						currentTransform -= transform[ currentDeviceMode ];
1151						currentPosition += 1;
1152					}
1153
1154					if ( 'prev' === direction && currentPosition > 0 ) {
1155						currentTransform += transform[ currentDeviceMode ];
1156						currentPosition -= 1;
1157					}
1158
1159					if ( currentPosition > 0 ) {
1160						$prevArrow.removeClass( 'jet-arrow-disabled' );
1161					} else {
1162						$prevArrow.addClass( 'jet-arrow-disabled' );
1163					}
1164
1165					if ( currentPosition === maxPosition[ currentDeviceMode ] ) {
1166						$nextArrow.addClass( 'jet-arrow-disabled' );
1167					} else {
1168						$nextArrow.removeClass( 'jet-arrow-disabled' );
1169					}
1170
1171					if ( currentPosition === 0 ) {
1172						currentTransform = 0;
1173					}
1174
1175					$timelineTrack.css({
1176						'transform': 'translateX(' + currentTransform + '%)'
1177					});
1178
1179				} );
1180			}
1181
1182			setArrowPosition();
1183			$( window ).on( 'resize.jetHorTimeline orientationchange.jetHorTimeline', setArrowPosition );
1184			$( window ).on( 'resize.jetHorTimeline orientationchange.jetHorTimeline', timelineSliderResizeHandler );
1185
1186			function setArrowPosition() {
1187				if ( ! $arrows[0] ) {
1188					return;
1189				}
1190
1191				var $middleList = $scope.find( '.jet-hor-timeline-list--middle' ),
1192					middleListTopPosition = $middleList.position().top,
1193					middleListHeight = $middleList.outerHeight();
1194
1195				$arrows.css({
1196					'top': middleListTopPosition + middleListHeight/2
1197				});
1198			}
1199
1200			function timelineSliderResizeHandler( event ) {
1201				if ( ! $timeline.hasClass( 'jet-hor-timeline--arrows-nav' ) ) {
1202					return;
1203				}
1204
1205				var currentDeviceMode = elementorFrontend.getCurrentDeviceMode(),
1206					resetSlider = function() {
1207						$prevArrow.addClass( 'jet-arrow-disabled' );
1208
1209						if ( $nextArrow.hasClass( 'jet-arrow-disabled' ) ) {
1210							$nextArrow.removeClass( 'jet-arrow-disabled' );
1211						}
1212
1213						if ( maxPosition[ currentDeviceMode ] === 0 ) {
1214							$nextArrow.addClass( 'jet-arrow-disabled' );
1215						}
1216
1217						currentTransform = 0;
1218						currentPosition = 0;
1219
1220						$timelineTrack.css({
1221							'transform': 'translateX(0%)'
1222						});
1223					};
1224
1225				switch ( currentDeviceMode ) {
1226					case 'desktop':
1227						if ( 'desktop' !== prevDeviceMode ) {
1228							resetSlider();
1229							prevDeviceMode = 'desktop';
1230						}
1231						break;
1232
1233					case 'tablet':
1234						if ( 'tablet' !== prevDeviceMode ) {
1235							resetSlider();
1236							prevDeviceMode = 'tablet';
1237						}
1238						break;
1239
1240					case 'mobile':
1241						if ( 'mobile' !== prevDeviceMode ) {
1242							resetSlider();
1243							prevDeviceMode = 'mobile';
1244						}
1245						break;
1246				}
1247			}
1248		},
1249
1250		widgetPieChart: function( $scope ) {
1251			var $container     = $scope.find( '.jet-pie-chart-container' ),
1252				$canvas        = $scope.find( '.jet-pie-chart' )[0],
1253				data           = $container.data( 'chart' ) || {},
1254				options        = $container.data( 'options' ) || {},
1255				defaultOptions = {
1256					maintainAspectRatio: false
1257				};
1258
1259			options = $.extend( {}, defaultOptions, options );
1260
1261			elementorFrontend.waypoint( $scope, function() {
1262				var chartInstance = new Chart( $canvas, {
1263					type:    'pie',
1264					data:    data,
1265					options: options
1266				} );
1267			}, {
1268				offset: 'bottom-in-view'
1269			} );
1270		}
1271	};
1272
1273	$( window ).on( 'elementor/frontend/init', JetElements.init );
1274
1275	var JetElementsTools = {
1276		debounce: function( threshold, callback ) {
1277			var timeout;
1278
1279			return function debounced( $event ) {
1280				function delayed() {
1281					callback.call( this, $event );
1282					timeout = null;
1283				}
1284
1285				if ( timeout ) {
1286					clearTimeout( timeout );
1287				}
1288
1289				timeout = setTimeout( delayed, threshold );
1290			};
1291		},
1292
1293		getObjectNextKey: function( object, key ) {
1294			var keys      = Object.keys( object ),
1295				idIndex   = keys.indexOf( key ),
1296				nextIndex = idIndex += 1;
1297
1298			if( nextIndex >= keys.length ) {
1299				//we're at the end, there is no next
1300				return false;
1301			}
1302
1303			var nextKey = keys[ nextIndex ];
1304
1305			return nextKey;
1306		},
1307
1308		getObjectPrevKey: function( object, key ) {
1309			var keys      = Object.keys( object ),
1310				idIndex   = keys.indexOf( key ),
1311				prevIndex = idIndex -= 1;
1312
1313			if ( 0 > idIndex ) {
1314				//we're at the end, there is no next
1315				return false;
1316			}
1317
1318			var prevKey = keys[ prevIndex ];
1319
1320			return prevKey;
1321		},
1322
1323		getObjectFirstKey: function( object ) {
1324			return Object.keys( object )[0];
1325		},
1326
1327		getObjectLastKey: function( object ) {
1328			return Object.keys( object )[ Object.keys( object ).length - 1 ];
1329		},
1330
1331		getObjectValues: function( object ) {
1332			var values;
1333
1334			if ( !Object.values ) {
1335				values = Object.keys( object ).map( function( e ) {
1336					return object[e]
1337				} );
1338
1339				return values;
1340			}
1341
1342			return Object.values( object );
1343		},
1344
1345		validateEmail: function( email ) {
1346			var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
1347
1348			return re.test( email );
1349		}
1350	}
1351
1352	/**
1353	 * Jet animated text Class
1354	 *
1355	 * @return {void}
1356	 */
1357	window.jetAnimatedText = function( $selector, settings ) {
1358		var self                   = this,
1359			$instance              = $selector,
1360			$animatedTextContainer = $( '.jet-animated-text__animated-text', $instance ),
1361			$animatedTextList      = $( '.jet-animated-text__animated-text-item', $animatedTextContainer ),
1362			timeOut                = null,
1363			defaultSettings        = {
1364				effect: 'fx1',
1365				delay: 3000
1366			},
1367			settings               =  $.extend( defaultSettings, settings || {} ),
1368			currentIndex           = 0,
1369			animationDelay         = settings.delay;
1370
1371		/**
1372		 * Avaliable Effects
1373		 */
1374		self.avaliableEffects = {
1375			'fx1' : {
1376				in: {
1377					duration: 1000,
1378					delay: function( el, index ) { return 75 + index * 100; },
1379					easing: 'easeOutElastic',
1380					elasticity: 650,
1381					opacity: {
1382						value: [ 0, 1 ],
1383						easing: 'easeOutExpo',
1384					},
1385					translateY: ['100%','0%']
1386				},
1387				out: {
1388					duration: 300,
1389					delay: function(el, index) { return index*40; },
1390					easing: 'easeInOutExpo',
1391					opacity: 0,
1392					translateY: '-100%'
1393				}
1394			},
1395			'fx2' : {
1396				in: {
1397					duration: 800,
1398					delay: function( el, index) { return index * 50; },
1399					easing: 'easeOutElastic',
1400					opacity: {
1401						value: [ 0, 1 ],
1402						easing: 'easeOutExpo',
1403					},
1404					translateY: function(el, index) {
1405						return index%2 === 0 ? ['-80%', '0%'] : ['80%', '0%'];
1406					}
1407				},
1408				out: {
1409					duration: 300,
1410					delay: function( el, index ) { return index * 20; },
1411					easing: 'easeOutExpo',
1412					opacity: 0,
1413					translateY: function( el, index ) {
1414						return index%2 === 0 ? '80%' : '-80%';
1415					}
1416				}
1417			},
1418			'fx3' : {
1419				in: {
1420					duration: 700,
1421					delay: function(el, index) {
1422						return ( el.parentNode.children.length - index - 1 ) * 80;
1423					},
1424					easing: 'easeOutElastic',
1425					opacity: {
1426						value: [ 0, 1 ],
1427						easing: 'easeOutExpo',
1428					},
1429					translateY: function(el, index) {
1430						return index%2 === 0 ? [ '-80%', '0%' ] : [ '80%', '0%' ];
1431					},
1432					rotateZ: [90,0]
1433				},
1434				out: {
1435					duration: 300,
1436					delay: function(el, index) { return (el.parentNode.children.length-index-1) * 50; },
1437					easing: 'easeOutExpo',
1438					opacity: 0,
1439					translateY: function(el, index) {
1440						return index%2 === 0 ? '80%' : '-80%';
1441					},
1442					rotateZ: function(el, index) {
1443						return index%2 === 0 ? -25 : 25;
1444					}
1445				}
1446			},
1447			'fx4' : {
1448				in: {
1449					duration: 700,
1450					delay: function( el, index ) { return 550 + index * 50; },
1451					easing: 'easeOutQuint',
1452					opacity: {
1453						value: [ 0, 1 ],
1454						easing: 'easeOutExpo',
1455					},
1456					translateY: [ '-150%','0%' ],
1457					rotateY: [ 180, 0 ]
1458				},
1459				out: {
1460					duration: 200,
1461					delay: function( el, index ) { return index * 30; },
1462					easing: 'easeInQuint',
1463					opacity: {
1464						value: 0,
1465						easing: 'linear',
1466					},
1467					translateY: '100%',
1468					rotateY: -180
1469				}
1470			},
1471			'fx5' : {
1472				in: {
1473					duration: 250,
1474					delay: function( el, index ) { return 200 + index * 25; },
1475					easing: 'easeOutCubic',
1476					opacity: {
1477						value: [ 0, 1 ],
1478						easing: 'easeOutExpo',
1479					},
1480					translateY: ['-50%','0%']
1481				},
1482				out: {
1483					duration: 250,
1484					delay: function( el, index ) { return index * 25; },
1485					easing: 'easeOutCubic',
1486					opacity: 0,
1487					translateY: '50%'
1488				}
1489			},
1490			'fx6' : {
1491				in: {
1492					duration: 400,
1493					delay: function( el, index ) { return index * 50; },
1494					easing: 'easeOutSine',
1495					opacity: {
1496						value: [ 0, 1 ],
1497						easing: 'easeOutExpo',
1498					},
1499					rotateY: [ -90, 0 ]
1500				},
1501				out: {
1502					duration: 200,
1503					delay: function( el, index ) { return index * 50; },
1504					easing: 'easeOutSine',
1505					opacity: 0,
1506					rotateY: 45
1507				}
1508			},
1509			'fx7' : {
1510				in: {
1511					duration: 1000,
1512					delay: function( el, index ) { return 100 + index * 30; },
1513					easing: 'easeOutElastic',
1514					opacity: {
1515						value: [ 0, 1 ],
1516						easing: 'easeOutExpo',
1517					},
1518					rotateZ: function( el, index ) {
1519						return [ anime.random( 20, 40 ), 0 ];
1520					}
1521				},
1522				out: {
1523					duration: 300,
1524					opacity: {
1525						value: [ 1, 0 ],
1526						easing: 'easeOutExpo',
1527					}
1528				}
1529			},
1530			'fx8' : {
1531				in: {
1532					duration: 400,
1533					delay: function( el, index ) { return 200 + index * 20; },
1534					easing: 'easeOutExpo',
1535					opacity: 1,
1536					rotateY: [ -90, 0 ],
1537					translateY: [ '50%','0%' ]
1538				},
1539				out: {
1540					duration: 250,
1541					delay: function( el, index ) { return index * 20; },
1542					easing: 'easeOutExpo',
1543					opacity: 0,
1544					rotateY: 90
1545				}
1546			},
1547			'fx9' : {
1548				in: {
1549					duration: 400,
1550					delay: function(el, index) { return 200+index*30; },
1551					easing: 'easeOutExpo',
1552					opacity: 1,
1553					rotateX: [90,0]
1554				},
1555				out: {
1556					duration: 250,
1557					delay: function(el, index) { return index*30; },
1558					easing: 'easeOutExpo',
1559					opacity: 0,
1560					rotateX: -90
1561				}
1562			},
1563			'fx10' : {
1564				in: {
1565					duration: 400,
1566					delay: function( el, index ) { return 100 + index * 50; },
1567					easing: 'easeOutExpo',
1568					opacity: {
1569						value: [ 0, 1 ],
1570						easing: 'easeOutExpo',
1571					},
1572					rotateX: [ 110, 0 ]
1573				},
1574				out: {
1575					duration: 250,
1576					delay: function( el, index ) { return index * 50; },
1577					easing: 'easeOutExpo',
1578					opacity: 0,
1579					rotateX: -110
1580				}
1581			},
1582			'fx11' : {
1583				in: {
1584					duration: function( el, index ) { return anime.random( 800, 1000 ); },
1585					delay: function( el, index ) { return anime.random( 100, 300 ); },
1586					easing: 'easeOutExpo',
1587					opacity: {
1588						value: [ 0, 1 ],
1589						easing: 'easeOutExpo',
1590					},
1591					translateY: [ '-150%','0%' ],
1592					rotateZ: function( el, index ) { return [ anime.random( -50, 50 ), 0 ]; }
1593				},
1594				out: {
1595					duration: function( el, index ) { return anime.random( 200, 300 ); },
1596					delay: function( el, index ) { return anime.random( 0, 80 ); },
1597					easing: 'easeInQuart',
1598					opacity: 0,
1599					translateY: '50%',
1600					rotateZ: function( el, index ) { return anime.random( -50, 50 ); }
1601				}
1602			},
1603			'fx12' : {
1604				in: {
1605					elasticity: false,
1606					duration: 1,
1607					delay: function( el, index ) {
1608						var delay = index * 100 + anime.random( 50, 100 );
1609
1610						return delay;
1611					},
1612					width: [ 0, function( el, i ) { return $( el ).width(); } ]
1613				},
1614				out: {
1615					duration: 1,
1616					delay: function( el, index ) { return ( el.parentNode.children.length - index - 1 ) * 20; },
1617					easing: 'linear',
1618					width: {
1619						value: 0
1620					}
1621				}
1622			}
1623		};
1624
1625		self.textChange = function() {
1626			var currentDelay = animationDelay,
1627				$prevText    = $animatedTextList.eq( currentIndex ),
1628				$nextText;
1629
1630			if ( currentIndex < $animatedTextList.length - 1 ) {
1631				currentIndex++;
1632			} else {
1633				currentIndex = 0;
1634			}
1635
1636			$nextText = $animatedTextList.eq( currentIndex );
1637
1638			self.hideText( $prevText, settings.effect, null, function( anime ) {
1639				$prevText.toggleClass( 'visible' );
1640
1641				var currentDelay = animationDelay;
1642
1643				if ( timeOut ) {
1644					clearTimeout( timeOut );
1645				}
1646
1647				self.showText(
1648					$nextText,
1649					settings.effect,
1650					function() {
1651						$nextText.toggleClass( 'active' );
1652						$prevText.toggleClass( 'active' );
1653
1654						$nextText.toggleClass( 'visible' );
1655					},
1656					function() {
1657						timeOut = setTimeout( function() {
1658							self.textChange();
1659						}, currentDelay );
1660					}
1661				);
1662
1663			} );
1664		};
1665
1666		self.showText = function( $selector, effect, beginCallback, completeCallback ) {
1667			var targets = [];
1668
1669			$( 'span', $selector ).each( function() {
1670				$( this ).css( {
1671					'width': 'auto',
1672					'opacity': 1,
1673					'WebkitTransform': '',
1674					'transform': ''
1675				});
1676				targets.push( this );
1677			});
1678
1679			self.animateText( targets, 'in', effect, beginCallback, completeCallback );
1680		};
1681
1682		self.hideText = function( $selector, effect, beginCallback, completeCallback ) {
1683			var targets = [];
1684
1685			$( 'span', $selector ).each( function() {
1686				targets.push(this);
1687			});
1688
1689			self.animateText( targets, 'out', effect, beginCallback, completeCallback );
1690		};
1691
1692		self.animateText = function( targets, direction, effect, beginCallback, completeCallback ) {
1693			var effectSettings   = self.avaliableEffects[ effect ] || {},
1694				animationOptions = effectSettings[ direction ],
1695				animeInstance = null;
1696
1697			animationOptions.targets = targets;
1698
1699			animationOptions.begin = beginCallback;
1700			animationOptions.complete = completeCallback;
1701
1702			animeInstance = anime( animationOptions );
1703		};
1704
1705		self.init = function() {
1706			var $text = $animatedTextList.eq( currentIndex );
1707
1708			self.showText(
1709				$text,
1710				settings.effect,
1711				null,
1712				function() {
1713					var currentDelay = animationDelay;
1714
1715					if ( timeOut ) {
1716						clearTimeout( timeOut );
1717					}
1718
1719					timeOut = setTimeout( function() {
1720						self.textChange();
1721					}, currentDelay );
1722
1723				}
1724			);
1725		};
1726	}
1727
1728	/**
1729	 * Jet Images Layout Class
1730	 *
1731	 * @return {void}
1732	 */
1733	window.jetImagesLayout = function( $selector, settings ) {
1734		var self            = this,
1735			$instance       = $selector,
1736			$instanceList   = $( '.jet-images-layout__list', $instance ),
1737			$itemsList      = $( '.jet-images-layout__item', $instance ),
1738			defaultSettings = {},
1739			settings        = settings || {};
1740
1741		/*
1742		 * Default Settings
1743		 */
1744		defaultSettings = {
1745			layoutType: 'masonry',
1746			columns: 3,
1747			columnsTablet: 2,
1748			columnsMobile: 1,
1749			justifyHeight: 300
1750		}
1751
1752		/**
1753		 * Checking options, settings and options merging
1754		 */
1755		$.extend( defaultSettings, settings );
1756
1757		/**
1758		 * Layout build
1759		 */
1760		self.layoutBuild = function() {
1761			switch ( settings['layoutType'] ) {
1762				case 'masonry':
1763					salvattore.init();
1764				break;
1765				case 'justify':
1766					$itemsList.each( function() {
1767						var $this          = $( this ),
1768							$imageInstance = $( '.jet-images-layout__image-instance', $this),
1769							imageWidth     = $imageInstance.data( 'width' ),
1770							imageHeight    = $imageInstance.data( 'height' ),
1771							imageRatio     = +imageWidth / +imageHeight,
1772							flexValue      = imageRatio * 100,
1773							newWidth       = +settings['justifyHeight'] * imageRatio,
1774							newHeight      = 'auto';
1775
1776						$this.css( {
1777							'flex-grow': flexValue,
1778							'flex-basis': newWidth
1779						} );
1780					} );
1781				break;
1782			}
1783
1784			$( '.jet-images-layout__image', $itemsList ).imagesLoaded().progress( function( instance, image ) {
1785				var $image      = $( image.img ),
1786					$parentItem = $image.closest( '.jet-images-layout__item' ),
1787					$loader     = $( '.jet-images-layout__image-loader', $parentItem );
1788
1789				$parentItem.addClass( 'image-loaded' );
1790
1791				$loader.fadeTo( 500, 0, function() {
1792					$( this ).remove();
1793				} );
1794
1795			});
1796		}
1797
1798		/**
1799		 * Init
1800		 */
1801		self.init = function() {
1802			self.layoutBuild();
1803		}
1804	}
1805
1806	/**
1807	 * Jet Scroll Navigation Class
1808	 *
1809	 * @return {void}
1810	 */
1811	window.jetScrollNavigation = function( $selector, settings ) {
1812		var self            = this,
1813			$window         = $( window ),
1814			$document       = $( document ),
1815			$instance       = $selector,
1816			$htmlBody       = $( 'html, body' ),
1817			$itemsList      = $( '.jet-scroll-navigation__item', $instance ),
1818			sectionList     = [],
1819			defaultSettings = {
1820				speed: 500,
1821				blockSpeed: 500,
1822				offset: 200,
1823				sectionSwitch: false
1824			},
1825			settings        = $.extend( {}, defaultSettings, settings ),
1826			sections        = {},
1827			currentSection  = null,
1828			isScrolling     = false,
1829			isSwipe         = false,
1830			hash            = window.location.hash.slice(1),
1831			timeout         = null,
1832			timeStamp       = 0,
1833			platform        = navigator.platform;
1834
1835		jQuery.extend( jQuery.easing, {
1836			easeInOutCirc: function (x, t, b, c, d) {
1837				if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
1838				return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
1839			}
1840		});
1841
1842		/**
1843		 * [init description]
1844		 * @return {[type]} [description]
1845		 */
1846		self.init = function() {
1847			self.setSectionsData();
1848
1849			// Add Events
1850			$itemsList.on( 'click.jetScrollNavigation', self.onAnchorChange );
1851
1852			$window.on( 'scroll.jetScrollNavigation', self.onScroll );
1853			$window.on( 'resize.jetScrollNavigation orientationchange.jetScrollNavigation', JetElementsTools.debounce( 50, self.onResize ) );
1854			$window.on( 'load', function() { self.setSectionsData(); } );
1855
1856			$document.keydown( function( event ) {
1857
1858				if ( 38 == event.keyCode ) {
1859					self.directionSwitch( event, 'up' );
1860				}
1861
1862				if ( 40 == event.keyCode ) {
1863					self.directionSwitch( event, 'down' );
1864				}
1865			} );
1866
1867			if ( settings.sectionSwitch ) {
1868
1869				if ( 'onwheel' in window ) {
1870					// onwheel check handler
1871				}
1872
1873				$document.on( 'mousewheel.jetScrollNavigation DOMMouseScroll.jetScrollNavigation', self.onWheel );
1874
1875				/*if ( self.mobileAndTabletcheck() ) {
1876					var touchstartY = 0,
1877						touchendY   = 0;
1878
1879					$document.on( 'touchstart', function( event ) {
1880						var originalEvent = event.originalEvent;
1881
1882						isSwipe = true;
1883
1884						touchstartY = originalEvent.changedTouches[0].screenY;
1885
1886					} );
1887
1888					$document.on( 'touchend', function( event ) {
1889						var originalEvent = event.originalEvent;
1890
1891						isSwipe = false;
1892
1893						touchendY = originalEvent.changedTouches[0].screenY;
1894
1895						if ( touchendY < touchstartY ) {
1896							self.directionSwitch( event, 'down' );
1897						}
1898
1899						if ( touchendY > touchstartY ) {
1900							self.directionSwitch( event, 'up' );
1901						}
1902					} );
1903
1904				}*/
1905			}
1906
1907			if ( hash && sections.hasOwnProperty( hash ) ) {
1908				$itemsList.addClass( 'invert' );
1909			}
1910
1911			for ( var section in sections ) {
1912				var $section = sections[section].selector;
1913
1914				elementorFrontend.waypoint( $section, function( direction ) {
1915					var $this = $( this ),
1916						sectionId = $this.attr( 'id' );
1917
1918						if ( 'down' === direction && ! isScrolling && ! isSwipe ) {
1919							window.history.pushState( null, null, '#' + sectionId );
1920							currentSection = sectionId;
1921							$itemsList.removeClass( 'active' );
1922							$( '[data-anchor=' + sectionId + ']', $instance ).addClass( 'active' );
1923
1924							$itemsList.removeClass( 'invert' );
1925
1926							if ( sections[sectionId].invert ) {
1927								$itemsList.addClass( 'invert' );
1928							}
1929						}
1930				}, {
1931					offset: '95%',
1932					triggerOnce: false
1933				} );
1934
1935				elementorFrontend.waypoint( $section, function( direction ) {
1936					var $this = $( this ),
1937						sectionId = $this.attr( 'id' );
1938
1939						if ( 'up' === direction && ! isScrolling && ! isSwipe ) {
1940							window.history.pushState( null, null, '#' + sectionId );
1941							currentSection = sectionId;
1942							$itemsList.removeClass( 'active' );
1943							$( '[data-anchor=' + sectionId + ']', $instance ).addClass( 'active' );
1944
1945							$itemsList.removeClass( 'invert' );
1946
1947							if ( sections[sectionId].invert ) {
1948								$itemsList.addClass( 'invert' );
1949							}
1950						}
1951				}, {
1952					offset: '0%',
1953					triggerOnce: false
1954				} );
1955			}
1956		};
1957
1958		/**
1959		 * [onAnchorChange description]
1960		 * @param  {[type]} event [description]
1961		 * @return {[type]}       [description]
1962		 */
1963		self.onAnchorChange = function( event ) {
1964			var $this     = $( this ),
1965				sectionId = $this.data('anchor'),
1966				offset    = null;
1967
1968			if ( ! sections.hasOwnProperty( sectionId ) ) {
1969				return false;
1970			}
1971
1972			offset = sections[sectionId].offset - settings.offset;
1973
1974			if ( ! isScrolling ) {
1975				isScrolling = true;
1976				window.history.pushState( null, null, '#' + sectionId );
1977				currentSection = sectionId;
1978
1979				$itemsList.removeClass( 'active' );
1980				$this.addClass( 'active' );
1981
1982				$itemsList.removeClass( 'invert' );
1983
1984				if ( sections[sectionId].invert ) {
1985					$itemsList.addClass( 'invert' );
1986				}
1987
1988				$htmlBody.stop().clearQueue().animate( { 'scrollTop': offset }, settings.speed, 'easeInOutCirc', function() {
1989					isScrolling = false;
1990				} );
1991			}
1992		};
1993
1994		/**
1995		 * [directionSwitch description]
1996		 * @param  {[type]} event     [description]
1997		 * @param  {[type]} direction [description]
1998		 * @return {[type]}           [description]
1999		 */
2000		self.directionSwitch = function( event, direction ) {
2001			var direction = direction || 'up',
2002				sectionId,
2003				nextItem = $( '[data-anchor=' + currentSection + ']', $instance ).next(),
2004				prevItem = $( '[data-anchor=' + currentSection + ']', $instance ).prev();
2005
2006			//event.preventDefault();
2007
2008			if ( isScrolling ) {
2009				return false;
2010			}
2011
2012			if ( 'up' === direction ) {
2013				if ( prevItem[0] ) {
2014					prevItem.trigger( 'click.jetScrollNavigation' );
2015				}
2016			}
2017
2018			if ( 'down' === direction ) {
2019				if ( nextItem[0] ) {
2020					nextItem.trigger( 'click.jetScrollNavigation' );
2021				}
2022			}
2023		};
2024
2025		/**
2026		 * [onScroll description]
2027		 * @param  {[type]} event [description]
2028		 * @return {[type]}       [description]
2029		 */
2030		self.onScroll = function( event ) {
2031			/* On Scroll Event */
2032			if ( isScrolling || isSwipe ) {
2033				event.preventDefault();
2034			}
2035		};
2036
2037		/**
2038		 * [onWheel description]
2039		 * @param  {[type]} event [description]
2040		 * @return {[type]}       [description]
2041		 */
2042		self.onWheel = function( event ) {
2043
2044			if ( isScrolling || isSwipe ) {
2045				event.preventDefault();
2046				return false;
2047			}
2048
2049			var $target         = $( event.target ),
2050				$section        = $target.closest( '.elementor-top-section' ),
2051				sectionId       = $section.attr( 'id' ),
2052				offset          = 0,
2053				newSectionId    = false,
2054				prevSectionId   = false,
2055				nextSectionId   = false,
2056				delta           = event.originalEvent.wheelDelta || -event.originalEvent.detail,
2057				direction       = ( 0 < delta ) ? 'up' : 'down',
2058				windowScrollTop = $window.scrollTop();
2059
2060			if ( self.beforeCheck() ) {
2061				sectionId = JetElementsTools.getObjectFirstKey( sections );
2062			}
2063
2064			if ( self.afterCheck() ) {
2065				sectionId = JetElementsTools.getObjectLastKey( sections );
2066			}
2067
2068			if ( sectionId && sections.hasOwnProperty( sectionId ) ) {
2069
2070				prevSectionId = JetElementsTools.getObjectPrevKey( sections, sectionId );
2071				nextSectionId = JetElementsTools.getObjectNextKey( sections, sectionId );
2072
2073				if ( 'up' === direction ) {
2074					if ( ! nextSectionId && sections[sectionId].offset < windowScrollTop ) {
2075						newSectionId = sectionId;
2076					} else {
2077						newSectionId = prevSectionId;
2078					}
2079				}
2080
2081				if ( 'down' === direction ) {
2082					if ( ! prevSectionId && sections[sectionId].offset > windowScrollTop + 5 ) {
2083						newSectionId = sectionId;
2084					} else {
2085						newSectionId = nextSectionId;
2086					}
2087				}
2088
2089				if ( newSectionId ) {
2090
2091					if ( event.timeStamp - timeStamp > 10 && 'MacIntel' == platform ) {
2092						timeStamp = event.timeStamp;
2093						event.preventDefault();
2094						return false;
2095					}
2096
2097					event.preventDefault();
2098
2099					offset = sections[newSectionId].offset - settings.offset;
2100					window.history.pushState( null, null, '#' + newSectionId );
2101					currentSection = newSectionId;
2102
2103					$itemsList.removeClass( 'active' );
2104					$( '[data-anchor=' + newSectionId + ']', $instance ).addClass( 'active' );
2105
2106					$itemsList.removeClass( 'invert' );
2107
2108					if ( sections[newSectionId].invert ) {
2109						$itemsList.addClass( 'invert' );
2110					}
2111
2112					isScrolling = true;
2113					self.scrollStop();
2114					$htmlBody.animate( { 'scrollTop': offset }, settings.blockSpeed, 'easeInOutCirc', function() {
2115						isScrolling = false;
2116					} );
2117				}
2118			}
2119
2120		};
2121
2122		/**
2123		 * [setSectionsData description]
2124		 */
2125		self.setSectionsData = function() {
2126			$itemsList.each( function() {
2127				var $this         = $( this ),
2128					sectionId     = $this.data('anchor'),
2129					sectionInvert = 'yes' === $this.data('invert') ? true : false,
2130					$section      = $( '#' + sectionId );
2131
2132				$section.addClass( 'jet-scroll-navigation-section' );
2133				$section.attr( { 'touch-action': 'none'} );
2134
2135				if ( $section[0] ) {
2136					sections[ sectionId ] = {
2137						selector: $section,
2138						offset: Math.round( $section.offset().top ),
2139						height: $section.outerHeight(),
2140						invert: sectionInvert
2141					};
2142				}
2143			} );
2144		};
2145
2146
2147		/**
2148		 * [beforeCheck description]
2149		 * @param  {[type]} event [description]
2150		 * @return {[type]}       [description]
2151		 */
2152		self.beforeCheck = function( event ) {
2153			var windowScrollTop = $window.scrollTop(),
2154				firstSectionId = JetElementsTools.getObjectFirstKey( sections ),
2155				offset = sections[ firstSectionId ].offset,
2156				topBorder = windowScrollTop + $window.outerHeight();
2157
2158			if ( topBorder > offset ) {
2159				return false;
2160			}
2161
2162			return true;
2163		};
2164
2165		/**
2166		 * [afterCheck description]
2167		 * @param  {[type]} event [description]
2168		 * @return {[type]}       [description]
2169		 */
2170		self.afterCheck = function( event ) {
2171			var windowScrollTop = $window.scrollTop(),
2172				lastSectionId = JetElementsTools.getObjectLastKey( sections ),
2173				offset = sections[ lastSectionId ].offset,
2174				bottomBorder = sections[ lastSectionId ].offset + sections[ lastSectionId ].height;
2175
2176			if ( windowScrollTop < bottomBorder ) {
2177				return false;
2178			}
2179
2180			return true;
2181		};
2182
2183		/**
2184		 * [onResize description]
2185		 * @param  {[type]} event [description]
2186		 * @return {[type]}       [description]
2187		 */
2188		self.onResize = function( event ) {
2189			self.setSectionsData();
2190		};
2191
2192		/**
2193		 * [scrollStop description]
2194		 * @return {[type]} [description]
2195		 */
2196		self.scrollStop = function() {
2197			$htmlBody.stop( true );
2198		};
2199
2200		/**
2201		 * Mobile and tablet check funcion.
2202		 *
2203		 * @return {boolean} Mobile Status
2204		 */
2205		self.mobileAndTabletcheck = function() {
2206			var check = false;
2207
2208			(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
2209
2210			return check;
2211		};
2212
2213	}
2214
2215	/**
2216	 * jetSectionParallax Class
2217	 *
2218	 * @return {void}
2219	 */
2220	window.jetSectionParallax = function( $target ) {
2221		var self             = this,
2222			sectionId        = $target.data('id'),
2223			settings         = false,
2224			editMode         = Boolean( elementor.isEditMode() ),
2225			$window          = $( window ),
2226			$body            = $( 'body' ),
2227			scrollLayoutList = [],
2228			mouseLayoutList  = [],
2229			winScrollTop     = $window.scrollTop(),
2230			winHeight        = $window.height(),
2231			requesScroll     = null,
2232			requestMouse     = null,
2233			tiltx            = 0,
2234			tilty            = 0,
2235			isSafari         = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/),
2236			platform         = navigator.platform;
2237
2238		/**
2239		 * Init
2240		 */
2241		self.init = function() {
2242
2243			if ( ! editMode ) {
2244				settings = jetElements[ 'jetParallaxSections' ][ sectionId ] || false;
2245			} else {
2246				settings = self.generateEditorSettings( sectionId );
2247			}
2248
2249			if ( ! settings ) {
2250				return false;
2251			}
2252
2253			$target.addClass( 'jet-parallax-section' );
2254			self.generateLayouts();
2255
2256			//$window.on( 'scroll.jetSectionParallax resize.jetSectionParallax', JetElementsTools.debounce( 5, self.scrollHandler ) );
2257
2258			if ( 0 !== scrollLayoutList.length ) {
2259				$window.on( 'scroll.jetSectionParallax resize.jetSectionParallax', self.scrollHandler );
2260			}
2261
2262			if ( 0 !== mouseLayoutList.length ) {
2263				$target.on( 'mousemove.jetSectionParallax resize.jetSectionParallax', self.mouseMoveHandler );
2264				$target.on( 'mouseleave.jetSectionParallax', self.mouseLeaveHandler );
2265			}
2266
2267			self.scrollUpdate();
2268		};
2269
2270		self.generateEditorSettings = function( sectionId ) {
2271			var editorElements      = null,
2272				sectionsData        = {},
2273				sectionData         = {},
2274				sectionParallaxData = {},
2275				settings            = [];
2276
2277			if ( ! window.elementor.hasOwnProperty( 'elements' ) ) {
2278				return false;
2279			}
2280
2281			editorElements = window.elementor.elements;
2282
2283			if ( ! editorElements.models ) {
2284				return false;
2285			}
2286
2287			$.each( editorElements.models, function( index, obj ) {
2288				if ( sectionId == obj.id ) {
2289					sectionData = obj.attributes.settings.attributes;
2290				}
2291			} );
2292
2293			if ( ! sectionData.hasOwnProperty( 'jet_parallax_layout_list' ) || 0 === Object.keys( sectionData ).length ) {
2294				return false;
2295			}
2296
2297			sectionParallaxData = sectionData[ 'jet_parallax_layout_list' ].models;
2298
2299			$.each( sectionParallaxData, function( index, obj ) {
2300				settings.push( obj.attributes );
2301			} );
2302
2303			if ( 0 !== settings.length ) {
2304				return settings;
2305			}
2306
2307			return false;
2308		};
2309
2310		self.generateLayouts = function() {
2311
2312			$( '.jet-parallax-section__layout', $target ).remove();
2313
2314			$.each( settings, function( index, layout ) {
2315
2316				var imageData      = layout['jet_parallax_layout_image'],
2317					speed          = layout['jet_parallax_layout_speed']['size'] || 50,
2318					zIndex         = layout['jet_parallax_layout_z_index'],
2319					bgSize         = layout['jet_parallax_layout_bg_size'] || 'auto',
2320					animProp       = layout['jet_parallax_layout_animation_prop'] || 'bgposition',
2321					bgX            = layout['jet_parallax_layout_bg_x'],
2322					bgY            = layout['jet_parallax_layout_bg_y'],
2323					type           = layout['jet_parallax_layout_type'] || 'none',
2324					device         = layout['jet_parallax_layout_on'] || ['desktop', 'tablet'],
2325					_id            = layout['_id'],
2326					isDynamicImage = layout.hasOwnProperty( '__dynamic__' ) && layout.__dynamic__.hasOwnProperty( 'jet_parallax_layout_image' ),
2327					$layout        = null,
2328					layoutData     = {},
2329					safariClass    = isSafari ? ' is-safari' : '',
2330					macClass       = 'MacIntel' == platform ? ' is-mac' : '';
2331
2332				if ( '' === imageData['url'] && ! isDynamicImage ) {
2333					return false;
2334				}
2335
2336				$layout = $( '<div class="jet-parallax-section__layout elementor-repeater-item-' + _id + ' jet-parallax-section__' + type +'-layout' + macClass + '"><div class="jet-parallax-section__image"></div></div>' )
2337					.prependTo( $target )
2338					.css({
2339						'z-index': zIndex
2340					});
2341
2342				var imageCSS = {
2343					'background-size': bgSize,
2344					'background-position-x': bgX + '%',
2345					'background-position-y': bgY + '%'
2346				};
2347
2348				if ( '' !== imageData['url'] ) {
2349					imageCSS['background-image'] = 'url(' + imageData['url'] + ')';
2350				}
2351
2352				$( '> .jet-parallax-section__image', $layout ).css( imageCSS );
2353
2354				layoutData = {
2355					selector: $layout,
2356					image: imageData['url'],
2357					size: bgSize,
2358					prop: animProp,
2359					type: type,
2360					device: device,
2361					xPos: bgX,
2362					yPos: bgY,
2363					speed: 2 * ( speed / 100 )
2364				};
2365
2366				if ( 'none' !== type ) {
2367					if ( 'scroll' === type || 'zoom' === type ) {
2368						scrollLayoutList.push( layoutData );
2369					}
2370
2371					if ( 'mouse' === type ) {
2372						mouseLayoutList.push( layoutData );
2373					}
2374				}
2375
2376			});
2377
2378		};
2379
2380		self.scrollHandler = function( event ) {
2381			winScrollTop = $window.scrollTop();
2382			winHeight    = $window.height();
2383
2384			self.scrollUpdate();
2385		};
2386
2387		self.scrollUpdate = function() {
2388			$.each( scrollLayoutList, function( index, layout ) {
2389
2390				var $this      = layout.selector,
2391					$image     = $( '.jet-parallax-section__image', $this ),
2392					speed      = layout.speed,
2393					offsetTop  = $this.offset().top,
2394					thisHeight = $this.outerHeight(),
2395					prop       = layout.prop,
2396					type       = layout.type,
2397					posY       = ( winScrollTop - offsetTop + winHeight ) / thisHeight * 100,
2398					device     = elementorFrontend.getCurrentDeviceMode();
2399
2400				if ( -1 == layout.device.indexOf( device ) ) {
2401					$image.css( {
2402						'transform': 'translateY(0)',
2403						'background-position-y': layout.yPos
2404					} );
2405
2406					return false;
2407				}
2408
2409				if ( winScrollTop < offsetTop - winHeight ) posY = 0;
2410				if ( winScrollTop > offsetTop + thisHeight) posY = 200;
2411
2412				posY = parseFloat( speed * posY ).toFixed(1);
2413
2414				switch( type ) {
2415					case 'scroll':
2416						if ( 'bgposition' === layout.prop ) {
2417							$image.css( {
2418								'background-position-y': 'calc(' + layout.yPos + '% + ' + posY + 'px)'
2419							} );
2420						} else {
2421							$image.css( {
2422								'transform': 'translateY(' + posY + 'px)'
2423							} );
2424						}
2425						break;
2426					case 'zoom':
2427						var deltaScale = ( winScrollTop - offsetTop + winHeight ) / winHeight,
2428							scale      = deltaScale * speed;
2429
2430						scale = scale + 1;
2431
2432						$image.css( {
2433							'transform': 'scale(' + scale + ')'
2434						} );
2435						break;
2436				}
2437
2438			} );
2439
2440			//requesScroll = requestAnimationFrame( self.scrollUpdate );
2441			//requestAnimationFrame( self.scrollUpdate );
2442		};
2443
2444		self.mouseMoveHandler = function( event ) {
2445			var windowWidth  = $window.width(),
2446				windowHeight = $window.height(),
2447				cx           = Math.ceil( windowWidth / 2 ),
2448				cy           = Math.ceil( windowHeight / 2 ),
2449				dx           = event.clientX - cx,
2450				dy           = event.clientY - cy;
2451
2452			tiltx = -1 * ( dx / cx );
2453			tilty = -1 * ( dy / cy);
2454
2455			self.mouseMoveUpdate();
2456		};
2457
2458		self.mouseLeaveHandler = function( event ) {
2459
2460			$.each( mouseLayoutList, function( index, layout ) {
2461				var $this  = layout.selector,
2462					$image = $( '.jet-parallax-section__image', $this );
2463
2464				switch( layout.prop ) {
2465					case 'transform3d':
2466						TweenMax.to(
2467							$image[0],
2468							1.2, {
2469								x: 0,
2470								y: 0,
2471								z: 0,
2472								rotationX: 0,
2473								rotationY: 0,
2474								ease:Power2.easeOut
2475							}
2476						);
2477					break;
2478				}
2479
2480			} );
2481		};
2482
2483		self.mouseMoveUpdate = function() {
2484			$.each( mouseLayoutList, function( index, layout ) {
2485				var $this   = layout.selector,
2486					$image  = $( '.jet-parallax-section__image', $this ),
2487					speed   = layout.speed,
2488					prop    = layout.prop,
2489					posX    = parseFloat( tiltx * 125 * speed ).toFixed(1),
2490					posY    = parseFloat( tilty * 125 * speed ).toFixed(1),
2491					posZ    = layout.zIndex * 50,
2492					rotateX = parseFloat( tiltx * 25 * speed ).toFixed(1),
2493					rotateY = parseFloat( tilty * 25 * speed ).toFixed(1),
2494					device  = elementorFrontend.getCurrentDeviceMode();
2495
2496				if ( -1 == layout.device.indexOf( device ) ) {
2497					$image.css( {
2498						'transform': 'translateX(0) translateY(0)',
2499						'background-position-x': layout.xPos,
2500						'background-position-y': layout.yPos
2501					} );
2502
2503					return false;
2504				}
2505
2506				switch( prop ) {
2507					case 'bgposition':
2508						TweenMax.to(
2509							$image[0],
2510							1, {
2511								backgroundPositionX: 'calc(' + layout.xPos + '% + ' + posX + 'px)',
2512								backgroundPositionY: 'calc(' + layout.yPos + '% + ' + posY + 'px)',
2513								ease:Power2.easeOut
2514							}
2515						);
2516					break;
2517
2518					case 'transform':
2519						TweenMax.to(
2520							$image[0],
2521							1, {
2522								x: posX,
2523								y: posY,
2524								ease:Power2.easeOut
2525							}
2526						);
2527					break;
2528
2529					case 'transform3d':
2530						TweenMax.to(
2531							$image[0],
2532							2, {
2533								x: posX,
2534								y: posY,
2535								z: posZ,
2536								rotationX: rotateY,
2537								rotationY: -rotateX,
2538								ease:Power2.easeOut
2539							}
2540						);
2541					break;
2542				}
2543
2544			} );
2545		};
2546
2547	}
2548
2549	/**
2550	 * Jet Portfolio Class
2551	 *
2552	 * @return {void}
2553	 */
2554	window.jetPortfolio = function( $selector, settings ) {
2555		var self            = this,
2556			$instance       = $selector,
2557			$instanceList   = $( '.jet-portfolio__list', $instance ),
2558			$itemsList      = $( '.jet-portfolio__item', $instance ),
2559			$filterList     = $( '.jet-portfolio__filter-item', $instance ),
2560			$moreWrapper    = $( '.jet-portfolio__view-more', $instance ),
2561			$moreButton     = $( '.jet-portfolio__view-more-button', $instance ),
2562			isViewMore      = $moreButton[0],
2563			itemsData       = {},
2564			filterData      = {},
2565			activeSlug      = [],
2566			defaultSettings = {
2567				layoutType: 'masonry',
2568				columns: 3,
2569				columnsTablet: 2,
2570				columnsMobile: 1,
2571				perPage: 6
2572			},
2573			masonryOptions = {
2574				itemSelector: '.jet-portfolio__item',
2575				percentPosition: true,
2576				//isAnimated: true
2577			},
2578			settings        = $.extend( defaultSettings, settings ),
2579			$masonryInstance,
2580			page            = 1;
2581
2582		/**
2583		 * Init
2584		 */
2585		self.init = function() {
2586			self.layoutBuild();
2587		}
2588
2589		/**
2590		 * Layout build
2591		 */
2592		self.layoutBuild = function() {
2593
2594			self.generateData();
2595
2596			$filterList.data( 'showItems', isViewMore ? settings.perPage : 'all' );
2597
2598			if ( 'justify' == settings['layoutType'] ) {
2599				masonryOptions['columnWidth'] = '.grid-sizer';
2600			}
2601
2602			$masonryInstance = $instanceList.masonry( masonryOptions );
2603
2604			$( '.jet-portfolio__image', $itemsList ).imagesLoaded().progress( function( instance, image ) {
2605				var $image      = $( image.img ),
2606					$parentItem = $image.closest( '.jet-portfolio__item' ),
2607					$loader     = $( '.jet-portfolio__image-loader', $parentItem );
2608
2609				$loader.remove();
2610
2611				$parentItem.addClass( 'item-loaded' );
2612
2613				$masonryInstance.masonry( 'layout' );
2614			} );
2615
2616			//$instanceList.imagesLoaded( function( instance ) {} );
2617
2618			$filterList.on( 'click.jetPortfolio', self.filterHandler );
2619			$moreButton.on( 'click.jetPortfolio', self.moreButtonHandler );
2620
2621			self.render();
2622			self.checkMoreButton();
2623		};
2624
2625		self.generateData = function() {
2626			if ( $filterList[0] ) {
2627				$filterList.each( function( index ) {
2628					var $this = $( this ),
2629						slug  = $this.data('slug');
2630
2631					filterData[ slug ] = false;
2632
2633					if ( 'all' == slug ) {
2634						filterData[ slug ] = true;
2635					}
2636				} );
2637			} else {
2638				filterData['all'] = true;
2639			}
2640
2641			$itemsList.each( function( index ) {
2642				var $this = $( this ),
2643					slug  = $this.data('slug');
2644
2645				itemsData[ index ] = {
2646					selector: $this,
2647					slug: slug,
2648					visible: $this.hasClass( 'visible-status' ) ? true : false,
2649					more: $this.hasClass( 'hidden-status' ) ? true : false
2650				};
2651			} );
2652		};
2653
2654		self.filterHandler = function( event ) {
2655			var $this = $( this ),
2656				counter = 1,
2657				slug  = $this.data( 'slug' ),
2658				showItems = $this.data( 'showItems' );
2659
2660			$filterList.removeClass( 'active' );
2661			$this.addClass( 'active' );
2662
2663			for ( var slugName in filterData ) {
2664				filterData[ slugName ] = false;
2665
2666				if ( slugName == slug ) {
2667					filterData[ slugName ] = true;
2668				}
2669			}
2670
2671			$.each( itemsData, function( index, obj ) {
2672				var visible = false;
2673
2674				if ( 'all' === showItems ) {
2675
2676					if ( self.isItemVisible( obj.slug ) && ! obj['more'] ) {
2677						visible = true;
2678					}
2679
2680				} else if ( self.isItemVisible( obj.slug ) ) {
2681
2682					if ( counter <= showItems ) {
2683						visible = true;
2684						obj.more = false;
2685					} else {
2686						obj.more = true;
2687					}
2688
2689					counter++
2690				}
2691
2692				obj.visible = visible;
2693
2694			} );
2695
2696			self.render();
2697			self.checkMoreButton();
2698		}
2699
2700		/**
2701		 * [moreButtonHandler description]
2702		 * @param  {[type]} event [description]
2703		 * @return {[type]}       [description]
2704		 */
2705		self.moreButtonHandler = function( event ) {
2706			var $this   = $( this ),
2707				counter = 1,
2708				activeFilter = $( '.jet-portfolio__filter-item.active', $instance ),
2709				showItems;
2710
2711			$.each( itemsData, function( index, obj ) {
2712
2713				if ( self.isItemVisible( obj.slug ) && obj.more && counter <= settings.perPage ) {
2714					obj.more = false;
2715					obj.visible = true;
2716
2717					counter++;
2718				}
2719			} );
2720
2721			if ( activeFilter[0] ) {
2722				showItems = activeFilter.data( 'showItems' );
2723				activeFilter.data( 'showItems', showItems + counter - 1 );
2724			}
2725
2726			self.render();
2727			self.checkMoreButton();
2728		}
2729
2730		/**
2731		 * [checkmoreButton description]
2732		 * @return {[type]} [description]
2733		 */
2734		self.checkMoreButton = function() {
2735			var check = false;
2736
2737			$.each( itemsData, function( index, obj ) {
2738
2739				if ( self.isItemVisible( obj.slug ) && obj.more ) {
2740					check = true;
2741				}
2742			} );
2743
2744			if ( check ) {
2745				$moreWrapper.removeClass( 'hidden-status' );
2746			} else {
2747				$moreWrapper.addClass( 'hidden-status' );
2748			}
2749		}
2750
2751		/**
2752		 * [anyFilterEnabled description]
2753		 * @return {Boolean} [description]
2754		 */
2755		self.isItemVisible = function( slugs ) {
2756			var slugList = JetElementsTools.getObjectValues( slugs );
2757
2758			for ( var slug in filterData ) {
2759				var checked = filterData[ slug ];
2760
2761				if ( checked && -1 !== slugList.indexOf( slug ) ) {
2762					return true;
2763				}
2764			}
2765
2766			return false;
2767		}
2768
2769		/**
2770		 * [anyFilterEnabled description]
2771		 * @return {Boolean} [description]
2772		 */
2773		self.anyFilterEnabled = function() {
2774
2775			for ( var slug in filterData ) {
2776				if ( filterData[ slug ] ) {
2777					return true;
2778				}
2779			}
2780
2781			return false;
2782		}
2783
2784		/**
2785		 * Render
2786		 *
2787		 * @return void
2788		 */
2789		self.render = function() {
2790			var hideAnimation,
2791				showAnimation;
2792
2793			$itemsList.removeClass( 'visible-status' ).removeClass( 'hidden-status' );
2794
2795			$.each( itemsData, function( index, itemData ) {
2796				var selector = $( '.jet-portfolio__inner', itemData.selector );
2797
2798				if ( itemData.visible ) {
2799					itemData.selector.addClass( 'visible-status' );
2800
2801					showAnimation = anime( {
2802						targets: selector[0],
2803						opacity: {
2804							value: 1,
2805							duration: 400,
2806						},
2807						scale: {
2808							value: 1,
2809							duration: 500,
2810							easing: 'easeOutExpo'
2811						},
2812						delay: 50,
2813						elasticity: false
2814					} );
2815				} else {
2816					itemData.selector.addClass( 'hidden-status' );
2817
2818					hideAnimation = anime( {
2819						targets: selector[0],
2820						opacity: 0,
2821						scale: 0,
2822						duration: 500,
2823						elasticity: false
2824					} );
2825				}
2826			} );
2827
2828			$masonryInstance.masonry( 'layout' );
2829		}
2830	}
2831
2832	/**
2833	 * Jet Timeline Class
2834	 *
2835	 * @return {void}
2836	 */
2837	window.jetTimeLine = function ( $element ){
2838		var $viewport		= $(window),
2839			self			= this,
2840			$line 			= $element.find( '.jet-timeline__line' ),
2841			$progress		= $line.find( '.jet-timeline__line-progress' ),
2842			$cards			= $element.find( '.jet-timeline-item' ),
2843			$points 		= $element.find('.timeline-item__point'),
2844
2845			currentScrollTop 		= $viewport.scrollTop(),
2846			lastScrollTop 			= -1,
2847			currentWindowHeight 	= $(window).height(),
2848			currentViewportHeight 	= $viewport.outerHeight(),
2849			lastWindowHeight 		= -1,
2850			requestAnimationId 		= null,
2851			flag 					= false;
2852
2853		self.onScroll = function (){
2854			currentScrollTop = $viewport.scrollTop();
2855
2856			self.updateFrame();
2857			self.animateCards();
2858		};
2859
2860		self.onResize = function() {
2861			currentScrollTop = $viewport.scrollTop();
2862			currentWindowHeight = $viewport.height();
2863
2864			self.updateFrame();
2865		};
2866
2867		self.updateWindow = function() {
2868			flag = false;
2869
2870			$line.css({
2871				'top' 		: $cards.first().find( $points ).offset().top - $cards.first().offset().top,
2872				'bottom'	: ( $element.offset().top + $element.outerHeight() ) - $cards.last().find( $points ).offset().top
2873			});
2874
2875			if ( ( lastScrollTop !== currentScrollTop ) ) {
2876				lastScrollTop 		= currentScrollTop;
2877				lastWindowHeight = currentWindowHeight;
2878
2879				self.updateProgress();
2880			}
2881		};
2882
2883		self.updateProgress = function() {
2884			var progressFinishPosition = $cards.last().find( $points ).offset().top,
2885				progressHeight = ( currentScrollTop - $progress.offset().top ) + ( currentViewportHe
2885ight / 2 );
2886
2887			if ( progressFinishPosition <= ( currentScrollTop + currentViewportHeight / 2 ) ) {
2888				progressHeight = progressFinishPosition - $progress.offset().top;
2889			}
2890
2891			$progress.css({
2892				'height' : progressHeight + 'px'
2893			});
2894
2895			$cards.each( function() {
2896				if ( $(this).find( $points ).offset().top < ( currentScrollTop + currentViewportHeight * 0.5 ) ) {
2897					$(this).addClass('is--active');
2898				} else {
2899					$(this).removeClass('is--active');
2900				}
2901			});
2902		};
2903
2904		self.updateFrame = function() {
2905			if ( ! flag ) {
2906				requestAnimationId = requestAnimationFrame( self.updateWindow );
2907			}
2908			flag = true;
2909		};
2910
2911		self.animateCards = function() {
2912			$cards.each( function() {
2913				if( $(this).offset().top <= currentScrollTop + currentViewportHeight * 0.9 && $(this).hasClass('jet-timeline-item--animated') ) {
2914					$(this).addClass('is--show');
2915				}
2916			});
2917		};
2918
2919		self.init = function(){
2920			$(document).ready(self.onScroll);
2921			$(window).on('scroll.jetTimeline', self.onScroll);
2922			$(window).on('resize.jetTimeline orientationchange.jetTimeline', JetElementsTools.debounce( 50, self.onResize ));
2923		};
2924	}
2925
2926}( jQuery, window.elementorFrontend ) );

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.