PageSourceSearch

https://www.oacps.org/wp-content/plugins/jet-tabs/assets/js/jet-tabs-frontend.js?ver=2.3.3.2

js oacps.org collected 2026-10-02 03:57:12 UTC 61,105 bytes, 1,954 lines download raw bytes

1// Promise polyfill
2!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(e){return!(!e||"undefined"==typeof e.length)}function t(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],c(e,this)}function r(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(r){return void f(n.promise,r)}i(n.promise,o)}else(1===e._state?i:f)(n.promise,e._value)})):e._deferreds.push(n)}function i(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof o)return e._state=3,e._value=n,void u(e);if("function"==typeof t)return void c(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,u(e)}catch(r){f(e,r)}}function f(e,n){e._state=2,e._value=n,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;t>n;n++)r(e,e._deferreds[n]);e._deferreds=null}function c(e,n){var t=!1;try{e(function(e){t||(t=!0,i(n,e))},function(e){t||(t=!0,f(n,e))})}catch(o){if(t)return;t=!0,f(n,o)}}var a=setTimeout;o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var o=new this.constructor(t);return r(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,n,o)),o},o.prototype["finally"]=e,o.all=function(e){return new o(function(t,o){function r(e,n){try{if(n&&("object"==typeof n||"function"==typeof n)){var u=n.then;if("function"==typeof u)return void u.call(n,function(n){r(e,n)},o)}i[e]=n,0==--f&&t(i)}catch(c){o(c)}}if(!n(e))return o(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(t,r){if(!n(e))return r(new TypeError("Promise.race accepts an array"));for(var i=0,f=e.length;f>i;i++)o.resolve(e[i]).then(t,r)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=o});
3
4( function( $, elementor, settings ) {
5
6	'use strict';
7
8	var JetTabs = {
9
10		addedScripts: {},
11
12		addedStyles: {},
13
14		addedAssetsPromises: [],
15
16		init: function() {
17			var widgets = {
18				'jet-tabs.default': JetTabs.tabsInit,
19				'jet-accordion.default': JetTabs.accordionInit,
20				'jet-image-accordion.default': JetTabs.imageAccordionInit,
21				'jet-switcher.default': JetTabs.switcherInit,
22			};
23
24			$.each( widgets, function( widget, callback ) {
25				elementor.hooks.addAction( 'frontend/element_ready/' + widget, callback );
26			});
27
28			// Add an action when the Swiper Loop Carousel widget is ready on the frontend
29			elementorFrontend.hooks.addAction('frontend/element_ready/loop-carousel.post', function($scope, $) {
30
31				$(window).on('load', function() {
32
33					var loopCarousel = $scope.find('.swiper'),
34					swiperInstance = loopCarousel.data( 'swiper' ),
35					$toggle  = $scope.find( '.jet-toggle__control'),
36					$switcher  = $scope.find( '.jet-switcher__control-instance');
37
38					if( swiperInstance && ($toggle || $switcher) ) {
39
40						swiperInstance.on('slideChange', function () {
41							$toggle.off('click.jetAccordion');
42							$switcher.off('click.jetSwitcher');
43							JetTabs.initLoopCarouselHandlers( $scope );
44						});
45					}
46				});
47			});
48		},
49
50		initLoopCarouselHandlers: function( $selector ) {
51			$selector.find( '.elementor-widget-jet-accordion, .elementor-widget-jet-switcher' ).each( function() {
52
53				var $this  = $( this ),
54
55				elementType = $this.data( 'element_type' );
56
57				if ( !elementType ) {
58					return;
59				}
60
61				if ( 'widget' === elementType ) {
62					elementType = $this.data( 'widget_type' );
63					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
64				}
65
66				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
67				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
68
69
70			} );
71		},
72
73		tabsInit: async function( $scope ) {
74			var $target         = $( '.jet-tabs', $scope ).first(),
75				$widgetId       = $target.data( 'id' ),
76				$window         = $( window ),
77				$controlWrapper = $( '.jet-tabs__control-wrapper', $target ).first(),
78				$contentWrapper = $( '.jet-tabs__content-wrapper', $target ).first(),
79				$controlList    = $( '.jet-tabs__control', $controlWrapper ),
80				$contentList    = $( '> .jet-tabs__content', $contentWrapper ),
81				settings        = $.extend( $target.data( 'settings' ) || {}, JetTabs.getElementorElementSettings( $scope ) ),
82				anchorSelectors = [],
83				toogleEvents    = 'mouseenter mouseleave',
84				scrollOffset,
85				autoSwitchInterval = null,
86				resumeTimeout   = null,
87				curentHash      = window.location.hash || false,
88				tabsArray       = curentHash ? curentHash.replace( '#', '' ).split( '&' ) : false,
89				$tabsPosition = settings['tabsPosition'],
90				$tabsPositionClassList = [],
91				$tabsPositionBreakpoints = [],
92				prevDevice,
93				currentDeviceMode = elementorFrontend.getCurrentDeviceMode(),
94				activeBreakpoints = elementor.config.responsive.activeBreakpoints,
95				swiperSettings 	  = $target.data( 'swiper-settings' ) || {},
96				swiper;
97
98			JetTabs.prepareVideoIframes( $contentWrapper );
99			JetTabs.observeVideoIframes( $contentWrapper );
100
101			function syncSwiperToIndex( index, immediate = false ) {
102				if ( ! swiper ) return;
103				try {
104					swiper.slideToLoop( index, immediate ? 0 : swiperOptions.speed, true );
105				} catch ( e ) {
106				}
107			}
108
109			prevDevice = 'desktop';
110
111			$tabsPositionBreakpoints['desktop'] = '' != settings['tabs_position'] ? settings['tabs_position'] : 'top';
112			$tabsPositionClassList['desktop']   = "jet-tabs-position-" + $tabsPositionBreakpoints['desktop'];
113
114			Object.keys( activeBreakpoints ).reverse().forEach( function( breakpointName ) {
115
116				if ( 'widescreen' === breakpointName ) {
117					$tabsPositionBreakpoints[breakpointName] = ( settings['tabs_position_' + breakpointName] && '' != settings['tabs_position_' + breakpointName] ) ? settings['tabs_position_' + breakpointName] : 'top';
118					$tabsPositionClassList[breakpointName]   =  "jet-tabs-position-" + $tabsPositionBreakpoints[breakpointName];
119				} else {
120					$tabsPositionBreakpoints[breakpointName] = ( settings['tabs_position_' + breakpointName] && '' != settings['tabs_position_' + breakpointName] ) ? settings['tabs_position_' + breakpointName] : $tabsPositionBreakpoints[prevDevice];
121					$tabsPositionClassList[breakpointName]   = "jet-tabs-position-" + $tabsPositionBreakpoints[breakpointName];
122
123					prevDevice = breakpointName;
124				}
125			} );
126
127			if ( !$target.hasClass( $tabsPositionClassList[currentDeviceMode] ) ) {
128				for ( const [key, value] of Object.entries( $tabsPositionClassList ) ) {
129					$target.removeClass( value );
130				}
131
132				$target.addClass( $tabsPositionClassList[currentDeviceMode] );
133			}
134
135			if ( 'click' === settings['event'] ) {
136				addClickEvent();
137			} else {
138				addMouseEvent();
139			}
140
141			$window.load(function() {
142
143				var currentActiveContent = $contentList.eq( [settings['activeIndex']] ),
144					currentActiveContentHeight = currentActiveContent.outerHeight( true );
145
146				if ( 'yes' != settings['no_active_tabs'] ) {
147					currentActiveContentHeight += parseInt( $contentWrapper.css( 'border-top-width' ) ) + parseInt( $contentWrapper.css( 'border-bottom-width' ) );
148					$contentWrapper.css( 'min-height', currentActiveContentHeight );
149				}
150
151			});
152
153			if ( 'left' !== $tabsPositionBreakpoints[currentDeviceMode] && 'right' !== $tabsPositionBreakpoints[currentDeviceMode] ) {
154				var observerConfig = {childList: true, subtree: true },
155					observerTarget = $( ".jet-tabs__content.active-content", $scope );
156
157				if ( observerTarget[0] ) {
158					var observerCallback = ( mutationList, observer ) => {
159						for ( var mutation of mutationList ) {
160							if ( mutation.type === 'childList' ) {
161								observerTarget.closest( '.jet-tabs__content-wrapper' ).css( 'min-height', 'auto' );
162
163								var activeContentHeight = observerTarget.outerHeight( true );
164
165								activeContentHeight += parseInt( observerTarget.css( 'border-top-width' ) ) + parseInt( observerTarget.css( 'border-bottom-width' ) );
166								observerTarget.closest( '.jet-tabs__content-wrapper' ).css( 'min-height', activeContentHeight );
167							}
168						}
169					};
170
171					var observer = new MutationObserver( observerCallback );
172
173					observer.observe( observerTarget[0], observerConfig );
174				}
175			}
176
177			const swiperOptions = {
178				slidesPerView: 'auto',
179				centeredSlides: swiperSettings.centeredSlides || false,
180				loop: swiperSettings.loop || false,
181				loopFillGroupWithBlank: true,
182				speed: 300,
183				navigation: {
184					nextEl: $target.find('.swiper-button-next')[0],
185					prevEl: $target.find('.swiper-button-prev')[0],
186				},
187				keyboard: true,
188				allowTouchMove: true,
189				slideToClickedSlide: false,
190				autoplay: settings['autoSwitch'] ? {
191					delay: settings['autoSwitchDelay'],
192					disableOnInteraction: false,
193					stopOnLastSlide: true,
194				} : false,
195			};
196
197			const $swiper     = $scope.find( '.jet-tabs-swiper' ),
198				adjustedDelay = settings['autoSwitchDelay'] ? +settings['autoSwitchDelay'] + ( $swiper.length ? swiperOptions.speed : 0 ) : 0;
199
200			function scheduleAutoSwitch( fromIndex ) {
201				if ( ! settings[ 'autoSwitch' ] ) return;
202
203				var controlListLength = $controlList.length;
204
205				clearInterval( autoSwitchInterval );
206				if ( resumeTimeout ) clearTimeout( resumeTimeout );
207
208				var nextIndex = ( typeof fromIndex === 'number' )
209					? fromIndex
210					: ( settings[ 'activeIndex' ] === -1 ? -1 : settings[ 'activeIndex' ] );
211
212				autoSwitchInterval = setInterval( function() {
213					nextIndex = ( nextIndex + 1 + controlListLength ) % controlListLength;
214
215					if ( settings[ 'ajaxTemplate' ] ) {
216						ajaxLoadTemplate( nextIndex );
217					}
218					switchTab( nextIndex );
219					if ( $swiper.length ) {
220						syncSwiperToIndex( nextIndex );
221						const $swiperContainer = $swiper.find( '.jet-tabs-swiper-container' );
222						$swiperContainer.find( '.swiper-slide' ).removeClass( 'active-tab' );
223						$swiperContainer.find( '.swiper-slide[data-swiper-slide-index="' + nextIndex + '"]' ).addClass( 'active-tab' );
224					}
225				}, adjustedDelay );
226			}
227
228			function resumeAutoSwitch( fromIndex ) {
229				if ( ! settings[ 'autoSwitch' ] ) return;
230
231				clearInterval( autoSwitchInterval );
232				if ( resumeTimeout ) clearTimeout( resumeTimeout );
233
234				resumeTimeout = setTimeout( function() {
235					scheduleAutoSwitch( fromIndex );
236				}, adjustedDelay );
237			}
238
239			function stopAutoplay() {
240				if ( swiper.autoplay && swiper.autoplay.running ) {
241					swiper.autoplay.stop();
242					clearInterval( autoSwitchInterval );
243				}
244			}
245
246			if ( $swiper.length ) {
247				const $swiperContainer = $swiper.find( '.jet-tabs-swiper-container' );
248
249				if ( swiperSettings.slidesPerView === 'fixed' ) {
250					$swiperContainer.find( '.swiper-slide' ).css( 'width', swiperSettings.itemWidth );
251				}
252
253				if ( $swiperContainer.length && $swiperContainer.hasClass( 'swiper' ) ) {
254					swiper = await new window.elementorFrontend.utils.swiper( $swiperContainer[0], swiperOptions );
255
256					const formFieldSelector = [
257						'.jet-tabs__content-wrapper input',
258						'.jet-tabs__content-wrapper textarea',
259						'.jet-tabs__content-wrapper select',
260						'.jet-tabs__content-wrapper [contenteditable="true"]',
261					].join(', ');
262
263					$target.on('keydown.jetTabsSwiperFix', formFieldSelector, function( e ) {
264						var code = e.which || e.keyCode;
265
266						if ( code === 37 || code === 38 || code === 39 || code === 40 ) {
267							e.stopPropagation();
268						}
269					});
270
271					const initialIndex = settings['activeIndex'] === -1 ? 0 : settings['activeIndex'];
272
273					swiper.slideToLoop( initialIndex, 0, false );
274
275					if ( settings['autoSwitch'] && settings['activeIndex'] === -1 ) {
276						swiper.autoplay.stop();
277						setTimeout( () => swiper.autoplay.start(), adjustedDelay );
278					}
279
280					swiper.on( 'reachEnd', function () {
281
282						if ( settings['autoSwitch'] && swiper.isEnd && ! swiperSettings.loop ) {
283							const lastSlide = $swiperContainer.find( '.swiper-slide' ).last()[0];
284
285							const observer = new MutationObserver( ( mutationsList ) => {
286
287								for ( const mutation of mutationsList ) {
288									if ( mutation.type === 'attributes' && lastSlide.classList.contains('active-tab') ) {
289										observer.disconnect();
290
291										setTimeout( () => {
292											swiper.slideTo( 0, swiperOptions.speed, true );
293											swiper.autoplay.start();
294										}, adjustedDelay );
295
296									}
297								}
298
299							});
300
301							observer.observe( lastSlide, { attributes: true, attributeFilter: ['class'] } );
302						}
303
304					});
305
306					function handleTabSwitch( eventSlide ) {
307						const realIndex = parseInt( eventSlide.getAttribute( 'data-swiper-slide-index' ), 10 );
308
309						$swiperContainer.find('.swiper-slide.active-tab').removeClass('active-tab');
310						$( eventSlide ).addClass('active-tab');
311
312						switchTab( realIndex );
313						stopAutoplay();
314						clearInterval( autoSwitchInterval );
315					}
316
317					function addHoverAndTouchEvents() {
318						const $allSlides = $swiperContainer.find( '.swiper-slide' );
319
320						$allSlides.off( 'mouseenter touchend' );
321
322						$allSlides.on( 'mouseenter', function () {
323							stopAutoplay();
324							handleTabSwitch( this );
325						});
326
327						$allSlides.on( 'touchend', function () {
328
329							if ( scrollOffset !== $( window ).scrollTop() ) {
330								return false;
331							}
332
333							handleTabSwitch( this );
334						});
335					}
336
337					if ( swiperSettings.loop ) {
338						if ( settings['event'] === 'click' ) {
339							swiper.on( 'click', function () {
340
341								if ( swiper.clickedSlide ) {
342									handleTabSwitch( swiper.clickedSlide) ;
343								}
344
345							});
346						} else if ( settings['event'] === 'hover' ) {
347							addHoverAndTouchEvents();
348
349							swiper.on( 'transitionEnd', function () {
350								addHoverAndTouchEvents();
351							});
352						}
353					}
354
355					$swiperContainer.on( 'click', function() {
356						stopAutoplay();
357						clearInterval( autoSwitchInterval );
358					});
359
360					if ( settings['event'] === 'hover' ) {
361						$swiperContainer.on('mouseenter', function () {
362							stopAutoplay();
363						});
364					}
365
366					swiper.on( 'autoplay', function () {
367						$swiperContainer.find('.swiper-slide').removeClass('active-tab');
368
369						const currentIndex = swiper.realIndex;
370						$swiperContainer.find('.swiper-slide[data-swiper-slide-index="' + currentIndex + '"]').addClass('active-tab');
371					});
372
373					swiper.on( 'navigationPrev', stopAutoplay );
374					swiper.on( 'navigationNext', stopAutoplay );
375					swiper.on( 'touchStart', stopAutoplay );
376				}
377			}
378
379			if ( settings[ 'autoSwitch' ] ) {
380				var currentIndex   = -1;
381				autoSwitchInterval = setInterval( function() {
382					var $visibleControls = $controlWrapper.find( '.jet-tabs__control:visible' );
383					var len              = $visibleControls.length;
384
385					if ( ! len ) return;
386
387					currentIndex = ( currentIndex + 1 ) % len;
388
389					var $activeControl = $visibleControls.eq( currentIndex );
390					var tabId          = parseInt( $activeControl.data( 'tab' ), 10 ) - 1;
391
392					if ( settings[ 'ajaxTemplate' ] && $activeControl.data( 'template-id' ) ) {
393						ajaxLoadTemplate( tabId );
394					}
395
396					switchTab( tabId );
397
398				}, adjustedDelay );
399
400			}
401
402			if ( settings['ajaxTemplate'] ) {
403				ajaxLoadTemplate( settings['activeIndex'] );
404			}
405
406			$( window ).on( 'resize.jetTabs orientationchange.jetTabs', JetTabs.debounce( 50, function() {
407				currentDeviceMode = elementorFrontend.getCurrentDeviceMode();
408
409				for ( const [key, value] of Object.entries( $tabsPositionClassList ) ) {
410					$target.removeClass( value );
411				}
412
413				$target.addClass( $tabsPositionClassList[currentDeviceMode] );
414			} ) );
415
416			/**
417			 * [addClickEvent description]
418			 */
419			function addClickEvent() {
420				$controlList.on( 'click.jetTabs', function() {
421					var $this = $( this ),
422						tabId = +$this.data( 'tab' ) - 1,
423						templateId = $this.data( 'template-id' );
424
425					clearInterval( autoSwitchInterval );
426
427					if ( settings['ajaxTemplate'] && templateId ) {
428						ajaxLoadTemplate( tabId );
429					}
430
431					switchTab( tabId );
432					resumeAutoSwitch( tabId );
433				});
434			}
435
436			/**
437			 * [addMouseEvent description]
438			 */
439			function addMouseEvent() {
440				if ( 'ontouchend' in window || 'ontouchstart' in window ) {
441					$controlList.on( 'touchstart', function( event ) {
442						scrollOffset = $( window ).scrollTop();
443					} );
444
445					$controlList.on( 'touchend', function( event ) {
446						var $this = $( this ),
447							tabId = +$this.data( 'tab' ) - 1,
448							templateId = $this.data( 'template-id' );
449
450						if ( scrollOffset !== $( window ).scrollTop() ) {
451							return false;
452						}
453
454						clearInterval( autoSwitchInterval );
455
456						if ( settings['ajaxTemplate'] && templateId ) {
457							ajaxLoadTemplate( tabId );
458						}
459
460						switchTab( tabId );
461						if ( $swiper.length ) syncSwiperToIndex( tabId );
462						resumeAutoSwitch( tabId );
463					} );
464
465				} else {
466					$controlList.on( 'mouseenter', function( event ) {
467						var $this = $( this ),
468							tabId = +$this.data( 'tab' ) - 1,
469							templateId = $this.data( 'template-id' );
470
471						clearInterval( autoSwitchInterval );
472
473						if ( settings['ajaxTemplate'] && templateId ) {
474							ajaxLoadTemplate( tabId );
475						}
476
477						switchTab( tabId );
478					} );
479				}
480			}
481
482			$( '.jet-tabs__control', $scope ).keydown( function( e ) {
483				var $this  = $( this ),
484					$which = e.which || e.keyCode;
485
486					if ( $which == 13 || $which == 32 ) {
487						if ( !$this.hasClass( 'active-tab' ) ) {
488							$this.click();
489							return false;
490						}
491					}
492
493					if ( $which == 37 ) {
494						var prevTabId  = $this.prev().data('tab'),
495							templateId = $this.prev().data( 'template-id' );
496
497						if ( undefined != prevTabId ) {
498							clearInterval( autoSwitchInterval );
499
500							if ( settings['ajaxTemplate'] && templateId ) {
501								ajaxLoadTemplate( prevTabId - 1 );
502							}
503
504							switchTab( prevTabId - 1);
505							$this.prev().focus();
506						} else {
507							$this.focus();
508						}
509					}
510
511					if ( $which == 39 ) {
512						var nextTabId  = $this.next().data('tab'),
513							templateId = $this.next().data( 'template-id' );
514
515						if ( undefined != nextTabId ) {
516							clearInterval( autoSwitchInterval );
517
518							if ( settings['ajaxTemplate'] && templateId ) {
519								ajaxLoadTemplate( nextTabId - 1 );
520							}
521
522							switchTab( nextTabId - 1 );
523							$this.next().focus();
524						} else {
525							$this.focus();
526						}
527					}
528			} );
529
530			/**
531			 * [switchTab description]
532			 * @param  {[type]} curentIndex [description]
533			 * @return {[type]}             [description]
534			 */
535			function switchTab( curentIndex ) {
536				var activeContentHeight   = 'auto',
537					timer,
538					$controlWrapperHeight = $controlWrapper.outerHeight( true ),
539					currentDeviceMode     = elementorFrontend.getCurrentDeviceMode(),
540					controlsHeight        = 0;
541
542				$controlList = $controlWrapper.find( '.jet-tabs__control' );
543				$contentList = $contentWrapper.children( '.jet-tabs__content' );
544
545				var $prevActiveContent = $contentWrapper.children( '.jet-tabs__content.active-content' );
546				JetTabs.pauseMediaInContainer( $prevActiveContent );
547
548				var $activeControl = $controlList.filter( '[data-tab="' + ( curentIndex + 1 ) + '"]' ).first();
549
550				if ( ! $activeControl.length ) {
551					$activeControl = $controlList.eq( curentIndex );
552				}
553
554				var controlId      = $activeControl.attr( 'id' );
555				var $activeContent = controlId
556					? $contentList.filter( '[aria-labelledby="' + controlId + '"]' )
557					: $();
558
559				if ( ! $activeContent.length ) {
560					$activeContent = $contentList.filter( '[data-tab="' + ( curentIndex + 1 ) + '"]' );
561				}
562				if ( ! $activeContent.length ) {
563					$activeContent = $contentList.eq( curentIndex );
564				}
565
566				$controlList.removeClass( 'active-tab' ).attr( 'aria-expanded', 'false' );
567				$contentList.removeClass( 'active-content' ).attr( 'aria-hidden', 'true' );
568
569				$activeControl.addClass( 'active-tab' ).attr( 'aria-expanded', 'true' );
570				$activeContent.addClass( 'active-content' ).attr( 'aria-hidden', 'false' );
571				JetTabs.restoreMediaInContainer( $activeContent );
572
573
574				if ( $controlWrapper.css( 'align-self' ) === 'stretch' ) {
575					$( '.jet-tabs__control', $controlWrapper ).each( function() {
576						controlsHeight += $( this ).outerHeight( true );
577					} );
578					$controlWrapperHeight = controlsHeight;
579				}
580
581				activeContentHeight = $activeContent.outerHeight( true );
582				activeContentHeight += parseInt( $contentWrapper.css( 'border-top-width' ) ) + parseInt( $contentWrapper.css( 'border-bottom-width' ) );
583
584				if ( 'left' === $tabsPositionBreakpoints[ currentDeviceMode ] || 'right' === $tabsPositionBreakpoints[ currentDeviceMode ] ) {
585					if ( activeContentHeight < $controlWrapperHeight ) {
586						$target.css( { 'min-height': 'auto' } );
587						$contentWrapper.css( { 'min-height': $controlWrapperHeight } );
588						$target.css( { 'min-height': $controlWrapperHeight } );
589					} else if ( activeContentHeight < $contentWrapper.outerHeight( true ) ) {
590						$contentWrapper.css( { 'min-height': activeContentHeight } );
591						$target.css( { 'min-height': activeContentHeight } );
592					}
593				} else {
594					$contentWrapper.css( { 'min-height': activeContentHeight } );
595
596					var observerConfig = { childList: true, subtree: true },
597						observerTarget = $contentWrapper;
598
599					if ( observerTarget[ 0 ] ) {
600						var observerCallback = ( mutationList, observer ) => {
601							for ( var mutation of mutationList ) {
602								if ( mutation.type === 'childList' ) {
603									activeContentHeight = $activeContent.outerHeight( true );
604									activeContentHeight += parseInt( $contentWrapper.css( 'border-top-width' ) ) + parseInt( $contentWrapper.css( 'border-bottom-width' ) );
605									$contentWrapper.css( { 'min-height': activeContentHeight } );
606								}
607							}
608						};
609
610						var observer = new MutationObserver( observerCallback );
611
612						observer.observe( observerTarget[ 0 ], observerConfig );
613					}
614				}
615
616				$window.trigger( 'jet-tabs/tabs/show-tab-event/before', {
617					target: $target,
618					tabIndex: curentIndex,
619				} );
620
621				if ( timer ) {
622					clearTimeout( timer );
623				}
624
625				timer = setTimeout( function() {
626					$window.trigger( 'jet-tabs/tabs/show-tab-event/after', {
627						target: $target,
628						tabIndex: curentIndex,
629					} );
630
631					if ( true === settings['switchScrolling'] ) {
632						$( 'html, body' ).animate( {
633							scrollTop: $contentWrapper.offset().top - settings['switchScrollingOffset']['size']
634						}, 300 );
635					}
636				}, 500 );
637			}
638
639			/**
640			 * [ajaxLoadTemplate description]
641			 * @param  {[type]} $index [description]
642			 * @return {[type]}        [description]
643			 */
644			function ajaxLoadTemplate( $index ) {
645				var $contentHolder = $contentList.eq( $index ),
646					templateLoaded = $contentHolder.data( 'template-loaded' ) || false,
647					templateId     = $contentHolder.data( 'template-id' ),
648					loader         = $( '.jet-tabs-loader', $contentHolder ),
649					ajaxData = {
650						'id': templateId,
651						'dev': window.JetTabsSettings.devMode,
652					};
653
654				if ( templateLoaded || false === templateId ) {
655					return false;
656				}
657
658				$window.trigger( 'jet-tabs/ajax-load-template/before', {
659					toggleIndex: $index,
660					target: $target,
661					contentHolder: $contentHolder
662				} );
663
664				$contentHolder.data( 'template-loaded', true );
665
666				if ( window.JetTabsSettings.isSelfRequest ) {
667					ajaxData['jet_tabs_self'] = 1;
668					ajaxData['no-cache'] 	  = 'true';
669					ajaxData['timeStamp']     = Date.now();
670				}
671
672				$.ajax( {
673					type: 'GET',
674					url: window.JetTabsSettings.templateApiUrl,
675					dataType: 'json',
676					data: ajaxData,
677					success: function( response ) {
678						if ( ! response || 'undefined' === typeof response.template_content ) {
679							loader.remove();
680							$contentHolder.data( 'template-loaded', false );
681							return;
682						}
683
684						var templateContent = response.template_content,
685						    templateScripts = response.template_scripts || {},
686						    templateStyles  = response.template_styles || {},
687						    assetsPromises  = [];
688
689						for ( var scriptHandler in templateScripts ) {
690							assetsPromises.push(
691								JetTabs.loadScriptAsync( scriptHandler, templateScripts[ scriptHandler ] )
692							);
693						}
694
695						for ( var styleHandler in templateStyles ) {
696							assetsPromises.push(
697								JetTabs.loadStyle( styleHandler, templateStyles[ styleHandler ] )
698							);
699						}
700
701						Promise.allSettled( assetsPromises ).then( function( results ) {
702							loader.remove();
703
704							$contentHolder.html( templateContent );
705
706							JetTabs.prepareVideoIframes( $contentHolder );
707							JetTabs.observeVideoIframes( $contentWrapper );
708							JetTabs.elementorFrontendInit( $contentHolder );
709
710							$window.trigger( 'jet-tabs/ajax-load-template/after', {
711								toggleIndex: $index,
712								target: $target,
713								contentHolder: $contentHolder,
714								responce: response,
715								response: response
716							} );
717						}, );
718					},
719					error: function( jqXHR, textStatus, errorThrown ) {
720						loader.remove();
721						$contentHolder.data( 'template-loaded', false );
722					}
723				} );//end
724			}
725
726			// Hash Watch Handler
727			if ( tabsArray ) {
728
729				$controlList.each( function( index ) {
730					var $this      = $( this ),
731						id         = $this.attr( 'id' ),
732						templateId = $this.data( 'template-id' ),
733						tabIndex   = index;
734
735					tabsArray.forEach( function( itemHash, i ) {
736
737						if ( itemHash === id ) {
738
739							if ( settings['ajaxTemplate'] && templateId ) {
740								ajaxLoadTemplate( tabIndex );
741							}
742
743							switchTab( tabIndex );
744						}
745					} );
746
747				} );
748			}
749
750			$controlList.each( function() {
751				anchorSelectors.push( 'a[href*="#' + $( this ).attr( 'id' ) + '"]' );
752			} );
753
754			$( document ).on( 'click.jetTabAnchor', anchorSelectors.join( ',' ), function( event ) {
755				var $hash = $( this.hash );
756
757				if ( ! $hash.closest( $scope )[0] ) {
758					return;
759				}
760
761				var tabInx = $hash.data( 'tab' ) - 1;
762
763				if ( settings['ajaxTemplate'] ) {
764					ajaxLoadTemplate( tabInx );
765				}
766
767				switchTab( tabInx );
768			} );
769
770		},// tabsInit end
771
772		switcherInit: function( $scope ) {
773			var $target          = $( '.jet-switcher', $scope ).first(),
774				$widgetId        = $target.data( 'id' ),
775				$window          = $( window ),
776				$controlWrapper  = $( '.jet-switcher__control-wrapper', $target ).first(),
777				$contentWrapper  = $( '.jet-switcher__content-wrapper', $target ).first(),
778				$controlInstance = $( '> .jet-switcher__control-instance', $controlWrapper ),
779				$controlList     = $( '> .jet-switcher__control-instance > .jet-switcher__control, > .jet-switcher__control', $controlWrapper ),
780				$contentList     = $( '> .jet-switcher__content', $contentWrapper ),
781				$disableContent  = $( '> .jet-switcher__content--disable', $contentWrapper ),
782				$enableContent   = $( '> .jet-switcher__content--enable', $contentWrapper ),
783				state            = $target.hasClass( 'jet-switcher--disable' ),
784				settings         = $target.data( 'settings' ) || {},
785				toogleEvents     = 'mouseenter mouseleave',
786				scrollOffset;
787
788			var heightResetTimer = null;
789			$target.on('click.jetSwitcherAnchors', '.jet-listing a[href^="#"]', function(e) {
790				var href = this.getAttribute('href');
791				if (!href || href === '#') return;
792
793				var targetID = href.slice(1);
794				var targetEl = document.getElementById(targetID);
795				if (!targetEl) return;
796
797				e.preventDefault();
798
799				if (heightResetTimer) {
800					clearTimeout(heightResetTimer);
801					heightResetTimer = null;
802				}
803
804				$contentWrapper.css({ height: 'auto' });
805
806				var $activeTab = $(targetEl).closest('.jet-switcher__content');
807				var firstListing = $activeTab.length ? $activeTab[0].querySelector('.jet-listing') : null;
808				var offset = firstListing ? (firstListing.offsetHeight - firstListing.scrollHeight) : 0;
809
810				var adminBar = document.getElementById('wpadminbar');
811				var adminOffset = adminBar ? adminBar.offsetHeight : 0;
812
813				var topPos = targetEl.getBoundingClientRect().top + window.scrollY + offset - adminOffset;
814
815				window.scrollTo({ top: topPos, behavior: 'smooth' });
816
817				if (history && history.replaceState) {
818					history.replaceState(null, '', '#' + targetID);
819				} else {
820					window.location.hash = targetID;
821				}
822			});
823
824			JetTabs.observeVideoIframes( $contentWrapper );
825
826			if ( 'ontouchend' in window || 'ontouchstart' in window ) {
827				addTouchEvent();
828			} else {
829				addClickEvent();
830			}
831
832			$( window ).on( 'resize.jetSwitcher orientationchange.jetSwitcher', function() {
833				$contentWrapper.css( { 'height': 'auto' } );
834			} );
835
836			$( '.jet-switcher__control', $scope ).keydown( function( e ) {
837				var $this  = $( this ),
838					$which = e.which || e.keyCode;
839
840				if ( $which == 13 || $which == 32 ) {
841					switchTab();
842					$( '[aria-expanded="true"]', $scope ).focus();
843				}
844
845				if ( $which == 37 ) {
846					if ( 0 != $this.prev().length && $this.prev().hasClass( 'jet-switcher__control' ) && $target.hasClass( 'jet-switcher--preset-1' ) ) {
847						$this.prev().focus();
848						switchTab();
849					} else if ( $target.hasClass( 'jet-switcher--preset-2' ) ) {
850						if ( $this.hasClass( 'jet-switcher__control--disable' ) ) {
851							return false;
852						} else if ( $this.hasClass( 'jet-switcher__control--enable' ) ) {
853							$( '.jet-switcher__control--disable', $scope ).focus();
854							switchTab();
855						}
856					}
857				}
858
859				if ( $which == 39 ) {
860					if ( 0 != $this.next().length && $this.next().hasClass( 'jet-switcher__control' ) && $target.hasClass( 'jet-switcher--preset-1' ) ) {
861						$this.next().focus();
862						switchTab();
863					} else if ( $target.hasClass( 'jet-switcher--preset-2' ) ) {
864						if ( $this.hasClass( 'jet-switcher__control--disable' ) ) {
865							$( '.jet-switcher__control--enable', $scope ).focus();
866							switchTab();
867						} else if ( $this.hasClass( 'jet-switcher__control--enable' ) ) {
868							return false;
869						}
870					}
871				}
872			} );
873
874			function addClickEvent() {
875				$controlInstance.on( 'click.jetSwitcher', function() {
876					switchTab();
877				});
878			}
879
880			function addTouchEvent() {
881
882				$controlInstance.on( 'touchstart', function( event ) {
883					scrollOffset = $( window ).scrollTop();
884				} );
885
886				$controlInstance.on( 'touchend', function( event ) {
887					if ( scrollOffset !== $( window ).scrollTop() ) {
888						return false;
889					}
890
891					switchTab();
892
893				} );
894			}
895
896			function switchTab( curentIndex ) {
897				var $activeControl, $activeContent,
898					activeContentHeight = 'auto',
899					timer;
900
901				if (heightResetTimer) {
902					clearTimeout(heightResetTimer);
903					heightResetTimer = null;
904				}
905
906				$contentWrapper.css( { 'height': $contentWrapper.outerHeight( true ) } );
907
908				$target.toggleClass( 'jet-switcher--disable jet-switcher--enable' );
909
910				if ( $target.hasClass( 'jet-switcher--disable' ) ) {
911					state = false;
912				} else {
913					state = true;
914				}
915
916				$activeControl = ! state ? $controlList.eq(0) : $controlList.eq(1);
917				$activeContent = ! state ? $contentList.eq(0) : $contentList.eq(1);
918
919				$contentList.removeClass( 'active-content' );
920				activeContentHeight = $activeContent.outerHeight( true );
921				activeContentHeight += parseInt( $contentWrapper.css( 'border-top-width' ) ) + parseInt( $contentWrapper.css( 'border-bottom-width' ) );
922				$activeContent.addClass( 'active-content' );
923
924				$controlList.attr( 'aria-expanded', 'false' );
925				$activeControl.attr( 'aria-expanded', 'true' );
926
927				$contentList.attr( 'aria-hidden', 'true' );
928				$activeContent.attr( 'aria-hidden', 'false' );
929
930				$contentWrapper.css( { 'height': activeContentHeight } );
931
932				heightResetTimer = setTimeout( function() {
933					$contentWrapper.css( { 'height': 'auto' } );
934					heightResetTimer = null;
935				}, 500 );
936
937				$window.trigger( 'jet-tabs/switcher/show-case-event/before', {
938					target: $target,
939					caseIndex: curentIndex,
940				} );
941
942				if ( timer ) {
943					clearTimeout( timer );
944				}
945
946				timer = setTimeout( function() {
947					$window.trigger( 'jet-tabs/switcher/show-case-event/after', {
948						target: $target,
949						caseIndex: curentIndex,
950					} );
951				}, 500 );
952			}
953		},
954
955		recalcReadMoreBox: function($anyChild) {
956			var $box = $anyChild.closest('.jet-view-more-section.view-more-visible');
957			if (!$box.length) {
958				$box = $anyChild.closest('.jet-view-more__content');
959			}
960			if (!$box.length) {
961				$box = $anyChild.closest('[data-jet-view-more]');
962			}
963			if (!$box.length) return;
964
965			var content = $box.find('.jet-view-more__content, .elementor-widget-container, .e-con-inner').first()[0] || $box[0];
966
967			requestAnimationFrame(function(){
968				$box[0].style.height = '';
969				var h = content.scrollHeight;
970				$box.css('max-height', h + 'px');
971			});
972		},
973
974		accordionInit: function( $scope ) {
975			var $target              = $( '.jet-accordion', $scope ).first(),
976				$widgetId            = $target.data( 'id' ),
977				$window              = $( window ),
978				$controlsList        = $( '> .jet-accordion__inner > .jet-toggle > .jet-toggle__control', $target ),
979				settings             = $.extend( $target.data( 'settings' ) || {}, JetTabs.getElementorElementSettings( $scope ) ),
980				$toggleList          = $( '> .jet-accordion__inner > .jet-toggle', $target ),
981				anchorSelectors      = [],
982				timer, timer2, timerСlick,
983				curentHash           = window.location.hash || false,
984				togglesArray         = curentHash ? curentHash.replace( '#', '' ).split( '&' ) : false;
985
986			function getResponsiveAccordionSetting( baseKey ) {
987				var currentDeviceMode = elementorFrontend.getCurrentDeviceMode();
988
989				if ( 'mobile' === currentDeviceMode && settings.hasOwnProperty( baseKey + 'Mobile' ) ) {
990					return settings[ baseKey + 'Mobile' ];
991				}
992
993				if ( 'tablet' === currentDeviceMode && settings.hasOwnProperty( baseKey + 'Tablet' ) ) {
994					return settings[ baseKey + 'Tablet' ];
995				}
996
997				return settings[ baseKey ];
998			}
999
1000			function isResponsiveScrollEnabled() {
1001				var value = getResponsiveAccordionSetting( 'switchScrolling' );
1002
1003				return true === value || 'yes' === value || 'true' === value;
1004			}
1005
1006			function getResponsiveScrollOffset() {
1007				var value = getResponsiveAccordionSetting( 'switchScrollingOffset' );
1008
1009				if ( value && 'object' === typeof value && undefined !== value.size ) {
1010					return parseInt( value.size || 0, 10 );
1011				}
1012
1013				return parseInt( value || 0, 10 );
1014			}
1015
1016			function getResponsiveScrollDelay() {
1017				var value = getResponsiveAccordionSetting( 'switchScrollingDelay' );
1018				value     = parseInt( value, 10 );
1019
1020				return isNaN( value ) ? 500 : value;
1021			}
1022
1023			$toggleList.each( function() {
1024				if ( $( this ).hasClass( 'active-toggle' ) && settings['ajaxTemplate'] ) {
1025					var activeIndex = $( this ).find( '.jet-toggle__control' ).data( 'toggle' ) - 1;
1026					ajaxLoadTemplate( activeIndex );
1027				}
1028			} );
1029
1030
1031			$( window ).on( 'resize.jetAccordion orientationchange.jetAccordion', function() {
1032				var activeToggle        = $( '> .jet-accordion__inner > .active-toggle', $target ),
1033					activeToggleContent = $( '> .jet-toggle__content', activeToggle );
1034
1035				activeToggleContent.css( { 'height': 'auto' } );
1036			} );
1037
1038			$( '.jet-toggle__control', $scope ).keydown( function( e ) {
1039				var $this   = $( this ),
1040					$which  = e.which || e.keyCode;
1041
1042				if ( $which == 13 || $which == 32 ) {
1043					$this.click();
1044					return false;
1045				}
1046
1047				if ( $which == 37 ) {
1048					if ( 0 != $this.closest( '.jet-accordion__item' ).prev().length ) {
1049						$this.closest( '.jet-accordion__item' ).prev().find( '.jet-toggle__control' ).focus();
1050					}
1051				}
1052
1053				if ( $which == 39 ) {
1054					if ( 0 != $this.closest( '.jet-accordion__item' ).next().length ) {
1055						$this.closest( '.jet-accordion__item' ).next().find( '.jet-toggle__control' ).focus();
1056					}
1057				}
1058			} );
1059
1060			function closeToggle( $toggle, $toggleContent, $toggleControl, callback ) {
1061				var transitionDuration = 500;
1062
1063				$toggleContent.css( { 'height': $toggleContent.outerHeight() } );
1064
1065				$toggleControl.attr( 'aria-expanded', 'false' );
1066
1067				requestAnimationFrame( function() {
1068					requestAnimationFrame( function() {
1069						$toggleContent.css( { 'height': 0 } );
1070					} );
1071				} );
1072
1073				setTimeout( function() {
1074					$toggle.removeClass( 'active-toggle' );
1075
1076					if ( 'function' === typeof callback ) {
1077						callback();
1078					}
1079				}, transitionDuration );
1080			}
1081
1082			$controlsList.on( 'click.jetAccordion', function() {
1083				var $this               = $( this ),
1084					$toggle             = $this.closest( '.jet-toggle' ),
1085					toggleIndex         = +$this.data( 'toggle' ) - 1,
1086					currentDeviceMode   = elementorFrontend.getCurrentDeviceMode();
1087
1088				if ( typeof timer !== 'undefined' && timer ) clearTimeout( timer );
1089				if ( typeof timer2 !== 'undefined' && timer2 ) clearTimeout( timer2 );
1090				if ( typeof timerСlick !== 'undefined' && timerСlick ) clearTimeout( timerСlick );
1091
1092				if ( $toggle.data('animating') ) return;
1093				$toggle.data('animating', true);
1094				setTimeout(function(){ $toggle.removeData('animating'); }, 100);
1095
1096				if ( settings['collapsible'] ) {
1097					var $toggleControl  = $( '> .jet-toggle__control', $toggle ),
1098						$toggleContent  = $( '> .jet-toggle__content', $toggle );
1099
1100					if ( ! $toggleControl.length || ! $toggleContent.length ) {
1101						return;
1102					}
1103					const classIsOpen = 'active-toggle';
1104					const isOpened = $toggle.hasClass( classIsOpen );
1105
1106					// Capture scroll start position.
1107					const togglerInitialY = $toggleControl[0].getBoundingClientRect().top + window.scrollY;
1108
1109					// Find currently open item (if any).
1110					let currentlyOpenItem    = null;
1111					let currentlyOpenControl = null;
1112					let currentlyOpenContent = null;
1113					$toggleList.each( function() {
1114						if (
1115							this !== $toggle[0] &&
1116							this.classList.contains( classIsOpen )
1117						) {
1118							currentlyOpenItem    = this;
1119							currentlyOpenControl = this.querySelector( '.jet-toggle__control' );
1120							currentlyOpenContent = this.querySelector( '.jet-toggle__content' );
1121						}
1122					} );
1123
1124					// Measure content shift (closing content).
1125					const closingHeight = currentlyOpenContent?.scrollHeight || 0;
1126
1127					if ( !isOpened && currentlyOpenControl && currentlyOpenContent ) {
1128						currentlyOpenItem.classList.remove( classIsOpen );
1129						currentlyOpenContent.style.height = '0';
1130						currentlyOpenControl.setAttribute( 'aria-expanded', 'false' );
1131
1132						// Calculate the predicted scroll position after layout shift.
1133						if ( closingHeight ) {
1134							const currentTogglerY =
1135									  currentlyOpenControl.getBoundingClientRect().top +
1136									  window.scrollY;
1137
1138							// Only scroll if clicked toggler is below the currently open one.
1139							if ( togglerInitialY > currentTogglerY ) {
1140								const predictedY = togglerInitialY - closingHeight;
1141
1142								if ( window.scrollY > predictedY) {
1143									requestAnimationFrame( () => {
1144										let offset = 0;
1145
1146										if ( true === isResponsiveScrollEnabled() ) {
1147											offset = getResponsiveScrollOffset();
1148										}
1149										window.scrollTo( {
1150											top: predictedY - offset,
1151											behavior: 'auto',
1152										} );
1153									} );
1154								}
1155							}
1156						}
1157					}
1158
1159					$toggleList.each( function( index ) {
1160						var $this                = $( this ),
1161							$toggleControl       = $( '> .jet-toggle__control', $this ),
1162							$toggleContent       = $( '> .jet-toggle__content', $this ),
1163							$toggleContentHeight = $( '> .jet-toggle__content > .jet-toggle__content-inner', $this ).outerHeight();
1164
1165						$toggleContentHeight += parseInt( $toggleContent.css( 'border-top-width' ) ) + parseInt( $toggleContent.css( 'border-bottom-width' ) );
1166
1167						if ( index === toggleIndex && ! $toggle.hasClass( 'active-toggle' ) ) {
1168							$this.addClass( 'active-toggle' );
1169							$toggleContent.css( { 'height': $toggleContentHeight } );
1170
1171							$toggleControl.attr( 'aria-expanded', 'true' );
1172
1173							if ( settings['ajaxTemplate'] ) {
1174								ajaxLoadTemplate( toggleIndex );
1175							}
1176
1177							$window.trigger( 'jet-tabs/accordion/show-toggle-event/before', {
1178								target: $target,
1179								toggleIndex: toggleIndex,
1180							} );
1181
1182							if ( timer ) {
1183								clearTimeout( timer );
1184							}
1185
1186							timer = setTimeout( function() {
1187
1188								$window.trigger( 'jet-tabs/accordion/show-toggle-event/after', {
1189									target: $target,
1190									toggleIndex: toggleIndex,
1191								} );
1192
1193								$toggleContent.css( { 'height': 'auto' } );
1194								JetTabs.recalcReadMoreBox($target);
1195
1196								if ( isResponsiveScrollEnabled() ) {
1197									$( 'html, body' ).animate( {
1198										scrollTop: $this.offset().top - getResponsiveScrollOffset()
1199									}, getResponsiveScrollDelay() );
1200								}
1201							}, 500 );
1202
1203						} else {
1204							if ( $this.hasClass( 'active-toggle' ) ) {
1205								if ( timer2 ) {
1206									clearTimeout( timer2 );
1207								}
1208
1209								closeToggle( $this, $toggleContent, $toggleControl );
1210							}
1211						}
1212					} );
1213
1214				} else {
1215
1216					var $toggleContent       = $( '> .jet-toggle__content', $toggle ),
1217						$toggleContentHeight = $( '> .jet-toggle__content > .jet-toggle__content-inner', $toggle ).outerHeight();
1218
1219					$toggleContentHeight += parseInt( $toggleContent.css( 'border-top-width' ) ) + parseInt( $toggleContent.css( 'border-bottom-width' ) );
1220
1221					if ( timerСlick ) {
1222						clearTimeout( timerСlick );
1223					}
1224
1225					timerСlick = setTimeout( function() {
1226
1227					if ( ! $toggle.hasClass( 'active-toggle') ) {
1228
1229						$toggle.addClass( 'active-toggle' );
1230
1231						$toggleContent.css( { 'height': $toggleContentHeight } );
1232
1233						$this.attr( 'aria-expanded', 'true' );
1234
1235						if ( settings['ajaxTemplate'] ) {
1236							ajaxLoadTemplate( toggleIndex );
1237						}
1238
1239						$window.trigger( 'jet-tabs/accordion/show-toggle-event/before', {
1240							target: $target,
1241							toggleIndex: toggleIndex,
1242						} );
1243
1244						if ( timer ) {
1245							clearTimeout( timer );
1246						}
1247
1248						timer = setTimeout( function() {
1249							$window.trigger( 'jet-tabs/accordion/show-toggle-event/after', {
1250								target: $target,
1251								toggleIndex: toggleIndex,
1252							} );
1253
1254							$toggleContent.css( { 'height': 'auto' } );
1255							JetTabs.recalcReadMoreBox($target);
1256
1257							if ( isResponsiveScrollEnabled() && settings['collapsible'] !== true ) {
1258								$( 'html, body' ).animate( {
1259									scrollTop: $this.offset().top - getResponsiveScrollOffset()
1260								}, getResponsiveScrollDelay() );
1261							}
1262						}, 200 );
1263
1264					} else {
1265						if ( timer2 ) {
1266							clearTimeout( timer2 );
1267						}
1268
1269						closeToggle( $toggle, $toggleContent, $this, function() {
1270							var $box = $target.closest( '.jet-view-more-section.view-more-visible' );
1271
1272							if ( $box.length ) {
1273								requestAnimationFrame( function() {
1274									$box.css( 'max-height', $box[0].scrollHeight + 'px' );
1275								} );
1276							}
1277						} );
1278					}
1279
1280					}, 200 );
1281				}
1282
1283			});
1284
1285			/**
1286			 * [ajaxLoadTemplate description]
1287			 * @param  {[type]} $index [description]
1288			 * @return {[type]}        [description]
1289			 */
1290			function ajaxLoadTemplate( $index ) {
1291				var $toggle        = $toggleList.eq( $index ),
1292					$contentHolder = $( '> .jet-toggle__content', $toggle ),
1293					$contentHolderInner = $( '> .jet-toggle__content > .jet-toggle__content-inner', $toggle ),
1294					templateLoaded = $contentHolder.data( 'template-loaded' ) || false,
1295					templateId     = $contentHolder.data( 'template-id' ),
1296					loader         = $( '.jet-tabs-loader', $contentHolderInner );
1297
1298				if ( templateLoaded || false === templateId ) {
1299					return false;
1300				}
1301
1302				$window.trigger( 'jet-tabs/ajax-load-template/before', {
1303					toggleIndex: $index,
1304					target: $target,
1305					contentHolder: $contentHolder
1306				} );
1307
1308				$contentHolder.data( 'template-loaded', true );
1309
1310				var ajaxData = {
1311					id: templateId,
1312					dev: window.JetTabsSettings.devMode
1313				};
1314
1315				if ( window.JetTabsSettings && window.JetTabsSettings.isSelfRequest ) {
1316					ajaxData.jet_tabs_self = 1;
1317					ajaxData._ = Date.now();
1318				}
1319
1320				$.ajax( {
1321					type: 'GET',
1322					url: window.JetTabsSettings.templateApiUrl,
1323					dataType: 'json',
1324					data: ajaxData,
1325					success: function( responce ) {
1326						if ( !responce || typeof responce.template_content === 'undefined' ) {
1327							loader.remove();
1328							$contentHolder.data( 'template-loaded', false );
1329							return;
1330						}
1331						var templateContent = responce.template_content,
1332							templateScripts = responce.template_scripts || {},
1333							templateStyles  = responce.template_styles || {};
1334
1335						for ( var scriptHandler in templateScripts ) {
1336							JetTabs.addedAssetsPromises.push( JetTabs.loadScriptAsync( scriptHandler, templateScripts[ scriptHandler ] ) );
1337						}
1338
1339						for ( var styleHandler in templateStyles ) {
1340							JetTabs.addedAssetsPromises.push( JetTabs.loadStyle( styleHandler, templateStyles[ styleHandler ] ) );
1341						}
1342
1343						Promise.all( JetTabs.addedAssetsPromises ).then( function( value ) {
1344							loader.remove();
1345
1346							$contentHolderInner.html( templateContent );
1347
1348							JetTabs.elementorFrontendInit( $contentHolderInner );
1349
1350							$window.trigger( 'jet-tabs/ajax-load-template/after', {
1351								toggleIndex: $index,
1352								target: $target,
1353								contentHolder: $contentHolder,
1354								responce: response,
1355								response: response
1356							} );
1357						}, function( reason ) {
1358							console.log( 'Script Loaded Error' );
1359						});
1360					}
1361				} );//end
1362			}
1363
1364			// Hash Watch Handler
1365			if ( togglesArray ) {
1366
1367				$controlsList.each( function( index ) {
1368					var $this    = $( this ),
1369						id       = $this.attr( 'id' ),
1370						toggleIndex = index;
1371
1372					togglesArray.forEach( function( itemHash, i ) {
1373						if ( itemHash === id ) {
1374							$this.trigger('click.jetAccordion');
1375						}
1376					} );
1377
1378				} );
1379			}
1380
1381			$controlsList.each( function() {
1382				anchorSelectors.push( 'a[href*="#' + $( this ).attr( 'id' ) + '"]' );
1383			} );
1384
1385			$( document ).on( 'click.jetAccordionAnchor', anchorSelectors.join( ',' ), function( event ) {
1386				var $hash = $( this.hash );
1387
1388				if ( ! $hash.closest( $scope )[0] ) {
1389					return;
1390				}
1391
1392				$hash.trigger( 'click.jetAccordion' );
1393			} );
1394
1395		},// accordionInit end
1396
1397		imageAccordionInit: function( $scope) {
1398			var $target  = $( '.jet-image-accordion', $scope ),
1399				instance = null,
1400				settings = {};
1401
1402			if ( ! $target.length ) {
1403				return;
1404			}
1405
1406			settings = $target.data( 'settings' );
1407
1408			instance = new jetImageAccordion( $target, settings );
1409			instance.init();
1410		},// imageAccordionInit end
1411
1412		loadScriptAsync: function( script, uri ) {
1413
1414			if ( ! uri ) {
1415				return Promise.resolve( script );
1416			}
1417
1418			if ( JetTabs.addedScripts.hasOwnProperty( script ) ) {
1419				return JetTabs.addedScripts[ script ];
1420			}
1421
1422			JetTabs.addedScripts[ script ] = new Promise( function( resolve, reject ) {
1423				var existingTag = document.querySelector( 'script[src="' + uri + '"]' );
1424
1425				if ( existingTag ) {
1426					resolve( script );
1427					return;
1428				}
1429
1430				var tag = document.createElement( 'script' );
1431
1432				tag.src   = uri;
1433				tag.async = true;
1434
1435				tag.onload = function() {
1436					resolve( script );
1437				};
1438
1439				tag.onerror = function() {
1440					reject( {
1441						type: 'script',
1442						handler: script,
1443						uri: uri
1444					} );
1445				};
1446
1447				document.head.appendChild( tag );
1448			});
1449		},
1450
1451		loadStyle: function( style, uri ) {
1452
1453			if ( !uri ) {
1454				return Promise.resolve( style );
1455			}
1456
1457			if ( JetTabs.addedStyles.hasOwnProperty( style ) ) {
1458				return JetTabs.addedStyles[ style ];
1459			}
1460
1461			JetTabs.addedStyles[ style ] = new Promise( function( resolve, reject ) {
1462				var existingTag = document.querySelector( 'link[href="' + uri + '"]' );
1463
1464				if ( existingTag ) {
1465					resolve( style );
1466					return;
1467				}
1468
1469				var tag = document.createElement( 'link' );
1470
1471				tag.id    = style;
1472				tag.rel   = 'stylesheet';
1473				tag.href  = uri;
1474				tag.type  = 'text/css';
1475				tag.media = 'all';
1476
1477				tag.onload = function() {
1478					resolve( style );
1479				};
1480
1481				tag.onerror = function() {
1482					reject( {
1483						type: 'style',
1484						handler: style,
1485						uri: uri
1486					} );
1487				};
1488
1489				document.head.appendChild( tag );
1490			} );
1491
1492			return JetTabs.addedStyles[ style ];
1493		},
1494
1495		elementorFrontendInit: function( $container ) {
1496
1497			$container.find( '[data-element_type]' ).each( function() {
1498				var $this       = $( this ),
1499					elementType = $this.data( 'element_type' );
1500
1501				if ( ! elementType ) {
1502					return;
1503				}
1504
1505				try {
1506					if ( 'widget' === elementType ) {
1507						elementType = $this.data( 'widget_type' );
1508						window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
1509					}
1510
1511					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
1512					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
1513
1514				} catch ( err ) {
1515					console.log(err);
1516
1517					$this.remove();
1518
1519					return false;
1520				}
1521			} );
1522
1523		},
1524
1525		getElementorElementSettings: function( $scope ) {
1526
1527			if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) {
1528				return JetTabs.getEditorElementSettings( $scope );
1529			}
1530
1531			return $scope.data( 'settings' ) || {};
1532		},
1533
1534		getEditorElementSettings: function( $scope ) {
1535			var modelCID = $scope.data( 'model-cid' ),
1536				elementData;
1537
1538			if ( ! modelCID ) {
1539				return {};
1540			}
1541
1542			if ( ! elementor.hasOwnProperty( 'config' ) ) {
1543				return {};
1544			}
1545
1546			if ( ! elementor.config.hasOwnProperty( 'elements' ) ) {
1547				return {};
1548			}
1549
1550			if ( ! elementor.config.elements.hasOwnProperty( 'data' ) ) {
1551				return {};
1552			}
1553
1554			elementData = elementor.config.elements.data[ modelCID ];
1555
1556			if ( ! elementData ) {
1557				return {};
1558			}
1559
1560			return elementData.toJSON();
1561		},
1562
1563		prepareVideoIframes: function( $container ) {
1564			if ( ! $container || ! $container.length ) return;
1565
1566			$container.find( 'iframe' ).each( function() {
1567				var $iframe = $( this );
1568
1569				var srcAttr = $iframe.attr( 'src' ) ? 'src'
1570					: ( $iframe.attr( 'data-src' ) ? 'data-src'
1571						: ( $iframe.attr( 'data-lazy-src' ) ? 'data-lazy-src'
1572							: ( $iframe.attr( 'data-lazy-load' ) ? 'data-lazy-load' : null ) ) );
1573
1574				if ( ! srcAttr ) return;
1575
1576				var src = $iframe.attr( srcAttr );
1577				if ( ! src ) return;
1578
1579				var isYouTube = /youtube\.com|youtube-nocookie\.com|youtu\.be/i.test( src );
1580				var isVimeo   = /vimeo\.com/i.test( src );
1581
1582				if ( ! isYouTube && ! isVimeo ) return;
1583
1584				try {
1585					var fixedSrc = src.indexOf( '//' ) === 0 ? window.location.protocol + src : src;
1586					var url      = new URL( fixedSrc );
1587
1588					if ( isYouTube ) {
1589						if ( ! url.searchParams.has( 'enablejsapi' ) ) url.searchParams.set( 'enablejsapi', '1' );
1590						if ( ! url.searchParams.has( 'origin' ) ) url.searchParams.set( 'origin', window.location.origin );
1591					}
1592
1593					if ( isVimeo ) {
1594						if ( ! url.searchParams.has( 'api' ) ) url.searchParams.set( 'api', '1' );
1595					}
1596
1597					var newSrc = url.toString();
1598
1599					if ( src.indexOf( '//' ) === 0 ) {
1600						newSrc = newSrc.replace( window.location.protocol, '' );
1601					}
1602
1603					if ( newSrc !== src ) {
1604						$iframe.attr( srcAttr, newSrc );
1605					}
1606				} catch ( e ) {
1607				}
1608			} );
1609		},
1610
1611		pauseMediaInContainer: function( $container ) {
1612			if ( ! $container || ! $container.length ) return;
1613
1614			$container.find( 'video, audio' ).each( function() {
1615				try {
1616					this.pause();
1617				} catch ( e ) {
1618				}
1619			} );
1620
1621			function getUrlAndAttr( $iframe ) {
1622				if ( $iframe.attr( 'src' ) ) return { attr: 'src', url: $iframe.attr( 'src' ) };
1623				if ( $iframe.attr( 'data-src' ) ) return { attr: 'data-src', url: $iframe.attr( 'data-src' ) };
1624				if ( $iframe.attr( 'data-lazy-src' ) ) return {
1625					attr: 'data-lazy-src',
1626					url: $iframe.attr( 'data-lazy-src' )
1627				};
1628				if ( $iframe.attr( 'data-lazy-load' ) ) return {
1629					attr: 'data-lazy-load',
1630					url: $iframe.attr( 'data-lazy-load' )
1631				};
1632				return { attr: null, url: '' };
1633			}
1634
1635			$container.find( 'iframe' ).each( function() {
1636				var iframe = this;
1637				var $iframe = jQuery( iframe );
1638
1639				var info = getUrlAndAttr( $iframe );
1640				var url  = info.url || '';
1641				if ( ! url ) return;
1642
1643				var isYouTube = /youtube\.com|youtube-nocookie\.com|youtu\.be/i.test( url );
1644				var isVimeo   = /vimeo\.com/i.test( url );
1645				if ( ! isYouTube && ! isVimeo ) return;
1646
1647				var hasYTApi = isYouTube && /enablejsapi=1/i.test( url );
1648				var hasVmApi = isVimeo && /api=1/i.test( url );
1649
1650				if ( ( hasYTApi || hasVmApi ) && iframe.contentWindow ) {
1651					try {
1652						if ( hasYTApi ) {
1653							iframe.contentWindow.postMessage( JSON.stringify( {
1654								event: 'command',
1655								func: 'pauseVideo',
1656								args: ''
1657							} ), '*' );
1658							return;
1659						}
1660
1661						if ( hasVmApi ) {
1662							iframe.contentWindow.postMessage( JSON.stringify( {
1663								method: 'pause'
1664							} ), '*' );
1665							return;
1666						}
1667					} catch ( e ) {
1668					}
1669				}
1670
1671				try {
1672					if ( ! $iframe.attr( 'data-jet-tabs-restore-src' ) ) {
1673						$iframe.attr( 'data-jet-tabs-restore-src', url );
1674					}
1675
1676					$iframe.attr( 'src', 'about:blank' );
1677					$iframe.removeAttr( 'srcdoc' );
1678				} catch ( e ) {
1679				}
1680			} );
1681		},
1682
1683		observeVideoIframes: function( $root ) {
1684			if ( ! $root || ! $root.length ) return;
1685
1686			if ( $root.data( 'jetTabsVideoObserver' ) ) return;
1687
1688			var observer = new MutationObserver( function( mutations ) {
1689				mutations.forEach( function( m ) {
1690
1691					if ( m.type === 'attributes' ) {
1692						var el = m.target;
1693
1694						if ( el && el.nodeType === 1 && el.tagName === 'IFRAME' ) {
1695							JetTabs.prepareVideoIframes( jQuery( el ).parent() );
1696						}
1697
1698						return;
1699					}
1700
1701					if ( m.type === 'childList' ) {
1702						if ( ! m.addedNodes || ! m.addedNodes.length ) return;
1703
1704						m.addedNodes.forEach( function( node ) {
1705							if ( node.nodeType !== 1 ) return;
1706
1707							var $node = jQuery( node );
1708
1709							if ( $node.is( 'iframe' ) ) {
1710								JetTabs.prepareVideoIframes( $node.parent() );
1711								return;
1712							}
1713
1714							var $iframes = $node.find ? $node.find( 'iframe' ) : jQuery();
1715							if ( $iframes.length ) {
1716								JetTabs.prepareVideoIframes( $node );
1717							}
1718						} );
1719					}
1720
1721				} );
1722			} );
1723
1724			observer.observe( $root[ 0 ], {
1725				childList: true,
1726				subtree: true,
1727				attributes: true,
1728				attributeFilter: [ 'src', 'data-src', 'data-lazy-src', 'data-lazy-load' ],
1729			} );
1730			$root.data( 'jetTabsVideoObserver', observer );
1731		},
1732
1733		restoreMediaInContainer: function( $container ) {
1734			if ( ! $container || ! $container.length ) return;
1735
1736			$container.find( 'iframe[data-jet-tabs-restore-src]' ).each( function() {
1737				var $iframe    = jQuery( this );
1738				var restoreUrl = $iframe.attr( 'data-jet-tabs-restore-src' );
1739				if ( ! restoreUrl ) return;
1740
1741				$iframe.attr( 'src', restoreUrl );
1742				$iframe.removeAttr( 'data-jet-tabs-restore-src' );
1743
1744				JetTabs.prepareVideoIframes( $iframe.parent() );
1745			} );
1746		},
1747
1748		debounce: function( threshold, callback ) {
1749			var timeout;
1750
1751			return function debounced( $event ) {
1752				function delayed() {
1753					callback.call( this, $event );
1754					timeout = null;
1755				}
1756
1757				if ( timeout ) {
1758					clearTimeout( timeout );
1759				}
1760
1761				timeout = setTimeout( delayed, threshold );
1762			};
1763		}
1764
1765	};
1766
1767	/**
1768	 * jetImageAccordion Class
1769	 *
1770	 * @return {void}
1771	 */
1772	window.jetImageAccordion = function( $selector, settings ) {
1773		var self            = this,
1774			$instance       = $selector,
1775			$itemsList      = $( '.jet-image-accordion__item', $instance ),
1776			itemslength     = $itemsList.length,
1777			defaultSettings = {
1778				orientation: 'vertical',
1779				activeSize:  {
1780					size: 50,
1781					unit: '%'
1782				},
1783				duration: 500,
1784				activeItem: -1
1785			},
1786			settings        = settings || {},
1787			activeItem      = -1;
1788
1789		/**
1790		 * Checking options, settings and options merging
1791		 */
1792		settings = $.extend( defaultSettings, settings );
1793
1794		activeItem = settings['activeItem'];
1795
1796		/**
1797		 * Layout Build
1798		 */
1799		this.layoutBuild = function( ) {
1800
1801			$itemsList.css( {
1802				'transition-duration': settings.duration + 'ms'
1803			} );
1804
1805			$itemsList.each( function( index ) {
1806				if ( index === activeItem ) {
1807					$( this ).addClass( 'active-accordion' );
1808					self.layoutRender();
1809				}
1810			} );
1811
1812			$( '.jet-image-accordion__image-instance', $itemsList ).imagesLoaded().progress( function( instance, image ) {
1813				var $image      = $( image.img ),
1814					$parentItem = $image.closest( '.jet-image-accordion__item' ),
1815					$loader     = $( '.jet-image-accordion__item-loader', $parentItem );
1816
1817				$image.addClass( 'loaded' );
1818
1819				$loader.fadeTo( 250, 0, function() {
1820					$( this ).remove();
1821				} );
1822			});
1823
1824			self.layoutRender();
1825			self.addEvents();
1826		}
1827
1828		/**
1829		 * Layout Render
1830		 */
1831		this.layoutRender = function( $accordionItem ) {
1832			var $accordionItem = $accordionItem || false,
1833				activeSize     = settings.activeSize.size,
1834				basis          = ( 100 / itemslength ).toFixed(2),
1835				grow           = activeSize / ( ( 100 - activeSize  ) / ( itemslength - 1 ) );
1836
1837			$( '.jet-image-accordion__item:not(.active-accordion)', $instance ).css( {
1838				'flex-grow': 1
1839			} );
1840
1841			$( '.active-accordion', $instance ).css( {
1842				'flex-grow': grow
1843			} );
1844		}
1845
1846		this.addEvents = function() {
1847			var toogleEvents = 'mouseenter',
1848				scrollOffset = $( window ).scrollTop();
1849
1850			if ( 'ontouchend' in window || 'ontouchstart' in window ) {
1851				$itemsList.on( 'touchstart.jetImageAccordion', function( event ) {
1852					scrollOffset = $( window ).scrollTop();
1853				} );
1854
1855				$itemsList.on( 'touchend.jetImageAccordion', function( event ) {
1856					event.stopPropagation();
1857
1858					var $this = $( this );
1859
1860					if ( scrollOffset !== $( window ).scrollTop() ) {
1861						return false;
1862					}
1863
1864					if ( ! $this.hasClass( 'active-accordion' ) ) {
1865						$itemsList.removeClass( 'active-accordion' );
1866						$this.addClass( 'active-accordion' );
1867					} else {
1868						$itemsList.removeClass( 'active-accordion' );
1869					}
1870
1871					self.layoutRender();
1872				} );
1873			} else {
1874				$itemsList.on( 'mouseenter', function( event ) {
1875					var $this = $( this );
1876
1877					if ( ! $this.hasClass( 'active-accordion' ) ) {
1878						$itemsList.removeClass( 'active-accordion' );
1879						$this.addClass( 'active-accordion' );
1880					}
1881
1882					self.layoutRender();
1883				} );
1884
1885				$( '.jet-image-accordion__item', $instance ).keydown( function( e ) {
1886					var $this  = $( this ),
1887						$which = e.which || e.keyCode;
1888
1889						if ( $which == 13 || $which == 32 ) {
1890							if ( ! $this.hasClass( 'active-accordion' ) ) {
1891								$itemsList.removeClass( 'active-accordion' );
1892								$this.addClass( 'active-accordion' );
1893							} else {
1894								$itemsList.removeClass( 'active-accordion' );
1895
1896								if ( -1 !== activeItem ) {
1897									$itemsList.eq( activeItem ).addClass( 'active-accordion' );
1898								}
1899
1900								self.layoutRender();
1901							}
1902
1903							self.layoutRender();
1904						}
1905
1906						if ( $which == 37 ) {
1907							if ( 0 != $this.prev().length ) {
1908								$itemsList.removeClass( 'active-accordion' );
1909								$this.prev().focus();
1910								$this.prev().addClass( 'active-accordion' );
1911								self.layoutRender();
1912							}
1913						}
1914
1915						if ( $which == 39 ) {
1916							if ( 0 != $this.next().length ) {
1917								$itemsList.removeClass( 'active-accordion' );
1918								$this.next().focus();
1919								$this.next().addClass( 'active-accordion' );
1920								self.layoutRender();
1921							}
1922						}
1923				} );
1924			}
1925
1926			$instance.on( 'mouseleave.jetImageAccordion', function( event ) {
1927				$itemsList.removeClass( 'active-accordion' );
1928
1929				if ( -1 !== activeItem ) {
1930					$itemsList.eq( activeItem ).addClass( 'active-accordion' );
1931				}
1932
1933				self.layoutRender();
1934			} );
1935
1936			/*$( document ).on( 'touchend.jetImageAccordion', function( event ) {
1937				$itemsList.removeClass( 'active-accordion' );
1938				self.layoutRender();
1939			} );*/
1940		}
1941
1942		/**
1943		 * Init
1944		 */
1945		this.init = function() {
1946			self.layoutBuild();
1947		}
1948	}
1949
1950	$( window ).on( 'elementor/frontend/init', JetTabs.init );
1951
1952	window.JetTabs = JetTabs;
1953
1954}( jQuery, window.elementorFrontend, window.JetTabsSettings ) );

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.