PageSourceSearch

https://esveu.es/wp-content/plugins/jet-tricks/assets/js/jet-tricks-frontend.js?ver=1.5.10

js esveu.es collected 2026-09-24 11:10:00 UTC 46,220 bytes, 1,493 lines download raw bytes

1( function( $, elementor ) {
2
3	'use strict';
4
5	var JetTricks = {
6
7		init: function() {
8			elementor.hooks.addAction( 'frontend/element_ready/section', JetTricks.elementorSection );
9			elementor.hooks.addAction( 'frontend/element_ready/section', JetTricks.elementorColumn );
10			elementor.hooks.addAction( 'frontend/element_ready/container', JetTricks.elementorSection );
11			elementor.hooks.addAction( 'frontend/element_ready/container', JetTricks.elementorColumn );
12			elementor.hooks.addAction( 'frontend/element_ready/column', JetTricks.elementorColumn );
13			elementor.hooks.addAction( 'frontend/element_ready/widget', JetTricks.elementorWidget );
14
15			var widgets = {
16				'jet-view-more.default' : JetTricks.widgetViewMore,
17				'jet-unfold.default' : JetTricks.widgetUnfold,
18				'jet-hotspots.default' : JetTricks.widgetHotspots
19			};
20
21			$.each( widgets, function( widget, callback ) {
22				elementor.hooks.addAction( 'frontend/element_ready/' + widget, callback );
23			});
24
25			// Re-init widgets in nested tabs
26			window.elementorFrontend.elements.$window.on(
27				'elementor/nested-tabs/activate',
28				( event, content ) => {
29
30					const $content = $( content );
31
32					var $button  = $content.find( '.jet-unfold__button' );
33
34					$button.off( 'click.jetUnfold' );
35
36					JetTricks.initWidgetsHandlers( $content );
37					JetTricks.elementorSection( $content );
38
39				}
40			);
41
42			// Add an action when the Swiper Loop Carousel widget is ready on the frontend
43			var loopCarouselTypes = [
44				'loop-carousel.post',
45				'loop-carousel.product',
46				'loop-carousel.post_taxonomy',
47				'loop-carousel.product_taxonomy'
48			];
49			
50			loopCarouselTypes.forEach( function( carouselType ) {
51				elementorFrontend.hooks.addAction( 'frontend/element_ready/' + carouselType, function( $scope, $ ) {
52					
53					$( window ).on( 'load', function() {
54						var loopCarousel = $scope.find( '.swiper' ),
55							swiperInstance = loopCarousel.data( 'swiper' ),
56							$button = $scope.find( '.jet-unfold__button' );
57						
58						if ( swiperInstance && $button ) {
59				
60							$button.off( 'click.jetUnfold' );
61							JetTricks.initLoopCarouselHandlers( $scope );
62				
63							swiperInstance.on( 'slideChange', function() {
64								$button.off( 'click.jetUnfold' );
65								JetTricks.initLoopCarouselHandlers( $scope );
66							});
67						}
68					});
69				});
70			});
71		},
72
73		initLoopCarouselHandlers: function( $selector ) {
74			$selector.find( '.elementor-widget-jet-unfold' ).each( function() {
75
76				var $this  = $( this ),
77
78				elementType = $this.data( 'element_type' );
79
80				if ( !elementType ) {
81					return;
82				}
83
84				if ( 'widget' === elementType ) {
85					elementType = $this.data( 'widget_type' );
86					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
87				}
88
89				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
90				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
91
92
93			} );
94		},
95
96		initWidgetsHandlers: function( $selector ) {
97
98				$selector.find( '[data-element_type]' ).each( function() {
99
100					var excludeWidgets = [
101						'jet-woo-product-gallery-slider.default',
102						'accordion.default',
103						'jet-form-builder-form.default',
104						'nav-menu.default'
105					];
106
107					var $this  = $( this ),
108
109					elementType = $this.data( 'element_type' );
110
111					if ( !elementType ) {
112						return;
113					}
114
115					if ( 'widget' === elementType ) {
116
117						elementType = $this.data( 'widget_type' );
118						
119						if ( excludeWidgets.includes( elementType ) ) {
120							return;
121						}
122						
123						window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
124					}
125
126					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
127					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
128
129
130				} );
131		},
132
133		elementorSection: function( $scope ) {
134			var $target        = $scope,
135				sectionId      = $scope.data( 'id' ),
136				editMode       = Boolean( elementor.isEditMode() ),
137				jetListing     = $target.parents( '.elementor-widget-jet-listing-grid' ).data( 'id' ),
138				settings       = {};
139
140			if ( window.JetTricksSettings && window.JetTricksSettings.elements_data.sections.hasOwnProperty( sectionId ) ) {
141				settings = window.JetTricksSettings.elements_data.sections[ sectionId ];
142			}
143
144			if ( editMode ) {
145				settings = JetTricks.sectionEditorSettings( $scope );
146			}
147
148			if ( ! settings ) {
149				return false;
150			}
151
152			if ( jQuery.isEmptyObject( settings ) ) {
153				return false;
154			}
155
156			if ( 'false' === settings.particles || '' === settings.particles_json ) {
157				return false;
158			}
159
160			// Compatibility jet tricks particles with jet listing
161
162			if ( jetListing && $target.parent().data( 'elementor-type' ) === 'jet-listing-items' ){
163				sectionId += jetListing + $target.parents( '.jet-listing-grid__item' ).data( 'post-id' );
164			} 
165
166			var particlesId   = 'jet-tricks-particles-instance-' + sectionId,
167				particlesJson = JSON.parse( settings.particles_json );
168
169			$scope.prepend( '<div id="' + particlesId + '" class="jet-tricks-particles-section__instance"></div>' );
170
171			// Initialize particles based on library version
172
173			if ( typeof tsParticles !== 'undefined' && tsParticles.load && tsParticles.version && tsParticles.version.startsWith('3.') ) {
174				tsParticles.load({
175					id: particlesId,
176					options: particlesJson
177				});
178			} else if ( typeof tsParticles !== 'undefined' && tsParticles.load ) {
179				tsParticles.load( particlesId, particlesJson );
180			}
181
182		},
183
184		elementorColumn: function( $scope ) {
185			var $target  = $scope,
186				$parentSection = $scope.closest( '.elementor-section' ),
187				isLegacyModeActive = !!$target.find( '> .elementor-column-wrap' ).length,
188				$window  = $( window ),
189				columnId = $target.data( 'id' ),
190				editMode = Boolean( elementor.isEditMode() ),
191				settings = {},
192				stickyInstance = null,
193				stickyInstanceOptions = {
194					topSpacing: 50,
195					bottomSpacing: 50,
196					containerSelector: isLegacyModeActive ? '.elementor-row' : '.elementor-container, .e-con-inner',
197					innerWrapperSelector: isLegacyModeActive ? '.elementor-column-wrap' : '.elementor-widget-wrap',
198				},
199				$observerTarget = $target.find('.elementor-element');
200
201			if ( ! editMode ) {
202				settings = $target.data( 'jet-settings' );
203
204				if ( $target.hasClass( 'jet-sticky-column' ) ) {
205					if ( -1 !== settings['stickyOn'].indexOf( elementorFrontend.getCurrentDeviceMode() ) ) {
206						$target.each( function() {
207							var $this  = $( this ),
208								elementType = $this.data( 'element_type' );
209		
210							if ( settings['behavior'] === 'fixed' ) {
211								initFixedSticky( $this, settings );
212							} else if ( elementType !== 'container' && elementType !== 'section' ) {
213								initSidebarSticky( $this, settings, stickyInstanceOptions );
214							} else if ( settings['behavior'] === 'scroll_until_end' ) {
215								initScrollUntilEndSticky( $this, settings );
216							} else {
217								initDefaultSticky( $this, settings );
218							}
219						});
220					}
221				}
222			}
223
224			function initFixedSticky($element, settings) {
225				var offsetTop = parseInt(settings['topSpacing']) || 0;
226				var bottomSpacing = parseInt(settings['bottomSpacing']) || 0;
227				var $window = $(window);
228				var elementId = $element.data('id');
229				var originalOffsetTop = $element.offset().top;
230				var originalHeight = $element.outerHeight();
231			
232				var $allStickyElements = $('.jet-sticky-column').filter(function() {
233					var $this = $(this);
234					var elementSettings = $this.data('jet-settings');
235
236					return elementSettings && elementSettings.stickyOn.indexOf(elementorFrontend.getCurrentDeviceMode()) !== -1;
237				});
238
239				var currentIndex = $allStickyElements.index($element);
240				var $nextSticky = currentIndex + 1 < $allStickyElements.length ? $allStickyElements.eq(currentIndex + 1) : null;
241				var $stopper = null;
242				if ($nextSticky) {
243					$stopper = $nextSticky.closest('.elementor-top-section, .e-parent');
244					if (!$stopper.length) {
245						$stopper = $nextSticky;
246					}
247				}
248			
249				const $placeholder = $('<div></div>')
250					.addClass('jet-sticky-placeholder')
251					.css({
252						display: 'none',
253						height: originalHeight,
254						width: $element.outerWidth(),
255						visibility: 'hidden'
256					});
257			
258				$element.before($placeholder);				
259			
260				function enableSticky() {
261					$placeholder.show();
262					$element.addClass('jet-sticky-container--stuck');
263			
264					var stopperTop = $stopper?.offset()?.top;
265					var stopPoint = stopperTop ? (stopperTop - $element.outerHeight() - offsetTop - bottomSpacing) : null;
266					var diff = 0;
267			
268					if (stopPoint && stopPoint < $window.scrollTop()) {
269						diff = (stopPoint - $window.scrollTop());
270					}
271			
272					$element.css({
273						position: 'fixed',
274						top: diff + 'px',
275						transform: `translateY(${offsetTop}px)`,
276						left: $placeholder.offset().left + 'px',
277						width: $placeholder.outerWidth() + 'px'
278					});
279				}
280			
281				function disableSticky() {
282					$placeholder.hide();
283					$element.removeClass('jet-sticky-container--stuck');
284			
285					$element.css({
286						position: '',
287						top: '',
288						transform: '',
289						left: '',
290						width: ''
291					});
292				}
293			
294				function onScroll() {
295					var scrollTop = $window.scrollTop();
296					if (scrollTop >= originalOffsetTop) {
297						enableSticky();
298					} else {
299						disableSticky();
300					}
301				}
302			
303				function onResize() {
304					originalOffsetTop = $placeholder.offset().top;
305					originalHeight = $element.outerHeight();
306			
307					$placeholder.css({
308						height: originalHeight,
309						width: $element.outerWidth()
310					});
311			
312					onScroll();
313				}
314			
315				let ticking = false;
316				$window.on('scroll.jetStickyHeader-' + elementId, function() {
317					if (!ticking) {
318						requestAnimationFrame(function() {
319							onScroll();
320							ticking = false;
321						});
322						ticking = true;
323					}
324				});
325			
326				$window.on('resize.jetStickyHeader-' + elementId, JetTricksTools.debounce(100, onResize));
327				onScroll();
328			
329				$window.on('resize.jetStickyHeader-' + elementId, JetTricksTools.debounce(100, function() {
330					if (-1 === settings['stickyOn'].indexOf(elementorFrontend.getCurrentDeviceMode())) {
331						cleanupSticky($element, $placeholder, elementId);
332					}
333				}));
334			}
335			
336			function cleanupSticky( $element, $placeholder, elementId ) {
337				$placeholder.remove();
338				$element.css({
339					position: '',
340					top: '',
341					transform: '',
342					left: '',
343					width: '',
344					zIndex: '',
345					transition: '',
346					willChange: ''
347				});
348				$element.removeClass('jet-sticky-container--stuck');
349				$window.off('scroll.jetStickyHeader-' + elementId);
350				$window.off('resize.jetStickyHeader-' + elementId);
351			}
352
353			function initSidebarSticky( $element, settings, options ) {
354				options.topSpacing = settings['topSpacing'];
355				options.bottomSpacing = settings['bottomSpacing'];
356
357				imagesLoaded( $parentSection, function() {
358					$target.data( 'stickyColumnInit', true );
359					stickyInstance = new StickySidebar( $target[0], options );
360				});
361
362				var targetMutation = $target[0],
363					config = { attributes: true, childList: true, subtree: true };
364
365				var observer = new MutationObserver( function( mutations ) {
366					for( var mutation of mutations ) {
367						if ( 'attributes' === mutation.type && mutation.attributeName !== 'style' ) {
368							$target[0].style.height = 'auto';
369						}
370					}
371				});
372
373				observer.observe( targetMutation, config );
374
375				$window.on( 'resize.JetTricksStickyColumn orientationchange.JetTricksStickyColumn', 
376					JetTricksTools.debounce( 50, resizeDebounce ) );
377
378				var observer = new MutationObserver( function( mutations ) {
379					if ( stickyInstance ) {
380						mutations.forEach( function(mutation){
381							if (mutation.attributeName === 'class') {
382								setTimeout( function() {
383									stickyInstance.destroy();
384									stickyInstance = new StickySidebar( $target[0], options );
385								}, 100 );
386							}
387						});
388					}
389				});
390
391				$observerTarget.each( function(){
392					observer.observe( $( this )[0], {
393						attributes: true
394					});
395				});
396			}
397
398			function initScrollUntilEndSticky( $element, settings ) {
399				const stickyHeight = $element.outerHeight();
400				const stickyContentBottom = $element.offset().top + stickyHeight;
401				const stickyViewportOffset = $window.height() - stickyHeight - settings['bottomSpacing'];
402
403				$('body').addClass('jet-sticky-container');
404
405				$window.on( 'scroll.jetSticky', function () {
406					const scrollPosition = $window.scrollTop();
407
408					if ( scrollPosition + $window.height() >= stickyContentBottom ) {
409						$element.css({
410							position: 'sticky',
411							top: stickyViewportOffset + 'px',
412							bottom: 'auto',
413							left: 'auto',
414							zIndex: settings['zIndex'],
415						});
416					}
417				});
418
419				$observerTarget.on( 'destroy.jetSticky', function () {
420					$window.off( 'scroll.jetSticky' );
421					$('body').removeClass('jet-sticky-container');
422				});
423			}
424
425			function initDefaultSticky( $element, settings ) {
426				$('body').addClass('jet-sticky-container');
427				$element.addClass( 'jet-sticky-container-sticky' );
428				$element.css({ 
429					'top': settings['topSpacing'], 
430					'bottom': settings['bottomSpacing']
431				});
432			}
433
434			function resizeDebounce() {
435				var currentDeviceMode = elementorFrontend.getCurrentDeviceMode(),
436					availableDevices  = settings['stickyOn'] || [],
437					isInit            = $target.data( 'stickyColumnInit' );
438
439				if ( -1 !== availableDevices.indexOf( currentDeviceMode ) ) {
440					if ( ! isInit ) {
441						$target.data( 'stickyColumnInit', true );
442						stickyInstance = new StickySidebar( $target[0], stickyInstanceOptions );
443						stickyInstance.updateSticky();
444					}
445				} else {
446					$target.data( 'stickyColumnInit', false );
447					stickyInstance.destroy();
448				}
449			}
450		},
451
452		elementorWidget: function( $scope ) {
453			var parallaxInstance = null,
454				satelliteInstance = null,
455				tooltipInstance = null;
456
457			parallaxInstance = new jetWidgetParallax( $scope );
458			parallaxInstance.init();
459
460			satelliteInstance = new jetWidgetSatellite( $scope );
461			satelliteInstance.init();
462
463			tooltipInstance = new jetWidgetTooltip( $scope );
464			tooltipInstance.init();
465
466		},
467
468		getElementorElementSettings: function( $scope ) {
469
470			if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) {
471				return JetTricks.getEditorElementSettings( $scope );
472			}
473
474			return $scope.data( 'settings' ) || {};
475		},
476
477		getEditorElementSettings: function( $scope ) {
478			var modelCID = $scope.data( 'model-cid' ),
479				elementData;
480
481			if ( ! modelCID ) {
482				return {};
483			}
484
485			if ( ! elementor.hasOwnProperty( 'config' ) ) {
486				return {};
487			}
488
489			if ( ! elementor.config.hasOwnProperty( 'elements' ) ) {
490				return {};
491			}
492
493			if ( ! elementor.config.elements.hasOwnProperty( 'data' ) ) {
494				return {};
495			}
496
497			elementData = elementor.config.elements.data[ modelCID ];
498
499			if ( ! elementData ) {
500				return {};
501			}
502
503			return elementData.toJSON();
504		},
505
506		widgetViewMore: function( $scope ) {
507			var $target         = $scope.find( '.jet-view-more' ),
508				instance        = null,
509				settings        = $target.data( 'settings' );
510
511			instance = new jetViewMore( $target, settings );
512			instance.init();
513		},
514
515		widgetUnfold: function( $scope ) {
516			var $target                = $scope.find( '.jet-unfold' ),
517				$button                = $( '.jet-unfold__button', $target ),
518				$mask                  = $( '.jet-unfold__mask', $target ),
519				$content               = $( '.jet-unfold__content', $target ),
520				$contentInner          = $( '.jet-unfold__content-inner', $target),
521				$trigger               = $( '.jet-unfold__trigger', $target),
522				$separator             = $( '.jet-unfold__separator', $target ),
523				settings               = $.extend( {}, $target.data( 'settings' ), JetTricks.getElementorElementSettings( $scope ) ),
524				maskBreakpointsHeights = [],
525				prevBreakpoint         = '',
526				unfoldDuration         = settings['unfoldDuration'] || settings['unfold_duration'],
527				foldDuration           = settings['foldDuration'] || settings['fold_duration'],
528				unfoldEasing           = settings['unfoldEasing'] || settings['unfold_easing'],
529				foldEasing             = settings['foldEasing'] || settings['fold_easing'],
530				maskHeightAdv          = 20,
531				heightCalc             = '',
532				autoHide               = settings['autoHide'] || false,
533				autoHideTime           = settings['autoHideTime'] && 0 != settings['autoHideTime']['size'] ? settings['autoHideTime']['size'] : 5,
534				hideOutsideClick       = settings['hideOutsideClick'] || false,
535				heightControlType      = settings['heightControlType'] || 'height',
536				wordCount              = settings['wordCount'] || 20,
537				autoHideTrigger,
538				activeBreakpoints      = elementor.config.responsive.activeBreakpoints,
539				initialLoaded          = false;
540
541			function updateMaskGradientClass() {
542				if (settings.separatorType === 'gradient') {
543					if ($target.hasClass('jet-unfold-state') || $trigger.is(':hidden')) {
544						$mask.removeClass('jet-unfold__mask-gradient');
545					} else {
546						$mask.addClass('jet-unfold__mask-gradient');
547					}
548				}
549			}
550
551			function calculateHeightByWordCount() {
552				
553				var text = $contentInner.text().trim();
554				if (!text) {
555					return 0; 
556				}
557
558				var words = text.split(/\s+/);
559				var wordsToShow = Math.min(getDeviceWordCount(), words.length);
560				var visibleText = words.slice(0, wordsToShow).join(' ');
561				
562								
563				var $tempElement = $contentInner.clone();
564				$tempElement
565					.css({
566						position: 'absolute',
567						visibility: 'hidden',
568						height: 'auto',
569						overflow: 'visible'
570					})
571					.text(visibleText);
572				
573				$contentInner.after($tempElement);
574				var height = $tempElement.outerHeight();
575				
576				$tempElement.remove();
577				
578				return height; 
579			}
580
581			maskBreakpointsHeights['desktop']    = [];
582			maskBreakpointsHeights['widescreen'] = [];
583
584			maskBreakpointsHeights['desktop']['maskHeight'] = (settings['mask_height'] && settings['mask_height']['size'] && '' != settings['mask_height']['size']) ? settings['mask_height']['size'] : 50;
585
586			prevBreakpoint = 'desktop';
587
588			Object.keys(  activeBreakpoints ).reverse().forEach(  function( breakpointName ) {
589
590				if ( 'widescreen' === breakpointName ) {
591					maskBreakpointsHeights['widescreen']['maskHeight'] = (settings['mask_height_widescreen'] && settings['mask_height_widescreen']['size'] && '' != settings['mask_height_widescreen']['size']) ? settings['mask_height_widescreen']['size'] : maskBreakpointsHeights['desktop']['maskHeight'];
592				} else {
593					maskBreakpointsHeights[breakpointName] = [];
594
595					var breakpointSetting = settings['mask_height_' + breakpointName];
596					maskBreakpointsHeights[breakpointName]['maskHeight'] = (breakpointSetting && breakpointSetting['size'] && '' != breakpointSetting['size']) ? breakpointSetting['size'] : maskBreakpointsHeights[prevBreakpoint]['maskHeight'];
597
598					prevBreakpoint = breakpointName;
599				}
600			} );
601
602			onLoaded();
603
604			if ( typeof ResizeObserver !== 'undefined' ) {
605				new ResizeObserver( function( entries ) {
606					if ( $target.hasClass( 'jet-unfold-state' ) ) {
607						$mask.css( {
608							'height': $contentInner.outerHeight()
609						} );
610					}
611				} ).observe( $contentInner[0] );
612			}
613			
614			if ( 'true' === hideOutsideClick ) {
615				$( window ).on( 'mouseup', function( event ) {
616					let container = $target;
617					if ( !container.is( event.target ) && 0 === container.has( event.target ).length && $target.hasClass( 'jet-unfold-state' ) ) {
618						$button.trigger( 'click' );
619					}
620				} )
621			}
622
623			$target.one('transitionend webkitTransitionEnd oTransitionEnd', function() {
624				if ( !initialLoaded ) {
625					onLoaded();
626					initialLoaded = true;
627				}
628			});
629
630			function onLoaded() {
631				initialLoaded = true;
632
633				var deviceHeight = getDeviceHeight();
634
635				heightCalc = +deviceHeight + maskHeightAdv;
636
637				if ( heightCalc < $contentInner.height() ) {
638
639					if ( ! $target.hasClass( 'jet-unfold-state' ) ) {
640						$separator.css( {
641							'opacity': '1'
642						} );
643					}
644
645					if ( ! $target.hasClass( 'jet-unfold-state' ) ) {
646						$mask.css( {
647							'height': deviceHeight
648						} );
649					} else {
650						$mask.css( {
651							'height': $contentInner.outerHeight()
652						} );
653					}
654					$trigger.css( 'display', 'flex' );
655					updateMaskGradientClass();
656				} else {
657					$trigger.hide();
658					$mask.css( {
659						'height': '100%'
660					} );
661					$content.css( {
662						'max-height': 'none'
663					} );
664					$separator.css( {
665						'opacity': '0'
666					} );
667					updateMaskGradientClass();
668				}
669			}
670
671			$( window ).on( 'resize.jetWidgetUnfold orientationchange.jetWidgetUnfold', JetTricksTools.debounce( 50, function(){
672				initialLoaded = false;
673				onLoaded();
674			} ) );
675
676			$button.keypress( function( e ) {
677				if ( e.which == 13 ) {
678					$button.click();
679					return false;
680				}
681			} );
682
683			$button.on( 'click.jetUnfold', function(e) {
684				var $this         = $( this ),
685					$buttonText   = $( '.jet-unfold__button-text', $this ),
686					unfoldText    = $this.data( 'unfold-text' ),
687					foldText      = $this.data( 'fold-text' ),
688					$buttonIcon   = $( '.jet-unfold__button-icon', $this ),
689					unfoldIcon    = $this.data( 'unfold-icon' ),
690					foldIcon      = $this.data( 'fold-icon' ),
691					contentHeight = $contentInner.outerHeight(),
692					deviceHeight  = getDeviceHeight();
693
694				e.preventDefault();
695
696				if ( ! $target.hasClass( 'jet-unfold-state' ) ) {
697					$target.addClass( 'jet-unfold-state' );
698
699					$separator.css( {
700						'opacity': '0'
701					} );
702
703					$buttonIcon.html( foldIcon );
704					$buttonText.html( foldText );
705
706					// Force recalculation of content height after state change
707					setTimeout(function() {
708						contentHeight = $contentInner.outerHeight();
709						
710						anime( {
711							targets: $mask[0],
712							height: contentHeight,
713							duration: unfoldDuration['size'],
714							easing: unfoldEasing,
715							complete: function( anim ) {
716								// Recalculate listing masonry.
717								$( document ).trigger( 'jet-engine/listing/recalculate-masonry' );
718							}
719						} );
720					}, 0);
721
722					if ( 'true' === autoHide ) {
723						autoHideTrigger = setTimeout( function() {
724							$button.trigger( 'click' );
725						}, autoHideTime * 1000 );
726					}
727				} else {
728					clearTimeout( autoHideTrigger );
729
730					$target.removeClass( 'jet-unfold-state' );
731
732					$separator.css( {
733						'opacity': '1'
734					} );
735
736					$buttonIcon.html( unfoldIcon );
737					$buttonText.html( unfoldText );
738
739					anime( {
740						targets: $mask[0],
741						height: deviceHeight,
742						duration: foldDuration['size'],
743						easing: foldEasing,
744						complete: function( anim ) {
745							if ( 'true' === settings['foldScrolling'] ) {
746								$( 'html, body' ).animate( {
747									scrollTop: $target.offset().top - settings['foldScrollOffset']['size']
748								}, 'slow' );
749							}
750
751							// Recalculate listing masonry.
752							$( document ).trigger( 'jet-engine/listing/recalculate-masonry' );
753						}
754					} );
755				}
756				
757				updateMaskGradientClass();
758			} );
759
760			function getDeviceHeight() {
761				if (heightControlType === 'word_count') {
762					return calculateHeightByWordCount();
763				}
764
765				let device = elementorFrontend.getCurrentDeviceMode();
766				let heightSettings;
767
768				switch ( device ) {
769
770					case 'mobile':
771						heightSettings = settings.mask_height_mobile;
772						break;
773
774					case 'tablet':
775						heightSettings = settings.mask_height_tablet;
776						break;
777
778					default:
779						heightSettings = settings.mask_height;
780
781				}
782
783				if ( ! heightSettings || ! heightSettings.size || ! heightSettings.unit ) {
784					heightSettings = settings.mask_height;
785				}
786
787				switch ( heightSettings.unit ) {
788
789					case 'vh':
790						return ( window.innerHeight * heightSettings.size ) / 100;
791
792					case '%':
793						let parentHeight = $contentInner.parent().height();
794						return ( parentHeight * heightSettings.size ) / 100;
795
796					default:
797						return heightSettings.size;
798				}
799			}
800
801			function getDeviceWordCount() {
802				let device = elementorFrontend.getCurrentDeviceMode();
803				let value;
804
805				switch ( device ) {
806					case 'mobile':
807						value = settings.word_count_mobile;
808						break;
809					case 'tablet':
810						value = settings.word_count_tablet;
811						break;
812					default:
813						value = settings.word_count;
814				}
815
816				if ( value !== null && value !== undefined ) {
817					return parseInt( value, 10 );
818				}
819
820				return 20;
821			}
822		},
823
824		widgetHotspots: function( $scope ) {
825			var $target   = $scope.find( '.jet-hotspots' ),
826				$hotspots = $( '.jet-hotspots__item', $target),
827				settings  = $target.data( 'settings' ),
828				editMode  = Boolean( elementor.isEditMode() ),
829				itemActiveClass = 'jet-hotspots__item--active';
830
831			$target.imagesLoaded().progress( function() {
832				$target.addClass( 'image-loaded' );
833			} );
834
835			$hotspots.each( function( index ) {
836				var $this          = $( this ),
837					horizontal     = $this.data( 'horizontal-position' ),
838					vertical       = $this.data( 'vertical-position' ),
839					tooltipWidth   = $this.data( 'tooltip-width' ) || null,
840					showOnInit     = $this.data( 'show-on-init' ),
841					itemSelector   = $this[0],
842					options        = {};
843
844				$this.css( {
845					'left': horizontal + '%',
846					'top': vertical + '%'
847				} );
848
849				if ( itemSelector._tippy ) {
850					itemSelector._tippy.destroy();
851				}
852
853				options = {
854					content: $this.data('tippy-content'),
855					arrow: settings['tooltipArrow'] ? true : false,
856					placement: settings['tooltipPlacement'],
857					trigger: settings['tooltipTrigger'],
858					appendTo: editMode ? document.body : $target[0],
859					hideOnClick: 'manual' !== settings['tooltipTrigger'],
860					maxWidth: 'none',
861					offset: [0, settings['tooltipDistance']['size']],
862					allowHTML: true,
863					interactive: settings['tooltipInteractive'] ? true : false,
864					onShow( instance ) {
865						$( itemSelector ).addClass( itemActiveClass );
866
867						if ( tooltipWidth ) {
868							instance.popper.querySelector( '.tippy-box' ).style.width = tooltipWidth;
869						}
870
871					},
872					onHidden( instance ) {
873						$( itemSelector ).removeClass( itemActiveClass );
874					}
875				}
876
877				if ( 'manual' != settings['tooltipTrigger'] ) {
878					options['duration']  = [ settings['tooltipShowDuration']['size'], settings['tooltipHideDuration']['size'] ];
879					options['animation'] = settings['tooltipAnimation'];
880					options['delay']     = settings['tooltipDelay'];
881				}
882
883				tippy( [ itemSelector ], options );
884
885				if ( 'manual' === settings['tooltipTrigger'] && itemSelector._tippy ) {
886					itemSelector._tippy.show();
887				}
888			
889				if ( ( showOnInit === 'yes' || settings['tooltipShowOnInit'] ) && itemSelector._tippy ) {
890					itemSelector._tippy.show();
891				}
892
893			} );
894		},
895
896		columnEditorSettings: function( columnId ) {
897			var editorElements = null,
898				columnData     = {};
899
900			if ( ! window.elementor.hasOwnProperty( 'elements' ) ) {
901				return false;
902			}
903
904			editorElements = window.elementor.elements;
905
906			if ( ! editorElements.models ) {
907				return false;
908			}
909
910			$.each( editorElements.models, function( index, obj ) {
911
912				$.each( obj.attributes.elements.models, function( index, obj ) {
913					if ( columnId == obj.id ) {
914						columnData = obj.attributes.settings.attributes;
915					}
916				} );
917
918			} );
919
920			return {
921				'sticky': columnData['jet_tricks_column_sticky'] || false,
922				'topSpacing': columnData['jet_tricks_top_spacing'] || 50,
923				'bottomSpacing': columnData['jet_tricks_bottom_spacing'] || 50,
924				'stickyOn': columnData['jet_tricks_column_sticky_on'] || [ 'desktop', 'tablet', 'mobile']
925			}
926
927		},
928
929		sectionEditorSettings: function( $scope ) {
930			var editorElements = null,
931				sectionData     = {};
932
933			if ( ! window.elementor.hasOwnProperty( 'elements' ) ) {
934				return false;
935			}
936
937			sectionData = JetTricks.getElementorElementSettings( $scope );
938
939			return {
940				'particles': sectionData['section_jet_tricks_particles'] || 'false',
941				'particles_json': sectionData['section_jet_tricks_particles_json'] || '',
942			}
943
944		}
945
946	};
947
948	$( window ).on( 'elementor/frontend/init', JetTricks.init );
949
950	var JetTricksTools = {
951		debounce: function( threshold, callback ) {
952			var timeout;
953
954			return function debounced( $event ) {
955				function delayed() {
956					callback.call( this, $event );
957					timeout = null;
958				}
959
960				if ( timeout ) {
961					clearTimeout( timeout );
962				}
963
964				timeout = setTimeout( delayed, threshold );
965			};
966		},
967
968		widgetEditorSettings: function( widgetId ) {
969			var editorElements = null,
970				widgetData = {};
971		
972			if ( !window.elementor.hasOwnProperty( 'elements' ) || !window.elementor.elements.models ) {
973				return false;
974			}
975		
976			editorElements = window.elementor.elements;
977		
978			function findWidgetById( models, widgetId ) {
979				let foundData = null;
980		
981				$.each( models, function( index, obj ) {
982					if ( obj.id === widgetId ) {
983						foundData = obj.attributes.settings.attributes;
984						return false;
985					}
986					if ( obj.attributes.elements && obj.attributes.elements.models ) {
987						foundData = findWidgetById( obj.attributes.elements.models, widgetId );
988						if ( foundData ) {
989							return false;
990						}
991					}
992				});
993		
994				return foundData;
995			}
996		
997			widgetData = findWidgetById( editorElements.models, widgetId ) || {};
998
999			return {
1000				'speed': widgetData['jet_tricks_widget_parallax_speed'] || { 'size': 50, 'unit': '%'},
1001				'parallax': widgetData['jet_tricks_widget_parallax'] || 'false',
1002				'invert': widgetData['jet_tricks_widget_parallax_invert'] || 'false',
1003				'stickyOn': widgetData['jet_tricks_widget_parallax_on'] || [ 'desktop', 'tablet', 'mobile'],
1004				'satellite': widgetData['jet_tricks_widget_satellite'] || 'false',
1005				'satelliteType': widgetData['jet_tricks_widget_satellite_type'] || 'text',
1006				'satellitePosition': widgetData['jet_tricks_widget_satellite_position'] || 'top-center',
1007				'satelliteText': widgetData['jet_tricks_widget_satellite_text'] || 'Lorem Ipsum',
1008				'satelliteIcon': widgetData['selected_jet_tricks_widget_satellite_icon'] || '',
1009				'satelliteImage': widgetData['jet_tricks_widget_satellite_image'] || '',
1010				'satelliteLink': widgetData['jet_tricks_widget_satellite_link'] || '',
1011				'tooltip': widgetData['jet_tricks_widget_tooltip'] || 'false',
1012				'tooltipDescription': widgetData['jet_tricks_widget_tooltip_description'] || 'Lorem Ipsum',
1013				'tooltipPlacement': widgetData['jet_tricks_widget_tooltip_placement'] || 'top',
1014				'tooltipArrow': 'true' === widgetData['jet_tricks_widget_tooltip_arrow'] ? true : false,
1015				'xOffset': widgetData['jet_tricks_widget_tooltip_x_offset'] || 0,
1016				'yOffset': widgetData['jet_tricks_widget_tooltip_y_offset'] || 0,
1017				'tooltipAnimation': widgetData['jet_tricks_widget_tooltip_animation'] || 'shift-toward',
1018				'tooltipTrigger': widgetData['jet_tricks_widget_tooltip_trigger'] || 'mouseenter',
1019				'customSelector': widgetData['jet_tricks_widget_tooltip_custom_selector'] || '',
1020				'zIndex': widgetData['jet_tricks_widget_tooltip_z_index'] || '999',
1021				'appendTo': widgetData['jet_tricks_widget_tooltip_append_to'] || 'widget',
1022				'delay': widgetData['jet_tricks_widget_tooltip_delay'] || '0',
1023				'followCursor': widgetData['jet_tricks_widget_tooltip_follow_cursor'] || 'false'
1024			}
1025		}
1026	}
1027
1028	/**
1029	 * Jet jetViewMore Class
1030	 *
1031	 * @return {void}
1032	 */
1033	window.jetViewMore = function( $selector, settings ) {
1034		var self            = this,
1035			$window         = $( window ),
1036			$button         = $( '.jet-view-more__button', $selector ),
1037			defaultSettings = {
1038				sections: {},
1039				effect: 'move-up',
1040				showall: false
1041			},
1042			settings        = $.extend( {}, defaultSettings, settings ),
1043			sections        = settings['sections'],
1044			sectionsData    = {},
1045			editMode        = Boolean( elementor.isEditMode() ),
1046			readLess      = settings['read_less'] || false,
1047			readMoreLabel   = settings['read_more_label'],
1048			readLessLabel   = settings['read_less_label'],
1049			readMoreIcon    = settings['read_more_icon'],
1050			readLessIcon    = settings['read_less_icon'],
1051			hideAll         = settings['hide_all'] || false,
1052			isOpened        = false;
1053
1054		/**
1055		 * Init
1056		 */
1057		self.init = function() {
1058			self.setSectionsData();
1059
1060			if ( editMode ) {
1061				return false;
1062			}			
1063
1064			function hideSection($section) {
1065				// Apply hide effect if available
1066				if (settings['hide_effect'] && settings['hide_effect'] !== 'none') {
1067					$section.addClass('view-more-hiding');
1068					$section.addClass('jet-tricks-' + settings['hide_effect'] + '-hide-effect');
1069					
1070					// Remove classes after animation completes
1071					(function($currentSection) {
1072						$currentSection.on('animationend', function animationEndHandler() {
1073							$currentSection.off('animationend', animationEndHandler);
1074							$currentSection.removeClass('view-more-hiding');
1075							$currentSection.removeClass('jet-tricks-' + settings['hide_effect'] + '-hide-effect');
1076							$currentSection.css('height', '');
1077							$currentSection.removeClass('view-more-visible');
1078							$currentSection.removeClass('jet-tricks-' + settings['effect'] + '-effect');
1079						});
1080					})($section);
1081				} else {
1082					$section.css('height', '');
1083					$section.removeClass('view-more-visible');
1084					$section.removeClass('jet-tricks-' + settings['effect'] + '-effect');
1085				}
1086			}
1087
1088			function showAllSections() {
1089				for ( var section in sectionsData ) {
1090					var $section = sectionsData[ section ]['selector'];
1091					sectionsData[ section ]['visible'] = true;
1092					$section.css('height', $section[0].scrollHeight + 'px');
1093					$section.addClass( 'view-more-visible' );
1094					$section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' );
1095				}
1096			}
1097
1098			function hideAllSections() {
1099				for ( var section in sectionsData ) {
1100					var $section = sectionsData[ section ]['selector'];
1101					sectionsData[ section ]['visible'] = false;
1102					hideSection($section);
1103				}
1104			}
1105
1106			function showNextSection() {
1107				for ( var section in sectionsData ) {
1108					var $section = sectionsData[ section ]['selector'];
1109					if ( !sectionsData[ section ]['visible'] ) {
1110						sectionsData[ section ]['visible'] = true;
1111						$section.css('height', $section[0].scrollHeight + 'px');
1112						$section.addClass( 'view-more-visible' );
1113						$section.addClass( 'jet-tricks-' + settings['effect'] + '-effect' );
1114						break;
1115					}
1116				}
1117			}
1118
1119			function hideNextSection() {
1120				var sectionKeys = Object.keys(sectionsData).reverse();
1121				for (var i = 0; i < sectionKeys.length; i++) {
1122					var sectionKey = sectionKeys[i];
1123					var $section = sectionsData[sectionKey]['selector'];
1124					if (sectionsData[sectionKey]['visible']) {
1125						sectionsData[sectionKey]['visible'] = false;
1126						hideSection($section);
1127						break;
1128					}
1129				}
1130			}
1131
1132			$button.on('click', function() {
1133				if (readLess) {
1134					if (!isOpened) {
1135						if (!settings.showall) {
1136							showNextSection();
1137							var allVisible = true;
1138							for (var section in sectionsData) {
1139								if (!sectionsData[section]['visible']) {
1140									allVisible = false;
1141									break;
1142								}
1143							}
1144							if (allVisible) {
1145								$button.find('.jet-view-more__label').text(readLessLabel);
1146								if (readLessIcon && readLessIcon.value) {
1147									$button.find('.jet-view-more__icon').html('<i class="' + readLessIcon.value + '"></i>');
1148								}
1149								$button.addClass('jet-view-more__button--read-less');
1150								isOpened = true;
1151							}
1152						} else {
1153							showAllSections();
1154							$button.find('.jet-view-more__label').text(readLessLabel);
1155							if (readLessIcon && readLessIcon.value) {
1156								$button.find('.jet-view-more__icon').html('<i class="' + readLessIcon.value + '"></i>');
1157							}
1158							$button.addClass('jet-view-more__button--read-less');
1159							isOpened = true;
1160						}
1161					} else {
1162						if (hideAll) {
1163							hideAllSections();
1164							$button.find('.jet-view-more__label').text(readMoreLabel);
1165							if (readMoreIcon && readMoreIcon.value) {
1166								$button.find('.jet-view-more__icon').html('<i class="' + readMoreIcon.value + '"></i>');
1167							}
1168							$button.removeClass('jet-view-more__button--read-less');
1169							isOpened = false;
1170						} else {
1171							hideNextSection();
1172							var allHidden = true;
1173							for (var section in sectionsData) {
1174								if (sectionsData[section]['visible']) {
1175									allHidden = false;
1176									break;
1177								}
1178							}
1179							if (allHidden) {
1180								$button.find('.jet-view-more__label').text(readMoreLabel);
1181								if (readMoreIcon && readMoreIcon.value) {
1182									$button.find('.jet-view-more__icon').html('<i class="' + readMoreIcon.value + '"></i>');
1183								}
1184								$button.removeClass('jet-view-more__button--read-less');
1185								isOpened = false;
1186							}
1187						}
1188					}
1189				} else {
1190					if (!settings.showall) {
1191						showNextSection();
1192					} else {
1193						showAllSections();
1194					}
1195					var allVisible = true;
1196					for (var section in sectionsData) {
1197						if (!sectionsData[section]['visible']) {
1198							allVisible = false;
1199							break;
1200						}
1201					}
1202					if (allVisible) {
1203						$button.css({ 'display': 'none' });
1204					}
1205				}
1206			});
1207
1208			$button.keydown(function(e) {
1209				var $which = e.which || e.keyCode;
1210				if ($which == 13 || $which == 32) {
1211					e.preventDefault();
1212					if (readLess) {
1213						$button.trigger('click');
1214					} else {
1215						if (!settings.showall) {
1216							showNextSection();
1217						} else {
1218							showAllSections();
1219						}
1220						var allVisible = true;
1221						for (var section in sectionsData) {
1222							if (!sectionsData[section]['visible']) {
1223								allVisible = false;
1224								break;
1225							}
1226						}
1227						if (allVisible) {
1228							$button.css({ 'display': 'none' });
1229						}
1230					}
1231				}
1232			});
1233		};
1234
1235		self.setSectionsData = function() {
1236
1237			for ( var section in sections ) {
1238				var $selector = $( '#' + sections[ section ] );
1239
1240				if ( ! editMode ) {
1241					$selector.addClass( 'jet-view-more-section' );
1242				} else {
1243					$selector.addClass( 'jet-view-more-section-edit-mode' );
1244				}
1245
1246				sectionsData[ section ] = {
1247					'section_id': sections[ section ],
1248					'selector': $selector,
1249					'visible': false,
1250				}
1251			}
1252		};
1253	};
1254
1255	/**
1256	 * [jetWidgetParallax description]
1257	 * @param  {[type]} $scope [description]
1258	 * @return {[type]}        [description]
1259	 */
1260	window.jetWidgetParallax = function( $scope ) {
1261		var self         = this,
1262			$target      = $scope,
1263			$section     = $scope.closest( '.elementor-top-section' ),
1264			widgetId     = $scope.data('id'),
1265			settings     = {},
1266			editMode     = Boolean( elementor.isEditMode() ),
1267			$window      = $( window ),
1268			isSafari     = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/),
1269			platform     = navigator.platform,
1270			safariClass  = isSafari ? 'is-safari' : '',
1271			macClass    = 'MacIntel' == platform ? ' is-mac' : '';
1272
1273		/**
1274		 * Init
1275		 */
1276		self.init = function() {
1277
1278			$scope.addClass( macClass );
1279
1280			if ( ! editMode ) {
1281				settings = $scope.data( 'jet-tricks-settings' );
1282			} else {
1283				settings = JetTricksTools.widgetEditorSettings( widgetId );
1284			}
1285
1286			if ( ! settings ) {
1287				return false;
1288			}
1289
1290			if ( 'undefined' === typeof settings ) {
1291				return false;
1292			}
1293
1294			if ( 'false' === settings['parallax'] || 'undefined' === typeof settings['parallax'] ) {
1295				return false;
1296			}
1297
1298			$window.on( 'scroll.jetWidgetParallax resize.jetWidgetParallax', self.scrollHandler ).trigger( 'resize.jetWidgetParallax' );
1299		};
1300
1301		self.scrollHandler = function( event ) {
1302			var speed             = +settings['speed']['size'] * 0.01,
1303				invert            = 'true' == settings['invert'] ? -1 : 1,
1304				winHeight         = $window.height(),
1305				winScrollTop      = $window.scrollTop(),
1306				offsetTop         = $scope.offset().top,
1307				thisHeight        = $scope.outerHeight(),
1308				sectionHeight     = $section.outerHeight(),
1309				positionDelta     = winScrollTop - offsetTop + ( winHeight / 2 ),
1310				abs               = positionDelta > 0 ? 1 : -1,
1311				posY              = abs * Math.pow( Math.abs( positionDelta ), 0.85 ),
1312				availableDevices  = settings['stickyOn'] || [],
1313				currentDeviceMode = elementorFrontend.getCurrentDeviceMode();
1314
1315			posY = invert * Math.ceil( speed * posY );
1316
1317			if ( -1 !== availableDevices.indexOf( currentDeviceMode ) ) {
1318				$target.css( {
1319					'transform': 'translateY(' + posY + 'px)'
1320				} );
1321			} else {
1322				$target.css( {
1323					'transform': 'translateY(0)'
1324				} );
1325			}
1326		};
1327	};
1328
1329	/**
1330	 * [jetWidgetSatellite description]
1331	 * @param  {[type]} $scope [description]
1332	 * @return {[type]}        [description]
1333	 */
1334	window.jetWidgetSatellite = function( $scope ) {
1335		var self     = this,
1336			widgetId = $scope.data('id'),
1337			settings = {},
1338			editMode = Boolean( elementor.isEditMode() );
1339
1340		/**
1341		 * Init
1342		 */
1343		self.init = function() {
1344
1345			if ( ! editMode ) {
1346				settings = $scope.data( 'jet-tricks-settings' );
1347			} else {
1348				settings = JetTricksTools.widgetEditorSettings( widgetId );
1349			}
1350
1351			if ( ! settings || typeof settings !== 'object' ) {
1352				return false;
1353			}
1354
1355			if ( 'false' === settings['satellite'] || 'undefined' === typeof settings['satellite'] ) {
1356				return false;
1357			}
1358
1359			$scope.addClass( 'jet-satellite-widget' );
1360
1361			$( '.jet-tricks-satellite', $scope ).addClass( 'jet-tricks-satellite--' + settings['satellitePosition'] );
1362
1363			//satellite display in edit mode
1364			if ( editMode && $scope.find( '.jet-tricks-satellite' ).length === 0 ) {
1365				var html = '';
1366				var pos = settings['satellitePosition'] || 'top-center';
1367
1368				var link = settings['satelliteLink'] || {};
1369				var linkStart = '', linkEnd = '';
1370				if ( link.url ) {
1371					linkStart = '<a class="jet-tricks-satellite__link">';
1372					linkEnd = '</a>';
1373				}
1374
1375				if ( settings['satelliteType'] === 'text' && settings['satelliteText'] ) {
1376					html = '<div class="jet-tricks-satellite jet-tricks-satellite--' + pos + '"><div class="jet-tricks-satellite__inner"><div class="jet-tricks-satellite__text">' + linkStart + '<span>' + settings['satelliteText'] + '</span>' + linkEnd + '</div></div></div>';
1377				} else if ( settings['satelliteType'] === 'icon' && settings['satelliteIcon'] && settings['satelliteIcon'].value ) {
1378					html = '<div class="jet-tricks-satellite jet-tricks-satellite--' + pos + '"><div class="jet-tricks-satellite__inner"><div class="jet-tricks-satellite__icon">' + linkStart + '<div class="jet-tricks-satellite__icon-instance jet-tricks-icon"><i class="' + settings['satelliteIcon'].value + '"></i></div>' + linkEnd + '</div></div></div>';
1379				} else if ( settings['satelliteType'] === 'image' && settings['satelliteImage'] && settings['satelliteImage'].url ) {
1380					html = '<div class="jet-tricks-satellite jet-tricks-satellite--' + pos + '"><div class="jet-tricks-satellite__inner"><div class="jet-tricks-satellite__image">' + linkStart + '<img class="jet-tricks-satellite__image-instance" src="' + settings['satelliteImage'].url + '" alt="">' + linkEnd + '</div></div></div>';
1381				}
1382
1383				if ( html ) {
1384					$scope.prepend(html);
1385				}
1386			}
1387		};
1388	};
1389
1390	/**
1391	 * [jetWidgetTooltip description]
1392	 * @param  {[type]} $scope [description]
1393	 * @return {[type]}        [description]
1394	 */
1395	window.jetWidgetTooltip = function( $scope ) {
1396		var self            = this,
1397			widgetId        = $scope.data('id'),
1398			widgetSelector  = $scope[0],
1399			tooltipSelector = widgetSelector,
1400			settings        = {},
1401			editMode        = Boolean( elementor.isEditMode() ),
1402			delay,
1403			tooltipEvent    = editMode ? 'click' : 'mouseenter';
1404
1405		/**
1406		 * Init
1407		 */
1408		self.init = function() {
1409
1410			if ( ! editMode ) {
1411				settings = $scope.data( 'jet-tricks-settings' );
1412			} else {
1413				settings = JetTricksTools.widgetEditorSettings( widgetId );
1414			}
1415
1416			if ( widgetSelector._tippy ) {
1417				widgetSelector._tippy.destroy();
1418			}
1419
1420			if ( ! settings ) {
1421				return false;
1422			}
1423
1424			if ( 'undefined' === typeof settings ) {
1425				return false;
1426			}
1427
1428			if ( 'false' === settings['tooltip'] || 'undefined' === typeof settings['tooltip'] || '' === settings['tooltipDescription'] ) {
1429				return false;
1430			}
1431
1432			$scope.addClass( 'jet-tooltip-widget' );
1433
1434			if ( settings['customSelector'] ) {
1435				tooltipSelector = $( '.' + settings['customSelector'], $scope )[0];
1436			}
1437
1438			if ( editMode && ! $( '#jet-tricks-tooltip-content-' + widgetId )[0] ) {
1439				var template = $( '<div>', {
1440					id: 'jet-tricks-tooltip-content-' + widgetId,
1441					class: 'jet-tooltip-widget__content'
1442				} );
1443
1444				template.html( settings['tooltipDescription'] );
1445				$scope.append( template );
1446			}
1447
1448			var appendToBody = editMode || ( settings['appendTo'] === 'body' );
1449
1450			tippy(
1451				[ tooltipSelector ],
1452				{
1453					content: $scope.find( '.jet-tooltip-widget__content' )[0].innerHTML,
1454					allowHTML: true,
1455					//appendTo: widgetSelector,
1456					appendTo: appendToBody ? document.body : widgetSelector,
1457					arrow: settings['tooltipArrow'] ? true : false,
1458					placement: settings['tooltipPlacement'],
1459					offset: [ settings['xOffset'], settings['yOffset'] ],
1460					animation: settings['tooltipAnimation'],
1461					trigger: settings['tooltipTrigger'],
1462					interactive: settings['followCursor'] === 'false' || settings['followCursor'] === '
1462initial',
1463					zIndex: settings['zIndex'],
1464					maxWidth: 'none',
1465					delay: settings['delay']['size'] ? settings['delay']['size'] : 0,
1466					followCursor: settings['followCursor'] === 'false' ? false : (settings['followCursor'] === 'true' ? true : settings['followCursor']),
1467					onCreate: function (instance) {
1468						if ( appendToBody ) {
1469							var tippyId = editMode ? ( tooltipSelector.getAttribute('data-id') || widgetId ) : widgetId;
1470							if ( tippyId ) {
1471								instance.popper.classList.add( 'tippy-' + tippyId );
1472							}
1473						}
1474					},
1475					onShow: function (instance) {
1476						// JetFormBuilder Formless Actions Endpoints compatibility
1477						var addButtonListeners = window.crocoblock && window.crocoblock.frontComponents && window.crocoblock.frontComponents.addButtonListeners;
1478						if ( addButtonListeners && instance.popper ) {
1479							var buttons = instance.popper.querySelectorAll( '[data-jfb-submit-endpoint]' );
1480							buttons.forEach( function (el) { addButtonListeners( el ); } );
1481						}
1482					}
1483				}
1484			);
1485
1486			if ( editMode && widgetSelector._tippy ) {
1487				widgetSelector._tippy.show();
1488			}
1489
1490		};
1491	};
1492	
1493}( 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.