PageSourceSearch

https://www.rkmg.ch/_kirchenweb/js/jqueryKw.js?v=8eccc

js rkmg.ch collected 2026-10-02 21:21:23 UTC 113,792 bytes, 3,544 lines download raw bytes

1/* TEXT */
2
3String.prototype.capitalizeFirstLetter = function(){
4	return this.charAt(0).toUpperCase() + this.slice(1);
5};
6
7String.prototype.lowercaseFirstLetter = function(){
8	return this.charAt(0).toLowerCase() + this.slice(1);
9};
10
11/**
12 * Converts a camelCaseString to a kebab-case-string
13 * @returns {string}
14 */
15String.prototype.camelToKebab = function() {
16	return this.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
17};
18
19/**
20 * Converts a kebab-case-string to a camelCaseString
21 * @returns {string}
22 */
23String.prototype.kebabToCamel = function() {
24	return this.replace(/(-[a-z])/g, function(match) {
25		return match.substr(1,1).toUpperCase();
26	});
27};
28
29String.prototype.replaceMulti = function(needles, replacements) {
30	if (needles.length !== replacements.length) {
31		console.log('Needles and replacements need to be the same length');
32		return this;
33	}
34
35	var _this = this;
36	needles.forEach(function(needle, index) {
37		_this = _this.replace(needle, replacements[index]);
38	});
39
40	return _this;
41};
42
43/**
44 * Use window.location.parameters if you want the parameters of the current location!
45 *
46 * @param url
47 * @returns {any}
48 */
49String.urlToJson = function(url) {
50	if (!url) {
51		return window.location.parameters;
52	}
53	var pairs = url.split('?').pop().split('&');
54	var result = {};
55
56	pairs.forEach(function(pair) {
57		pair = pair.split('=');
58
59		var name = decodeURIComponent(pair[0]);
60		name = name.replace(/(\[\d?\])+$/g, '');
61		var value = decodeURIComponent(pair[1].replace(/\+/g, '%20') || '');
62		if( name.length )
63			if (result[name] !== undefined) {
64				if (!result[name].push) {
65					result[name] = [result[name]];
66				}
67				result[name].push(value);
68			} else {
69				result[name] = value;
70			}
71	});
72
73	return JSON.parse(JSON.stringify(result));
74};
75
76
77/* NUMBERS */
78
79Number.prototype.pad = function(size, char) {
80	if (typeof char === 'undefined') char = '0';
81	var s = String(this);
82	while (s.length < (size || 2)) {s = char + s;}
83	return s;
84};
85
86
87/* DATES */
88
89Date.parseKwFormat = function(dateString) {
90	if (typeof dateString !== 'string' || !dateString.match(/\d{1,2}.\d{1,2}.\d{4}/g)) {
91		return null;
92	}
93	var date = dateString.trim().split('.');
94	return new Date(parseInt(date[2]), parseInt(date[1]) - 1, parseInt(date[0]));
95};
96
97Date.prototype.diff = function(diffYears, diffMonths, diffDays, diffHours, diffMinutes) {
98	return new Date(this.getFullYear() + diffYears, this.getMonth() + diffMonths, this.getDate() + diffDays, this.getHours() + (diffHours ? diffHours : 0), this.getMinutes() + (diffMinutes ? diffMinutes : 0));
99};
100
101Date.prototype.weekNumber = function() {
102	// Copy date so don't modify original
103	var copy = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
104	// Set to nearest Thursday: current date + 4 - current day number
105	// Make Sunday's day number 7
106	copy.setUTCDate(copy.getUTCDate() + 4 - (copy.getUTCDay()||7));
107	// Get first day of year
108	var yearStart = new Date(Date.UTC(copy.getUTCFullYear(),0,1));
109	// Calculate full weeks to nearest Thursday
110	return Math.ceil(( ( (copy - yearStart) / 86400000) + 1)/7);
111};
112
113Date.prototype.daysInMonth = function () {
114	return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate();
115};
116
117Date.prototype.equals = function(date) {
118	return this.getTime() === date.getTime();
119};
120
121Date.prototype.isAfter = function(date) {
122	return this.getTime() > date.getTime();
123};
124
125Date.prototype.SUNDAY = 0;
126Date.prototype.MONDAY = 1;
127Date.prototype.TUESDAY = 2;
128Date.prototype.WEDNESDAY = 3;
129Date.prototype.THURSDAY = 4;
130Date.prototype.FRIDAY = 5;
131Date.prototype.SATURDAY = 6;
132
133/**
134 * Replacements:
135 * d => 2-digit day e.g. 01-31
136 * m => 2-digit month e.g. 01-12
137 * Y => 4-digit year e.g. 2020
138 * H => 2-digit hour in 24 hour format e.g. 00-23
139 * i => 2-digit minute e.g. 00-59
140 * s => 2-digit second e.g. 00-59
141 *
142 * @param {string} format
143 * @returns {string} date
144 */
145Date.prototype.toString = function(format) {
146	if (typeof format === 'undefined') format = 'd.m.Y';
147	var needles = [
148		'd',
149		'm',
150		'Y',
151		'H',
152		'i',
153		's',
154	];
155	var replacements = [
156		this.getDate().pad(2),
157		(this.getMonth() + 1).pad(2),
158		this.getFullYear(),
159		this.getHours().pad(2),
160		this.getMinutes().pad(2),
161		this.getSeconds().pad(2)
162	];
163	return format.replaceMulti(needles, replacements);
164};
165
166/* TIME */
167Date.parseTimeString = function(time) {
168	time = time.split('.');
169	return new Date(1970, 1, 1, parseInt(time[0]), parseInt(time[1]));
170};
171
172window.location.parameters = function () {
173	var parameters = {};
174	var params = decodeURI(window.location.search).substring(1).split("&");
175
176	for (var i = 0; i < params.length; i++) {
177		var pair = params[i].split("=");
178
179		if (typeof parameters[pair[0]] === "undefined") {
180			parameters[pair[0]] = pair[1];
181		} else if (typeof parameters[pair[0]] === "string") {
182			// if more than one parameter with the same name exists, change to array
183			parameters[pair[0]] = [parameters[pair[0]], pair[1]];
184		} else {
185			parameters[pair[0]].push(pair[1]);
186		}
187	}
188
189	return parameters;
190}();
191
192// jobs teaser
193if(window.location.hostname !== 'www.kirche-straettligen.ch') {
194	var spacing = '5px';
195	var stylesKwWhite = 'font-size: 1.3em; background: white; color: #00669f;';
196	var stylesKwBlue = 'font-size: 1.3em; background: #00669f; color: white;';
197	var styles = 'font-size: 1.3em;';
198	console.groupCollapsed('%c kirchen%cweb %c - Interested in programming and web design? Join us!', stylesKwWhite, stylesKwBlue, styles);
199	console.log('We are a motivated team of 11 employees. www.kirchenweb.ch/team');
200	console.log('See for more information www.kirchenweb.ch/jobs');
201	console.groupEnd();
202
203	$('html').prepend(''
204		+ '<!-- ############################################# -->'
205		+ '<!-- ############################################# -->'
206		+ '<!-- ########| |#####(_)###################| |#### -->'
207		+ '<!-- ########| |###########################| |#### -->'
208		+ '<!-- ########| |/ _ \\| | \'_ \\##| |#| / __|#| |#### -->'
209		+ '<!-- ###| |##| | (#) | | |#| |#| |#| \\__ \\#|_|#### -->'
210		+ '<!-- ####\\____/ \\___/|_|_|#|_|##\\__,_|___/#(_)#### -->'
211		+ '<!-- ############################################# -->'
212		+ '<!-- ###### https://www.kirchenweb.ch/jobs ####### -->'
213		+ '<!-- ############################################# -->')
214}
215
216// kwWort
217kwWort = function () {
218	var wortKey;
219	var wortVal;
220	var i;
221	var k;
222	this.wortKey = [];
223	this.wortVal = [];
224	this.i = 0;
225	this.k = -1;
226	this.add = function (_key, _val) {
227		this.wortKey[this.i] = _key;
228		this.wortVal[this.i] = _val;
229		++this.i;
230	};
231	this.get = function (_key) {
232		this.k = jQuery.inArray(_key, this.wortKey);
233		if (this.k > -1) return this.wortVal[this.k];
234		return 'Fehler! Wort nicht definiert';
235	};
236};
237var wort = new kwWort();
238
239
240// anzeige gross von einem bild
241function openPic(url, winName, winParams) {
242	theWindow = window.open(url, winName, winParams);
243	if (theWindow) theWindow.focus();
244}
245
246
247// neues fenster öffnen
248function openWindow(strUrl, strTitle, intWidth, intHeight) {
249	var strFeatureMode = false;
250	var strFeatures = '';
251	if (typeof intWidth == 'string') {
252		strFeatures = intWidth;
253		strFeatureMode = true;
254	} else {
255		var winWidth = 20 + parseInt(intWidth);
256		var winHeight = 30 + parseInt(intHeight);
257		var ieWinWidth = 50 + parseInt(intWidth);
258		var ieWinHeight = 80 + parseInt(intHeight);
259		strFeatures = "width=" + winWidth + ",height=" + winHeight + ",status=no,locationbar=no,menubar=no,resizable=yes,scrollbars";
260	}
261	myOpenedWindow = window.open(strUrl, strTitle, strFeatures);
262	myOpenedWindow.focus();
263	// return
264	return false;
265}
266
267
268// toggle elements (erweiterte suche)
269function toggleElements(idA, idB, idLink, linkTextA, linkTextB) {
270	var objA = null;
271	var objB = null;
272	var objLink = null;
273	if (document.getElementById(idA)) objA = document.getElementById(idA);
274	if (document.getElementById(idB)) objB = document.getElementById(idB);
275	if (idLink != "" && document.getElementById(idLink)) objLink = document.getElementById(idLink);
276	if (objA != null && objA.style.display == "") {
277		objA.style.display = "none";
278		if (objB != null) objB.style.display = "";
279		if (idLink != null) objLink.innerHTML = linkTextA;
280	} else if (objB != null && objB.style.display == "") {
281		objB.style.display = "none";
282		if (objA != null) objA.style.display = "";
283		if (objLink != null) objLink.innerHTML = linkTextB;
284	}
285	return false;
286}
287
288
289// text kürzen (analog toolbox::kwSubstr)
290function kwSubstr(_str, _len, _toleranz) {
291	var toleranz = (_toleranz > 0) ? _toleranz : 2;
292	var len = Math.max(_len, 0);
293	var str = _str.toString();
294	var gekuerzt = "";
295	if (str.length > (len + toleranz)) {
296		gekuerzt = "...";
297		str = _str.substring(0, _str.indexOf(". ", len - toleranz));
298		if (str.length > (len + toleranz) || str.length == 0) str = _str.substring(0, _str.indexOf(" ", len - 5));
299		if (str.length > (len + toleranz) || str.length == 0) str = _str.substring(0, len);
300	}
301	return jQuery.trim(str) + gekuerzt;
302}
303
304
305// check cookie enabled
306function kwCookieEnabled() {
307	// modern browsers
308	if (navigator.cookieEnabled) return true;
309	// fallback for older browsers, set and read cookie
310	document.cookie = "kwcookietest=1";
311	var ret = (document.cookie.indexOf("cookietest=") != -1);
312	// delete cookie
313	document.cookie = "kwcookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
314	// return
315	return ret;
316}
317
318
319// str codieren
320function kwStrRot(_str, _num, _repAt) {
321	var letter = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz_.-@=;:,"> <';
322	_num = parseInt(_num % 32, 10);
323	if (_repAt == -1) _str = _str.replace(/\$/g, '@');
324	if (_num == 0) return _srt;
325	if (_num < 0) _num += 32;
326	var rep = letter.substr(_num * 2) + letter.substr(0, _num * 2);
327	var res = "";
328	var p = 0;
329	for (i = 0; i < _str.length; ++i) {
330		p = letter.indexOf(_str[i]);
331		if (p == -1) {
332			res += _str[i];
333		} else {
334			res += rep[p];
335		}
336	}
337	if (_repAt == 1) res.replace(/@/g, '$');
338	return res;
339}
340
341
342function kwDecryptMt(_str, _num) {
343	document.write(kwStrRot(_str, _num, -1));
344}
345
346
347// div liste anzeigen
348function showKwSelect(id, objCal, offX, offY) {
349	// geöffneter kwSelect schliessen bei klick auf body
350	$(document).on("click.kwSelect keydown.kwSelect", function (event) {
351		if (!$(event.target).next().hasClass("kwSelect") && !$(event.target).parent().hasClass("kwSelect")) {
352			$("div.kwSelect").hide(300);
353			$(document).off(".kwSelect");
354		}
355	});
356	// andere geöffnete kwSelect schliessen
357	$("div.kwSelect").not("#" + id).hide(300);
358	$("div.kwSelect").not("#" + id).parent().removeClass("active");
359	// toggle
360	$("#" + id).toggle(300);
361	$("#" + id).parent().toggleClass("active");
362	// return
363	return false;
364}
365
366
367// link login auf front, in favoriten speichern
368function addBookmark(url, title) {
369	if (window.sidebar) {
370		// Mozilla Firefox Bookmark
371		window.sidebar.addPanel(title, url, "");
372		return false;
373	} else if (window.external) {
374		// IE Favorite
375		window.external.AddFavorite(url, title);
376		return false;
377	} else if (window.opera && window.print) {
378		// Opera Hotlist
379		var elem = document.createElement("A");
380		elem.setAttribute("href", url);
381		elem.setAttribute("title", title);
382		elem.setAttribute("rel", "sidebar");
383		elem.click();
384	}
385	return false;
386}
387
388
389// zeit
390function kwDateFormat(date) {
391	var dd = date.getDate();
392	var mm = date.getMonth() + 1; // january is 0
393	var yyyy = date.getFullYear();
394	if (dd < 10) dd = '0' + dd;
395	if (mm < 10) mm = '0' + mm;
396	return dd + '.' + mm + '.' + yyyy;
397}
398
399
400// wochentag
401function wday(num, spr) {
402	var sprache = "de";
403	if (typeof spr == "string") sprache = spr;
404	if (sprache == "de") {
405		var day = new Array("So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.");
406	} else if (sprache == "fr") {
407		var day = new Array("dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam.");
408	}
409	return day[num % 7];
410}
411
412function wdayFull(num, spr) {
413	var sprache = "de";
414	if (typeof spr == "string") sprache = spr;
415	if (sprache == "de") {
416		var day = new Array("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag");
417	} else if (sprache == "fr") {
418		var day = new Array("dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi");
419	}
420	return day[num % 7];
421}
422
423
424// monat
425function monthInWords(m, spr, short) {
426	var month = Array("Dezember", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November");
427	var monthS = Array("Dez.", "Jan.", "Feb.", "Mrz.", "Apr.", "Mai", "Jun.", "Jul.", "Aug.", "Sep.", "Okt.", "Nov.");
428	if (short == undefined) short = false;
429	if (spr == undefined) spr = "de";
430	if (spr == "fr") {
431		month = Array("décembre", "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "aout", "septembre", "octobre", "novembre");
432		monthS = Array("déc.", "jan.", "fév.", "mar.", "avr.", "mai", "jun.", "jui.", "aou.", "sep.", "oct.", "nov.");
433	}
434	if (m >= 0) {
435		if (short) return monthS[(m + 1) % 12];
436		return month[(m + 1) % 12];
437	} else {
438		if (short) {
439			return monthS;
440		} else {
441			return month;
442		}
443	}
444}
445
446
447function kwCopyToClipboard(elem) {
448	// inhalt eines DOM-Elements in zwischenablage kopieren (18.11.2016 dj)
449	// erstelle hidden text element falls es noch nicht existiert
450	var targetId = "_hiddenCopyText_";
451	var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
452	var origSelectionStart, origSelectionEnd;
453	if (isInput) {
454		// originales element verwenden zum kopieren
455		target = elem;
456		origSelectionStart = elem.selectionStart;
457		origSelectionEnd = elem.selectionEnd;
458	} else {
459		// temporäres element verwenden zum kopieren
460		target = document.getElementById(targetId);
461		if (!target) {
462			var target = document.createElement("textarea");
463			target.style.position = "absolute";
464			target.style.left = "-9999px";
465			target.style.top = "0";
466			target.id = targetId;
467			document.body.appendChild(target);
468		}
469		if (typeof elem === "string" || elem instanceof String) {
470			target.textContent = elem;
471		} else {
472			target.textContent = elem.textContent;
473		}
474	}
475	// inhalt markieren
476	var currentFocus = document.activeElement;
477	target.focus({preventScroll: true});
478	target.setSelectionRange(0, target.value.length);
479	// auswahl kopieren
480	var succeed;
481	try {
482		succeed = document.execCommand("copy");
483	} catch (e) {
484		succeed = false;
485	}
486	// alter fokus wieder herstellen
487	if (currentFocus && typeof currentFocus.focus === "function") {
488		currentFocus.focus();
489	}
490	if (isInput) {
491		// alte auswahl wieder herstellen
492		elem.setSelectionRange(origSelectionStart, origSelectionEnd);
493	} else {
494		// temporärer inhalt leeren
495		target.textContent = "";
496	}
497	return succeed;
498}
499
500
501// rubrik per ajax setzen, id entspricht bereich
502function setRubrik(_rubrik, _link, _id) {
503	$.post("/_kirchenweb/ajaxSetRubrik.php", {r: _rubrik, i: _id}, function (data) {
504		if (data == "1") {
505			window.location.href = _link;
506		} else {
507			alert("Ein Fehler ist Aufgetreten.");
508		}
509	});
510	return false;
511}
512
513
514// kwTooltip
515var kwTooltipTimeout = null;
516
517function kwTooltip(_obj, _url, _classn, _html, _posX, _posY) {
518	var obj = null;
519	var url = "";
520	var classn = "kwTooltip";
521	var html = "";
522	var posX = 10;
523	var posY = -5;
524	var objTooltip = null;
525	// übergabe
526	if (typeof _obj == "object") obj = _obj;
527	if (typeof _url == "string") url = _url;
528	if (typeof _classn == "string") classn = _classn;
529	if (typeof _html == "string") html = decodeURIComponent(_html);
530	if (typeof _posX == "string") posX = parseInt(_posX, 10);
531	if (typeof _posY == "string") posY = parseInt(_posY, 10);
532	// Versetzten aufruf löschen
533	clearTimeout(kwTooltipTimeout);
534	// schliessen
535	if (obj == null) {
536		$("#kwTooltip").css("display", "none");
537		$("#kwTooltipInhalt").html("");
538		return false;
539	}
540	// Versetzt aufruffen
541	kwTooltipTimeout = setTimeout(function () {
542		// tooltip erstellen
543		if ($("#kwTooltip").length == 0) {
544			$("body").append("<div id=\"kwTooltip\" class=\"" + classn + "\"></div>");
545			$("#kwTooltip").append("<div class=\"kwTooltipPfeil\"></div>");
546			$("#kwTooltip").append("<div id=\"kwTooltipInhalt\" class=\"kwTooltipInhalt\"></div>");
547		}
548		$("#kwTooltip").css("display", "block");
549		$("#kwTooltip").removeClass().addClass(classn);
550		// positionierung
551		var pos = $(_obj).offset();
552		if (classn.substr(0, 4) == "left") {
553			$("#kwTooltip").css("left", (parseInt(pos.left - $("#kwTooltip").width()) - posX) + "px");
554			$("#kwTooltip").css("top", (parseInt(pos.top) + posY) + "px");
555		} else {
556			$("#kwTooltip").css("left", (parseInt(pos.left + $(_obj).width()) + posX) + "px");
557			$("#kwTooltip").css("top", (parseInt(pos.top) + posY) + "px");
558		}
559		// inhalt
560		if (html != "") {
561			$("#kwTooltipInhalt").html(html);
562			// BA mha
563			if (obj) {
564				obj.setAttribute('aria-describedby', 'kwTooltipInhalt');
565			}
566			// ueberlappung feststellen ggf. position korrigieren
567			var hoehe = $("#kwTooltip div").first().next().outerHeight();
568			var fenster = $(window).height();
569			var scroll = $(window).scrollTop();
570			if (fenster + scroll < pos.top + hoehe) {
571				var differ = fenster + scroll - hoehe;
572				var overflow = pos.top + hoehe - fenster - scroll;
573				if (overflow + 11 + 25 >= hoehe) {
574					$("#kwTooltip div").first().next().css("top", parseInt(overflow + 11 + 25 - hoehe) + "px");
575				}
576				$("#kwTooltip").css("top", parseInt(differ) + "px");
577				$("#kwTooltip div").first().css("top", parseInt(overflow + 11) + "px");
578			} else {
579				$("#kwTooltip").css("top", (parseInt(pos.top) + posY) + "px");
580				$("#kwTooltip div").first().css("top", "16px");
581				$("#kwTooltip div").first().next().css("top", "0px");
582			}
583		} else if (url != "") {
584			$("#kwTooltipInhalt").html("<div class=\"laden\"></div>");
585			$.get(url, function (data) {
586				$("#kwTooltipInhalt").html(data);
587				// BA mha
588				if (obj.setAttribute) {
589					obj.setAttribute('aria-describedby', 'kwTooltipInhalt');
590				}
591				// ueberlappung feststellen ggf. position korrigieren
592				var hoehe = $("#kwTooltip div").first().next().outerHeight();
593				var fenster = $(window).height();
594				var scroll = $(window).scrollTop();
595				if (fenster + scroll < pos.top + hoehe) {
596					var differ = fenster + scroll - hoehe;
597					var overflow = pos.top + hoehe - fenster - scroll;
598					if (overflow + 11 + 25 >= hoehe) {
599						$("#kwTooltip div").first().next().css("top", parseInt(overflow + 11 + 25 - hoehe) + "px");
600					}
601					$("#kwTooltip").css("top", parseInt(differ) + "px");
602					$("#kwTooltip div").first().css("top", parseInt(overflow + 11) + "px");
603				} else {
604					$("#kwTooltip").css("top", (parseInt(pos.top) + posY) + "px");
605					$("#kwTooltip div").first().css("top", "16px");
606					$("#kwTooltip div").first().next().css("top", "0px");
607				}
608			});
609		}
610		// Versetzter aufruf fertig, wartezeit bis Erscheinen von tooltip
611	}, 200);
612	// return
613	return false;
614}
615
616
617// fuer dynamisches nachladen (28.09.2015 ae)
618function kwIsSichtbar(ele) {
619	//special bonus for those using jQuery
620	if (typeof jQuery === "function" && ele instanceof jQuery) ele = ele[0];
621	// var
622	var rect = ele.getBoundingClientRect();
623	// return
624	return (rect.right >= 0 && rect.left <= $(window).width() && rect.bottom >= 0 && rect.top <= $(window).height()+200);
625}
626
627// mit event handler (08.10.2015 dj)
628function kwOnSichtbar(ele, callback) {
629	$(window).on("DOMContentLoaded load resize scroll kwOnSichtbar", function () {
630		if (kwIsSichtbar(ele)) callback.call();
631	});
632}
633
634
635$(window).resize(function () {
636	if (this.resizeTimeout) clearTimeout(this.resizeTimeout);
637	this.resizeTimeout = setTimeout(function () {
638		$(this).trigger("resizeEnd");
639	}, 500);
640});
641
642
643// slideshow crossfader
644function kwSlider(_images, _options) {
645	// defaults
646	var options = _options || {};
647	options.anzeigedauer = options.anzeigedauer || 12;
648	options.wechseldauer = options.wechseldauer || 2;
649	options.typ = options.typ || "ueberblenden"
650	var selector = options.selector || "#slideshow";
651	// kein bild übergeben
652	if (typeof _images == "undefined" || typeof _images.length == "undefined" || _images.length == 0 || _images.join("") == "") {
653		$(selector).addClass("fallbackBg");
654		return;
655	}
656	var position = 0;
657	// container bereitstellen
658	var ueberblenden = function () {
659		$(selector).html('<div class="container"><div class="background"></div><div class="foreground"></div></div>');
660		$(selector).find("div.container").css({
661			position: "relative",
662			top: 0,
663			left: 0,
664			width: "100%",
665			height: "100%"
666		});
667		$(selector).find("div.container > div").css({
668			position: "absolute",
669			top: 0,
670			left: 0,
671			width: "100%",
672			height: "100%",
673			"background-position": "50% 50%",
674			"background-size": "cover"
675		});
676		$(selector).find(".foreground").css({
677			"background-image": "url(" + _images[position] + ")"
678		});
679		var next = function () {
680			// position
681			position = (position + 1) % _images.length;
682			// bild im hintergrund laden
683			$(selector).find(".background").css({
684				"background-image": "url(" + _images[position] + ")"
685			});
686			// vordergrund ausblenden
687			$(selector).find(".foreground").animate({
688				"opacity": 0
689			}, options.wechseldauer * 1000, function () {
690				// vordergrundbild aktualisieren und anzeigen
691				$(selector).find(".foreground").css({
692					"background-image": "url(" + _images[position] + ")",
693					opacity: 1
694				});
695			});
696		}
697		// slideshow starten
698		if (_images.length > 1) window.setInterval(next, options.anzeigedauer * 1000);
699	}
700	// initialisieren
701	switch (options.typ) {
702		case "ueberblenden":
703			ueberblenden();
704			break;
705		default:
706			ueberblenden();
707	}
708}
709
710
711// slideshow accordion
712(function ($) {
713	var options = {};
714	var defaults = {
715		percentVisible: 17,
716		autoInterval: 10 * 1000 // 10 sekunden
717	};
718	$.fn.kwAccordion = function (_options) {
719		// overwrite defaults with custom options
720		_options = _options || {};
721		options = $.extend({}, defaults, _options);
722		// iterate over selected elements
723		this.each(function () {
724			$container = $(this);
725			$container.addClass("kwAccordion");
726			// initialisierung erstes bild
727			repositionImages($container, $container.children().first());
728			// falls kein slider gebraucht wird
729			if ($container.children().length > 1) {
730				addEventListeners($container);
731				initAutoChange($container);
732			}
733		});
734		return this;
735	};
736
737	// mouseover & out listeners um aktives bild wählen
738	function addEventListeners($container) {
739		$container.children().on("mouseover.kwAccordion", function (event) {
740			pauseAutoChange($container);
741			repositionImages($container, $(this));
742		});
743		$container.on("mouseleave.kwAccordion", function (event) {
744			initAutoChange($container);
745		});
746		$(window).on("resizeEnd", function () {
747			repositionImages($container, $(this));
748		});
749	}
750	// autoslider
751	function initAutoChange($container) {
752		var timeout = window.setInterval(function () {
753			showNextImage($container);
754		}, options.autoInterval);
755		$container.data("kwAccordionTimeout", timeout);
756	}
757	function pauseAutoChange($container) {
758		window.clearInterval($container.data("kwAccordionTimeout"));
759	}
760	// automatisch nächstes bild auswählen
761	function showNextImage($container) {
762		var $nextImage = $container.find(".kwAccordionActive").next();
763		if ($nextImage.length == 0) $nextImage = $container.children().first();
764		repositionImages($container, $nextImage);
765	}
766	// berechnungen um bild aktiv zu setzen
767	function repositionImages($container, $activeElem) {
768		var offset = 0;
769		var height = ($container.width() * (9 / 16)) / (1 + (options.percentVisible / 100) * ($container.children().length - 1));
770		var activeWidth = (16 / 9) * height;
771		var inactiveWidth = activeWidth * (options.percentVisible / 100);
772		// containerhöhe anpassen
773		$container.css({
774			height: Math.ceil(height)
775		});
776		// verfügbaren platz für bilder setzen
777		$container.children().css({
778			width: Math.floor(activeWidth)
779		});
780		$container.children().removeClass("kwAccordionActive");
781		// aktives element setzen
782		$activeElem.addClass("kwAccordionActive");
783		// offsets für alle bilder
784		$container.children().each(function (index, elem) {
785			$(elem).css({
786				left: offset + "px"
787			});
788			if ($(elem).is($activeElem)) {
789				offset += $(elem).width();
790			} else {
791				offset += Math.floor(inactiveWidth);
792			}
793		});
794	}
795}(jQuery));
796
797
798// kombisuche (01.09.2015 dj)
799var kwSucheKombiTimeout = null;
800function kwSucheKombi(_id){
801	// Definitionen
802	var id; // html id von suchfeld
803	var pos; // auswahl position
804	var anz; // anzahl treffer
805	var strBegriff; // ganzes Such-Pattern
806	var strSuchwort; // letztes suchwort
807	var strListe; // Vorschlagliste HTML
808	var listenFocus; // flag Focus Listener
809	var basedir; // subsite verzeichnis
810	var site; // site name
811	// Defaultwerte
812	this.id = "tvmulti";
813	this.pos = -1;
814	this.anz = 0;
815	this.strBegriff = "";
816	this.strSuchwort = "";
817	this.strListe = "";
818	this.listenFocus = false;
819	this.basedir = "/";
820	this.site = "";
821	// Uebergabe einlesen
822	if(_id!=undefined && _id!=null) this.id = _id;
823}
824kwSucheKombi.prototype = {
825	// initialisierung
826	init : function(){
827		// Eventhandler binden ("search" is triggered by the clear button [x] in chrome)
828		var obj = this;
829		$("#"+this.id+"Input").on("keydown", function(e){ obj.eventKeydown(e); });
830		$("#"+this.id+"Input").on("keyup", function(e){ obj.eventKeyup(e); });
831		$("#"+this.id+"Input").on("focus", function(e){ obj.eventFocus(e); });
832		$("#"+this.id+"Icon").on("click", function(e){ obj.setSucheStart(); });
833		$("#"+this.id+"Input").on("search change", function(e){ obj.setClear(e); });
834		$("body").on("click", function(e){ obj.eventClickBody(e); });
835		// einfuegen liste
836		if($("#"+this.id+"Liste").length == 0) $("#"+this.id+"Input").after($("<ul/>", {id:this.id+"Liste", "class":"kwMultiListe", "style":"display:none"}));
837	},
838	eventKeydown : function(_e){
839		if(_e.keyCode == "13"){
840			// Key ENTER
841			_e.preventDefault();
842			if(this.pos != -1){
843				this.setVorschlag();
844			}else{
845				this.setSucheStart();
846			}
847		}else if(_e.keyCode == "40"){
848			// Key DOWN
849			_e.preventDefault();
850			if(this.pos == -1 || this.pos == this.anz-1){
851				this.selectEintrag(0);
852				this.pos = 0;
853			}else{
854				this.selectEintrag(++this.pos);
855			}
856		}else if(_e.keyCode == "38"){
857			// Key UP
858			_e.preventDefault();
859			if (this.pos == -1 || this.pos == 0){
860				this.selectEintrag(this.anz-1);
861				this.pos = this.anz-1;
862			}else{
863				this.selectEintrag(--this.pos);
864			}
865		}else if(_e.keyCode == "27"){
866			// Key ESC
867			_e.preventDefault();
868			$("#"+this.id+"Input").val("");
869			this.resetVorschlag();
870		}
871	},
872	eventKeyup : function(_e){
873		// Key nicht DOWN / UP / ENTER / ESC
874		if(_e.keyCode!="40" && _e.keyCode!="38" && _e.keyCode!="13" && _e.keyCode!="27"){
875			// Input einlesen & verarbeiten
876			this.getBegriff();
877			// Vorschlag generieren
878			this.getVorschlag(this.strSuchwort);
879		}
880	},
881	eventFocus : function(_e){
882		if(this.listenFocus){
883			// Input einlesen & verarbeiten
884			this.getBegriff();
885			// Vorschlag generieren
886			this.getVorschlag(this.strSuchwort);
887		}
888	},
889	eventMouseoverListe : function(_e){
890		this.pos = _e.target.id.substr(this.id.length+3);
891		this.selectEintrag(this.pos);
892	},
893	eventClickListe : function(_e){
894		this.listenFocus = false;
895		$("#"+this.id+"Input").focus();
896		this.setVorschlag();
897	},
898	eventClickBody : function(_e){
899		if(_e.target.id!=this.id+"Input" && _e.target.parentNode && _e.target.parentNode.id!=this.id+"Liste"){
900			this.hideListe();
901			this.listenFocus = true;
902		}
903	},
904	setClear : function(_e){
905		if($("#"+this.id+"Input").val()===""){
906			this.hideListe();
907			this.resetVorschlag();
908			$.post("/_kirchenweb/ajax.php", {obj: "suchekombi", site: this.site, f: "setSuchtextAjax", v1: "", v2: this.id});
909		}
910	},
911	getBegriff : function(){
912		var tmp = $("#"+this.id+"Input").val();
913		tmp = tmp.split(" ");
914		// Begriff aufstellen
915		this.strBegriff = "";
916		for(var i=0; i<tmp.length-1; i++){
917			this.strBegriff += this.lTrim(tmp[i])+" ";
918		}
919		// Suchwort herausfiltern
920		suchwort = this.lTrim(tmp[tmp.length-1]);
921		this.strSuchwort = suchwort;
922		if(this.strSuchwort==="") this.resetVorschlag();
923	},
924	getVorschlag : function(_begriff){
925		// aufruf bei jeder änderung, liste anzeigen
926		if(_begriff!="" && _begriff.length>1){
927			this.getVorschlagListe(_begriff);
928		}else{
929			// zuruecksetzen, wenn input leer
930			this.resetVorschlag();
931		}
932	},
933	getVorschlagListe : function(_begriff){
934		var obj = this;
935		// versetzten aufruf löschen
936		clearTimeout(kwSucheKombiTimeout);
937		// versetzten aufruf lancieren
938		kwSucheKombiTimeout = setTimeout(function(){
939			// ajax abfrage
940			$.post("/_kirchenweb/ajax.php", { obj: "suchekombi", site: obj.site, f: "getTextvorschlagAjax", v1: _begriff, v2: obj.id}, function(data){
941				if(data.substr(0,2) == "OK"){
942					// berechnung treffer
943					var treffer = $.parseJSON(data.substr(2));
944					// ausgabe vorschlagliste
945					if(treffer.length>0){
946						var innerListe = "";
947						// Liste generieren
948						for(i=0; i<treffer.length; ++i){
949							if(treffer[i].w!=undefined){
950								innerListe += "<li id=\""+obj.id+"Tv_"+i+"\" title=\""+treffer[i].w+"\">"+treffer[i].v+"</li>";
951							}else{
952								innerListe += "<li id=\""+obj.id+"Tv_"+i+"\">"+treffer[i].v+"</li>";
953							}
954						}
955						obj.anz = treffer.length;
956						obj.pos = -1;
957						obj.strListe = innerListe;
958						obj.showListe();
959					}else{
960						obj.resetVorschlag();
961					}
962				}
963			});
964			// ende versetzten aufruf lancieren
965		}, 500);
966	},
967	showListe : function(){
968		// liste aufbauen
969		var tmp = this.strListe;
970		$("#"+this.id+"Liste").html(tmp);
971		$("#"+this.id+"Liste").css({ "display": "block" });
972		// Eventhandler für Vorschlaege
973		var obj = this;
974		$("#"+this.id+"Liste > li").on("mouseover", function(e){ obj.eventMouseoverListe(e); });
975		$("#"+this.id+"Liste > li").on("click", function(e){ obj.eventClickListe(e); });
976		// CSS Vorschlaege
977		$("#"+this.id+"Liste > li").css({"cursor": "pointer"});
978	},
979	hideListe : function(){
980		$("#"+this.id+"Liste").css("display", "none");
981	},
982	selectEintrag : function(_id){
983		$("#"+this.id+"Liste > li").removeClass("aktiv");
984		$("#"+this.id+"Tv_"+_id).addClass("aktiv");
985		if($("#"+this.id+"Tv_"+_id).is("[title]")){
986			this.strSuchwort = $("#"+this.id+"Tv_"+_id).attr("title");
987		}else{
988			this.strSuchwort = $("#"+this.id+"Tv_"+_id).text();
989		}
990	},
991	setBasedir : function(_str){
992		this.basedir = _str;
993	},
994	setSite : function(_str){
995		this.site = _str;
996	},
997	setVorschlag : function(){
998		var obj = this;
999		var str = this.strSuchwort;
1000		$("#"+this.id+"Input").val(str).keyup();
1001		this.setSucheStart();
1002		/* Mehrere Begriffe Suchen
1003		var str = this.strBegriff+this.strSuchwort;
1004		$("#"+this.id+"Input").val(str+" ").keyup();
1005		this.setSucheStart();
1006		$("#"+this.id+"Input").val(this.strBegriff + this.strSuchwort + " ").keyup();
1007		this.resetVorschlag();
1008		*/
1009	},
1010	setSucheStart : function(){
1011		var str = $("#"+this.id+"Input").val();
1012		var obj = this;
1013		// suche nicht starten wenn leer
1014		if(str=="") return false;
1015		// suchberiff speichern
1016		$.post("/_kirchenweb/ajax.php", { obj: "suchekombi", site: this.site, f: "setSuchtextAjax", v1: str, v2: this.id}, function(data){
1017			$("#"+obj.id+"Input").parent().attr("action",obj.basedir+"suche/"+encodeURIComponent(str).replace(/%2F/g,"/"));
1018			$("#"+obj.id+"Input").parent().submit();
1019		});
1020	},
1021	resetVorschlag : function(){
1022		this.hideListe();
1023		$("#"+this.id+"Liste").html("");
1024		this.pos = -1;
1025		this.anz = 0;
1026		this.strBegriff = "";
1027		this.strSuchwort = "";
1028		this.strListe = "";
1029	},
1030	lTrim : function(text){
1031		// trim Links, vlg. jQuery 1.4.2
1032		var trim = /^(\s|\u00A0)+/g;
1033		return (text || "").replace(trim, "");
1034	}
1035};
1036
1037
1038// dokumentbaum
1039(function ($) {
1040	var options;
1041	var defaults = {
1042		folder: [],
1043		dokumente: [],
1044		readonly: true,
1045		monitor: false,
1046		saveTimeout: 2000,
1047		sucheTimeout: 500,
1048		openFolders: [],
1049		selected: {
1050			folder: [],
1051			dokument: []
1052		},
1053		markedId: {
1054			folder: null,
1055			dokument: null
1056		},
1057		active: {
1058			folder: null,
1059			dokument: null
1060		},
1061		monitorSelector: ".monitor.kontobox.dokumentmonitor"
1062	};
1063	var treeContainer;
1064	var monitorContainer;
1065	var uploadCounter;
1066	var dragTimeout;
1067	var touchTimeout;
1068	var touchStart;
1069	var folderEditTimer;
1070	var dokEditTimer;
1071	var sucheTimer;
1072	var expandedFolders;
1073	var freigabe = {
1074		privat: 1,
1075		gruppe: 2,
1076		mailgruppe: 2,
1077		intern: 3,
1078		extern: 4
1079	};
1080	// maximale dateigrösse 500 MB
1081	var maxFileSize = 500 * 1024 * 1024;
1082
1083	$.fn.kwFileTree = function (_options) {
1084		// overwrite defaults with custom options
1085		options = $.extend({}, defaults, _options);
1086		if (options.monitor) options.readonly = true;
1087		// references
1088		treeContainer = $(this);
1089		treeContainer.off();
1090		uploadCounter = -1;
1091		// references monitor
1092		monitorContainer = $(options.monitorSelector);
1093		monitorContainer.css("margin-top", "");
1094		clearTimeout(dragTimeout);
1095		dragTimeout = null;
1096		clearTimeout(touchTimeout);
1097		touchTimeout = null;
1098		touchStart = null;
1099		clearTimeout(folderEditTimer);
1100		folderEditTimer = null;
1101		clearTimeout(dokEditTimer);
1102		dokEditTimer = null;
1103		expandedFolders = [];
1104		// initialisation
1105		initTree();
1106	};
1107
1108	$.fn.kwFileTree.setActive = function (id, isFolder) {
1109		if (treeContainer == null) return;
1110		var elem = getTreeElem(id, isFolder);
1111		if (isFolder) {
1112			options.active.folder = id;
1113			options.active.dokument = null;
1114		} else {
1115			options.active.folder = null;
1116			options.active.dokument = id;
1117		}
1118		if (elem.length > 0) {
1119			// gefunden
1120			elem.parents(".folder:not(.extended)").find("> .name").trigger("click");
1121			elem.find("> .name .doklink").focus();
1122			setMonitor(id, isFolder, false, false);
1123		} else {
1124			$.ajax({
1125				url: '/_kirchenweb/ajax.php',
1126				method: "POST",
1127				data: {
1128					objtyp: isFolder ? 'dokumentordner' : 'dokument',
1129					id: id,
1130					f: 'getParentIDs'
1131				},
1132				success: function (data) {
1133					if (data.substr(0, 2) == "OK") {
1134						var idArray = JSON.parse(data.substr(2));
1135						options.openFolders = options.openFolders.concat(idArray);
1136						options.openFolders.filter(function (item, index, self) {
1137							return self.indexOf(item) === index;
1138						});
1139						treeContainer.find("div.folder:not(.extended)").filter(function (index, elem) {
1140							return $.inArray(parseInt($(elem).attr("data-dokid")), options.openFolders) !== -1;
1141						}).each(function (index, elem) {
1142							toggleChildren($(elem).attr("data-dokid"));
1143						});
1144					}
1145				}
1146			})
1147		}
1148	}
1149
1150	function isInteger(number) {
1151		return number === parseInt(number, 10);
1152	}
1153
1154	function initTree() {
1155		var treeHTML =
1156			'<div class="treecontainer" role="application">' +
1157			'	<div class="controls">' +
1158			'		<a class="reload"></a>' +
1159			'		<a class="collapse"></a>' +
1160			'		<a class="extend"></a>' +
1161			'	</div>' +
1162			'	<div class="folder root" data-dokid="0" data-noadd="true" data-nomod="true">' +
1163			'		<div class="children"></div>' +
1164			'	</div>' +
1165			'	<div class="meldungGefiltert">
1165' + wort.get("dokumentAnhangHinweis") + '</div>' +
1166			'</div>';
1167		treeContainer.html(treeHTML);
1168		setMonitor();
1169		initDesktopDragUpload();
1170		initClickEvents();
1171		initKeyNavigation();
1172		initTouchHandler();
1173		initShortcuts();
1174		loadInitialFolders();
1175	}
1176
1177	function initShortcuts() {
1178		$(window).off(".filetree");
1179		$(window).on("keydown.filetree", function (event) {
1180			// control shortcuts
1181			if (event.ctrlKey || event.metaKey) {
1182				switch (String.fromCharCode(event.which).toLowerCase()) {
1183					case 'd': // Dokumente fokussieren
1184						event.preventDefault();
1185						$(document.activeElement).blur();
1186						focusNextElement();
1187						break;
1188				}
1189			}
1190		});
1191	}
1192
1193	function touchHandler(event) {
1194		event = event.originalEvent;
1195		var touch = event.changedTouches[0];
1196		var simulatedEvent = document.createEvent("MouseEvent");
1197		simulatedEvent.initMouseEvent({
1198				touchstart: "mousedown",
1199				touchmove: "mousemove",
1200				touchend: "mouseup"
1201			}[event.type], true, true, window, 1,
1202			touch.screenX, touch.screenY,
1203			touch.clientX, touch.clientY, false,
1204			false, false, false, 0, null);
1205		touch.target.dispatchEvent(simulatedEvent);
1206		event.preventDefault();
1207	}
1208
1209	function initTouchHandler() {
1210		$(document).on("touchstart", function () {
1211			if ($("#kwTooltip").length > 0 && $("#kwTooltip").css("display") != "none") {
1212				kwTooltip();
1213			}
1214		});
1215		treeContainer.on("touchstart", "div.name", function (event) {
1216			var touch = event.originalEvent.changedTouches[0];
1217			touchTimeout = setTimeout(function () {
1218				var simulatedEvent = document.createEvent("MouseEvent");
1219				simulatedEvent.initMouseEvent("contextmenu", true, true, window, 1,
1220					touch.screenX, touch.screenY, touch.clientX, touch.clientY,
1221					false, false, false, false, 0, null);
1222				touch.target.dispatchEvent(simulatedEvent);
1223			}, 1000);
1224			touchStart = touch;
1225		});
1226		treeContainer.on("touchmove", "div.name", function (event) {
1227			var pX = event.originalEvent.changedTouches[0].clientX;
1228			var pY = event.originalEvent.changedTouches[0].clientY;
1229
1230			var qX = touchStart.clientX;
1231			var qY = touchStart.clientY;
1232			var distance = Math.sqrt(((pX - qX) ^ 2) * ((pY - qY) ^ 2));
1233			if (distance >= 10) clearTimeout(touchTimeout);
1234		})
1235		treeContainer.on("touchend touchcancel", "div.name", function (event) {
1236			clearTimeout(touchTimeout);
1237		});
1238		treeContainer.on("touchstart", "div.name", touchHandler);
1239		treeContainer.on("touchmove", "div.name", touchHandler);
1240		treeContainer.on("touchend", "div.name", touchHandler);
1241		treeContainer.on("touchcancel", "div.name", touchHandler);
1242	}
1243
1244	function initDesktopDragUpload() {
1245		if (options.readonly) return;
1246		treeContainer.on("drop", ".folder,.document", function (event) {
1247			treeContainer.find(".droppable").removeClass("droppable");
1248			monitorContainer.removeClass("droppable");
1249			event.stopPropagation();
1250			event.preventDefault();
1251			if (!event.originalEvent.dataTransfer
1252				|| !event.originalEvent.dataTransfer.files
1253				|| event.originalEvent.dataTransfer.files.length == 0) return;
1254			var parentId = -1;
1255			var beforeElem = false;
1256			if ($(this).hasClass("folder") && $(event.target).hasClass("nameSpan")) {
1257				// zu kindern
1258				if (!$(event.target).closest(".folder").hasClass("extended")) toggleChildren($(event.target).closest(".folder").attr("data-dokid"));
1259				parentId = $(event.target).parents(".folder").first().attr("data-dokid");
1260			} else {
1261				// als sibling
1262				parentId = $(this).parents(".folder").first().attr("data-dokid");
1263				beforeElem = $(this);
1264			}
1265			if (getTreeElem(parentId, true).attr("data-noadd")) return;
1266			var files = event.originalEvent.dataTransfer.files;
1267			for (var i = 0, f; f = files[i]; i++) {
1268				createNewFileFromDrop(parentId, f, i == files.length - 1, beforeElem);
1269			}
1270		});
1271		treeContainer.on("dragover", ".document,.folder", function (event) {
1272			event.stopPropagation();
1273			event.preventDefault();
1274			treeContainer.find(".droppable").not($(this)).removeClass("droppable");
1275			$(this).addClass("droppable");
1276		});
1277		treeContainer.on("dragover", ".folder > .name .nameSpan", function (event) {
1278			event.stopPropagation();
1279			event.preventDefault();
1280			treeContainer.find(".droppable").not($(this)).removeClass("droppable");
1281			$(this).addClass("droppable");
1282		});
1283		treeContainer.on("dragleave", ".folder,.document", function (event) {
1284			event.stopPropagation();
1285			treeContainer.find(".droppable").removeClass("droppable");
1286		});
1287		treeContainer.on("drop", function (event) {
1288			treeContainer.find(".droppable").removeClass("droppable");
1289		});
1290		monitorContainer.find(".content").on("dragover", function (event) {
1291			if (monitorContainer.find(".info.folder").length > 0 || monitorContainer.find("form.dokument").length > 0) {
1292				monitorContainer.addClass("droppable");
1293				event.preventDefault();
1294			}
1295		});
1296		monitorContainer.on("drop", function (event) {
1297			event.preventDefault();
1298			treeContainer.find(".droppable").removeClass("droppable");
1299			monitorContainer.removeClass("droppable");
1300			if (!event.originalEvent.dataTransfer) return;
1301			var monitorInfo = monitorContainer.find("div.info[data-dokid]");
1302			if (monitorInfo.length == 0) return;
1303			if (monitorInfo.hasClass("dokument")) {
1304				// replace document, only
1305				if (event.originalEvent.dataTransfer.files.length > 1) return;
1306				var dokid = monitorInfo.attr("data-dokid");
1307				uploadFile(dokid, event.originalEvent.dataTransfer.files[0], true, false);
1308			} else if (monitorInfo.hasClass("folder")) {
1309				// neue/neues dokument in ordner erstellen
1310				var folderId = monitorInfo.attr("data-dokid");
1311				var elem = getTreeElem(folderId, true);
1312				if (elem.attr("data-noadd")) return;
1313				for (var i = 0; i < event.originalEvent.dataTransfer.files.length; i++) {
1314					monitorContainer.addClass("droppable");
1315					createNewFileFromDrop(folderId, event.originalEvent.dataTransfer.files[i], true, false);
1316					monitorContainer.removeClass("droppable");
1317				}
1318			}
1319		});
1320		monitorContainer.on("dragleave", ".dragMask", function (event) {
1321			monitorContainer.removeClass("droppable");
1322		});
1323	}
1324
1325	function createNewFileFromDrop(parentId, f, showMonitor, beforeElem) {
1326		var newId = --uploadCounter;
1327		var parentElem = getTreeElem(parentId, true);
1328		var titel = f.name;
1329		var sortPos = 0;
1330		// check filename to either contain or not begin with a dot
1331		if (titel.lastIndexOf('.') > 0) {
1332			titel = titel.substr(0, titel.lastIndexOf('.'));
1333		}
1334		// sort position if sorted manually
1335		if (beforeElem && parentElem.attr("data-sorttyp") == 'manual') {
1336			sortPos = beforeElem.index();
1337		}
1338		// file anlegen
1339		$.ajax({
1340			url: "/_kirchenweb/dokverwaltung/ajax/dokNeu.php",
1341			data: {
1342				parentIndex: parentId,
1343				titel: titel,
1344				sortPosition: sortPos
1345			},
1346			success: function (data) {
1347				if (data.substr(0, 2) == "OK") {
1348					var dokid = data.substr(2);
1349					createDok(dokid, parentId, true);
1350					getTreeElem(dokid, false).find("> .name .nameSpan").text(f.name);
1351					uploadFile(dokid, f, showMonitor, beforeElem);
1352				} else {
1353					kwMitteilung(data.substr(2));
1354				}
1355			}
1356		});
1357	}
1358
1359	function uploadFile(dokid, f, showMonitor, beforeElem) {
1360		var monitorElem = monitorContainer.has("div.info.dokument[data-dokid=" + dokid + "]");
1361		var elem = getTreeElem(dokid, false);
1362		var parentElem = elem.closest(".folder");
1363		var parentId = parentElem.attr("data-dokid");
1364		monitorElem.addClass("droppable");
1365		$('<input type="file" />').fileupload({
1366			url: '/_kirchenweb/dokverwaltung/ajax/dokErsetzen.php',
1367			type: 'POST',
1368			autoUpload: false,
1369			dataType: "json",
1370			dropZone: null,
1371			maxFileSize: maxFileSize
1372		})
1373			.on("fileuploadadd", function (event, data) {
1374				var $this = $(this);
1375				var validation = data.process(function () {
1376					return $this.fileupload('process', data);
1377				});
1378				validation.done(function () {
1379					parentElem.attr("data-parent", "true");
1380					if (!parentElem.hasClass("extended")) toggleChildren(parentId);
1381					elem.addClass("uploading");
1382					monitorElem.find(".dragMask").addClass("uploading");
1383					if (beforeElem != false) beforeElem.before(elem);
1384					data.formData = {
1385						dokid: dokid,
1386						timestamp: Math.round((data.files[0].lastModified || new Date().getTime()) / 1000)
1387					};
1388					var uploadRef = data.submit();
1389					elem.find(".cancel").on("click", function (event) {
1390						uploadRef.abort();
1391					});
1392					monitorElem.find(".cancel").on("click", function (event) {
1393						uploadRef.abort();
1394					});
1395				});
1396				validation.fail(function () {
1397					monitorElem.removeClass("droppable");
1398					kwMitteilung(wort.get("fehlerDokZuGross"));
1399				});
1400			})
1401			.on("fileuploadprogress", function (event, data) {
1402				var progress = Math.min(parseInt(data.loaded / data.total * 100, 10), 100);
1403				elem.find(".uploadProgress .bar").css({
1404					"width": progress + "%"
1405				});
1406				monitorElem.find(".uploadProgress .bar").css({
1407					"width": progress + "%"
1408				});
1409			})
1410			.on("fileuploaddone", function (event, data) {
1411				if (showMonitor) setMonitor(dokid, false, true);
1412				monitorElem.removeClass("droppable");
1413				elem.removeClass("uploading");
1414				createChildren(parentId);
1415			})
1416			.on("fileuploadfail", function (event, data) {
1417				if (elem.siblings().length == 0) {
1418					parentElem.removeAttr("data-parent");
1419				}
1420				elem.remove();
1421			})
1422			.fileupload("add", {files: f});
1423	}
1424
1425	function loadInitialFolders() {
1426		if (isInteger(options.folder)) options.folder = [options.folder];
1427		if (isInteger(options.dokumente)) options.dokumente = [options.dokumente];
1428
1429		// copy options.folder zu options.openFolders
1430		if (options.openFolders.length == 0) options.openFolders = options.folder.slice();
1431		// startordner gesetzt?
1432		$.each(options.folder, function (index, elem) {
1433			createFolder(elem, 0);
1434		});
1435		// startdokumente gesetzt?
1436		$.each(options.dokumente, function (index, elem) {
1437			createDok(elem, 0);
1438		});
1439		// keine startdokumente und ordner gesetzt, lade root ordner
1440		if (options.folder.length + options.dokumente.length == 0) {
1441			createRootFolders();
1442		} else {
1443			loadInfo({
1444				"dokumente": options.dokumente,
1445				"ordner": options.folder
1446			})
1447		}
1448	}
1449
1450	function initClickEvents() {
1451		// monitor checkboxen
1452		treeContainer.on("click", ".name > .checkboxNA", function (event) {
1453			event.preventDefault();
1454		});
1455		treeContainer.on("click", ".name > .checkboxEin, .name > .checkboxAus", function (event) {
1456			event.preventDefault();
1457			var dok = $(this).closest(".folder,.document");
1458			objKwForm.setCheckbox(
1459				this,
1460				'getAusgabeDokumente',
1461				dok.attr("data-dokid") + (dok.hasClass("folder") ? "0" : "1"),
1462				1,
1463				'dokumentAnzeige'
1464			);
1465		});
1466		// links auf name nicht öffnen!
1467		treeContainer.on("click", ".folder > .name a.doklink", function (event) {
1468			event.preventDefault();
1469		});
1470		if (options.monitor || !options.readonly) treeContainer.on("click", ".document > .name a.doklink", function (event) {
1471			event.preventDefault();
1472		});
1473		// tree control: collapse all folders, extend all folders, reload tree
1474		treeContainer.find("div.controls a.reload").on("click", function (event) {
1475			event.preventDefault();
1476			treeContainer.kwFileTree(options);
1477		});
1478		treeContainer.find("div.controls a.collapse").on("click", function (event) {
1479			event.preventDefault();
1480			treeContainer.find("div.extended > div.name").each(function (index, elem) {
1481				toggleChildren($(this).closest(".folder").attr("data-dokid"));
1482			});
1483			options.openFolders = [];
1484			setMonitor();
1485		});
1486		treeContainer.find("div.controls a.extend").on("click", function (event) {
1487			event.preventDefault();
1488			expandedFolders = [0];
1489			treeContainer.find("div.folder:not(.extended) > div.name").each(function (index, elem) {
1490				toggleChildren($(this).closest(".folder").attr("data-dokid"));
1491			});
1492		});
1493		// firefox draggable=false-hack
1494		treeContainer.on("dragstart", "a.doklink", function (event) {
1495			event.preventDefault();
1496		});
1497		// tooltip für ordner & dokumente
1498		treeContainer.on("mouseenter touchstart", "div.name", function (event) {
1499			// uploads und neue ordner ignorieren
1500			if ($(this).closest(".document").hasClass("uploading") || $(this).find("input").length > 0) {
1501				return;
1502			}
1503			// ios download bug
1504			if ($(this).closest(".document").length > 0 && event.type == 'touchstart') {
1505				download($(this).closest(".document").attr("data-dokid"));
1506			}
1507			// tooltip darstellen
1508			var id = $(this).closest(".folder,.document").attr("data-dokid");
1509			id += $(this).closest(".folder,.document").hasClass("document") ? "1" : "0";
1510			var tooltipClass = options.monitor ? "left" : "";
1511			kwTooltip(this, '/_kirchenweb/dokverwaltung/loadNodeInfo.php?id=' + id, tooltipClass, undefined, "40");
1512		});
1513		treeContainer.on("mouseleave", "div.name", function (event) {
1514			// tooltip löschen
1515			kwTooltip();
1516		});
1517		// contextmenu treecontainer
1518		if (!options.readonly) treeContainer.on("contextmenu", "div.name", function (event) {
1519			// downloadlink und text-inputfelder ignorieren
1520			if ($(event.target).hasClass("downloadIcon") || $(event.target).is("input[type='text']")) return true;
1521			// default abbrechen
1522			event.preventDefault();
1523			event.stopPropagation();
1524			// uploads auffangen
1525			if ($(event.target).parents(".document").hasClass("uploading")) return;
1526			var top = event.clientY + $(window).scrollTop();
1527			var left = event.clientX + $(window).scrollLeft();
1528			$(this).kwFileTreeContextMenu(top, left);
1529		});
1530		// contextmenu aktuelle dokumente
1531		if (!options.readonly) $("div.kontobox.aktuell").on("contextmenu", ".folder,.document", function (event) {
1532			event.preventDefault();
1533			event.stopPropagation();
1534			var top = event.clientY + $(window).scrollTop();
1535			var left = event.clientX + $(window).scrollLeft();
1536			$(this).kwFileTreeContextMenu(top, left, true);
1537		});
1538		// contextmenu suche
1539		if (!options.readonly) $("div.kontobox.suche").on("contextmenu", ".folder,.document", function (event) {
1540			event.preventDefault();
1541			event.stopPropagation();
1542			var top = event.clientY + $(window).scrollTop();
1543			var left = event.clientX + $(window).scrollLeft();
1544			$(this).kwFileTreeContextMenu(top, left, true);
1545		});
1546		// suche
1547		$("div.kontobox.suche #formFilter").on("submit", function (event) {
1548			event.preventDefault();
1549			submitSuche();
1550		});
1551		$("div.kontobox.suche #filterTextDSucheEin").on("click", function (event) {
1552			event.preventDefault();
1553			$("div.kontobox.suche #formFilter").submit();
1554		});
1555		$("div.kontobox.suche").on("click", "div.row.weitere a", function (event) {
1556			event.preventDefault();
1557			$("div.kontobox.suche #formFilter").submit();
1558		});
1559		$("div.kontobox.suche #filterTextDSucheAus").on("click", function (event) {
1560			event.preventDefault();
1561			$("div.kontobox.suche #formFilter").find("input#filterTextD").val("");
1562			$("div.kontobox.suche #formFilter").submit();
1563		});
1564		// autosubmit suche
1565		$("div.kontobox.suche #filterTextD").on("input", function (event) {
1566			clearTimeout(sucheTimer);
1567			if ($(this).val().length >= 3) {
1568				sucheTimer = setTimeout(function () {
1569					submitSuche(24);
1570				}, options.sucheTimeout);
1571			}
1572		});
1573		// aktuelle dokumente & suche klicks
1574		// links auf name nicht öffnen!
1575		$("div.kontobox.suche, div.kontobox.aktuell").on("click", ".folder a,.document a:not(.downloadIcon)", function (event) {
1576			event.preventDefault();
1577			var dokid = $(this).closest(".document,.folder").attr("data-dokid");
1578			var isFolder = $(this).closest(".document").length == 0;
1579			treeContainer.kwFileTree.setActive(dokid, isFolder);
1580		});
1581		// doppelklick download
1582		$("div.kontobox.suche, div.kontobox.aktuell").on("dblclick", ".document", function (event) {
1583			download(this.getAttribute("data-dokid"));
1584		});
1585		// doppelklick öffnen
1586		$("div.kontobox.suche, div.kontobox.aktuell").on("dblclick", ".folder", function (event) {
1587			window.location.href = $(this).find("a").first().attr("href");
1588		});
1589		// ordner ein/ausklappen, monitor setzen
1590		treeContainer.on("click touchstart", "div.folder > div.name", function (event) {
1591			if (event.target.tagName === "A" || event.target.tagName === "INPUT" || $(this).closest("div.folder").hasClass("recentlyClicked")) return true;
1592			// doppelclick verhindern
1593			$(this).closest("div.folder").addClass("recentlyClicked");
1594			setTimeout(function () {
1595				treeContainer.find(".recentlyClicked").removeClass("recentlyClicked");
1596			}, 400);
1597			toggleChildren($(this).closest("div.folder").attr("data-dokid"));
1598			setMonitor($(this).closest("div.folder").attr("data-dokid"), true);
1599		});
1600		// monitor für dokument setzen
1601		treeContainer.on("click touchstart", "div.document > div.name", function (event) {
1602			if (event.target.tagName === "A") return true;
1603			setMonitor($(this).closest(".document").attr("data-dokid"), false);
1604		});
1605		// doppelklick download
1606		treeContainer.on("dblclick", "div.document > div.name", function (event) {
1607			download($(this).closest(".document").attr("data-dokid"));
1608		});
1609	}
1610
1611	function initKeyNavigation() {
1612		treeContainer.on("keydown", function (event) {
1613			if (!$(document.activeElement).is(":input,[contenteditable]")) {
1614				var key = event.which || event.keyCode;
1615				if (key == 40) {
1616					// down arrow
1617					event.preventDefault();
1618					focusNextElement();
1619				} else if (key == 38) {
1620					// up arrow
1621					event.preventDefault();
1622					focusPrevElement();
1623				} else if (key == 39) {
1624					// right arrow
1625					event.preventDefault();
1626					downFolderOrFocus();
1627				} else if (key == 37) {
1628					// left arrow
1629					event.preventDefault();
1630					upFolder();
1631				}
1632			}
1633		});
1634		treeContainer.on("keydown", ".document .doklink", function (event) {
1635			var key = event.which || event.keyCode;
1636			var tag = event.target.tagName.toLowerCase();
1637			if ((key == 32 || key == 13) && !$(document.activeElement).is(":input,[contenteditable]")) {
1638				// Enter or space pressed
1639				event.preventDefault();
1640				window.location.href = this.href;
1641			}
1642		});
1643	}
1644
1645	function focusNextElement() {
1646		var focused = treeContainer.find(".doklink:focus");
1647		if (focused.length == 0) {
1648			treeContainer.find(".document,.folder").not(".root").first().find("> .name .doklink").focus();
1649		} else {
1650			var elements = treeContainer.find(".document:visible,.folder:visible").not(".root").find("> .name .doklink");
1651			var index = elements.index(focused);
1652			elements.eq((index + 1) % elements.length).focus();
1653		}
1654	}
1655
1656	function focusPrevElement() {
1657		var focused = treeContainer.find(".doklink:focus");
1658		if (focused.length > 0) {
1659			var elements = treeContainer.find(".document:visible,.folder:visible").not(".root").find("> .name .doklink");
1660			var index = elements.index(focused);
1661			elements.eq((index - 1) % elements.length).focus();
1662		}
1663	}
1664
1665	function downFolderOrFocus() {
1666		var focused = treeContainer.find(".doklink:focus");
1667		var elem = focused.closest(".folder,.document");
1668		if (focused.length > 0) {
1669			if (elem.hasClass("extended") || elem.attr("data-parent") != "true" || elem.hasClass("document")) {
1670				setMonitor(elem.attr("data-dokid"), elem.hasClass("folder"), true, false);
1671			} else if (elem.hasClass("folder")) {
1672				toggleChildren(focused.closest(".folder").attr("data-dokid"));
1673			}
1674		}
1675	}
1676
1677	function upFolder() {
1678		var focused = treeContainer.find(".doklink:focus");
1679		if (focused.length > 0) {
1680			var elem = focused.closest(".document,.folder");
1681			if (elem.hasClass("extended")) {
1682				toggleChildren(elem.attr("data-dokid"))
1683			} else {
1684				var parent = elem.parents(".folder").first();
1685				parent.find("> .name .doklink").focus();
1686			}
1687		}
1688	}
1689
1690	function submitSuche(limit) {
1691		clearTimeout(sucheTimer);
1692		$("div.kontobox.suche").addClass("waiting");
1693		$.ajax({
1694			url: "/_kirchenweb/ajax.php",
1695			data: {
1696				objtyp: "dokumentManage",
1697				f: "getMonitorSuche",
1698				v1: $("div.kontobox.suche #formFilter").find("input#filterTextD").val(),
1699				v2: limit || 0,
1700				v3: $(".treecontainer .folder.root > .children > .folder").map(function(){
1701						return parseInt($(this).attr("data-dokid"));
1702					}).get()
1703			},
1704			success: function (data) {
1705				$("div.kontobox.suche").removeClass("waiting");
1706				if (data.substr(0, 2) == "OK") {
1707					$("#monitorSuche").html(data.substr(2));
1708				}
1709			}
1710		});
1711	}
1712
1713	function setMonitor(dokid, isFolder, focusForm, noAlign) {
1714		treeContainer.find(".marked").removeClass("marked");
1715		getTreeElem(dokid, isFolder).addClass("marked");
1716		clearTimeout(dokEditTimer);
1717		clearTimeout(folderEditTimer);
1718		if (monitorContainer.hasClass("waiting")) {
1719			monitorContainer.find("form").trigger("submit");
1720		}
1721		if (options.monitor || !monitorContainer.get(0)) return;
1722		if (noAlign !== false) {
1723			monitorContainer.css("margin-top", Math.abs(Math.min(0, monitorContainer.get(0).getBoundingClientRect().top - parseInt(monitorContainer.css("margin-top")) - 15)) + "px");
1724		}
1725		if (dokid == "" || dokid == null || dokid == undefined) {
1726			monitorContainer.find("div.content").html(wort.get("infoPerKlick"));
1727			return;
1728		}
1729		options.markedId.dokument = isFolder ? null : dokid;
1730		options.markedId.folder = isFolder ? dokid : null;
1731		$.ajax({
1732			url: "/_kirchenweb/ajax.php",
1733			method: "POST",
1734			data: {
1735				objtyp: isFolder ? 'dokumentordner' : 'dokument',
1736				id: dokid,
1737				f: 'getHtmlInfo',
1738				v: JSON.stringify({
1739					readonly: options.readonly
1740				})
1741			},
1742			success: function (data) {
1743				if (data.substr(0, 2) == "OK") {
1744					monitorContainer.find("div.content").html(data.substr(2));
1745					if (focusForm) {
1746						var inputName = isFolder ? 'name' : 'titel';
1747						monitorContainer.find("div.content input[name='" + inputName + "']")
1748							.focus()
1749							.select();
1750					}
1751					if (isFolder) {
1752						initFolderMonitorClicks();
1753						initFolderEdit();
1754					} else {
1755						initFileMonitorClicks();
1756						initFileEdit();
1757					}
1758				}
1759			}
1760		})
1761	}
1762
1763	function createRootFolders() {
1764		var post = {
1765			objtyp: 'dokumentordner',
1766			f: 'getRootFolders'
1767		}
1768		$.post("/_kirchenweb/ajax.php", post, function (data) {
1769			if (data.substr(0, 2) == "OK") {
1770				var roots = JSON.parse(data.substr(2));
1771				if (options.openFolders.length == 0) options.openFolders = [parseInt(roots["privat"], 10)];
1772				else options.openFolders.push(parseInt(roots["privat"], 10));
1773
1774				$.each(roots, function (index, elem) {
1775					createFolder(elem, 0);
1776				})
1777				loadFolderInfo(roots);
1778			}
1779		});
1780	}
1781
1782	function createFolder(dokid, _elternIndex) {
1783		var parent = getTreeElem(_elternIndex, true);
1784		var elem = getTreeElem(dokid, true);
1785		if (elem.length == 0) {
1786			parent.find('> div.children').append('<div class="folder loading" data-dokid="' + dokid + '"><div class="name"><div class="icon"></div><a href="/dok/z' + dokid + '" class="doklink" draggable="false"><span class="nameSpan"></span></a></div><div class="children"></div></div>');
1787			if (options.monitor) {
1788				getTreeElem(dokid, true).find("> .name .doklink").before('<a id="chk' + dokid + '0" class="checkboxAus"></a>');
1789			}
1790		} else {
1791			parent.find("> div.children").append(elem);
1792		}
1793	}
1794
1795	function createDok(dokid, _elternIndex, upload) {
1796		var parent = getTreeElem(_elternIndex, true);
1797		var elem = getTreeElem(dokid, false);
1798		if (elem.length == 0) {
1799			parent.find('> div.children').append('<div class="document" data-dokid="' + dokid + '"><div class="name"><div class="icon"></div><a href="/dok/' + dokid + '" class="doklink" draggable="false"><span class="nameSpan"></span></a><a href="/dok/' + dokid + '" class="downloadIcon" draggable="false"></a></div></div>');
1800			elem = getTreeElem(dokid, false);
1801			if (options.monitor) {
1802				elem.find("> .name .doklink").before('<a id="chk' + dokid + '1" class="checkboxAus"></a>');
1803			}
1804		} else {
1805			parent.find('> div.children').append(elem);
1806		}
1807		if (upload === true) {
1808			elem.find('.doklink').after('<span class="uploadProgress"><span class="bar"></span></span><span class="cancel" title="' + wort.get("abbrechen") + '"></span>');
1809		}
1810	}
1811
1812	function createChildren(_elternIndex) {
1813		var parent = getTreeElem(_elternIndex, true);
1814		if (parent.find("> .children > .uploading").length > 0) return;
1815		parent.removeClass("error").addClass("loading");
1816		var post = {
1817			objtyp: 'dokumentordner',
1818			id: _elternIndex,
1819			f: 'getChildren'
1820		}
1821		$.post('/_kirchenweb/ajax.php', post, function (data) {
1822			if (data.substr(0, 2) == 'OK') {
1823				var ret = JSON.parse(data.substr(2));
1824				insertChildren(ret, _elternIndex);
1825				if (!parent.hasClass("extended")) toggleChildren(_elternIndex);
1826				if (ret['gefiltert'] == true) {
1827					treeContainer.find(".meldungGefiltert").addClass("active");
1828				}
1829			} else {
1830				parent.removeClass("loading").addClass("error");
1831				if (parent.hasClass("extended")) toggleChildren(_elternIndex);
1832			}
1833		});
1834	}
1835
1836	function insertChildren(children, parentIndex) {
1837		var doks = [];
1838		var folders = [];
1839		$.each(children['elemente'], function (index, value) {
1840			if (index.substr(0, 1) == 'z') {
1841				createFolder(index.substr(1), parentIndex);
1842				insertFolderInfo(value);
1843			} else {
1844				createDok(index.substr(1), parentIndex);
1845				insertDokInfo(value);
1846			}
1847		});
1848		getTreeElem(parentIndex, true).removeClass("loading");
1849	}
1850
1851	function positionUpdated(elem, oldParentId) {
1852		if (options.readonly) return;
1853		var newParentId = elem.parents("div.folder").first().attr("data-dokid");
1854		var myArguments = {
1855			oldParent: oldParentId,
1856			newParent: newParentId,
1857			position: elem.index() + 1
1858		}
1859		$.ajax({
1860			url: "/_kirchenweb/ajaxFormSetData.php",
1861			method: "POST",
1862			data: {
1863				objtyp: elem.hasClass("folder") ? 'dokumentordner' : 'dokument',
1864				id: elem.attr("data-dokid"),
1865				f: 'changePosition',
1866				v: JSON.stringify(myArguments)
1867			},
1868			success: function (data) {
1869				if (data.substr(0, 2) == "OK" && JSON.parse(data.substr(2)) == true) {
1870					createChildren(oldParentId);
1871					if (newParentId != oldParentId) createChildren(newParentId);
1872				} else if (data.substr(0, 2) == "OK") {
1873					var dialog = new kwDialog(400, 190, "warnung");
1874					dialog.setHtml(JSON.parse(data.substr(2)));
1875					dialog.show();
1876					$("#kwDialog").find("a.button").on("click", function (event) {
1877						event.preventDefault();
1878						dialog.hide();
1879						treeContainer.kwFileTree(options);
1880					});
1881				}
1882			}
1883		});
1884	}
1885
1886	function loadDokInfo(doks) {
1887		var values = [];
1888		for (var key in doks) {
1889			if (Object.prototype.hasOwnProperty.call(doks, key)) {
1890				values.push(doks[key]);
1891			}
1892		}
1893		loadInfo({
1894			"dokumente": values
1895		})
1896	}
1897
1898	function loadFolderInfo(folders) {
1899		var values = [];
1900		for (var key in folders) {
1901			if (Object.prototype.hasOwnProperty.call(folders, key)) {
1902				values.push(folders[key]);
1903			}
1904		}
1905		loadInfo({
1906			"ordner": values
1907		});
1908	}
1909
1910	function loadInfo(elements) {
1911		$.ajax({
1912			url: "/_kirchenweb/ajax.php",
1913			method: "POST",
1914			data: {
1915				objtyp: 'dokumentordner',
1916				f: "getInfo",
1917				v: JSON.stringify(elements)
1918			},
1919			complete: function (jqXHR, textStatus) {
1920				if (jqXHR.responseText.substr(0, 2) == "OK") {
1921					var info = JSON.parse(jqXHR.responseText.substr(2));
1922
1923					var values = [];
1924					for (var key in info['ordner']) {
1925						if (Object.prototype.hasOwnProperty.call(info['ordner'], key)) {
1926							values.push(info['ordner'][key]);
1927						}
1928					}
1929					insertFolderInfo(values);
1930
1931					values = [];
1932					for (var key in info['dokumente']) {
1933						if (Object.prototype.hasOwnProperty.call(info['dokumente'], key)) {
1934							values.push(info['dokumente'][key]);
1935						}
1936					}
1937					insertDokInfo(values);
1938					$.each(info['ordner'], function (index, value) {
1939						info['ordner'][index] = this.id;
1940					});
1941					$.each(info['dokumente'], function (index, value) {
1942						info['dokumente'][index] = this.id;
1943					});
1944					return;
1945				}
1946			}
1947		})
1948	}
1949
1950	function insertDokInfo(dokinfo) {
1951		var updatedParents = [];
1952		$(dokinfo).each(function (index, info) {
1953			var elem = getTreeElem(info['id'], false);
1954			if (info['noAccess'] == true) {
1955				treeContainer.find(".meldungGefiltert").addClass("active");
1956				elem.remove();
1957				return;
1958			} else if (info['hidden'] == true) {
1959				elem.remove();
1960				return;
1961			}
1962			if (elem.length == 0) {
1963				return;
1964			}
1965			// parents to sort
1966			var parentId = elem.closest(".folder").attr("data-dokid");
1967			if (updatedParents.indexOf(parentId) === -1) updatedParents.push(parentId);
1968			elem
1969				.removeClass("error")
1970				.removeAttr("data-unselectable")
1971				.removeAttr("data-owner")
1972				.removeAttr("data-nomod")
1973				.removeAttr("data-noshare")
1974			elem.find("> div.name .nameSpan")
1975				.text(info['name']);
1976			elem.find("> div.name .icon")
1977				.css("background-image", "url(" + info['iconPath'] + ")");
1978			elem
1979				.attr("data-sort", info['sortierung'])
1980				.attr("data-freigabe", info['freigabe'])
1981				.attr("data-mailgruppe", info['mailgruppe']);
1982			if (options.markedId.dokument == info['id']) {
1983				treeContainer.find(".marked").removeClass("marked");
1984				elem.addClass("marked");
1985				if (monitorContainer.find("form.dokument input[name=dokid]").val() != info['id']) setMonitor(info['id'], false);
1986			}
1987			if (options.active.dokument == info['id']) {
1988				elem.find("> .name a.doklink").focus();
1989				setMonitor(info['id'], false);
1990				options.active.dokument = null;
1991			}
1992			if (options.monitor) {
1993				if (freigabe[info['freigabe']] < freigabe[options.monitorFreigabe]) {
1994					elem.find(".checkboxAus")
1995						.addClass("checkboxNA")
1996						.removeClass("checkboxAus");
1997					elem.attr("data-unselectable", "true");
1998				} else if (freigabe[options.monitorFreigabe] == freigabe["mailgruppe"] && freigabe[info['freigabe']] == freigabe["mailgruppe"] && $.inArray(info['mailgruppe'], options.monitorMailgruppe) === -1) {
1999					elem.find(".checkboxAus")
2000						.addClass("checkboxNA")
2001						.removeClass("checkboxAus");
2002					elem.attr("data-unselectable", "true");
2003				} else if ($.inArray(parseInt(info['id'], 10), options.selected.dokument) !== -1) {
2004					elem.find(".checkboxAus")
2005						.addClass("checkboxEin")
2006						.removeClass("checkboxAus");
2007				}
2008			}
2009			if (info['owner']) elem.attr("data-owner", "true");
2010			if (info['nomod']) elem.attr("data-nomod", "true");
2011			if (info['draggable']) elem.attr('data-draggable', 'true');
2012			if (info['draggable'] && !info['nomod'] && !options.readonly) {
2013				elem.draggable({
2014					addClass: false,
2015					appendTo: treeContainer,
2016					distance: 10,
2017					handle: "> .name",
2018					refreshPositions: true,
2019					revert: "invalid"
2020				});
2021			}
2022			if (!options.readonly) elem.droppable({
2023				accept: ".folder,.document",
2024				addClass: false,
2025				greedy: true,
2026				hoverClass: "droppable",
2027				tolerance: "pointer",
2028				drop: function (event, ui) {
2029					treeContainer.find(".droppable").removeClass("droppable");
2030					monitorContainer.removeClass("droppable");
2031					event.stopPropagation();
2032					clearTimeout(dragTimeout);
2033					if (ui) {
2034						dropElement(ui.draggable, $(this).closest(".folder"), $(this).closest(".document"));
2035					}
2036				}
2037			});
2038		});
2039	}
2040
2041	function insertFolderInfo(folderinfo) {
2042		var updatedParents = [];
2043		$(folderinfo).each(function (index, info) {
2044			var elem = getTreeElem(info['id'], true);
2045			if (info['noAccess'] == true) {
2046				treeContainer.find(".meldungGefiltert").addClass("active");
2047				elem.remove();
2048				return;
2049			} else if (info['hidden'] == true) {
2050				elem.remove();
2051				return;
2052			}
2053			if (elem.length == 0) {
2054				return;
2055			}
2056			// parents to sort
2057			var parentId = elem.parents(".folder").first().attr("data-dokid");
2058			if (updatedParents.indexOf(parentId) === -1) updatedParents.push(parentId);
2059			elem
2060				.removeClass("error")
2061				.removeClass("extended")
2062				.removeAttr("data-unselectable")
2063				.removeAttr("data-owner")
2064				.removeAttr("data-noadd")
2065				.removeAttr("data-nomod")
2066				.removeAttr("data-noshare")
2067				.removeAttr("data-parent")
2068				.removeAttr("data-root")
2069			elem.find("> div.name .nameSpan")
2070				.text(info['name']);
2071			elem
2072				.attr("data-sorttyp", info['sortierungTyp'])
2073				.attr("data-sort", info['sortierung'])
2074				.attr("data-freigabe", info['freigabe'])
2075				.attr("data-mailgruppe", info['mailgruppe'])
2076				.removeClass("loading");
2077			if (options.markedId.folder == info['id']) {
2078				treeContainer.find(".marked").removeClass("marked");
2079				elem.addClass("marked");
2080				if (monitorContainer.find("form.folder input[name=dokid]").val() != 
2080info['id']) setMonitor(info['id'], true);
2081			}
2082			if (options.active.folder == info['id']) {
2083				elem.find("> .name a.doklink").focus();
2084				setMonitor(info['id'], true);
2085				options.active.folder = null;
2086			}
2087			if (options.monitor) {
2088				if (freigabe[info['freigabe']] < freigabe[options.monitorFreigabe]) {
2089					elem.find(".checkboxAus")
2090						.addClass("checkboxNA")
2091						.removeClass("checkboxAus");
2092					elem.attr("data-unselectable", "true");
2093				} else if (freigabe[options.monitorFreigabe] == freigabe["mailgruppe"] && freigabe[info['freigabe']] == freigabe["mailgruppe"] && $.inArray(info['mailgruppe'], options.monitorMailgruppe) === -1) {
2094					elem.find(".checkboxAus")
2095						.addClass("checkboxNA")
2096						.removeClass("checkboxAus");
2097					elem.attr("data-unselectable", "true");
2098				} else if ($.inArray(parseInt(info['id'], 10), options.selected.folder) !== -1) {
2099					elem.find(".checkboxAus")
2100						.addClass("checkboxEin")
2101						.removeClass("checkboxAus");
2102				}
2103			}
2104			if (info['owner']) elem.attr("data-owner", "true");
2105			if (info['noadd']) elem.attr("data-noadd", "true");
2106			if (info['nomod']) elem.attr("data-nomod", "true");
2107			if (info['noshare']) elem.attr("data-noshare", "true");
2108			if (info['hasChildren']) elem.attr("data-parent", "true");
2109			if (info['root']) elem.attr("data-root", "true");
2110			if (info['draggable']) elem.attr('data-draggable', 'true');
2111			if (info['draggable'] && !info['nomod'] && !options.readonly) {
2112				elem.draggable({
2113					addClass: false,
2114					appendTo: treeContainer,
2115					distance: 10,
2116					handle: "> .name",
2117					refreshPositions: true,
2118					revert: "invalid",
2119
2120					start: function () {
2121						if ($(this).hasClass("extended")) toggleChildren($(this).attr("data-dokid"));
2122					}
2123				});
2124			}
2125			// drag to same folder
2126			if (!options.readonly && !elem.parents(".folder").first().attr("data-noadd")) elem.droppable({
2127				accept: ".folder,.document",
2128				addClass: false,
2129				greedy: true,
2130				hoverClass: "droppable",
2131				tolerance: "pointer",
2132				drop: function (event, ui) {
2133					treeContainer.find(".droppable").removeClass("droppable");
2134					monitorContainer.removeClass("droppable");
2135					event.stopPropagation();
2136					clearTimeout(dragTimeout);
2137					if (ui) {
2138						dropElement(ui.draggable, $(this).parents(".folder").first(), $(this).closest(".folder"));
2139					}
2140				}
2141			});
2142			// drag to children
2143			if (!options.readonly && !info['noadd']) elem.find("> .name .nameSpan").droppable({
2144				accept: ".folder,.document",
2145				addClass: false,
2146				greedy: true,
2147				hoverClass: "droppable",
2148				tolerance: "pointer",
2149				drop: function (event, ui) {
2150					treeContainer.find(".droppable").removeClass("droppable");
2151					monitorContainer.removeClass("droppable");
2152					event.stopPropagation();
2153					clearTimeout(dragTimeout);
2154					if (ui) {
2155						dropElement(ui.draggable, $(this).closest(".folder"));
2156					}
2157				},
2158				over: function (event, ui) {
2159					event.stopPropagation();
2160					var newParent = $(this).closest(".folder");
2161					if (!newParent.hasClass("extended")) {
2162						dragTimeout = window.setTimeout(function () {
2163							toggleChildren(newParent.attr("data-dokid"));
2164						}, 500);
2165					}
2166				},
2167				out: function (event, ui) {
2168					event.stopPropagation();
2169					clearTimeout(dragTimeout);
2170					dragTimeout = null;
2171				}
2172			});
2173			// autoexpand
2174			if (($.inArray(parseInt(info['id'], 10), options.openFolders) > -1)) {
2175				// in geöffneten ordner
2176				toggleChildren(info['id']);
2177			} else if (expandedFolders.length > 0) {
2178				// in geöffnetem parentordner
2179				$.each(expandedFolders, function (index, dokid) {
2180					if (elem.parents(".folder[data-dokid=" + dokid + "]").length > 0) {
2181						toggleChildren(info['id']);
2182						return false;
2183					}
2184				});
2185			}
2186		});
2187	}
2188
2189	function dropElement(elem, newParent, beforeElem) {
2190		if (options.readonly) return;
2191		var checkFreigabe = freigabe[elem.attr("data-freigabe")] >= freigabe[newParent.attr("data-freigabe")];
2192		var checkMailgruppe = newParent.attr("data-freigabe") != "mailgruppe" || elem.attr("data-freigabe") != "mailgruppe" || newParent.attr("data-mailgruppe") == elem.attr("data-mailgruppe");
2193		if (!checkFreigabe || !checkMailgruppe) {
2194			var dialog = new kwDialog();
2195			if (!checkFreigabe) {
2196				dialog.setHtml(wort.get("dialogFreigabeAendern"));
2197			} else if (!checkMailgruppe) {
2198				dialog.setHtml(wort.get("dialogMailgruppeAendern"));
2199			}
2200			dialog.show();
2201			$("#kwDialog").find("a.button").first().on("click", function (event) {
2202				event.preventDefault();
2203				dropElementOk(elem, newParent, beforeElem);
2204				dialog.hide();
2205			});
2206			$("#kwDialog").find("a.button").last().on("click", function (event) {
2207				event.preventDefault();
2208				dialog.hide();
2209			});
2210		} else {
2211			dropElementOk(elem, newParent, beforeElem);
2212		}
2213		elem.css({
2214			left: "",
2215			top: ""
2216		});
2217	}
2218
2219	function dropElementOk(elem, newParent, beforeElem) {
2220		if (options.readonly) return;
2221		var oldParent = elem.closest(".children");
2222		newParent.attr("data-parent", "true");
2223		if (!newParent.hasClass("extended")) toggleChildren(newParent.attr("data-dokid"));
2224		if (beforeElem !== undefined) {
2225			beforeElem.before(elem);
2226		} else {
2227			newParent.find("> .children").append(elem);
2228		}
2229		if (oldParent.children().length == 0) {
2230			oldParent.closest(".folder").removeAttr("data-parent");
2231		}
2232		positionUpdated(elem, oldParent.closest(".folder").attr("data-dokid"));
2233	}
2234
2235	function toggleChildren(folderid) {
2236		var folder = getTreeElem(folderid, true);
2237		if (folder.hasClass("loading") || folder.attr("data-parent") != "true") return;
2238		folder.toggleClass("extended");
2239		var index = $.inArray(parseInt(folderid, 10), options.openFolders);
2240		if (folder.hasClass("extended") && index === -1) {
2241			options.openFolders.push(parseInt(folderid, 10));
2242		} else if (!folder.hasClass("extended") && index > -1) {
2243			options.openFolders.splice(index, 1);
2244		}
2245		if (folder.hasClass("extended") && folder.find("> div.children").children().length == 0) createChildren(folderid);
2246	}
2247
2248	function handOver(dokid, isFolder) {
2249		var dialog = new kwDialog(500, 250);
2250		dialog.show();
2251		$.ajax({
2252			url: '/_kirchenweb/ajaxFormSetData.php',
2253			method: "POST",
2254			data: {
2255				objtyp: isFolder ? "dokumentordner" : "dokument",
2256				id: dokid,
2257				f: 'getDialogHandOver'
2258			},
2259			success: function (data) {
2260				if (data.substr(0, 2) == "OK") {
2261					dialog.setHtml(data.substr(2));
2262					dialog.hide();
2263					dialog.show();
2264					initUebergabe();
2265					$("#personText").focus().select();
2266					$("#kwDialog .buttons #uebergabeNein").first().on("click", function (event) {
2267						event.preventDefault();
2268						dialog.hide();
2269					});
2270					$("#kwDialog .buttons #uebergabeJa").last().on("click", function (event) {
2271						event.preventDefault();
2272						if ($(this).hasClass("ein")) {
2273							$(this).removeClass("ein");
2274							$("#personText").attr("disabled", "disabled");
2275							var pnummer = $("#uebergabePnummer").val();
2276							handOverOk(dokid, isFolder, pnummer, dialog);
2277						}
2278					});
2279				} else {
2280					kwMitteilung(data);
2281				}
2282			},
2283			error: function () {
2284				kwMitteilung(wort.get("fehlerAufgetreten"));
2285				$("#personText").removeAttr("disabled");
2286			}
2287		});
2288	}
2289
2290	function handOverOk(dokid, isFolder, targetPnummer, dialog) {
2291		$.ajax({
2292			url: '/_kirchenweb/ajaxFormSetData.php',
2293			method: "POST",
2294			data: {
2295				objtyp: isFolder ? 'dokumentordner' : 'dokument',
2296				id: dokid,
2297				f: 'handOverAjax',
2298				v: JSON.stringify({
2299					pnummer: targetPnummer,
2300					rekursiv: $("input#recursiveHandover").val() == "Y"
2301				})
2302			},
2303			success: function (data) {
2304				$("#personText").removeAttr("disabled");
2305				if (data.substr(0, 2) == "OK") {
2306					dialog.hide();
2307					var elem = getTreeElem(dokid, isFolder);
2308					var parentId = elem.parents(".folder").first().attr("data-dokid");
2309					elem.remove();
2310					createChildren(parentId);
2311				} else {
2312					kwMitteilung(data);
2313					$("#personText").removeAttr("disabled");
2314				}
2315			},
2316			error: function () {
2317				kwMitteilung(wort.get("fehlerAufgetreten"));
2318				$("#personText").removeAttr("disabled");
2319			}
2320		});
2321	}
2322
2323	// übergabe
2324	var objKwTextvorschlagU = "";
2325
2326	function kwTextvorschlagU() {
2327		this.getData = function () {
2328			var obj = this;
2329			$("#uebergabeListePersonen > li").each(function () {
2330				obj.arrData[obj.arrData.length] = $(this).html();
2331			});
2332		}
2333		this.getVorschlag = function () {
2334			var ret = "";
2335			var k = 0;
2336			for (i = 0; i < this.arrData.length; ++i) {
2337				if (this.arrData[i].toLowerCase().indexOf(this.strText.toLowerCase()) >= 0) {
2338					ret += "<li><a id=\"" + this.id + "_" + k + "\" href=\"\">" + this.arrData[i] + "</a></li>";
2339					++k;
2340				}
2341			}
2342			this.pos = -1;
2343			this.anz = k;
2344			return ret;
2345		}
2346	}
2347
2348	function initUebergabe() {
2349		// inhalt löschen, farbe setzten
2350		// bind event
2351		$("#personText").on("keyup", function (event) {
2352			$("#uebergabeJa").removeClass("ein").addClass("aus");
2353			$("#uebergabePnummer").val("");
2354			// key ENTER
2355			if (event.keyCode == "13") checkUebergabe();
2356		});
2357		// textvorschlag init
2358		kwTextvorschlagU.prototype = new kwTextvorschlag("personText", {keinElementGefunden: wort.get("keinePersonGefunden")});
2359		objKwTextvorschlagU = new kwTextvorschlagU();
2360		objKwTextvorschlagU.setActionClick(checkUebergabe);
2361		objKwTextvorschlagU.init();
2362	}
2363
2364	function checkUebergabe() {
2365		var ret = false;
2366		var str = $("#personText").val();
2367		for (i = 0; i < objKwTextvorschlagU.arrData.length; ++i) {
2368			if (objKwTextvorschlagU.arrData[i].toLowerCase() == str.toLowerCase()) {
2369				ret = true;
2370				break;
2371			}
2372		}
2373		if (ret) {
2374			$("#uebergabeJa").removeClass("aus").addClass("ein");
2375			var pnummer = $("#uebergabeListePersonen li[data-name='" + str + "']").attr("data-pnummer");
2376			$("#uebergabePnummer").val(pnummer)
2377		} else {
2378			$("#uebergabeJa").removeClass("ein").addClass("aus");
2379			$("#uebergabePnummer").val("");
2380		}
2381	}
2382
2383	function getTreeElem(dokid, isFolder) {
2384		var selector = (isFolder ? ".folder" : '.document') + "[data-dokid=" + dokid + "]";
2385		return treeContainer.find(selector);
2386	}
2387
2388	/* CONTEXTMENU */
2389	var contextmenu = $('<div id="contextMenu" />');
2390	$.fn.kwFileTreeContextMenu = function (top, left, small) {
2391		showContextMenu($(this).closest("div.folder, div.document"), top, left, small);
2392		return false;
2393	};
2394
2395	function removeContextMenu() {
2396		contextmenu.remove();
2397		contextmenu.html("");
2398		$("div.contextMenuActive").removeClass("contextMenuActive");
2399		$(document).off(".contextMenu");
2400	}
2401
2402	function showContextMenu(obj, top, left, smallMenu) {
2403		removeContextMenu();
2404		$(document).on("contextmenu.contextMenu click.contextMenu keydown.contextMenu", function (event) {
2405			if (event.target.closest(".name") !== obj.find(".name")[0]) removeContextMenu();
2406		});
2407		$.each(getContextMenuItems(obj, smallMenu), function (index, item) {
2408			var contextItem = $("<div>" + item['text'] + "</div>");
2409			var callback = item['callback'];
2410			contextItem.on("click", function (event) {
2411				event.stopPropagation();
2412				event.preventDefault();
2413				removeContextMenu();
2414				callback(item['arguments']);
2415			});
2416			contextmenu.append(contextItem);
2417		});
2418		treeContainer.find(".treecontainer").append(contextmenu);
2419		contextmenu.css({
2420			top: top,
2421			left: left
2422		});
2423		$(obj).addClass("contextMenuActive");
2424		// warten bis element hinzugefügt und opacity gesetzt ist
2425		window.getComputedStyle(contextmenu.get(0)).opacity;
2426		// menu einblenden
2427		contextmenu.addClass("active");
2428	}
2429
2430	function getContextMenuItems(obj, smallMenu) {
2431		var items = [];
2432		if (obj.hasClass("document")) items.push({
2433			text: wort.get("baumMenuHerunterladen"),
2434			callback: download,
2435			arguments: parseInt(obj.attr("data-dokid"), 10)
2436		});
2437		if (obj.hasClass("folder") && obj.attr("data-parent") === "true") items.push({
2438			text: wort.get("baumMenuHerunterladen"),
2439			callback: downloadZip,
2440			arguments: parseInt(obj.attr("data-dokid"), 10)
2441		});
2442		if (obj.attr("data-noshare") !== "true") items.push({
2443			text: wort.get("baumMenuLinkKopieren"),
2444			callback: linkKopieren,
2445			arguments: obj
2446		});
2447		if (smallMenu !== true && !options.readonly && obj.hasClass("folder") && !obj.attr("data-noadd")) {
2448			items.push({
2449				text: wort.get("baumMenuNeuerOrdner"),
2450				callback: neuerOrdner,
2451				arguments: parseInt(obj.attr("data-dokid"), 10)
2452			});
2453			items.push({
2454				text: wort.get("baumMenuNeuesDok"),
2455				callback: neuesDokument,
2456				arguments: parseInt(obj.attr("data-dokid"), 10)
2457			});
2458		}
2459		if (smallMenu !== true && obj.hasClass("folder") && obj.attr("data-parent") === "true") {
2460			items.push({
2461				text: wort.get("baumMenuInhaltAnzeigen"),
2462				callback: inhaltAnzeigen,
2463				arguments: parseInt(obj.attr("data-dokid"), 10)
2464			});
2465			items.push({
2466				text: wort.get("baumMenuInhaltAusblenden"),
2467				callback: inhaltAusblenden,
2468				arguments: parseInt(obj.attr("data-dokid"), 10)
2469			});
2470		}
2471		if (smallMenu !== true && !options.readonly && obj.hasClass("document") && obj.attr("data-owner") === "true") {
2472			items.push({
2473				text: wort.get("baumMenuErsetzen"),
2474				callback: elementErsetzen,
2475				arguments: parseInt(obj.attr("data-dokid"), 10)
2476			});
2477		}
2478		if (smallMenu !== true && !options.readonly && obj.attr("data-owner") === "true" && obj.attr("data-nomod") !== "true") {
2479			items.push({
2480				text: wort.get("baumMenuBearbeiten"),
2481				callback: elementBearbeiten,
2482				arguments: {
2483					dokid: parseInt(obj.attr("data-dokid"), 10),
2484					isFolder: obj.hasClass("folder")
2485				}
2486			});
2487			items.push({
2488				text: wort.get("baumMenuUmbenennen"),
2489				callback: elementUmbenennen,
2490				arguments: {
2491					dokid: parseInt(obj.attr("data-dokid"), 10),
2492					isFolder: obj.hasClass("folder")
2493				}
2494			});
2495			items.push({
2496				text: wort.get("baumMenuLoeschen"),
2497				callback: elementLoeschen,
2498				arguments: obj
2499			});
2500		}
2501		if (smallMenu !== true && !options.readonly && obj.hasClass("folder") && obj.attr("data-owner") === "true" && obj.attr("data-root") !== "true") {
2502			items.push({
2503				text: wort.get("baumMenuLeeren"),
2504				callback: elementLeeren,
2505				arguments: obj
2506			});
2507		}
2508		if (smallMenu !== true && !options.readonly && obj.attr("data-owner") != "true" && obj.attr("data-draggable") === "true" && obj.attr("data-nomod") !== "true") {
2509			items.push({
2510				text: wort.get("baumMenuLoeschen"),
2511				callback: elementLoeschen,
2512				arguments: obj
2513			});
2514		}
2515		if (smallMenu !== true && !options.readonly && obj.hasClass("folder") && obj.attr("data-owner") != "true" && obj.attr("data-draggable") === "true") {
2516			items.push({
2517				text: wort.get("baumMenuLeeren"),
2518				callback: elementLeeren,
2519				arguments: obj
2520			});
2521		}
2522		if (obj.attr("data-setActive") === "true") {
2523			items.push({
2524				text: wort.get("baumMenuAnzeigen"),
2525				callback: elementAktivSetzen,
2526				arguments: obj
2527			})
2528		}
2529		return items;
2530	}
2531
2532	function inhaltAnzeigen(dokid) {
2533		if (expandedFolders.indexOf(dokid) < 0) expandedFolders.push(dokid);
2534		getTreeElem(dokid, true).find(".folder").addBack().not(".extended").each(function (index, elem) {
2535			toggleChildren(elem.getAttribute("data-dokid"));
2536		});
2537	}
2538
2539	function inhaltAusblenden(dokid) {
2540		getTreeElem(dokid, true).find(".folder").addBack().filter(".extended").each(function (index, elem) {
2541			toggleChildren(elem.getAttribute("data-dokid"));
2542		});
2543	}
2544
2545	function elementAktivSetzen(elem) {
2546		treeContainer.kwFileTree.setActive(elem.attr("data-dokid"), elem.hasClass("folder"));
2547	}
2548
2549	function neuesDokument(dokid) {
2550		var newId = --uploadCounter;
2551		// dummy-upload to get selected file
2552		$('<input type="file" multiple />').fileupload({
2553			url: '/_kirchenweb/dokverwaltung/ajax/dokNeu.php',
2554			type: 'POST',
2555			autoUpload: false,
2556			dataType: "json",
2557			dropZone: null,
2558			maxFileSize: maxFileSize
2559		})
2560			.on("fileuploadadd", function (event, data) {
2561				// file hochladen
2562				neuesDokumentSelected(dokid, data.files[0]);
2563			})
2564			.click();
2565	}
2566
2567	function neuesDokumentSelected(parentId, file) {
2568		var titel = file.name;
2569		// check filename to either contain or not begin with a dot
2570		if (titel.lastIndexOf('.') > 0) {
2571			titel = titel.substr(0, titel.lastIndexOf('.'));
2572		}
2573		$.ajax({
2574			url: "/_kirchenweb/dokverwaltung/ajax/dokNeu.php",
2575			data: {
2576				parentIndex: parentId,
2577				titel: titel
2578			},
2579
2580			success: function (data) {
2581				if (data.substr(0, 2) == "OK") {
2582					var dokid = data.substr(2);
2583					createDok(dokid, parentId, true);
2584					uploadFile(dokid, file, true, false);
2585				} else {
2586					kwMitteilung(data.substr(2));
2587				}
2588			}
2589		});
2590	}
2591
2592	function elementErsetzen(dokid) {
2593		// dummy-upload to get selected file
2594		$('<input type="file" />').fileupload({
2595			url: '/_kirchenweb/dokverwaltung/ajax/dokNeu.php',
2596			type: 'POST',
2597			autoUpload: false,
2598			dataType: "json",
2599			dropZone: null,
2600			maxFileSize: maxFileSize
2601		})
2602			.on("fileuploadadd", function (event, data) {
2603				// file hochladen
2604				uploadFile(dokid, data.files[0], true, false);
2605			})
2606			.click();
2607	}
2608
2609	function initFolderMonitorClicks() {
2610		var dokid = monitorContainer.find(".dokverwaltung .info").attr("data-dokid");
2611		// löschen
2612		monitorContainer.find("a.loeschen").on("click", function (event) {
2613			event.preventDefault();
2614			var elem = getTreeElem(dokid, true);
2615			elementLoeschen(elem);
2616		});
2617		// link kopieren
2618		monitorContainer.find("a.doklinkcopy").on("click", function (event) {
2619			event.preventDefault();
2620			if (kwCopyToClipboard(this.href)) {
2621				kwMitteilung(wort.get("mitteilungLinkWurdeKopiert"));
2622			} else {
2623				kwMitteilung(wort.get("mitteilungLinkNichtKopiert"));
2624			}
2625		});
2626		// neuer ordner
2627		monitorContainer.find("a.neuOrdner").on("click", function (event) {
2628			event.preventDefault();
2629			neuerOrdner(dokid);
2630		});
2631		// neues dokument
2632		monitorContainer.find("a.neuDok").on("click", function (event) {
2633			event.preventDefault();
2634			neuesDokument(dokid);
2635		})
2636		// monitor übertragen
2637		monitorContainer.find("a.uebertragen").on("click", function (event) {
2638			event.preventDefault();
2639			handOver(dokid, true);
2640		});
2641		// sortierung
2642		monitorContainer.find(".sortierung a").on("click", function (event) {
2643			event.preventDefault();
2644			setRadiobox(this, this.getAttribute("data-sort"));
2645			checkUploadFolderForm(true);
2646		});
2647	}
2648
2649	function initFolderEdit() {
2650		if (monitorContainer.find("form").length == 0) return;
2651		// initialer check
2652		checkUploadFolderForm(false);
2653		// änderungs-events
2654		monitorContainer.find("input,textarea").on("keyup paste", function () {
2655			checkUploadFolderForm(true);
2656		});
2657		monitorContainer.find("select").on("change", function () {
2658			checkUploadFolderForm(true);
2659		});
2660		// check on submit
2661		monitorContainer.find("form.folder").on("submit", function (event) {
2662			if (!checkUploadFolderForm(false)) return false;
2663			monitorContainer.addClass("saving").removeClass("waiting");
2664			var dokid = $(this).find("input[name=dokid]").val();
2665			$.ajax({
2666				url: $(this).attr("action"),
2667				type: $(this).attr("method"),
2668				data: $(this).serialize(),
2669				success: function () {
2670					monitorContainer.removeClass("saving");
2671					loadFolderInfo([dokid]);
2672					createChildren(dokid);
2673					options.markedId.folder = null;
2674					createChildren(dokid);
2675					kwMitteilung(wort.get("mitteilungDatenGespeichertAuto"));
2676				}
2677			});
2678			return false;
2679		});
2680	}
2681
2682	function initFileMonitorClicks() {
2683		var dokid = monitorContainer.find(".dokverwaltung .info").attr("data-dokid");
2684		// löschen
2685		monitorContainer.find("a.loeschen").on("click", function (event) {
2686			event.preventDefault();
2687			var elem = getTreeElem(dokid, false);
2688			elementLoeschen(elem);
2689		});
2690		// link kopieren
2691		monitorContainer.find("a.doklinkcopy").on("click", function (event) {
2692			event.preventDefault();
2693			if (kwCopyToClipboard(this.href)) {
2694				kwMitteilung(wort.get("mitteilungLinkWurdeKopiert"));
2695			} else {
2696				kwMitteilung(wort.get("mitteilungLinkNichtKopiert"));
2697			}
2698		});
2699		// monitor übertragen
2700		monitorContainer.find("a.uebertragen").on("click", function (event) {
2701			event.preventDefault();
2702			handOver(dokid, false);
2703		});
2704		// dokument ersetzen
2705		monitorContainer.find("a.dokument").on("click", function (event) {
2706			event.preventDefault();
2707			elementErsetzen(dokid)
2708		});
2709	}
2710
2711	function initFileEdit() {
2712		if (monitorContainer.find("form").length == 0) return;
2713		checkUploadDokForm(false);
2714		monitorContainer.find("input,textarea").on("keyup paste", function (event) {
2715			checkUploadDokForm(true);
2716		});
2717		monitorContainer.find("select").on("change", function (event) {
2718			checkUploadDokForm(true);
2719		});
2720		monitorContainer.find("form.dokument").on("submit", function (event) {
2721			if (checkUploadDokForm(false) === false) return false;
2722			monitorContainer.addClass("saving").removeClass("waiting");
2723			var parentIndex = $(this).find("input[name=parentIndex]").val();
2724			$.ajax({
2725				url: $(this).attr("action"),
2726				type: $(this).attr("method"),
2727				data: $(this).serialize(),
2728				success: function () {
2729					kwMitteilung(wort.get("mitteilungDatenGespeichertAuto"));
2730					monitorContainer.removeClass("saving");
2731					options.markedId.dokument = null;
2732					createChildren(parentIndex);
2733				}
2734			});
2735			return false;
2736		});
2737	}
2738
2739	function checkUploadFolderForm(setTimeout) {
2740		clearTimeout(folderEditTimer);
2741		var status = true;
2742		var parentId = monitorContainer.find("input[name=parentIndex]").val()
2743		var parent = getTreeElem(parentId, true);
2744		var freigabeChild = freigabe[monitorContainer.find("select[name=freigabe]").val()];
2745		var freigabeParent = freigabe[parent.attr("data-freigabe")];
2746		if (monitorContainer.find("input[name=name]").val() == "") {
2747			monitorContainer.find("input[name=name]").addClass("error");
2748			status = false;
2749		} else {
2750			monitorContainer.find("input[name=name]").removeClass("error");
2751		}
2752		if (monitorContainer.find("select[name=freigabe]").val() != "mailgruppe") {
2753			monitorContainer.find("select[name=mailgruppe]").prop("disabled", true);
2754		} else {
2755			monitorContainer.find("select[name=mailgruppe]").prop("disabled", false);
2756		}
2757		if (freigabeChild < freigabeParent) {
2758			monitorContainer.find("select[name=freigabe]").addClass("error");
2759			status = false;
2760		} else {
2761			monitorContainer.find("select[name=freigabe]").removeClass("error");
2762		}
2763		if (freigabeChild == freigabe["mailgruppe"] && freigabeParent == freigabe["mailgruppe"] && parent.attr("data-mailgruppe") != monitorContainer.find("select[name=mailgruppe],input[name=mailgruppe]").val()) {
2764			monitorContainer.find("select[name=mailgruppe]").addClass("error");
2765			status = false;
2766		} else {
2767			monitorContainer.find("select[name=mailgruppe]").removeClass("error");
2768		}
2769		if (status && setTimeout) {
2770			monitorContainer.addClass("waiting");
2771			folderEditTimer = window.setTimeout(function () {
2772				monitorContainer.find("form").trigger("submit");
2773			}, options.saveTimeout);
2774		}
2775		return status;
2776	}
2777
2778	function checkUploadDokForm(setTimeout) {
2779		clearTimeout(dokEditTimer);
2780		var status = true;
2781		var parentId = monitorContainer.find("input[name=parentIndex]").val();
2782		var parent = getTreeElem(parentId, true);
2783		var freigabeDok = freigabe[monitorContainer.find("select[name=freigabe]").val()];
2784		var freigabeFolder = freigabe[parent.attr("data-freigabe")];
2785		if (monitorContainer.find("input[name=titel]").val() == "") {
2786			monitorContainer.find("input[name=titel]").addClass("error");
2787			status = false;
2788		} else {
2789			monitorContainer.find("input[name=titel]").removeClass("error");
2790		}
2791		if (monitorContainer.find("select[name=freigabe]").val() != "mailgruppe") {
2792			monitorContainer.find("select[name=mailgruppe]").prop("disabled", true);
2793		} else {
2794			monitorContainer.find("select[name=mailgruppe]").prop("disabled", false);
2795		}
2796		if (freigabeDok < freigabeFolder) {
2797			monitorContainer.find("select[name=freigabe]").addClass("error");
2798			status = false;
2799		} else {
2800			monitorContainer.find("select[name=freigabe]").removeClass("error");
2801		}
2802		if (freigabeDok == freigabe["mailgruppe"] && freigabeFolder == freigabe["mailgruppe"] && parent.attr("data-mailgruppe") != monitorContainer.find("input[name=mailgruppe],select[name=mailgruppe]").val()) {
2803			monitorContainer.find("select[name=mailgruppe]").addClass("error");
2804			status = false;
2805		} else {
2806			monitorContainer.find("select[name=mailgruppe]").removeClass("error");
2807		}
2808		if (status && setTimeout) {
2809			monitorContainer.addClass("waiting");
2810			dokEditTimer = window.setTimeout(function () {
2811				monitorContainer.find("form.dokument").trigger("submit");
2812			}, options.saveTimeout);
2813		}
2814		return status;
2815	}
2816
2817	function neuerOrdner(dokid) {
2818		var elem = getTreeElem(dokid, true);
2819		elem.attr("data-parent", "true");
2820		if (!elem.hasClass("extended")) toggleChildren(dokid);
2821		createFolder(-1, dokid);
2822		var newElem = getTreeElem(-1, true);
2823		newElem.removeClass("loading");
2824		newElem.find("> div.name .nameSpan").append('<input type="text" maxlength="250" placeholder="' + wort.get("name") + '" value="' + wort.get("ordnerNeu") + '" />');
2825		newElem.find("> div.name .nameSpan input").on("blur", function () {
2826			neuerOrdnerSpeichern(dokid);
2827		});
2828		newElem.find("> div.name .nameSpan input").on("keyup", function (event) {
2829			if (event.keyCode == 13) neuerOrdnerSpeichern(dokid);
2830			if (event.keyCode == 27) neuerOrdnerAbbrechen();
2831		});
2832		newElem.find("> div.name .nameSpan input").focus().select();
2833	}
2834
2835	function neuerOrdnerAbbrechen() {
2836		var newElem = getTreeElem(-1, true);
2837		if (newElem.siblings().length == 0) {
2838			newElem.parents(".folder").first().removeAttr("data-parent");
2839		}
2840		newElem.remove();
2841	}
2842
2843	function neuerOrdnerSpeichern(parentIndex) {
2844		var newElem = getTreeElem(-1, true);
2845		var newFolderInput = newElem.find("> div.name input");
2846		var newFolderSpan = newElem.find("> div.name .nameSpan");
2847		if (newFolderInput.val() == "") newFolderInput.val(wort.get("ordnerNeu"));
2848		newFolderSpan.text(newFolderInput.val());
2849		var myArguments = {
2850			parent: parentIndex,
2851			text: newFolderSpan.text()
2852		}
2853		$.ajax({
2854			url: "/_kirchenweb/ajaxFormSetData.php",
2855			method: "POST",
2856			data: {
2857				objtyp: 'dokumentordner',
2858				f: "neuerOrdner",
2859				v: JSON.stringify(myArguments)
2860			},
2861			success: function (data) {
2862				if (data.substr(0, 2) == "OK") {
2863					var elemente = JSON.parse(data.substr(2));
2864					folderid = elemente["ordner"][0]['id'];
2865					newElem.attr("data-dokid", folderid);
2866					insertFolderInfo(elemente["ordner"]);
2867				}
2868			}
2869		})
2870	}
2871
2872	function download(dokid) {
2873		window.location.href = "/dok/" + dokid;
2874	}
2875
2876	function downloadZip(dokid) {
2877		window.open("/_kirchenweb/?page=manageDocumentStorageZipFolder&id=" + dokid, "_blank");
2878	}
2879
2880	function linkKopieren(elem) {
2881		// elem.find("> .name .doklink" changed (01.09.2020 sj)
2882		if (kwCopyToClipboard(elem.find(".doklink:first").get(0).href)) {
2883			kwMitteilung(wort.get("mitteilungLinkWurdeKopiert"));
2884		} else {
2885			kwMitteilung(wort.get("mitteilungLinkNichtKopiert"));
2886		}
2887	}
2888
2889	function elementBearbeiten(options) {
2890		setMonitor(options.dokid, options.isFolder, true);
2891	}
2892
2893	function elementUmbenennen(options) {
2894		var dokid = options.dokid;
2895		var elem = getTreeElem(dokid, options.isFolder);
2896		var elemSpan = elem.find("> .name .nameSpan");
2897		var text = elemSpan.text();
2898		elemSpan.text("");
2899		var $input = $('<input type="text" class="rename" maxlength="250" placeholder="' + wort.get("name") + '" value="' + text + '" />').appendTo(elemSpan);
2900		$input.focus().select();
2901		$("body").on("click.kwRename", function (event) {
2902			var target = $(event.target);
2903			if (target.is("input") && target.hasClass("rename")) {
2904				// do nothing
2905			} else {
2906				$("body").off("click.kwRename");
2907				elementUmbenennenSpeichern(elem, text);
2908			}
2909		});
2910		$input.on("keydown", function (event) {
2911			if (event.keyCode == 13 || event.keyCode == 9) {
2912				// enter or tab
2913				$("body").off("click.kwRename");
2914				elementUmbenennenSpeichern(elem, text);
2915			} else if (event.keyCode == 27) {
2916				// esc
2917				$("body").off("click.kwRename");
2918				elementUmbenennenAbbrechen(elem);
2919			}
2920		});
2921
2922	}
2923
2924	function elementUmbenennenSpeichern(elem, oldText) {
2925		var $elemInput = $(elem).find("> div.name input");
2926		var $elemSpan = $(elem).find("> div.name .nameSpan");
2927		var text = $elemInput.val();
2928		$elemInput.remove();
2929		if (text == "") {
2930			elementUmbenennenAbbrechen(elem);
2931			return;
2932		}
2933		elem.addClass("loading");
2934		$elemSpan.text(text);
2935		$.ajax({
2936			url: "/_kirchenweb/ajaxFormSetData.php",
2937			method: "POST",
2938			data: {
2939				objtyp: elem.hasClass("folder") ? 'dokumentordner' : 'dokument',
2940				id: elem.attr("data-dokid"),
2941				f: 'renameTreeNode',
2942				v: text
2943			},
2944			success: function (data) {
2945				elem.removeClass("loading");
2946				if (data.substr(0, 2) == "OK") {
2947					var monitorInfo = monitorContainer.find(".info[data-dokid]");
2948					if (monitorInfo.attr("data-dokid") == elem.attr("data-dokid")) {
2949						if (elem.hasClass("folder") && monitorInfo.hasClass("folder")) {
2950							setMonitor(elem.attr("data-dokid"), true);
2951						} else if (elem.hasClass("document") && monitorInfo.hasClass("dokument")) {
2952							setMonitor(elem.attr("data-dokid"), false);
2953						}
2954					}
2955				} else {
2956					$elemSpan.text(oldText);
2957				}
2958			},
2959			error: function () {
2960				kwMitteilung(wort.get("fehlerAufgetreten"));
2961				elem.removeClass("loading");
2962				$elemSpan.text(oldText);
2963			}
2964		})
2965	}
2966
2967	function elementUmbenennenAbbrechen(elem) {
2968		if (elem.hasClass("folder")) loadFolderInfo([elem.attr("data-dokid")]);
2969		else loadDokInfo([elem.attr("data-dokid")]);
2970	}
2971
2972	function elementLeeren(elem) {
2973		elementLoeschen(elem, true)
2974	}
2975
2976	function elementLoeschen(elem, emptyOnly) {
2977		emptyOnly = emptyOnly || false;
2978		var dialog = new kwDialog(450, 350, "warnung");
2979
2980		if(emptyOnly){
2981			if (elem.attr("data-owner") == "true") {
2982				dialog.setHtml(wort.get("dialogElementInhaltLeeren"));
2983			} else {
2984				dialog.setHtml(wort.get("dialogElementInhaltLeerenAdmin"));
2985			}
2986		} else if (elem.attr("data-parent") == "true") {
2987			if (elem.attr("data-owner") == "true") {
2988				dialog.setHtml(wort.get("dialogElementInhaltLoeschen"));
2989			} else {
2990				dialog.setHtml(wort.get("dialogElementInhaltLoeschenAdmin"));
2991			}
2992		} else {
2993			if (elem.attr("data-owner") == "true") {
2994				dialog.setHtml(wort.get("dialogElementLoeschen"));
2995			} else {
2996				dialog.setHtml(wort.get("dialogElementLoeschenAdmin"));
2997			}
2998		}
2999		var request = $.ajax({
3000			url: "/_kirchenweb/ajaxFormSetData.php",
3001			data: {
3002				objtyp: (elem.hasClass("folder")) ? "dokumentordner" : "dokument",
3003				id: elem.attr("data-dokid"),
3004				f: "getVerwendung"
3005			},
3006			success: function (data) {
3007				if (data.substr(0, 2) == "OK") {
3008					$("#kwDialog").find(".verwendet").html(data.substr(2));
3009				} else {
3010					$("#kwDialog").find(".verwendet").html(wort.get("fehlerLadenVerwendung"));
3011				}
3012			},
3013			failure: function (data) {
3014				$("#kwDialog").find(".verwendet").html(wort.get("fehlerLadenVerwendung"));
3015			}
3016		});
3017		dialog.show();
3018		var text = elem.find("> .name .nameSpan").text();
3019		if (text.length > 28) {
3020			text = text.substr(0, 25) + "...";
3021		}
3022		$("#kwDialog").find("span.elemName").text(text);
3023		$("#kwDialog").find("a.button").first().on("click", function (event) {
3024			event.preventDefault();
3025			elementLoeschenOk(elem, emptyOnly);
3026			dialog.hide();
3027			request.abort();
3028		});
3029		$("#kwDialog").find("a.button").last().on("click", function (event) {
3030			event.preventDefault();
3031			dialog.hide();
3032			request.abort();
3033		});
3034	}
3035
3036	function elementLoeschenOk(elem, emptyOnly) {
3037		emptyOnly = emptyOnly || false;
3038		$.ajax({
3039			url: "/_kirchenweb/ajaxFormSetData.php",
3040			method: "POST",
3041			data: {
3042				objtyp: elem.hasClass("folder") ? 'dokumentordner' : 'dokument',
3043				f: emptyOnly ? "emptyTreeNode" : "deleteTreeNode",
3044				id: elem.attr("data-dokid")
3045			},
3046			success: function (data) {
3047				if (data.substr(0, 2) == "OK" && JSON.parse(data.substr(2)) == true) {
3048					if (monitorContainer.find("form input[name=dokid]").val() == elem.attr("data-dokid")) {
3049						monitorContainer.find("div.content").html(wort.get("infoPerKlick"));
3050					}
3051					if (!emptyOnly && elem.siblings().length == 0) {
3052						elem.parents(".folder").first().removeAttr("data-parent");
3053					}
3054					if(emptyOnly) {
3055						elem.find("> .children > *").remove();
3056						loadFolderInfo([elem.attr("data-dokid")]);
3057					}else{
3058						elem.remove();
3059					}
3060				} else if (data.substr(0, 2) == "OK") {
3061					kwMitteilung(wort.get("keinZugriff"));
3062				}
3063			}
3064		});
3065	}
3066}(jQuery));
3067
3068
3069(function ($) {
3070	/**
3071	 * Returns jQuery object from cache
3072	 *
3073	 * @param selector
3074	 * @param reload
3075	 * @returns jQuery object
3076	 */
3077	$.cachedSelector = function (selector, reload) {
3078		if (typeof reload === 'undefined') {
3079			reload = false;
3080		}
3081		if (undefined === $.selectorCache) {
3082			$.selectorCache = {};
3083		}
3084
3085		if (undefined === $.selectorCache[selector] || reload) {
3086			$.selectorCache[selector] = $(selector);
3087		}
3088
3089		return $.selectorCache[selector];
3090	};
3091
3092	/**
3093	 * bindWithDelay jQuery plugin
3094	 * @author: Brian Grinstead
3095	 * @license: MIT http://www.opensource.org/licenses/mit-license.php
3096	 *
3097	 * @example .onDelay( eventType, [ eventData ], handler(eventObject), timeout, throttle )
3098	 * @example $("#foo").onDelay('click', function(e) { }, 100);
3099	 * @example $(window).onDelay('resize', { optional: 'eventData' }, callback, 1000);
3100	 * @example $(window).onDelay('resize', callback, 1000, true);
3101	 */
3102	$.fn.onDelay = function (events, selector, data, handler, timeout, throttle) {
3103		// (evt, handler, timeout)
3104		if ($.isFunction(selector)) {
3105			throttle = handler;
3106			timeout = data;
3107			handler = selector;
3108			data = undefined;
3109			selector = undefined;
3110		}
3111		// (evt, selector, handler, timeout) OR (evt, data, handler, timeout)
3112		else if ($.isFunction(data)) {
3113			throttle = timeout;
3114			timeout = handler;
3115			handler = data;
3116			data = undefined;
3117
3118			// (evt, data, handler, timeout)
3119			if (typeof selector !== "string") {
3120				data = selector;
3121				selector = undefined;
3122			}
3123		}
3124
3125		// Allow delayed function to be removed with handler in unbind function
3126		handler.guid = handler.guid || ($.guid && $.guid++);
3127
3128		// Bind each separately so that each element has its own delay
3129		return this.each(function () {
3130			var wait = null;
3131
3132			function callback() {
3133				var event = $.extend(true, {}, arguments[0]);
3134				var that = this;
3135				var throttler = function () {
3136					wait = null;
3137					handler.apply(that, [event]);
3138				};
3139
3140				if (!throttle) {
3141					clearTimeout(wait);
3142					wait = null;
3143				}
3144				if (!wait) {
3145					wait = setTimeout(throttler, timeout);
3146				}
3147			}
3148
3149			callback.guid = handler.guid;
3150			$(this).on(events, selector, data, callback);
3151		});
3152	};
3153
3154	/**
3155	 * @returns an inverted set of a preceding jquery filter function
3156	 */
3157	$.fn.invert = function () {
3158		return this.end().not(this);
3159	};
3160
3161	/**
3162	 * Returns content of a data attribute escaped with twigs html_attr
3163	 *
3164	 * @param dataSetName
3165	 * @returns string data
3166	 */
3167	$.fn.dataTwig = function (dataSetName) {
3168		var elem = document.createElement('textarea');
3169		elem.innerHTML = this.data(dataSetName);
3170		return elem.value.replace(/<br\s*[\/]>?\n/gi, "\n");
3171	};
3172
3173	/**
3174	 * Set the caret to the end of the input field when focusing it
3175	 */
3176	$.fn.focusEnd = function () {
3177		this.focus();
3178		if (!this.is(':checkbox')) { // checkboxes don't have a caret
3179			var tmpStr = this.val();
3180			this.val('');
3181			return this.val(tmpStr);
3182		}
3183	};
3184
3185	/**
3186	 * @param castBackwards boolean
3187	 * @param castBackwardsBoundary number of years (in the feature; negative values for past) where the date will still
3188	 * get completed to a 19xx date.
3189	 * Example: today is 2019-03-14 the input year is '21.
3190	 *  - If castBackwards is not set or is set to false all input years get cast to 20xx
3191	 *  - If only castBackwards is set to true, all input dates with year > '19 get cast to 19xx. This is useful for
3192	 *    birthdays which will never be a feature date.
3193	 *  - If castBackwards is set to true and castBackwardsBoundary is set to 1 all input dates with year > '20 ( = '19 + '1)
3194	 *    get cast to 19xx. This is useful for mixed feature/past dates. A reasonable value would be around 5.
3195	 */
3196	$.fn.autocompleteDate = function (castBackwards, castBackwardsBoundary) {
3197		this.on('blur.autocompleteDate keyup.autocompleteDate', function(e) {
3198			if (e.type === 'keyup' && e.which !== KeyCode.ENTER) {
3199				return false;
3200			}
3201
3202			// cleanup and input validation
3203			var input = $(this).val().trim();
3204			input = input.replaceMulti([',', ' ', '-'], ['.', '.', '.']);
3205			if (input.trim() === '' || input.search(/[^\d\.]/) > -1) return;
3206
3207			// prepare working objects
3208			input = input.split('.').map(function(el) {return el.trim()});
3209			var completeDate = new Date();
3210			completeDate.setDate(1);
3211			var now = new Date();
3212
3213			// complete year
3214			if (input.length > 2 && input[2] !== '') {
3215				var year = parseInt(input[2]);
3216				if (year > 1000) {
3217					completeDate.setFullYear(year);
3218				} else if (typeof castBackwards !== 'undefined' && castBackwards && (
3219						(typeof castBackwardsBoundary !== 'undefined' && ((completeDate.getFullYear() % 100) + castBackwardsBoundary) < year)
3220						|| (completeDate.getFullYear() % 100) < year )) {
3221					completeDate.setFullYear(1900 + year);
3222				} else {
3223					completeDate.setFullYear(2000 + year);
3224				}
3225			}
3226
3227			// complete month
3228			// has to be before complaete day so 31.08. wont get casted to 01.08. during months that don't have 31 days (completeDate = now and
3229			// therefore it's maybe a month with only 30 days)
3230			if (input.length > 1 && input[1] !== '') {
3231				completeDate.setMonth(parseInt(input[1]) - 1);
3232			} else if (input.length > 0 && input[0] !== '' && parseInt(input[0]) < now.getDate()) {
3233				completeDate.setMonth(completeDate.getMonth() + 1);
3234			}
3235
3236			// complete day
3237			if (input.length > 0 && input[0] !== '') {
3238				completeDate.setDate(parseInt(input[0]));
3239			} else {
3240				completeDate.setDate(now.getDate());
3241			}
3242
3243			// replace original input
3244			$(this).val(completeDate.toString()).change();
3245		});
3246	};
3247
3248	$.fn.autoCompleteTime = function() {
3249		this.on('blur.autocompleteTime', function() {
3250			var input = $(this).val().trim(),
3251				h = 0,
3252				m = 0;
3253			// standardize input
3254			if(input.search(/:/) > -1){
3255				input = input.split(":").join(".");
3256			}else if(input.search(/,/) > -1){
3257				input = input.split(",").join(".");
3258			}else if(input.search(/ /) > -1){
3259				input = input.split(" ").join(".");
3260			}else if(input.search(/-/) > -1){
3261				input = input.split("-").join(".");
3262			}
3263
3264			// abort: not entered time
3265			if(input === '' || input.search(/[^\d.]/) > -1) return;
3266
3267			var time = input.split(".");
3268
3269			if (time[0].length === 4) {
3270				h = Math.min(23, parseInt(time[0].substr(0, 2), 10));
3271				m = Math.min(59, parseInt(time[0].substr(2, 2), 10));
3272			} else {
3273				// set hour
3274				if (time.length > 0 && time[0].length > 0) {
3275					h = Math.min(23, parseInt(time[0], 10));
3276				}
3277				// set minutes
3278				if (time.length > 1 && time[1].length > 0) {
3279					m = Math.min(59, parseInt(time[1],10));
3280					if (time[1].length === 1 && m < 6) {
3281						m = m * 10;
3282					}
3283				}
3284			}
3285			$(this).val(h.pad(2) + '.' + m.pad(2))
3286		});
3287	};
3288
3289	$.fn.getFullSelector = function() {
3290		return this.get(0).tagName + (this.get(0).id !== '' ? ('#' + this.attr('id')) : '') + (this.get(0).classList.length > 0 ? ('.' + this.get(0).classList.toString().split(' ').join('.')) : '');
3291	};
3292
3293	$.fn.prevInDOM = function(selector) {
3294		var elements = $(selector);
3295		if(elements.index(this) === -1) {
3296			// to get $this and hopefully nothing else in a list we select by th the given selector and tagname#id.classes of $this
3297			// care: if no id (and/or no classes) is set the selector might be way too wide
3298			// probably todo: try to find another way to include ONLY $this in elements (elements have to be in order like in DOM!)
3299			elements = $(selector + ', ' + this.getFullSelector());
3300			if(elements.index(this) === -1) {
3301				return this;
3302			}
3303		}
3304		return $(elements[elements.index(this) - 1]);
3305	};
3306
3307	$.fn.nextInDOM = function(selector) {
3308		// list must contain this, therefore we need to add it to the list 07.04.2019 mha
3309		var elements = $(selector);
3310		if(elements.index(this) === -1) {
3311			// to get $this and hopefully nothing else in a list we select by th the given selector and tagname#id.classes of $this
3312			// care: if no id (and/or no classes) is set the selector might be way too wide
3313			// probably todo: try to find another way to include ONLY $this in elements (elements have to be in order like in DOM!)
3314			elements = $(selector + ', ' + this.getFullSelector());
3315			if(elements.index(this) === -1) {
3316				return this;
3317			}
3318		}
3319		return $(elements[elements.index(this) + 1]);
3320	};
3321
3322	$.fn.tabbableChildren = function(selector) {
3323		if (typeof selector === 'undefined') {
3324			selector = 'a[href]:not([disabled], .disabled, [tabindex=-1]):visible, input:not([disabled], [readonly], [type="hidden"], .disabled, [tabindex=-1]):visible, select:not([disabled], .disabled, [tabindex=-1]):visible, textarea:not([disabled], .disabled, [tabindex=-1]):visible, button:not([disabled], .disabled, [tabindex=-1]):visible, [tabindex=0]:not([disabled], .disabled):visible, [contenteditable]:not([disabled], .disabled, [tabindex=-1]):visible';
3325		}
3326		return this.find(selector);
3327	};
3328
3329	$.fn.nextTabbable = function(selector) {
3330		if (typeof selector === 'undefined') {
3331			selector = 'a[href]:not([disabled], .disabled, [tabindex=-1]):visible, input:not([disabled], [readonly], [type="hidden"], .disabled, [tabindex=-1]):visible, select:not([disabled], .disabled, [tabindex=-1]):visible, textarea:not([disabled], .disabled, [tabindex=-1]):visible, button:not([disabled], .disabled, [tabindex=-1]):visible, [tabindex=0]:not([disabled], .disabled):visible, [contenteditable]:not([disabled], .disabled, [tabindex=-1]):visible';
3332		}
3333
3334		var elements = $(selector + ', ' + this.prop("tagName"));
3335		// index from where in the elements should be search for next tabbable element
3336		var index = elements.index(this);
3337		// consider only elements of selector (exclude this tag name elements)
3338		var filteredElements = elements.filterKeepIndices(selector);
3339
3340		for (var i = index + 1; i < elements.length; ++i) {
3341			if (filteredElements[i] !== null) {
3342				return $(filteredElements[i]);
3343			}
3344		}
3345	};
3346
3347	$.fn.prevTabbable = function(selector) {
3348		if (typeof selector === 'undefined') {
3349			selector = 'a[href]:not([disabled], .disabled, [tabindex=-1]):visible, input:not([disabled], [readonly], [type="hidden"], .disabled, [tabindex=-1]):visible, select:not([disabled], .disabled, [tabindex=-1]):visible, textarea:not([disabled], .disabled, [tabindex=-1]):visible, button:not([disabled], .disabled, [tabindex=-1]):visible, [tabindex=0]:not([disabled], .disabled):visible, [contenteditable]:not([disabled], .disabled, [tabindex=-1]):visible';
3350		}
3351
3352		var elements = $(selector + ', ' + this.prop("tagName"));
3353		// index from where in the elements should be search for next tabbable element
3354		var index = elements.index(this);
3355		// consider only elements of selector (exclude this tag name elements)
3356		var filteredElements = elements.filterKeepIndices(selector);
3357
3358		for (var i = index - 1; i >= 0; --i) {
3359			if (filteredElements[i] !== null) {
3360				return $(filteredElements[i]);
3361			}
3362		}
3363	};
3364
3365	/**
3366	 * Focus next element where class "autoFocus" is set
3367	 */
3368	$.fn.autoFocus = function() {
3369		if (this.is('.autoFocus')) {
3370			return this.focus();
3371		} else {
3372			return this.find('.autoFocus:not([disabled])').first().focusEnd();
3373		}
3374	};
3375
3376	/**
3377	 * Set any values that do not match the selector to null. Array indices remain unchanged.
3378	 * @param selector
3379	 * @returns {*}
3380	 */
3381	$.fn.filterKeepIndices = function (selector) {
3382		return this.init().get().map(function (element) {
3383			if ($(element).is(selector)) {
3384				return element;
3385			}
3386			return null;
3387		})
3388	};
3389
3390	$.fn.isOnScreen = function() {
3391		var $elem = this;
3392		var $window = $(window);
3393
3394		var docViewTop = $window.scrollTop();
3395		var docViewBottom = docViewTop + $window.height();
3396
3397		var elemTop = $elem.offset().top;
3398		var elemBottom = elemTop + $elem.height();
3399
3400		return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
3401	};
3402
3403	$.fn.isTimeAfter = function($otherTimeInput) {
3404		var time = this.val();
3405		var otherTime = $otherTimeInput.val();
3406
3407		if (!KwTwigForm.checkType(time, 'time') || !KwTwigForm.checkType(otherTime, 'time')) {
3408			return false;
3409		} else {
3410			time = time.split('.');
3411			otherTime = otherTime.split('.');
3412			time[0] = parseInt(time[0]);
3413			time[1] = parseInt(time[1]);
3414			otherTime[0] = parseInt(otherTime[0]);
3415			otherTime[1] = parseInt(otherTime[1]);
3416
3417			return time[0] > otherTime[0] || time[0] === otherTime[0] && time[1] > otherTime[1];
3418		}
3419	};
3420
3421	$.fn.kwSelect = function (options) {
3422		if (typeof options === 'undefined') {
3423			if (typeof this[0].kwSelect !== 'undefined') {
3424				return this[0].kwSelect;
3425			} else {
3426				return null;
3427			}
3428		} else {
3429			options = $.extend({
3430				selector: this.selector
3431			}, options );
3432			if (typeof this[0].kwSelect !== 'undefined') {
3433				this[0].kwSelect.dissolve();
3434			}
3435			this[0].kwSelect = new KwSelect(options);
3436			return this[0].kwSelect;
3437		}
3438	};
3439
3440	$.fn.tagName = function() {
3441		return this[0].tagName.toLowerCase();
3442	}
3443
3444	/**
3445	 * Click handler but the user has to click a second time within 5 s to fire the click event
3446	 *
3447	 * @param selector [optional] additional selector to filter the given jQuery set, like in $.on()
3448	 * @param youSureClass class to be used to warn the user, default is 'warning'
3449	 * @param _callback handler
3450	 */
3451	$.fn.bindClickWithCheck = function(selector, youSureClass, _callback) {
3452		if ($.isFunction(youSureClass)) {
3453			_callback = youSureClass;
3454			youSureClass = selector;
3455			selector = null;
3456		}
3457
3458		if (youSureClass === null) {
3459			youSureClass = 'warning';
3460		}
3461
3462		return this.on('click', selector, function(e) {
3463			e.preventDefault();
3464			if ($(this).hasClass(youSureClass)) {
3465				$(this).removeClass(youSureClass);
3466				clearTimeout($(this).checkTimeout);
3467				_callback($(this), e);
3468			} else {
3469				$(this).addClass(youSureClass);
3470				$(this).checkTimeout = setTimeout(() => {
3471					$(this).removeClass(youSureClass);
3472				}, 5000)
3473			}
3474		});
3475	};
3476
3477	$.fn.scrollIntoView = function() {
3478		$(this)[0].scrollIntoView({behavior: "smooth", block: "center", inline: "center"});
3479		return $(this);
3480	};
3481
3482	$.fn.statisticOnDemand = function($container, link) {
3483		new statisticsOnDemand(this, $container, link).bind();
3484	}
3485
3486	$.fn.characterCounter = function(showMax = false) {
3487		var $counter = $(this);
3488		var $input = $($counter.data('character-counter-selector'));
3489		var max = parseInt($input.attr('maxlength'));
3490		$input.on('input change', function() {
3491			var chars = $input.val().split(/[^\n]/ug).length - 1;
3492			if (showMax && max) {
3493				$counter.text(`${chars} / ${max}`);
3494			} else {
3495				$counter.text(chars);
3496			}
3497		});
3498
3499		$input.trigger('change');
3500	}
3501
3502}(jQuery));
3503
3504
3505
3506// statistics on demand
3507statisticsOnDemand = function ($loadImageButton, $container, link) {
3508	var statsImage = $('<img />');
3509	var that = this;
3510
3511	this.bind = function () {
3512		$loadImageButton.on('click', function(event){
3513			event.preventDefault();
3514			that.showLoading();
3515		});
3516	};
3517
3518	this.showLoading = function () {
3519		$loadImageButton.remove();
3520		$container.append(statsImage);
3521		statsImage.attr('src', '/_kirchenweb/images/iconLaden.gif');
3522		statsImage.on('load', that.load);
3523	};
3524
3525	this.load = function () {
3526		statsImage.off('load');
3527		statsImage.attr('src', link);
3528		statsImage.on('error', that.noStatistics);
3529		statsImage.on('success', that.resetWidth);
3530	};
3531
3532	this.noStatistics = function () {
3533		statsImage.remove();
3534		I18n.word('statistikKeineDaten').then(function (text) {
3535			$container.append(text);
3536		});
3537	};
3538
3539	this.resetWidth = function () {
3540		statsImage.css('width', 'auto');
3541	};
3542};
3543
3544window.append('jQuery.Kw', function jQueryKw() {}); // dummy entry for frontend libraries

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.