PageSourceSearch

https://www.edith-stein-kreis.de/templates/public/js/basic.js?1789551943

js edith-stein-kreis.de collected 2026-10-02 23:27:15 UTC 50,704 bytes, 1,742 lines download raw bytes

1// doc: 120718
2
3
4// Namespacing. Das et-Objekt und ggf. Unterobjekte nur einmal am Anfang initialisieren!
5var et = et || {},
6	jQ = jQuery;
7
8/*
9==================================================
10Helper-Funktionen 110623 (Wolfgang)
11==================================================
12ein paar kleine allgemeine Hilfsfunktionen
13*/
14
15// Allgemeine Methode zum Erstellen von Events
16et.addEvent = function (el, type, fn){
17	el.addEventListener(type, fn, false);
18};
19
20// ersetzt addLoadEvent
21et.onLoad = function(fn)
22{
23	this.addEvent(window,'load',function(){fn();});
24};
25
26// einfache Methode zum "Kopieren" von Objekten
27// Argumente können direkt an eine configure-Funktion übergeben werden
28et.clone = function (original, args) 
29{
30	var F = function () {}, obj;
31	F.prototype = original;
32	obj = new F();
33	if (obj.configure && args) 
34	{
35		obj.configure(args);
36	}
37	return obj;
38};
39
40
41// Methode zum Kombinieren von Objekten 
42// (Werte von updateObj überschreiben die von defaultObj)
43et.combine = function(defaultObj, updateObj)
44{
45	var name, 
46		returnObj = this.clone(defaultObj);
47	for (name in updateObj)
48	{
49		if (updateObj.hasOwnProperty(name))
50		{
51			returnObj[name] = updateObj[name];
52		}
53	}
54	return returnObj;
55};
56
57
58// Verwandelt das bei Typo3 standardmäßig ersetzte @ zurück (bei pageLoad)
59et.convertAt = function() {
60	var dels = document.getElementsByTagName("del"),
61		i;
62	for (i=0; i<dels.length; i++) {
63		if (dels[i].className && dels[i].className === "schutz") {
64			dels[i].firstChild.data = "@";
65			}
66		}
67	};	
68et.onLoad(et.convertAt);
69
70
71
72/*
73==================================================
74Auf Window-Resize reagieren 130530  (Wolfgang)
75==================================================
76Jetzt auch für mehrfache Anwendung auf einer Seite
77Der Zeitabstand lässt sich leider nur noch einmalig beim ersten Aufruf einstellen
78*/
79et.afterBrowserResize = function(func,lapse,andNow)
80{
81	var l = Number(lapse) | 100;
82	
83	et.afterBrowserResize.funcsArr.push(func);
84	if (!et.afterBrowserResize.timeOut)
85	{
86		$(window).resize(function() {	  
87			clearTimeout(et.afterBrowserResize.timeOut);
88			et.afterBrowserResize.timeOut = setTimeout(et.afterBrowserResize.runFuncs, l);
89		});
90	}
91	if (andNow)
92	{
93		func();
94	}
95};
96
97et.afterBrowserResize.timeOut = false;
98et.afterBrowserResize.funcsArr = [];
99et.afterBrowserResize.runFuncs = function(e)
100{	
101	for (i=0; i < et.afterBrowserResize.funcsArr.length; i++ )
102	{
103		et.afterBrowserResize.funcsArr[i]();
104	}
105};
106
107
108/*
109==================================================
110Größen vergleichen 130630  (Wolfgang)
111==================================================
112Gibt ein Objekt zurück, das die größte/kleinste Höhe/Breite etc. der mitgegebenen Elemente enthält
113*/
114et.getDimensions = function(elems)
115{
116	var d = 
117	{
118		wMax : 0,
119		wMin : 999999,
120		hMax : 0,
121		hMin : 999999,
122		/*wMaxElems,
123		wMinElems,
124		hMaxElems,
125		hMinElems,*/
126		outerWCombined : 0,
127		outerHCombined : 0
128	};
129	$(elems).each(function()
130	{
131		var outerW = $(this).outerWidth(true),
132			outerH = $(this).outerHeight(true);
133		d.wMax = outerW > d.wMax ? outerW : d.wMax;
134		d.wMin = outerW < d.wMin ? outerW : d.wMin;
135		d.hMax = outerH > d.hMax ? outerH : d.hMax;
136		d.hMin = outerH < d.hMin ? outerH : d.hMin;
137		d.outerWCombined += outerW;
138		d.outerHCombined += outerH;
139	});	
140	return d ;
141};
142
143
144/*
145==================================================
146Touchwipe für Slider 
147==================================================
148*/
149
150/**
151 * jQuery Plugin to obtain touch gestures from iPhone, iPod Touch and iPad, should also work with Android mobile phones (not tested yet!)
152 * Common usage: wipe images (left and right to show the previous or next image)
153 * 
154 * @author Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
155 * @version 1.1.1 (9th December 2010) - fix bug (older IE's had problems)
156 * @version 1.1 (1st September 2010) - support wipe up and wipe down
157 * @version 1.0 (15th July 2010)
158 */
159(function($){$.fn.touchwipe=function(settings){var config={min_move_x:20,min_move_y:20,wipeLeft:function(){},wipeRight:function(){},wipeUp:function(){},wipeDown:function(){},preventDefaultEvents:true};if(settings)$.extend(config,settings);this.each(function(){var startX;var startY;var isMoving=false;function cancelTouch(){this.removeEventListener('touchmove',onTouchMove);startX=null;isMoving=false}function onTouchMove(e){if(config.preventDefaultEvents){e.preventDefault();}if(isMoving){var x=e.touches[0].pageX;var y=e.touches[0].pageY;var dx=startX-x;var dy=startY-y;if(Math.abs(dx)>=config.min_move_x){cancelTouch();if(dx>0){config.wipeLeft()}else{config.wipeRight()}}else if(Math.abs(dy)>=config.min_move_y){cancelTouch();if(dy>0){config.wipeDown()}else{config.wipeUp()}}}}function onTouchStart(e){if(e.touches.length==1){startX=e.touches[0].pageX;startY=e.touches[0].pageY;isMoving=true;this.addEventListener('touchmove',onTouchMove,false)}}if('ontouchstart'in document.documentElement){this.addEventListener('touchstart',onTouchStart,false)}});return this}})(jQuery);
160
161
162/*
163==================================================
164Slider einrichten 110620  (Wolfgang) [jQuery]
165==================================================
166Erstellt aus allen statischen "div.container-slider" dynamische Switchboxen,
167deren Inhalte einzeln durchgeschaltet werden können.
168
169benötigt jQuery, et.clone, et.combine
170*/
171//var jQ = jQuery.noConflict();
172
173// Namespacing-Objekt
174et.slider = {};
175
176// Clone-Vorlage für die tatsächlichen slider (quasi die Klasse)
177et.slider.obj = 
178{
179	jQ_obj : "jQ",
180	jQ_targets : "jQ",
181	jQ_container: "jQ",
182	opt : {},
183	curNum : 0,
184	maxNum : 0,
185	interval : 0,
186	reactivateTimeout : 0,
187	layerWidth : 0,
188	fullWidth : 0,
189	anim : function() {},
190	switchTo : function() {},
191	extendSwitchTo : function(correctedNr) {},	
192	createHtml : function() {},
193	configure : function() {}
194};
195et.slider.objectsArray = [];
196
197// Option: Sliding-Animation (anim:"slideH")
198et.slider.obj.slideH = function(nr, correctedNr, corrected, dirForward, dontAnimate)
199{
200	var nr =  nr,
201		containerAnim = -this.layerWidth*nr;
202	// Auf Min/Maxnummer korrigieren, wenn nicht loopend
203	if (!this.opt.loop)
204	{
205		// aktive Box soll mittig stehen - Berechnung, welches Element ganz links steht
206		if (this.opt.centerAct)
207		{
208			nr =  nr - Math.floor((this.range-1)/2);
209		}
210		nr = nr + this.range > this.maxNum + 1 ? (this.maxNum + 1 - this.range) : nr;
211		nr = nr < 0 ? 0 : nr;
212		containerAnim = -this.layerWidth*nr;
213	}
214	// Berechungen nur bei loopendem Container notwendig
215	else //if (!dontAnimate)
216	{	
217		//tritt eine Lücke auf, wenn es vorwärts oder rückwärts geht?
218		//im ersten Fall bei backwardGap besteht bereits eine Lücke!
219		var forwardGap = this.curNum + this.range > this.maxNum,
220			backwardGap = this.curNum + this.range - 1 > this.maxNum || this.curNum === 0,
221			containerSet = -this.layerWidth*this.curNum;
222		//Reset der einzelnen Elemente
223		this.jQ_targets.css({left:0});
224		//Berechnung der Position und Animationsziel des Containers
225		//und Position der Elemente (wegen Anschluss vor dem ersten/Nach dem Letzten Element)
226		//alert(nr+' '+correctedNr+' '+corrected+' '+dirForward+' '+dontAnimate+' '+forwardGap);
227		if(forwardGap && dirForward)
228		{			
229			this.jQ_targets.slice(this.curNum).css({left:-this.fullWidth});
230			containerSet = this.layerWidth*(this.maxNum - this.curNum + 1);
231			containerAnim = this.layerWidth*(this.maxNum - nr + 1);
232		}  
233		else if (backwardGap && !dirForward)
234		{
235			this.jQ_targets.slice(nr).css({left:-this.fullWidth});
236			containerSet = this.curNum===0 ? 0 : this.layerWidth*(this.maxNum - this.curNum + 1);
237			containerAnim = this.layerWidth*(this.maxNum - correctedNr + 1);
238		}
239		this.jQ_container.stop(true).css({marginLeft:containerSet});
240	} 
241	//Animieren des Containers
242	if(!dontAnimate)
243	{
244		this.jQ_container.stop(true).animate({marginLeft:containerAnim},this.opt.speed, this.opt.easing);
245	}
246	else 
247	{
248		this.jQ_container.stop(true).css({marginLeft:containerAnim});
249	}
250};
251
252// Option: Fading-Animation (anim:"fade")
253et.slider.obj.fade = function(nr, correctedNr, corrected, dirForward)
254{
255	this.jQ_targets.eq(correctedNr).hide().addClass("new").fadeIn(this.opt.speed, function() 
256	{
257		jQ(this).siblings(".act").removeClass("act").hide();
258		jQ(this).addClass("act").removeClass("new");
259	});
260}
261
262
263// Wechselfunktion zwischen den Elementen, anstoßen der Animation
264et.slider.obj.switchTo = function(nr)
265{	
266	if ((this.jQ_container.is(':animated') && this.opt.loop) || this.jQ_targets.is(':animated') || this.dontSlide)
267	{
268		return;
269	}
270	if (this.opt.switchFullRange && nr < 0)
271	{
272		nr = 0;
273	}
274	var dirForward = nr > this.curNum;
275	var correctedNr = nr > this.maxNum ? 0 : nr;
276	correctedNr = correctedNr < 0 ? this.maxNum : correctedNr;
277	var corrected = correctedNr!==nr;
278	if ((!corrected || this.opt.loop) && nr !== this.curNum)
279	{
280		this.anim(nr, correctedNr, corrected, dirForward);
281		this.extendSwitchTo(correctedNr);
282		this.curNum = correctedNr;
283	}
284	this.updateState();
285};
286
287// Funktion, die von den Buttons ausgelöst wird
288et.slider.obj.uiSwitchTo = function(e, obj, btn, nr)
289{
290	e.preventDefault();
291	if(!jQ(btn).is('.inact'))
292	{
293		obj.switchTo(nr);
294		obj.stopSlideshow();
295	}
296}
297
298
299// Erstellt die wraps und css-Grundeistellungen
300et.slider.obj.createWraps = function()
301{
302	var outer = this.jQ_obj;
303	
304	// zuerst das äußerste Sliderobjekt finden, ggf. erstellen 
305	if (outer.is('.layer-container, .slider-mask'))
306	{
307		outer = outer.parent().is('.slider-mask') ? outer.parent() : outer;	
308		if (!outer.parent().is('.slider-outer'))
309		{
310			outer.wrap('<div class="slider-outer"></div>');
311		}
312		outer = outer.parent();
313	} 
314	// dann von außen nach innen die Wraps aufbauen
315	if(!outer.children().is('.slider-mask'))
316	{
317		outer.wrapInner('<div class="slider-mask"></div>');
318	}
319	if(!outer.children().children().is('.layer-container'))
320	{
321		outer.children().wrapInner('<div class="layer-container"></div>');
322	}
323	
324	this.jQ_obj = outer;
325	this.jQ_mask = outer.children();
326	this.jQ_container = outer.children().children();
327};
328
329// Erstellt die Navigations-Buttons etc.
330et.slider.obj.createControls = function()
331{
332	var that = this,
333	controls = jQ('<div class="slider-controls"></div>');
334	if (this.opt.controls)
335	{
336		jQ('<a class="btn-back '+this.opt.btnClasses+'" href="#zurueck" title="ein Bild zur&uuml;ck"><b>&lt;</b></a>').appendTo(controls).click(function(e){
337			that.uiSwitchTo(e, that, this, that.curNum-that.switchRange);
338		});
339		var menu = jQ('<ol class="menu"></ol>');
340		for (var i=0; i < that.maxNum+1; i++)
341		{
342			var li = jQ('<li>');
343			li.appendTo(menu).click(function(e)
344			{
345				var nr = jQ(this).index();
346				that.uiSwitchTo(e, that, this, nr);
347			});
348		}
349		menu.appendTo(controls);
350		
351		jQ('<a class="btn-forward '+this.opt.btnClasses+'" href="#vor" title="n&auml;chstes Bild anzeigen"><b>&gt;</b></a>').appendTo(controls).click(function(e){
352			that.uiSwitchTo(e, that, this, that.curNum+that.switchRange);
353		});	
354		this.jQ_controls = controls;
355		this.jQ_layerCounter = jQ('<div class="info layer-counter"></div>');
356		this.jQ_obj.append(this.jQ_layerCounter);
357		this.jQ_obj.append(controls);		
358	}
359	// Einfache Touch-Bedienung (Swipe löst Wechsel aus, leider kein stufenloses Ziehen)
360	this.jQ_mask.touchwipe(
361	{
362		wipeLeft: function() 
363		{ 
364			that.switchTo(that.curNum+that.switchRange);
365			that.stopSlideshow();
366		},
367		wipeRight: function() 
368		{ 
369			that.switchTo(that.curNum-that.switchRange);
370			that.stopSlideshow(); 
371		},
372		min_move_x: 20,
373		min_move_y: 20,
374		preventDefaultEvents: false
375	});
376}
377
378et.slider.obj.prepareAnimType = function()
379{
380	switch (this.opt.anim)
381	{
382		case "fade":
383			this.anim = this.fade;
384			//this.jQ_targets.css({position:'absolute'});
385			break;
386		default:
387			this.anim = this.slideH;
388	}
389}
390
391// aktuellen Stand des Sliders abbilden
392et.slider.obj.updateState = function()
393{
394	var firstSlide = this.curNum === 0,
395		lastSlide = this.curNum === this.maxNum || (this.opt.switchFullRange && (this.curNum > this.maxNum - this.range)),
396		maxTxt = this.maxNum+1,
397		curTxt = this.curNum+1,
398		counterText = curTxt+'/'+maxTxt;;
399	
400	this.dontSlide = false;
401	this.jQ_obj.removeClass('dont-slide');
402	if (this.jQ_targets.length < this.range+1){
403		this.dontSlide = true;
404		this.jQ_obj.addClass('dont-slide');
405	}
406	
407	if (!this.opt.loop)
408	{
409		this.jQ_controls.find('a').removeClass('inact');
410		if (lastSlide)
411		{
412			this.jQ_controls.find('.btn-forward').addClass('inact');
413		} 
414		else if (firstSlide)
415		{
416			this.jQ_controls.find('.btn-back').addClass('inact');
417		}
418	}
419	
420	this.jQ_layerCounter.text(counterText);
421	this.jQ_controls.find('.menu li').eq(this.curNum).add(this.jQ_targets.eq(this.curNum)).addClass('act').siblings().removeClass('act');
422}
423
424// Konfiguriert die sliderbox anhand des ausgesuchten jQuery-Objekts
425et.slider.obj.configure = function(confArray) 
426{
427	this.opt = confArray[1];
428	this.jQ_obj = confArray[0];
429	this.jQ_targets = this.jQ_obj.find(this.opt.layers).first().siblings().addBack();
430	this.maxNum = this.jQ_targets.length-1;
431	
432	this.createWraps();	
433	this.createControls();
434	this.prepareAnimType();
435	
436	this.setDimensions(this);
437	//this.updateState(); // jetzt auch am Ende von setDimensions()
438	this.startSlideshow();
439};
440
441// Startet das automatische Weiterblättern
442et.slider.obj.startSlideshow = function()
443{
444	var that = this;
445	clearInterval(this.interval);
446	clearTimeout(this.reactivateTimeout);
447	if (this.opt.autoslideInterval > 0)	
448	{
449		this.interval = window.setInterval(function()
450		{
451			that.switchTo(that.curNum+that.switchRange);
452		}, that.opt.autoslideInterval);
453	}
454};
455
456// Stoppt das automatische Weiterblättern
457et.slider.obj.stopSlideshow = function()
458{
459	var that = this;
460	clearInterval(this.interval);
461	if (this.opt.autoslideInterval > 0 && this.opt.autoslideReactivateAfter > 0)
462	{
463		clearTimeout(this.reactivateTimeout);
464		this.reactivateTimeout = window.setTimeout(function()
465		{
466			that.startSlideshow();
467		}, that.opt.autoslideReactivateAfter);
468	}
469};
470
471// Slider für Responsive anpassen
472et.slider.obj.setDimensions = function(obj)
473{
474	var obj = obj || this,
475		maxH;
476	obj.range = obj.opt.range;
477	if (obj.opt.responsive && obj.opt.range > 1  && obj.opt.layerMinWidth > 0 )
478	{		
479		obj.range = Math.min(obj.opt.range, Math.floor(obj.jQ_obj.width()/obj.opt.layerMinWidth));
480	}
481	
482	obj.switchRange = obj.opt.switchFullRange ? obj.range : 1;
483	// responsive funktioniert nur, wenn layers keinen Extra-Margin haben
484	// außerdem +1 Hack wegen Blitzern im FF
485	obj.layerWidth = obj.opt.responsive ? Math.round((obj.jQ_obj.width()/obj.range)) : obj.jQ_targets.outerWidth(true);
486	obj.fullWidth = obj.layerWidth*(obj.maxNum+1);
487	if (obj.opt.responsive)
488	{
489		// width() addiert fälschlich die Paddings dazu
490		obj.jQ_targets.css('width',obj.layerWidth);
491	}
492	obj.anim(obj.curNum, obj.curNum, false, true, true);
493	maxH = et.getDimensions(obj.jQ_targets).hMax;
494	switch (obj.opt.anim)
495	{
496		case "fade":
497			//obj.jQ_container.height(maxH);
498			break;
499		default:
500			obj.jQ_container.width(obj.fullWidth);
501	}
502	obj.maxH = maxH;
503	obj.jQ_controls.find('.menu').width(et.getDimensions(obj.jQ_controls.find('li')).outerWCombined);
504	obj.updateState();
505	obj.extendSwitchTo(obj.curNum);
506}
507
508et.slider.obj.extendSwitchTo = function(correctedNr)
509{
510}
511
512// Standard-Erstellungs-Optionen. Können durch init-Argument angepasst werden.
513et.slider.def = 
514{
515	containers:".slider-outer",	
516	layers:".layer",
517	responsive: true,
518	range: 1,
519	layerMinWidth: 0,
520	speed: 500,
521	autoslideInterval: 0,
522	autoslideReactivateAfter: 12000,
523	easing:"swing",
524	loop: false, // nicht mit switchFullRange!
525	anim:"slideH",
526	controls: true,
527	btnClasses: '',
528	centerAct: false, // nicht mit loop, switchFullRange!
529	switchFullRange: false,
530	noInitIfLayerCount: 1 // -1,0,1,2,3 ... 'range' 
531};
532
533// Gibt das Slider-Objekt zu einem $('.slider-outer') zurück
534et.slider.getObj = function(jQ_obj)
535{
536	var id = $(jQ_obj).data('switchId'),
537		obj = this.objectsArray[id];
538	return obj
539}
540
541// Sucht die slider im Html und erstellt entsprechend die Objekte
542et.slider.init = function(optObj)
543{
544	var opt = et.combine(this.def,optObj),
545		switchdivs = jQ(opt.containers), 
546		len = switchdivs.length,
547		noInitIfLayerCount,
548		layerCount, 
549		i;
550	for (i=0; i < len; i++)
551	{
552		// children() funktioniert nicht, wenn mehr als ein wrap bereits vorhanden ist
553		layerCount = switchdivs.eq(i).find(opt.layers).length;
554		noInitIfLayerCount = opt.noInitIfLayerCount === 'range' ? opt.range : Number(opt.noInitIfLayerCount);
555		if (isNaN(noInitIfLayerCount) || layerCount > noInitIfLayerCount)
556		{
557			(function(that, i)
558			{
559				var id = that.objectsArray.length,
560					obj = that["obj_"+id] = et.clone(that.obj, [switchdivs.eq(i), opt]);
561				obj.switchId = id;	
562				obj.jQ_obj.data({'switchId':id}).addClass('slider-id-'+id);
563				that.objectsArray.push(obj);
564				if (opt.responsive)
565				{
566					et.afterBrowserResize(function()
567					{
568						obj.setDimensions(obj);
569					});
570				}
571			})(et.slider, i);
572		}
573		else
574		{
575			switchdivs.eq(i).addClass('not-initialized');
576		}
577	}
578};
579
580
581
582// Ruft verschiedene slider mit den angepassten Optionen auf
583// Möglichst nur dieses anpassen
584var startSliders = function()
585{
586	// nicht sliden, wenn feediting aktiv ist!
587	if ($('.typo3-feedit-element, .content-link').length)
588	{
589		return;
590	}
591	
592	et.slider.init({
593		containers:".top-slider",	
594		autoslideInterval: 6000,
595		loop: true
596	});
597	et.slider.init({
598		containers:".teaser-slider",
599		loop: true
600	});
601	et.slider.init({
602		containers:".textpic-slider",	
603		autoslideInterval: 6000,
604		loop: true
605	});
606	et.slider.init({
607		containers:".gallery-slider",
608		loop: true
609	});
610	et.slider.init({
611		containers:".slider-6",	
612		layerMinWidth: 125,
613		range: 6,
614		switchFullRange: true,
615	});
616	et.slider.init({
617		containers:".logo-slider > div",
618		layers:".wrap-img",
619		layerMinWidth: 150,
620		range: 6,
621		loop: true
622	});
623	
624	// Thumbnail-Slider steuert großen Slider
625	$('.slider-with-thumbslider .slider-6 .layer').click(function()
626	{
627		var index = $(this).index();
628		$(this).parents('.slider-with-thumbslider').first().find('.slider-outer .menu li').eq(index).click();
629	});
630};
631
632
633et.onLoad(function()
634{
635	startSliders();
636	et.setMaxImgHeight('.slider-outer');
637});
638
639/*
640==================================================
641Bildhöhe angleichen 130710  (Wolfgang) [jQuery]
642==================================================
643Kein Slider-Bild soll größer sein als das erste
644
645benötigt jQuery
646*/
647et.setMaxImgHeight = function(container, index)
648{
649	//var index = index || 0;
650	
651	$(container).each(function()
652	{
653		var //refImg = $(this).find('img').eq(index),
654			//refH = refImg.height(),
655			sliderObj = et.slider.getObj(this),
656			dimensions = et.getDimensions($(this).find('img')),
657			wMax = dimensions.wMax,
658			hMin = Math.max(dimensions.hMin, wMax*9/16),
659			vpH = $(window).height(),
660			vpMax = Math.max(vpH*3/4, vpH-150, 320);			
661		refH = Math.min(hMin,vpMax);
662		$(this).find('img').each(function()
663		{
664			var factor = 100 * refH / $(this).height();
665			if ( factor < 100 )
666			{
667				$(this).parents('.inner-wrap').css('width',factor+'%');
668			}
669		});
670		if(sliderObj)
671		{
672			sliderObj.setDimensions(sliderObj);
673		}
674	});
675	
676};
677
678
679/*
680==================================================
681Variable Responsive-Menüs  130710 (Wolfgang) [jQuery]
682==================================================
683Responsive-Menüs werden erst hinter dem Button versteckt, 
684wenn sie auch tatsächlich zu breit werden 
685
686benötigt jQuery
687*/
688et.responsiveMenu = {}
689et.responsiveMenu.objsArr = []
690
691et.responsiveMenu.update = function()
692{
693	var len = et.responsiveMenu.objsArr.length,
694		winW = $(window).width(),
695		responsiveClass = 'responsive-on',
696		obj,
697		i;
698	for (i=0; i<len; i++)
699	{
700		obj = et.responsiveMenu.objsArr[i]
701		obj.container.removeClass(responsiveClass);
702		$('body').removeClass('responsive-menu-0');
703		if (obj.breakFullW > winW && obj.maxW >= winW)
704		{
705			obj.container.addClass(responsiveClass);
706			$('body').addClass('responsive-menu-0');
707		}
708	}
709}
710
711et.responsiveMenu.init = function()
712{
713	var menu0 =
714		{
715			container : $('.area-menu-0'),
716			breakFullW : et.getDimensions($('.menu-0 > li')).outerWCombined+30,
717			maxW : 1100
718		};
719	if ($('body').is('.layout-jugend'))
720	{
721		menu0.breakFullW = et.getDimensions($('.menu-0 > li, #header #logo, #header .search-header .show-search')).outerWCombined+35;
722		menu0.maxW = 1199;
723	}
724	if ($('body').is('.layout-dom'))
725	{
726		menu0.breakFullW = et.getDimensions($('.menu-0 > li, #header #logo, #header .search-header, .menu-lang li')).outerWCombined+100;
727		menu0.maxW = 1600;
728	}
729	// Buttons zum Menü-Öffnen
730	$('.menu-0 li').has('ul').each(function(){
731		var btn = $('<div href="#" class="btn icon"></div>');
732		$(this).append(btn);
733		btn.click(function(e){
734			$(this).parent().toggleClass('opened').siblings().removeClass('opened');
735		});
736	});
737	$('.menu-0 .act').has('ul').addClass('opened');
738    if (!$('body.mode-mobile').length) {
739        et.responsiveMenu.objsArr = [menu0];
740        et.afterBrowserResize(et.responsiveMenu.update, false, true);
741    }
742    $('.responsive-menu-btn').click(function(e)
743	{
744		$('.area-menu-0').toggleClass('opened');
745        $('body').toggleClass('mobile-mainmenu-open');
746	});
747
748}
749
750
751
752/*
753==================================================
754Popup-Search [jQuery]
755==================================================
756Such-Box im Header klappt aus (Jugend und Dom Template)
757*/
758var headerSearch = function () {
759	var wrap = $('.search-header.popup-search'),
760		btn = wrap.find('.show-search'),
761		form = wrap.find('form'),
762		input = wrap.find('.input-text');
763
764	btn.click(function (e) {
765		if (!wrap.is('.is-open')) {
766			form.css('display', 'block');
767			btn.attr('aria-expanded', true);
768			setTimeout(function () {
769				wrap.addClass('is-open');
770				input.trigger("focus");
771			}, 30);
772
773			form.on('focusout.closesearch', function (e2) {
774				setTimeout(function () {
775					if (form.has($(document.activeElement)).length === 0) {
776						wrap.removeClass('is-open');
777						btn.attr('aria-expanded', false);
778						form.off('.closesearch');
779						setTimeout(function () {
780							if (!wrap.is('is-open')) {
781								form.css('display', 'none');
782							}
783						}, 500);
784					}
785				});
786			});
787		}
788	});
789};
790$(document).ready(function () {
791	headerSearch();
792});
793
794
795
796/*
797==================================================
798Accordion [jQuery]
799==================================================
800*/
801et.initAccordions = function()
802{
803	$('.accordion-label').click(function(e)
804	{
805		var a = $(this).parents('.accordion').first();
806		a.toggleClass('act').children('.accordion-content').stop().slideToggle(300);
807		a.siblings().removeClass('act').children('.accordion-content').stop().slideUp(300);
808	});
809	$('.menu-archive .accordion:has(.act)').addClass('act');
810	$('.accordion:not(.act) .accordion-content').hide();
811}
812
813/*
814==================================================
815Footer-Social-Buttons ausrichten
816==================================================
817*/
818et.SocialFooterBtns = function()
819{
820	$('body:not(.layout-dom) #footer').find('a[href*="facebook."], a[href*="instagram."],  a[href*="twitter."], a[href*="youtube."], a[href*="google."], a[href*="whatsapp."]').each(function()
821	{
822		$(this).attr('title',$(this).text()).parent().addClass('wrap-social-btn');
823	});
824}
825
826
827/*
828==================================================
829Pdf-Links in Subsites korrigieren
830==================================================
831Funktionieren sonst wegen Base-URL + Absrefprefix = / nicht korrekt
832*/
833et.fixPdfLinks = function()
834{
835	$('a[href*=".pdf"], a[href*=".PDF"], a[href*=".Pdf"]').each(function()
836	{
837		if ($(this).is('a[href^="/"]'))
838		{
839			var href = $(this).attr('href');
840			href = href.substr(1, href.length-1);
841			$(this).attr('href',href);
842		}
843	});
844};
845
846/*
847==================================================
848Slider-Box komplett verlinken
849==================================================
850*/
851et.linkFullSliderBox = function()
852{
853	$('.top-slider .layer').each(function()
854	{
855		var textContainer = $(this).find('.overlay, .col-4'),
856			overLinks = textContainer.find('a'),
857			overHref = overLinks.attr('href'),
858			overTarget = overLinks.attr('target') || '_self',
859			differingOverHrefs = overLinks.length != overLinks.filter('a[href="'+overHref+'"]').length,
860			imgLink = $(this).find('.csc-textpic-imagewrap a, .wrap-img a'),
861			imgHref = imgLink.attr('href'),
862			imgTarget = imgLink.attr('target'),
863			imgLinkLightbox = imgLink.is('[rel^="lightbox"]'),
864			href = overHref || imgHref,
865			target = imgTarget || overTarget;
866		
867		if ( !differingOverHrefs && !imgLinkLightbox && href && (overHref == imgHref || !overHref || !imgHref) )
868		{
869			$(this).addClass('box-full-link').click(function(e)
870			{
871				e.preventDefault();
872				window.open(href, target);
873			});
874		}		
875		else if (!differingOverHrefs && overHref)
876		{
877			textContainer.addClass('box-full-link').click(function(e)
878			{
879				e.preventDefault();
880				window.open(href, target);
881			});
882		}
883		
884	});
885}
886
887
888/*
889==================================================
890Fancybox (Lightbox) starten [Fancybox, jQuery]
891==================================================
892*/
893et.initFancybox = function()
894{
895	$('.top-slider').each(function()
896	{
897		var rel= 'lightbox['+$(this).parent().attr('id')+']';
898		$(this).find('.lightbox').attr('rel',rel);
899	});
900	$(".lightbox").fancybox({
901		title:function()
902		{
903			var caption = $(this).find('.caption').html() || $(this).siblings('.caption').html() || '',
904				copyright = $(this).find('.copyright').html() || $(this).siblings('.copyright').html() || '';
905			copyright = copyright.length ? ' <span class="inline-copyright">'+copyright+'</span>' : '';
906			return caption+copyright
907		},		
908		type : 'image',
909		helpers: {
910			title : {
911				type : 'inside'
912			}
913		}
914	});
915}
916
917
918/*
919==================================================
920"Anchors" für Powermail-Formular-Actions
921==================================================
922*/
923et.setPowermailAnchors = function()
924{
925	var id = "#powermail-form";
926	$('.tx-powermail form').each(function(){
927		var f = $(this);
928		f.attr('action', f.attr('action')+id);
929	})
930}
931
932
933/*
934==================================================
935Menu-0: 1. touch -> hover
936==================================================
937*/
938et.initTouchHover = function()
939{
940	// Nur relevant, wenn das Gerät überhaupt Touch unterstützt
941	if (!$('.touch-support').length)
942	{
943		return;
944	}
945	// touchstart hat Scrollen unterbunden, daher click;  
946	// touchend hinzugefügt, da 'hover' auch bei nur leichter Berührung oder Scrollen funktionieren darf
947	$('.menu-0 > li > a, .box-cube a').on('click, touchend', function(e){		
948		// Nur weiter, wenn auch tatsächlich (bereits) getoucht wurde (wegen 'click')
949        if (!et.has.touchConfirmed)
950		{
951			return true
952		}
953		
954		var elem = $(this),
955			cl = 'touch-hover';
956		// Unterscheidung .menu-0/.box-cube
957		if (elem.parents('.menu-0').length)
958		{
959			// Wenn Responsive-Menü aktiv ist, gibt es kein hover
960			if ($('.area-menu-0.responsive-on').length) 
961			{			
962				return true;
963			}
964			elem = elem.parent();
965		}
966		// Link ausführen, wenn das Elem nach erstem touch/klick nochmal geklickt wird
967		if (elem.hasClass(cl))
968		{
969			return true;
970		}
971		// sonst stoppen, Klasse setzen und body-Listener setzen
972		else 
973		{
974			e.preventDefault();
975			$('.'+cl).removeClass(cl);
976			elem.addClass(cl);
977			// Nur das erste mal, wenn nach 'touch-hover' der body woanders getoucht/geklickt wird
978			// soll die Klasse auf dem Elem wieder entfernt werden
979			$('body').off('.touchhover').on('touchend.touchhover click.touchhover', function(e){
980				var t = $(e.target);
981				if (!t.hasClass(cl) && !t.parents('.'+cl).length)
982				{
983					$('.'+cl).removeClass(cl);
984					$(this).off('.touchhover');
985				}
986			});
987			
988			return false;
989		}
990	});
991};
992
993
994/*
995==================================================
996Fullsize-Img neben 600px-Teaser
997==================================================
998*/
999et.alignFullSizeImg = function()
1000{
1001	$('.full-size').each(function()
1002	{
1003		
1004		var otherCol = $(this).parents('.csc-textpic').first().parent('.col-6').siblings('.col-6');
1005		if(otherCol.find('.box-bigcube, .box-bigimgteaser').length)
1006		{
1007			$(this).addClass('h-600');
1008		}
1009	});
1010}
1011/*
1012==================================================
1013Support Youtube-iFrame mit "embed-container"
1014==================================================
1015*/
1016et.supportYoutubeHtml = function()
1017{
1018	$('*:not(.ece-media-element) > .embed-container:not(.no-helper)').wrap('<div class="col iframe-helper"></div>');
1019}
1020
1021/*
1022==================================================
1023Fix Audio statt Video in News
1024==================================================
1025*/
1026et.fixNewsAudio = function()
1027{
1028	$('audio').each(function()
1029	{
1030		$(this).parents('.video-responsive-wrapper').addClass('wrap-audio wrap-media').removeClass('video-responsive-wrapper');
1031	});
1032}
1033
1034
1035/*
1036==================================================
1037Externe News kenntlich machen
1038==================================================
1039*/
1040et.externalNews = function()
1041{
1042	var curDomain = window.location.hostname;
1043	
1044	$('.news-list-view a').each(function()
1045	{
1046		var a = $(this),
1047			href = a.attr('href'),
1048			hasDomain = href.indexOf('http') === 0 || href.indexOf('//') === 0,
1049			linkDomain = hasDomain ? href.split('//')[1].split('/')[0] : false;
1050		if (hasDomain && linkDomain !== curDomain)
1051		{
1052			a.addClass('external-news').attr('target','_blank').parent('.list-teaser').find('.wrap-txt p').after('<p class="source-news">Meldung von '+linkDomain+'</p>');
1053		}			
1054	});
1055}
1056
1057
1058/*
1059==================================================
1060Captions über 2 Zeilen unter das Bild schieben
1061==================================================
1062*/
1063et.fixCaptions = function()
1064{
1065	if ($('.caption').length > 0)
1066	{
1067		et.afterBrowserResize(et.fixCaptions.update,false,true);
1068	}
1069}
1070et.fixCaptions.update = function()
1071{
1072	setTimeout(function()
1073	{
1074		$('.caption').each(function()
1075		{
1076			var elem = $(this)
1077				h = elem.height();
1078			// Zeilenhöhe ca. 18-21px
1079			if (h > 50)
1080			{
1081				elem.addClass('caption-below-img');
1082			}
1083			else
1084			{
1085				elem.removeClass('caption-below-img');
1086			}
1087		});
1088	}, 800);
1089}
1090
1091$(document).ready(function()
1092{	
1093	et.responsiveMenu.init();
1094	et.initAccordions();
1095	et.initFancybox();
1096	et.SocialFooterBtns();
1097	et.linkFullSliderBox();
1098	et.alignFullSizeImg();
1099	et.supportYoutubeHtml();
1100	et.setPowermailAnchors();
1101	et.initTouchHover();
1102	et.externalNews();
1103	et.fixCaptions();
1104	et.fixNewsAudio();
1105	et.fixPdfLinks();
1106});
1107
1108
1109	function initOpenStreetMaps() {
1110		if (!$('div.openstreetmap').length) {
1111			return;
1112		}
1113		$("script.openstreetmap").each(function () {
1114			let script = $('<script></script>');
1115			script.attr('src', $(this).attr('src'));
1116			$(this).before(script).remove();
1117		});
1118	}
1119
1120	jQ(document).ready(function()
1121	{
1122		placeHolderInDevMode(false);
1123	});
1124	
1125	
1126	function placeHolderInDevMode(forceDev)
1127	{
1128		var isDev = window.location.href.indexOf("dev.") > -1 && window.location.href.indexOf("die-etagen") > -1;
1129		var isDev = (isDev) ? isDev : window.location.href.indexOf("vagrant") > -1;
1130		isDev = false;
1131		if(forceDev || isDev) 
1132		{
1133			jQ('img').each(function()
1134			{
1135				var el = jQ(this), w  = el.attr('width'), h  = el.attr('height');
1136				if(w && h) el.attr('src', 'https://www.placehold.it/' + w + 'x' + h);
1137			});
1138		}
1139	}
1140	
1141/**
1142 * Youtube API
1143 * 16-03-08
1144 * Andy
1145 * https://developers.google.com/youtube/v3/code_samples/javascript#authorizing_requests
1146 */
1147	et.youTube = {
1148		init: function()
1149		{
1150			var listContainer = $('.youtube-list');
1151			if (!listContainer.length)
1152			{
1153				return;
1154			}
1155			this.key 		= 'AIzaSyA5IVWtS2xBg8To6piDKKE2-TRiQoy78wQ';
1156			this.channel	= 'UCivfjXyf_3bPgwgIQaY2kRQ';
1157			this.perPage	= 20;
1158			this.listTarget = listContainer;
1159			
1160			this.currentPage = 1;	// gets ++ or -- according to the usage of the pagination since the api does not provide a page state
1161			
1162			this.videos		= {};
1163			this.url 		= 'https://www.googleapis.com/youtube/v3/search?key=' + this.key + '&channelId=' + this.channel + '&part=snippet,id&order=date&maxResults=' + this.perPage + '&type=video';
1164			this.iframe		= false;
1165
1166			this.iframeTarget = jQ('<div/>', 
1167			{
1168				class: 'embed-container',
1169				html: ''
1170			}).prependTo(listContainer);
1171			this.iframeTarget.wrap('<div class="yt-iframe-player col ece-media-element ece-media-type-youtube"></div>');
1172			this.iframeTarget.parent().wrap('<div class="yt-iframe-player-wrap row bg-nonwhite row-over bg-maincolor"></div>');
1173			
1174			this.fetch();
1175			this.listener();
1176
1177			// et.afterBrowserResize.funcsArr.push(et.youTube.resize());
1178		},
1179		fetch: function(pageToken)
1180		{
1181			var url = this.url;
1182				if(typeof pageToken != 'undefined') 
1183				{
1184					url += '&pageToken=' + pageToken;
1185				}
1186			jQ.ajax(url, {
1187				success: function(data) 
1188				{
1189					et.youTube.videos = data;
1190					et.youTube.renderList();
1191				},
1192				error: function() 
1193				{
1194					et.youTube.errorHandler();
1195				}
1196			});
1197		},
1198		errorHandler: function()
1199		{
1200			console.log('-');
1201		},
1202		renderList: function()
1203		{
1204			if(!this.list) 
1205			{
1206				this.list = jQ('<div/>', 
1207				{
1208					class: 'news-list-view row flex-grid',
1209					html: ''
1210				});
1211				this.list.appendTo(this.listTarget);
1212			}
1213			this.renderItems(et.youTube.videos.items);
1214			this.renderPagination();
1215		},
1216		renderItems: function(videos)
1217		{
1218			et.youTube.list.html('');
1219			jQ.each(videos, function(i, v)
1220			{
1221				var img		= '<div class="wrap-img"><img src="' + v.snippet.thumbnails.medium.url + '" /></div>',
1222					//text	= '<h3 class="h4">' + v.snippet.title + '</h3><div><div><p>' + v.snippet.description + '</p></div></div>',
1223					text	= '<h3 class="h4">' + v.snippet.title + '</h3><div><div></div></div>',
1224					btn		= '<div class="btn btn-pseudo arrow right">Ansehen</div>';
1225				
1226				var content = img + '<div class="wrap-txt">' + text + btn + '</div>';
1227				
1228				var teaser  = jQ('<a/>', 
1229				{
1230					class: 'row no-border',
1231					href: '#',
1232					html: content,
1233				}).attr('data-yt-id', v.id.videoId);
1234				
1235				var item = jQ('<div/>', {
1236					id: 'yt-video-' + v.id.videoId,
1237					class: 'box box-link box-teaser col-3',
1238					html: teaser,
1239				}).appendTo(et.youTube.list);
1240			});
1241			
1242			this.resize();
1243		},
1244		renderPagination: function()
1245		{
1246			var total   = et.youTube.videos.pageInfo.totalResults;
1247			if(total > this.perPage)
1248			{
1249				var pages = Math.floor(total / this.perPage);
1250			}
1251			if(this.paginationWrap) {
1252				this.paginationWrap.remove();
1253			}
1254			
1255			this.paginationWrap = jQ('<div/>', 
1256			{
1257				class: 'page-navigation col yt-pagination',
1258				html: ''
1259			}).appendTo(this.listTarget);
1260			
1261			var pagination = jQ('<ul/>', 
1262			{
1263				class: 'f3-widget-paginator menu menu-pagination',
1264				html: ''
1265			}).appendTo(this.paginationWrap);
1266			
1267			if(this.videos.prevPageToken) {
1268				jQ('<li/>', 
1269				{
1270					class: 'prev',
1271					html: '<a href="#" class="neg-arrow arrow left">vorherige</a>'
1272				}).on('click', 'a', function(e) {
1273					et.youTube.currentPage--;
1274					et.youTube.rerender(e, et.youTube.videos.prevPageToken);
1275				}).appendTo(pagination);
1276			}
1277			
1278				jQ('<li/>', 
1279				{
1280					class: 'pages',
1281					html: '<ul><li>Seite ' + et.youTube.currentPage + ' von ' + pages + '</li></ul>'
1282				}).appendTo(pagination);
1283			
1284			if(this.videos.nextPageToken && this.currentPage < pages) {
1285				jQ('<li/>', 
1286				{
1287					class: 'next',
1288					html: '<a href="#" class="neg-arrow arrow right">nächste</a>'
1289				}).on('click', 'a', function(e) {
1290					et.youTube.currentPage++;
1291					et.youTube.rerender(e, et.youTube.videos.nextPageToken);
1292				}).appendTo(pagination);
1293			}
1294			
1295		},
1296		rerender: function(e, token) {
1297			e.preventDefault();
1298			this.list.addClass('loading');
1299			this.fetch(token);
1300			this.list.scrollToTarget({offsetTop: 15});
1301			setTimeout(function() {
1302				et.youTube.list.removeClass('loading');
1303			}, 500);
1304		},
1305		listener: function()
1306		{
1307			this.listTarget.on('click', 'a[data-yt-id]', function(e)
1308			{
1309				e.preventDefault();
1310				var id = $(this).data('yt-id');
1311				
1312				if(et.youTube.iframe)
1313				{
1314					et.youTube.iframe.remove();
1315				}
1316				et.youTube.iframe = jQ('<iframe id="ytplayer" type="text/html" width="1280" height="720" allowfullscreen src="https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0" frameborder="0"/>');
1317				jQ('.yt-iframe-player-wrap').show();
1318				et.youTube.iframe.appendTo(et.youTube.iframeTarget).scrollToTarget({offsetTop: 15});
1319			});
1320		},
1321		resize: function()
1322		{
1323			setTimeout(function()
1324			{
1325				if(et.youTube.list) {
1326					et.youTube.list.find('.box-teaser').removeAttr('style').css('height', et.getDimensions(et.youTube.list.find('.box-teaser')).hMax);
1327				}
1328			}, 500);
1329		},
1330	};
1331 
1332	$.fn.scrollToTarget = function(conf) {
1333		var def = {duration: 500, offsetTop: 0, position: false, checkVisibility: false, callback: false};
1334		var c = $.extend({}, def, conf);
1335		$.extend({}, conf, c);
1336		c.checkVisibility = (c.checkVisibility && jQuery().visible);
1337		c.offsetTop = parseInt(c.offsetTop) || 0;
1338	 
1339		var offset = this.offset();
1340		var target = parseInt(c.position) || (offset.top - c.offsetTop);
1341	 
1342		if(!c.checkVisibility || (c.checkVisibility && !this.visible()) || (target <= (jQuery(window).scrollTop() + c.offsetTop)))
1343		{
1344			jQuery('body, html').animate({ scrollTop: target }, c.duration, function() {if(c.callback && typeof c.callback == "function") {c.callback();}});
1345		}
1346		return this;
1347	};
1348	
1349	jQ(document).ready(function()
1350	{
1351		// fix links to bet _blank inside "Bistumszeilen" on Subsites
1352		jQ('.layout-subsite .mainpage-subsite-addition a').each(function()
1353		{
1354			if(jQ(this).attr('target') != '_blank')
1355			{
1356				jQ(this).attr('target', '_blank');
1357			}
1358		});
1359		
1360		jQ('.box.box-link.list-teaser p').each(function() {
1361			var p = jQ(this);
1362			if(p.html().replace(/\s|&nbsp;/g, '').length == 0)
1363			{
1364				p.remove(); 
1365			}
1366			p.html(p.html().replace(/&nbsp;/g, ''));
1367		});
1368	});
1369	
1370	jQ(window).resize(function()
1371	{
1372		if(jQ(window).width() > 900)
1373		et.youTube.resize();
1374	});
1375	
1376	
1377	
1378	
1379	
1380/*
1381==================================================
1382Fix: Youtube-Videos ohne Related Videos (rel=0)
1383==================================================
1384Aktuell kann man rel=0 im Gegensatz zu anderen Parametern nicht per Fluid-Template setzen.
1385Entfernen, sobald nicht mehr benötigt.
1386*/
1387et.ytRemoveRelated = function()
1388{
1389	$('iframe[src*=youtube]').each(function()
1390	{
1391		var vid = $(this),
1392			separator = vid.attr('src').indexOf('?') !== -1 ? '&' : '?',
1393			vidSrc = vid.attr('src'),
1394			vidSrcArray = vidSrc.split('?');
1395		if (vidSrcArray.length > 2)
1396		{
1397			vidSrc = vidSrcArray[0]+'?'+vidSrcArray[1];
1398			for(i=2; i < vidSrcArray.length; i++ )
1399			{
1400				vidSrc += "&"+ vidSrcArray[i];
1401			}
1402		}
1403		vid.attr('src', vidSrc + separator + 'rel=0');
1404	});
1405}
1406
1407et.etagenCookie = function()
1408{
1409	// HTML-Youtube-Videos automatisch anpassen:
1410	$('iframe[src*="youtube-nocookie"], iframe[data-src*="youtube-nocookie"], iframe[data-src*="youtube.com"]').addClass('et-cookie-set-blocker bg-maincolor cookiePermission media youtube');
1411
1412	let etCookieOptions = {
1413		mainText: "Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten und die Zugriffe auf unsere Website analysieren zu können. Informationen können für soziale Medien, Werbung und Analysen an Dritte weitergegeben werden. Diese Dritten führen die Informationen möglicherweise mit Daten aus anderen Quellen zusammen." +
1414			"<br><br>" +
1415			"Hierbei können auch Dienstleister aus Drittländern, d.h. insbesondere aus Ländern außerhalb der EU ohne angemessenes Datenschutzniveau, eingesetzt werden. Das birgt folgende Risiken: Zugriff durch Behörden ohne Benachrichtigung, keine Betroffenenrechte oder Rechtsmittel, Verlust der Kontrolle über die Datenverarbeitung. Mit Ihrer Einstellung willigen Sie in die beschriebenen Vorgänge ein. Sie können Ihre Einwilligung mit Wirkung für die Zukunft widerrufen. Mehr Informationen finden Sie in unserer <a href='/datenschutz'>Datenschutzerklärung</a>.",
1416		kinds: [
1417			{
1418				kind: "necessary",
1419				title: "Notwendig",
1420				disabled: true,
1421				checked: true,
1422				details: "Diese Cookies sind notwendig, um den Betrieb unserer Seite für Sie reibungslos möglich zu machen."
1423			},
1424			{
1425				kind: "analytics",
1426				title: "Statistik",
1427				details: "Mit unserer Statistikeinstellung bestätigen Sie die Nutzung von Cookies zur Verbesserung unserer Angebote. Wir nutzen Google Analytics. Hierbei können wir zum Beispiel einsehen, wer sich auf unserer Seite wo bewegt, um Inhalte noch einfacher für Sie darstellen zu können."
1428			},
1429			{
1430				kind: "media",
1431				title: "Externe Medien",
1432				details: "Inhalte von Video- und Audioplattformen sowie von Karten- und Grafikdesigndiensten werden blockiert. Wenn Cookies von externen Medien akzeptiert werden, bedarf der Zugriff auf diese Inhalte keiner manuellen Einwilligung mehr."
1433			}
1434		],
1435		deleteCookies: ['cookieconsent_status'],
1436		contentBlockers: [
1437			{
1438				selector: "iframe[src*='youtube-nocookie.com'].et-cookie-set-blocker, iframe[data-src*='youtube-nocookie.com'].et-cookie-set-blocker",
1439				kind: "media",
1440				text: "<p>Wenn Sie hier klicken, wird ein Video geladen. <br>Ihre IP-Adresse wird hierbei an YouTube übermittelt.</p>",
1441				showBlockerWithoutHover: true
1442			},
1443			{
1444				selector: "iframe[data-src*='soundcloud.com']",
1445				kind: "media",
1446				text: "<p>Wenn Sie hier klicken, wird ein Audioplayer geladen. <br>Ihre IP-Adresse wird hierbei an Soundcloud übermittelt.</p>",
1447				showBlockerWithoutHover: true
1448			},
1449			{
1450				selector: ".map-canvas, .googlemap.et-cookie-set-blocker",
1451				kind: "media",
1452				text: "<p>Wenn Sie hier klicken, wird eine Karte geladen. <br>Ihre IP-Adresse wird hierbei an Google übermittelt.</p>",
1453				showBlockerWithoutHover: true
1454			},
1455			{
1456				selector: ".openstreetmap.et-cookie-set-blocker",
1457				kind: "media",
1458				text: "<p>Wenn Sie hier klicken, wird eine Karte geladen. <br>Ihre IP-Adresse wird hierbei an OpenStreetMap übermittelt.</p>",
1459				showBlockerWithoutHover: true
1460			},
1461			{
1462				selector: ".kizfeed",
1463				kind: "standalone-blocker",
1464				text: "<p>Wenn Sie hier klicken, wird ein Feed der KirchenZeitung im Bistum Hildesheim geladen. Dabei werden Ihre IP und externe Cookies, darunter auch statistische, übermittelt.</p>",
1465				showBlockerWithoutHover: true
1466			},
1467			{
1468				selector: ".youtube-list",
1469				kind: "media",
1470				text: "<p>Wenn Sie hier klicken, werden einige Video-Teaser geladen. <br>Ihre IP-Adresse wird hierbei an YouTube übermittelt.</p>",
1471				showBlockerWithoutHover: true
1472			},
1473			{
1474				selector: ".pikto-canvas-wrap.et-cookie-set-blocker",
1475				kind: "media",
1476				text: "<p>Wenn Sie hier klicken, wird eine Grafik mit statistischen Zahlen zum Bistum Hildesheim geladen.<br> Dabei werden Cookies auf dem Rechner gespeichert.</p>",
1477				showBlockerWithoutHover: true
1478			},
1479			{
1480				selector: ".crArchive.et-cookie-set-blocker",
1481				kind: "media",
1482				text: "<p>Wenn Sie hier klicken, wird eine Liste der versendeten Newsletter geladen.<br> Es erfolgt ein Datentransfer an CleverReach.</p>",
1483				showBlockerWithoutHover: true
1484			}
1485		],
1486	}
1487
1488	$(document).one('etCookiesAllowed-analytics', function () {
1489		console.log('Tracking jetzt einmalig ausführen!');
1490		if (typeof triggerAnalytics !== 'undefined')
1491		{
1492			triggerAnalytics();
1493		}
1494	});
1495	$(document).one('etCookiesAllowed-media', function () {
1496		et.youTube.init();
1497		initPiktoChart();
1498	});
1499
1500	$('body').etagenCookie(etCookieOptions);
1501
1502	$('.openstreetmap + .et-cookie-blocker .et-cookie-blocker--show-content').click(function(){
1503		initOpenStreetMaps();
1504	});
1505	$('.wrap-youtube-list .et-cookie-blocker--show-content').click(function(){
1506		et.youTube.init();
1507	});
1508	$('.piktowrapper-embed .et-cookie-blocker--show-content').click(function(){
1509		initPiktoChart();
1510	});
1511	$('.crArchive + .et-cookie-blocker .et-cookie-blocker--show-content').click(function(){
1512		const scr = $(this).parent().parent().parent().find('script.cookiePermission');
1513		let script = $('<script></script>');
1514		script.attr('src', scr.attr('src'));
1515		scr.before(script).remove();
1516	});
1517}
1518
1519// PiktoChart auf Seite https://www.bistum-hildesheim.de/bistum/bistum-in-zahlen/ (id=280)
1520initPiktoChart = function() {
1521	if ($('.piktowrapper-embed').length) {
1522		(function (d) {
1523			var js, id = "pikto-embed-js", ref = d.getElementsByTagName("script")[0];
1524			if (d.getElementById(id)) {
1525				return;
1526			}
1527			js = d.createElement("script");
1528			js.id = id;
1529			js.async = true;
1530			js.src = "https://create.piktochart.com/assets/embedding/embed.js";
1531			ref.parentNode.insertBefore(js, ref);
1532		}(document));
1533	}
1534}
1535
1536$(document).ready(function()
1537{
1538	et.ytRemoveRelated();
1539	et.etagenCookie();
1540
1541	// Google OptOut aufrufen (setzt einen lokalen Disable-Cookie)
1542	$('a[href*="#ga-opt-out"]').click(function(e){
1543		e.preventDefault();
1544		try {
1545			gaOptout();
1546		}
1547		catch(err) {
1548			console.log(err);
1549		}
1550	});
1551
1552});
1553	
1554// Google Analytics: PDFs usw. tracken	
1555// http://www.blastam.com/blog/how-to-track-downloads-in-google-analytics-v2
1556// angepasst auf ga:
1557// https://developers.google.com/analytics/devguides/collection/analyticsjs/events
1558if (typeof jQuery != 'undefined') {
1559
1560  jQuery(document).ready(function($) {
1561    var filetypes = /\.(zip|exe|dmg|pdf|doc.*|xls.*|ppt.*|mp3|txt|rar|wma|mov|avi|wmv|flv|wav)$/i;
1562    var baseHref = '';
1563    if (jQuery('base').attr('href') != undefined) baseHref = jQuery('base').attr('href');
1564 
1565    jQuery('a').on('click', function(event) {
1566      var el = jQuery(this);
1567      var track = true;
1568      var href = (typeof(el.attr('href')) != 'undefined' ) ? el.attr('href') :"";
1569      var isThisDomain = href.match(document.domain.split('.').reverse()[1] + '.' + document.domain.split('.').reverse()[0]);
1570      if (!href.match(/^javascript:/i)) {
1571        var elEv = []; elEv.value=0, elEv.non_i=false;
1572        if (href.match(/^mailto\:/i)) {
1573          elEv.category = "email";
1574          elEv.action = "click";
1575          elEv.label = href.replace(/^mailto\:/i, '');
1576          elEv.loc = href;
1577        }
1578        else if (href.match(filetypes)) {
1579          var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;
1580          elEv.category = "download";
1581          elEv.action = "click-" + extension[0];
1582          elEv.label = href.replace(/ /g,"-");
1583          elEv.loc = baseHref + href;
1584        }
1585        else if (href.match(/^https?\:/i) && !isThisDomain) {
1586          elEv.category = "external";
1587          elEv.action = "click";
1588          elEv.label = href.replace(/^https?\:\/\//i, '');
1589          elEv.non_i = true;
1590          elEv.loc = href;
1591        }
1592        else if (href.match(/^tel\:/i)) {
1593          elEv.category = "telephone";
1594          elEv.action = "click";
1595          elEv.label = href.replace(/^tel\:/i, '');
1596          elEv.loc = href;
1597        }
1598        else track = false;
1599        if (track && typeof ga != 'undefined') {
1600          ga('send','event',elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value, {nonInteraction: elEv.non_i});
1601          if ( el.attr('target') == undefined || el.attr('target').toLowerCase() != '_blank') {
1602            setTimeout(function() { location.href = elEv.loc; }, 400);
1603            return false;
1604		  }
1605		}
1606      }
1607    });
1608  });
1609}
1610
1611function resizeGridItem(item){
1612	var grid = document.getElementsByClassName("grid-masonry")[0];
1613	var rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows'));
1614	var rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap'));
1615	var rowSpan = Math.ceil((item.querySelector('.wrap-content').getBoundingClientRect().height+rowGap+30)/(rowHeight+rowGap));
1616	item.style.gridRowEnd = "span "+rowSpan;
1617}
1618function resizeAllGridItems(){
1619	var allItems = document.getElementsByClassName("prayer");
1620	for(x=0;x<allItems.length;x++){
1621		resizeGridItem(allItems[x]);
1622	}
1623}
1624window.onload = resizeAllGridItems();
1625window.addEventListener("resize", resizeAllGridItems);
1626
1627// In HTML-Elementen gesetzte Cleverreach-Formulare werden per TS umgeschrieben (action -> data-action)
1628// und per JS wieder lauffähig gemacht.
1629// Honeypot ".et_name" sollte nicht befüllt sein, sonst wird nicht versendet.
1630function spamPreventHtmlForms() {
1631	$('form.et-protected').each(function(){
1632		const f = $(this);
1633		if (!f.attr('action')) {
1634			f.attr('action',f.data('action'));
1635		}
1636		f.submit(function(e){
1637			const hp = f.find('.et_name');
1638			if (hp.val()) {
1639				e.preventDefault();
1640				alert('Spam detected.');
1641			}
1642		});
1643	});
1644}
1645// In diesen Cleverreach-Formularen fehlen zudem (meist) die passenden Pflichtfeld-Attribute
1646function addValidationHtmlForms() {
1647	$('.cr_form .musthave input:not([required])').attr('required','1');
1648	$('.cr_form .musthave[rel="email"] input[type="text"]').attr('type','email');
1649}
1650$(document).ready(function(){
1651	spamPreventHtmlForms();
1652	addValidationHtmlForms();
1653});
1654
1655
1656
1657/*
1658==================================================
1659Select-Link [jQuery]
1660==================================================
1661select.change-reload-value options haben als value eine URL
1662Diese wird geladen, wenn sich der select-value ändert
1663Va. für Solr-Facetten genutzt
1664*/
1665et.selectChangeUrl = function() {
1666	$('.change-reload-value').each(function () {
1667		var select = $(this);
1668		select.change(function () {
1669			var value = select.find('option:selected').val();
1670			if (value.charAt(0) !== "/" && !value.startsWith("http:") && !value.startsWith("https:")) {
1671				window.location = "/" + value;
1672			} else {
1673				window.location = value;
1674			}
1675		});
1676	});
1677}
1678
1679$(document).ready(function(){
1680	et.selectChangeUrl();
1681});
1682
1683
1684
1685/*
1686==================================================
1687Test webp und ggf. auf Fallback umstellen
1688==================================================
1689srcset wird von Browsern bevorzugt.
1690Da liegen aber nur webp Bilder drin.
1691Wird webp nicht unterstützt, entfernt dieses JS alle srcset-Attribute,
1692damit der Browser das Fallback-jpg/png im src anzeigt.
1693--> Irgendwann nebst jpg-Fallbacks einfach entfernen!
1694https://caniuse.com/webp
1695*/
1696et.checkWebp = function(callback) {
1697	var img = new Image();
1698	img.onload = function () {
1699		var result = (img.width > 0) && (img.height > 0);
1700		callback(result);
1701	};
1702	img.onerror = function () {
1703		callback(false);
1704	};
1705	img.src = "data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA";
1706}
1707$(document).ready(function()
1708{
1709	if ('supports-webp' in localStorage) {
1710		if (localStorage.getItem('supports-webp') !== 'true') {
1711			$('img[src]').removeAttr('srcset');
1712		}
1713	} else {
1714		et.checkWebp(function(result){
1715			if (!result) {
1716				$('img[src]').removeAttr('srcset');
1717			}
1718			localStorage.setItem('supports-webp', JSON.stringify(result));
1719		});
1720	}
1721});
1722
1723
1724/*
1725==================================================
1726Fix Powermail: Bessere Duplikat-Warnung
1727==================================================
1728https://github.com/in2code-de/powermail/blob/master/Documentation/ForAdministrators/BestPractice/PreventDuplicates.md
1729
1730TODO: Anpassung anders lösen (TS-replacement klappte aber nicht)
1731*/
1732$(document).ready(function()
1733{
1734    $('.powermail_message_error li').each(function(){
1735       let li = $(this),
1736        text = li.text() || '',
1737        msg = "Sie haben diese Mail bereits versendet.";
1738       if (text.indexOf('timestamppreventduplicates') !== -1) {
1739           li.text(msg);
1740       }
1741    });
1742});

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.