PageSourceSearch

https://www.kreis-lup.de/output/js/accordion/ikiss-accordion.js

js kreis-lup.de collected 2026-10-02 10:21:36 UTC 7,572 bytes, 267 lines download raw bytes

1;(function ($) {
2	
3	var defaults = { 
4		hashEvents			: 'load hashchange',
5		
6		titleSelector		: '.accordion-title',
7		containerSelector	: '.accordion-container',
8		
9		iconStyle			: 'fal',
10		iconOpen			: 'fa-plus',
11		iconClose			: 'fa-minus',
12		
13		autoOpenFirst		: false,
14		autoClose			: false,
15		
16		wrapInner			: true,
17		activeCls			: 'active',
18		useAnimations		: false
19	};
20	
21	var Plugin = function(rootNode, options) {
22		var me = this,
23			op = $.extend({}, options || {});
24		
25		//Optionen aus den Data-Attributen zuweisen 
26		$.each($(rootNode).data(), function(key, value) {
27			$.map(defaults, function(defValue, defKey) {
28				if (defKey.toLowerCase() == key.toLowerCase()) {
29					op[defKey] = value;
30				}
31			});
32		});
33		
34		$.extend(me, {
35			rootNode	: rootNode,
36			options		: $.extend({}, defaults, op)
37		});
38		
39		me.init();
40	};
41	
42	Plugin.prototype = {
43		
44		init: function() { 
45			var me 	= this,
46				op	= me.options;
47			
48			window.globalIkissAccordionCounter = (window.globalIkissAccordionCounter || 0)+1; 
49			
50			//Ueberschriften suchen und Elemente entsprechend modifizieren (bei dem neuen Accordion nur direkte Titel sammeln, daher Selektor mit > erweitern)
51			if (me.rootNode == document.body) {
52				me.header = $(op.titleSelector, me.rootNode);
53			} else {
54				me.header = $('> '+op.titleSelector, me.rootNode);
55				if (!me.header.length) me.header = $('> div > '+op.titleSelector, me.rootNode);
56			}
57			
58			
59			me.header.each(function(idx, node) {
60				var idKey = '-'+window.globalIkissAccordionCounter+'-'+(idx+1),
61					ctSel = op.containerSelector;
62				
63				if (op.wrapInner) {
64					$(node)
65						.wrapInner('<button id="acc'+idKey+'" aria-controls="sect'+idKey+'" aria-expanded="false" type="button"><span></span><i class="accordion-toggle-button '+op.iconStyle+' '+op.iconOpen+'" aria-hidden="true"></i></button>');
66				} else {
67					$(node)
68						.attr({'id': 'acc'+idKey, 'aria-controls': 'sect'+idKey, 'aria-expanded': 'false', 'tabindex': '0'})
69						.keypress(function(evt) { if (evt.which === 13) { me.onClick.apply(me, arguments); } });
70				}
71				
72				window.photoswipeAccCounter = window.photoswipeAccCounter || 1;
73				
74				$(node)
75					.click(function() { me.onClick.apply(me, arguments); })
76					.next(ctSel)
77					.attr({'id': 'sect'+idKey, 'aria-labelledby': 'acc'+idKey, 'role': 'region'})
78					.css('display', 'none')
79					.find('.photoswipe-gallery')
80					.filter(function() { return $(this).closest(ctSel).get(0) == $(node).next(ctSel).get(0); })
81					.attr('data-photoswipe-group', 'acc-'+(window.photoswipeAccCounter++));
82			});
83			
84			//Beim Fokus mittels TabKey CSS-Klasse setzen
85			me.header.on('focusin', function(e){
86				var me = this;
87				$(window).one('keyup.tabkey', function (e) {
88					if ((e.keyCode ? e.keyCode : e.which) == 9) {
89						$(me).addClass('accordion-tab-focus');
90					}
91				});
92			}).on('focusout', function(e){
93				$(this).removeClass('accordion-tab-focus');
94				$(window).off('keyup.tabkey');
95			});
96			
97			
98			//Erstes Element öffnen?
99			if (op.autoOpenFirst && me.header.length) {
100				me.toggle(me.header[0]);
101			}
102			
103			//Events bei denen der location.hash geprüft werden soll
104			$(window).on(op.hashEvents, function(){ me.checkHash.apply(me, arguments);});
105			
106			//ab jQuery 3.x wird das load event in docready manchmal nicht mehr ausgeführt, daher manueller Aufruf
107			if (document.readyState === 'complete') { 
108				me.checkHash();	
109			}
110		},
111		
112		onClick: function(e) {
113			var me	= this,
114				op	= me.options;
115			
116			var trgHeader = $(e.target).closest(op.titleSelector).get(0);
117			
118			if (!trgHeader)
119				return;
120			
121			e.preventDefault();
122			e.stopPropagation();
123			
124			this.toggle(trgHeader);
125		},
126		
127		open: function(header) {
128			this.toggle(header, 'open');
129		},
130		
131		close: function(header) {
132			this.toggle(header, 'close');
133		},
134		
135		toggle: function(header, forceMode) {
136			var me 		= this,
137				op		= me.options,
138				io		= op.iconOpen,
139				ic		= op.iconClose,
140				mode 	= $(header).hasClass(op.activeCls) ? 'close' : 'open',
141				open	= (mode == 'open' || forceMode == 'open'); 
142			
143			if (open && op.autoClose) {
144				var acHeader = 	(me.rootNode == document.body)
145								? $(op.titleSelector+'.'+op.activeCls, ($(header).closest(op.containerSelector).get(0) || document.body)).get(0)
146								: (me.header.filter('.'+op.activeCls)).get(0); 
147				
148				if (acHeader && acHeader != header) {
149					this.close(acHeader);
150					
151					var offTop 	= parseInt($(header).offset().top, 10),
152						scTop	= parseInt($(header).css('scroll-margin-top'), 10);	
153						if (scTop) {
154							offTop -= scTop;	
155						}
156					
157					if (offTop < $(window).scrollTop()) {
158						$('html, body').animate({scrollTop: offTop}, 500);	
159					}
160				} 
161			}
162			
163			$(header).toggleClass(op.activeCls);
164
165			var $container = $(header).next(op.containerSelector);
166			if (op.useAnimations === true) {
167				$container[open ? 'slideDown' : 'slideUp']();
168			} else {
169				$container.css('display', open ? '' : 'none');
170			}
171	
172			if ($('button', header).length) {
173				$('button', header).attr('aria-expanded', open ? 'true': 'false');
174			} else {
175				$(header).attr('aria-expanded', open ? 'true': 'false');
176			}
177			
178			$('i'+(op.wrapInner ? '.accordion-toggle-button' : ''), header).removeClass(open ? io : ic).addClass(open ? ic : io);
179		},
180		
181		checkHash: function() {
182			var me		= this,
183				op		= me.options, 
184				hash	= decodeURI(window.location.hash || ''),
185				hashID	= hash && hash.substr(1),
186				trgEl; 
187			
188			if (hashID) {
189				var els	= me.rootNode.getElementsByTagName("*");
190				for (var i=0, len = els.length; i < len; i++) {
191					if (els[i].getAttribute('id') == hashID || els[i].getAttribute('data-anchor') == hashID) {
192						trgEl = els[i];
193						break;	
194					}	
195				}
196			}
197			
198			if (!trgEl || $(trgEl).hasClass(op.activeCls))
199				return;
200			
201			var ctSelector 	= op.containerSelector,
202				tiSelector 	= op.titleSelector,
203				openHit		= 0;
204			
205			if (me.rootNode == document.body) { 
206				$(trgEl).parentsUntil(me.rootNode, ctSelector).each(function(idx, ct) {
207					me.open($(ct).prev(tiSelector).get(0));
208					openHit = 1;
209				});
210			} else {
211				var ct	= $(trgEl).parentsUntil(me.rootNode, ctSelector).last(),
212					hd	= ct.length ? 0 : $(trgEl).closest(tiSelector).get(0);
213				
214				openHit = 1;
215				
216				me.open(hd ? hd : $(ct).prev(tiSelector).get(0));
217			}
218			
219			if (openHit) {
220				var topPos 	= parseInt($(trgEl).offset().top, 10),
221					scTop	= parseInt($(trgEl).css('scroll-margin-top'), 10) || parseInt($('> button', trgEl).css('scroll-margin-top'), 10);	
222					
223				if (topPos < 10 || window.globalIkissAccordionIsScrolling === true) 
224					return;
225				
226				if (scTop) {
227					topPos -= scTop;	
228				}
229				
230				window.globalIkissAccordionIsScrolling = true;
231				
232				$('html, body').animate({scrollTop: topPos}, 500);
233								
234			}
235		}
236		
237	};
238	
239	$.fn.ikissAccordion = function (options) {
240		var pKey = (options && options.pluginKey) || 'ikissAccordion';
241		return this.each(function() {
242			if (!$.data(this, pKey)) {    
243				$.data(this, pKey, new Plugin(this, options));
244			}          
245		});
246	};
247	
248	//Kompatibilität zur alten Accordion Syntax
249	window.ikissAccordion = function(config) {
250		
251		var cf = $.extend({ 
252			titleSelector		: '.toggler-title',
253			containerSelector	: '.toggler-container',
254			openFirstOnLoad		: false, 
255			wrapInner			: false
256		}, config || {});
257		
258		$.extend(cf, {
259			pluginKey		: (cf.titleSelector+'-'+cf.containerSelector).replace(/\./g, ''),
260			autoOpenFirst	: (cf.openFirstOnLoad || cf.autoOpenFirst)
261		});
262		delete cf.openFirstOnLoad;
263		
264		$(document.body).ikissAccordion(cf);
265	};
266	
267})(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.