PageSourceSearch

https://www.gerricus-praxis.de/wp-content/plugins/keydesign-framew…/widgets/assets/js/advanced-tabs.js?ver=3.4

js gerricus-praxis.de collected 2026-10-08 10:48:36 UTC 10,895 bytes, 301 lines download raw bytes

1( function( $ ) {
2	'use strict';
3
4	class AdvancedTabsHandler extends elementorModules.frontend.handlers.Base {
5	getWidgetNumber() {
6		const $widget = this.$element.find( '> .elementor-widget-container > .kd-widget-container > .kd-advanced-tabs, > .kd-widget-container > .kd-advanced-tabs, > .kd-advanced-tabs' );
7		const widgetNumber = $widget.attr( 'data-widget-number' );
8		return widgetNumber;
9	}
10
11	getDefaultSettings() {
12		const widgetNumber = this.getWidgetNumber();
13		return {
14				selectors: {
15					widgetContainer: `[data-widget-number="${widgetNumber}"]`,
16					tabTitle: `[aria-controls*="kd-advanced-tabs-pane-${widgetNumber}"]`,
17					tabTitleIcon: `[id*="kd-advanced-tabs-tab-${widgetNumber}"] > .kd-advanced-tabs__tab-icon`,
18					tabTitleText: `[id*="kd-advanced-tabs-tab-${widgetNumber}"] .kd-advanced-tabs__tab-title`,
19					tabTitleDescription: `[id*="kd-advanced-tabs-tab-${widgetNumber}"] .kd-advanced-tabs__tab-description`,
20					tabContent: `[data-widget-number="${widgetNumber}"] .kd-advanced-tabs__panes > .kd-advanced-tabs__pane`,
21					headingContainer: `[data-widget-number="${widgetNumber}"] > .kd-advanced-tabs__tabs`,
22					activeTabContentContainers: `[id*="kd-advanced-tabs-pane-${widgetNumber}"].e-active`
23				},
24				classes: {
25					active: 'e-active'
26				},
27				dataAttributes: {
28					tabIndex: 'data-tab-index'
29				},
30				ariaAttributes: {
31					titleStateAttribute: 'aria-selected',
32					activeTitleSelector: '[aria-selected="true"]'
33				},
34				toggleSelf: false,
35				hidePrevious: true,
36				autoExpand: true
37			};
38		}
39
40	getDefaultElements() {
41		const selectors = this.getSettings( 'selectors' );
42		return {
43			$widgetContainer: this.findElement( selectors.widgetContainer ),
44			$tabTitles: this.findElement( selectors.tabTitle ),
45			$tabContents: this.findElement( selectors.tabContent ),
46			$headingContainer: this.findElement( selectors.headingContainer )
47		};
48	}
49
50		getTabTitleFilterSelector( tabIndex ) {
51			return `[${this.getSettings( 'dataAttributes' ).tabIndex}="${tabIndex}"]`;
52		}
53
54		getTabContentFilterSelector( tabIndex ) {
55			return `*:nth-child(${tabIndex})`;
56		}
57
58		getTabIndex( tabTitleElement ) {
59			return tabTitleElement.getAttribute( this.getSettings( 'dataAttributes' ).tabIndex );
60		}
61
62		getActiveTabIndex() {
63			const settings = this.getSettings(),
64				activeTitleFilter = settings.ariaAttributes.activeTitleSelector,
65				tabIndexSelector = settings.dataAttributes.tabIndex,
66				$activeTitle = this.elements.$tabTitles.filter( activeTitleFilter );
67			
68			return $activeTitle.attr( tabIndexSelector ) || null;
69		}
70
71		activateDefaultTab() {
72			const settings = this.getSettings();
73			const defaultActiveTab = this.getEditSettings( 'activeItemIndex' ) || 1;
74			const originalToggleMethods = {
75				showTabFn: settings.showTabFn,
76				hideTabFn: settings.hideTabFn
77			};
78
79			this.setSettings( {
80				showTabFn: 'show',
81				hideTabFn: 'hide'
82			} );
83
84			this.changeActiveTab( defaultActiveTab );
85			this.setSettings( originalToggleMethods );
86			this.elements.$widgetContainer.addClass( 'e-activated' );
87		}
88
89		deactivateActiveTab( newTabIndex ) {
90			const settings = this.getSettings(),
91				activeClass = settings.classes.active,
92				activeTitleFilter = settings.ariaAttributes.activeTitleSelector,
93				activeContentFilter = '.' + activeClass,
94				$activeTitle = this.elements.$tabTitles.filter( activeTitleFilter ),
95				$activeContent = this.elements.$tabContents.filter( activeContentFilter );
96
97			this.setTabDeactivationAttributes( $activeTitle, newTabIndex );
98			$activeContent.removeClass( activeClass );
99
100			return $activeContent;
101		}
102
103		getTitleActivationAttributes() {
104			const titleStateAttribute = this.getSettings( 'ariaAttributes' ).titleStateAttribute;
105			return {
106				tabindex: '0',
107				[ titleStateAttribute ]: 'true'
108			};
109		}
110
111		setTabDeactivationAttributes( $activeTitle ) {
112			const titleStateAttribute = this.getSettings( 'ariaAttributes' ).titleStateAttribute;
113			$activeTitle.attr( {
114				tabindex: '-1',
115				[ titleStateAttribute ]: 'false'
116			} );
117		}
118
119		activateTab( tabIndex ) {
120			const settings = this.getSettings(),
121				activeClass = settings.classes.active;
122			
123			let $requestedTitle = this.elements.$tabTitles.filter( this.getTabTitleFilterSelector( tabIndex ) );
124			let $requestedContent = this.elements.$tabContents.filter( this.getTabContentFilterSelector( tabIndex ) );
125
126			if ( ! $requestedTitle.length ) {
127				const previousTabIndex = Math.max( tabIndex - 1, 1 );
128				$requestedTitle = this.elements.$tabTitles.filter( this.getTabTitleFilterSelector( previousTabIndex ) );
129				$requestedContent = this.elements.$tabContents.filter( this.getTabContentFilterSelector( previousTabIndex ) );
130			}
131
132			$requestedTitle.attr( this.getTitleActivationAttributes() );
133			$requestedContent.addClass( activeClass );
134			this.onShowTabContent( $requestedContent );
135		}
136
137		onShowTabContent( $requestedContent ) {
138			elementorFrontend.elements.$window.trigger( 'elementor-pro/motion-fx/recalc' );
139			elementorFrontend.elements.$window.trigger( 'elementor/keydesign-advanced-tabs/activate', $requestedContent );
140			elementorFrontend.elements.$window.trigger( 'elementor/bg-video/recalc' );
141		}
142
143		isActiveTab( tabIndex ) {
144			const settings = this.getSettings();
145			const isActiveTabTitle = 'true' === this.elements.$tabTitles.filter( `[${settings.dataAttributes.tabIndex}="${tabIndex}"]` ).attr( settings.ariaAttributes.titleStateAttribute );
146			const isActiveTabContent = this.elements.$tabContents.filter( this.getTabContentFilterSelector( tabIndex ) ).hasClass( this.getActiveClass() );
147			
148			return isActiveTabTitle && isActiveTabContent;
149		}
150
151		onTabClick( event ) {
152			event.preventDefault();
153			const tabIndex = event.currentTarget?.getAttribute( this.getSettings( 'dataAttributes' ).tabIndex );
154			this.changeActiveTab( tabIndex, true );
155		}
156
157		getTabEvents() {
158			return {
159				click: this.onTabClick.bind( this )
160			};
161		}
162
163		bindEvents() {
164			this.elements.$tabTitles.on( this.getTabEvents() );
165			elementorFrontend.elements.$window.on( 'elementor/keydesign-advanced-tabs/activate', this.reInitSwipers );
166			elementorFrontend.elements.$window.on( 'elementor/nested-container/atomic-repeater', this.linkContainer.bind( this ) );
167		}
168
169		unbindEvents() {
170			this.elements.$tabTitles.off();
171			this.elements.$headingContainer.off();
172			this.elements.$tabContents.children().off();
173			elementorFrontend.elements.$window.off( 'elementor/keydesign-advanced-tabs/activate', this.reInitSwipers );
174			elementorFrontend.elements.$window.off( 'elementor/nested-container/atomic-repeater', this.linkContainer.bind( this ) );
175		}
176
177		reInitSwipers( event, content ) {
178			if ( ! content ) {
179				return;
180			}
181
182			const contentElement = content instanceof jQuery ? content[ 0 ] : content;
183
184			if ( ! contentElement || ! contentElement.querySelectorAll ) {
185				return;
186			}
187
188			const swiperElements = contentElement.querySelectorAll( '.swiper' );
189			for ( const element of swiperElements ) {
190				if ( ! element.swiper ) {
191					return;
192				}
193				element.swiper.initialized = false;
194				element.swiper.init();
195			}
196		}
197
198		onInit() {
199			super.onInit( ...arguments );
200			
201			if ( this.getSettings( 'autoExpand' ) ) {
202				this.activateDefaultTab();
203			}
204		}
205
206		onEditSettingsChange( propertyName, value ) {
207			if ( 'activeItemIndex' === propertyName ) {
208				this.changeActiveTab( value, false );
209			}
210		}
211
212		changeActiveTab( tabIndex, fromUser = false ) {
213			if ( fromUser && this.isEdit && this.isElementInTheCurrentDocument() ) {
214				return window.top.$e.run( 'document/repeater/select', {
215					container: elementor.getContainer( this.$element.attr( 'data-id' ) ),
216					index: parseInt( tabIndex )
217				} );
218			}
219
220			const isActiveTab = this.isActiveTab( tabIndex );
221			const settings = this.getSettings();
222
223			if ( ( settings.toggleSelf || ! isActiveTab ) && settings.hidePrevious ) {
224				this.deactivateActiveTab( tabIndex );
225			}
226
227			if ( ! settings.hidePrevious && isActiveTab ) {
228				this.deactivateActiveTab( tabIndex );
229			}
230
231			if ( ! isActiveTab ) {
232				this.activateTab( tabIndex );
233			}
234		}
235
236		getActiveClass() {
237			return this.getSettings( 'classes' ).active;
238		}
239
240		linkContainer( event ) {
241			const { container } = event.detail;
242			const id = container.model.get( 'id' );
243			const currentId = this.$element.data( 'id' );
244			const view = container.view.$el;
245
246			if ( id === currentId ) {
247				this.updateIndexValues();
248				this.updateListeners( view );
249				elementor.$preview[ 0 ].contentWindow.dispatchEvent( new CustomEvent( 'elementor/elements/link-data-bindings' ) );
250			}
251
252			if ( ! this.getActiveTabIndex() ) {
253				const targetIndex = event.detail.index + 1 || 1;
254				this.changeActiveTab( targetIndex );
255			}
256		}
257
258		updateListeners( view ) {
259			this.elements.$tabContents = view.find( this.getSettings( 'selectors.tabContent' ) );
260			this.elements.$tabTitles = view.find( this.getSettings( 'selectors.tabTitle' ) );
261			this.elements.$tabTitles.on( this.getTabEvents() );
262		}
263
264		updateIndexValues() {
265			const { $widgetContainer, $tabContents, $tabTitles } = this.getDefaultElements();
266			const settings = this.getSettings();
267			const dataTabIndex = settings.dataAttributes.tabIndex;
268			const widgetNumber = $widgetContainer.data( 'widgetNumber' );
269
270			$tabTitles.each( ( index, element ) => {
271				const newIndex = index + 1;
272				const updatedTabID = `kd-advanced-tabs-tab-${widgetNumber}${newIndex}`;
273				const updatedContainerID = `kd-advanced-tabs-pane-${widgetNumber}${newIndex}`;
274
275				element.setAttribute( 'id', updatedTabID );
276				element.setAttribute( dataTabIndex, newIndex );
277				element.setAttribute( 'aria-controls', updatedContainerID );
278
279				element.querySelector( settings.selectors.tabTitleIcon )?.setAttribute( 'data-binding-index', newIndex );
280				element.querySelector( settings.selectors.tabTitleText )?.setAttribute( 'data-binding-index', newIndex );
281				element.querySelector( settings.selectors.tabTitleDescription )?.setAttribute( 'data-binding-index', newIndex );
282
283				if ( $tabContents[ index ] ) {
284					$tabContents[ index ].setAttribute( 'aria-labelledby', updatedTabID );
285					$tabContents[ index ].setAttribute( dataTabIndex, newIndex );
286					$tabContents[ index ].setAttribute( 'id', updatedContainerID );
287					$tabContents[ index ].setAttribute( 'role', 'tabpanel' );
288				}
289			} );
290		}
291	}
292
293	$( window ).on( 'elementor/frontend/init', function() {
294		elementorFrontend.hooks.addAction( 'frontend/element_ready/keydesign-advanced-tabs.default', function( $scope ) {
295			elementorFrontend.elementsHandler.addHandler( AdvancedTabsHandler, {
296				$element: $scope
297			} );
298		} );
299	} );
300
301} )( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.