PageSourceSearch

https://www.ingolstadt.de/output/js/ikiss/basic.js

js ingolstadt.de collected 2026-09-24 19:19:38 UTC 19,787 bytes, 629 lines download raw bytes

1ikiss_basic = {
2
3	cache : {}, // Allgemein verfuegbares Cacheobjekt
4
5	clog : false, // true: ikiss_basic.log() ueber console.log ausgeben, wenn moeglich
6
7	log : function(){
8		if (!this.clog) return false;
9		this.log.history=this.log.history||[];
10		this.log.history.push(arguments);
11		if (window.console) {
12			console.log(Array.prototype.slice.call(arguments));
13		}
14	},
15
16
17	/**
18	* Allgemeiner Event-Handler mit flexibler Parameter-Uebergabe
19	* Beispiel: $('div.myclass').bind('mousedown',{fn: 'myFunction', scope: this, args: ['test','test2'] }, ikiss_basic.onEvent);
20	*	Event-Aufruf: myFunction : function(eventObject,arg1,arg2,...) {}
21	*/
22	onEvent: function(e) {
23		var sc = e.data.scope;
24		var fn = e.data.fn;
25		var args = [e].concat(e.data.args || []);
26		sc[fn] && sc[fn].apply(sc, args);
27	},
28
29
30	toggle : function(obj,acobj,mode) {
31		$(acobj || $(obj).nextAll('.aufklapper_container').first()).slideToggle((mode || 'slow'));
32		return false;
33	},
34
35
36	/**
37	 * Seite zurück mit Reload, wenn Referrer verfügbar
38 	 */
39	back : function() {
40		if ('referrer' in document) {
41			var lurl = ikiss_basic.parseUrl(window.location);
42			var rurl = ikiss_basic.parseUrl(document.referrer);
43			if (lurl.hostname === rurl.hostname) {
44				window.location = document.referrer;
45				return true;
46			}
47		}
48		window.history.back();
49	},
50
51
52	/**
53	 * URL-Parser
54	 * @param string href
55	 * @returns {HTMLAnchorElement}
56	    .protocol; // => "http:"
57		.hostname; // => "example.com"
58	    .port;     // => "3000"
59	    .pathname; // => "/pathname/"
60	    .search;   // => "?search=test"
61	    .hash;     // => "#hash"
62	    .host;     // => "example.com:3000"
63	 */
64	parseUrl : function(href) {
65		var l = document.createElement("a");
66		l.href = href;
67		return l;
68	},
69
70
71	/**
72	* Entfernt doppelte Werte aus einem Array
73	*
74	* @param array
75	*/
76	array_unique : function(array) {
77		return $.grep(array,function(el,index) {
78			return index == $.inArray(el,array);
79		});
80	},
81
82
83	/**
84	* Ermittelt die Schnittmenge der Array-Werte zweier Arrays
85	*
86	* @param a Array 1
87	* @param b Array 2
88	*/
89	array_intersect : function(a, b) {
90		var t;
91		if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter
92		return a.filter(function (e) {
93			if (b.indexOf(e) !== -1) return true;
94		});
95	},
96
97
98	/**
99	* Array-Key-Diff
100	*
101	* @param a
102	* @param b
103	* @param lrb
104	* @returns {Array}
105	*/
106	array_kdiff : function(a, b, lrb) {
107		var aa = [];
108		lrb = lrb||3;
109		if (lrb&1) for (var k in a) if (a[k] === true && !b[k]) aa[k] = true;
110		if (lrb&2) for (var k in b) if (b[k] === true && !a[k]) aa[k] = true;
111		return aa;
112	},
113
114
115	/**
116	* Array-Keys zurueckgeben
117	*
118	* @param a
119	* @returns {Array}
120	*/
121	array_keys : function (a) {
122		var aa = [];
123		for (var key in a) aa.push(key);
124		return aa;
125	},
126
127
128	/**
129	 * Einfacher Objektfilter
130	 * Filtert aus einem Array von Objekten die nicht zu den prop/val passenden Objekte heraus
131	 *
132	 * @param {Array} arr Eingabe-Array von Objekten
133	 * @param {String} prop Property-Name
134	 * @param {String/Array} Property-Value / Value-Array
135	 * @returns {Array}
136	 */
137	filterObject : function(arr,prop,val) {
138		var i = 0,
139			r = [],
140			len = arr.length;
141		
142		for (; i < len; i++ ) {
143			if ($.isArray(val) && $.inArray(arr[i][prop],val) !== -1) r.push(arr[i]);
144			else if (arr[i][prop] == val) r.push(arr[i]);
145		}
146		return r;
147	},
148
149
150	/**
151	* Popup-Fenster oeffnen
152	*
153	* @param Url
154	* @param {String} xs
155	* @param {String} ys
156	* @param opt
157	* @param {String} wname
158	*/
159	popup : function(Url, xs, ys, opt, wname) {
160		if (!wname) wname = '_new';
161		if (xs < 1) xs = '';
162		if (ys < 1) ys = '';
163		if (opt & 15) {
164			sb = (opt & 1) ? 'yes' : 'no';
165			rz = (opt & 2) ? 'yes' : 'no';
166			tb = (opt & 4) ? 'yes' : 'no';
167			st = (opt & 8) ? 'yes' : 'no';
168			ml = 'no';
169			ul = 'no';
170		} else {
171			sb = (opt & 8192) ? 'yes' : 'no';
172			rz = (opt & 2048) ? 'yes' : 'no';
173			tb = (opt & 4096) ? 'yes' : 'no';
174			st = (opt & 512)  ? 'yes' : 'no';
175			ml = (opt & 256)  ? 'yes' : 'no';
176			ul = (opt & 1024) ? 'yes' : 'no';
177		}
178		NWin = window.open(Url, wname, 'scrollbars=' + sb + ',resizable=' + rz + ',toolbar=' + tb + ',menubar=' + ml + ',location=' + ul + ',status=' + st + ',width=' + xs + ',height=' + ys);
179		NWin.focus();
180		return;
181	},
182
183
184	/**
185	* Cookie setzen / loeschen
186	*
187	* @param c_name
188	* @param value
189	* @param exdays
190	*/
191	setCookie : function (c_name,value,exdays) {
192		if (!value) document.cookie = c_name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/; samesite=lax;';
193		else {
194			var exdate=new Date();
195			exdate.setDate(exdate.getDate() + exdays);
196			document.cookie = c_name + "=" + escape(value) + ((exdays === null) ? "" : "; expires="+exdate.toUTCString()) + "; path=/; samesite=lax;";
197		}
198	},
199
200
201	/**
202	* Cookie zurueckliefern
203	*
204	* @param c_name
205	* @returns {Boolean}
206	*/
207	getCookie : function(c_name) {
208		var x,y,ARRcookies=document.cookie.split(";");
209		for (var i = ARRcookies.length-1; i > -1; i--) {
210			x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
211			y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
212			x = x.replace(/^\s+|\s+$/g,"");
213			if (x == c_name) return (y && y !== undefined) ? unescape(y) : false;
214		}
215		return false;
216	},
217
218
219	/**
220	* Form-Values in Array (mode = a) oder URL-String (mode = s) umwandeln
221	* removeEmtpyValues = true : leere Formularfelder auslassen
222	*/
223	serialize : function(formNode,mode,removeEmtpyValues) {
224		if (removeEmtpyValues) {
225			var spa = $(formNode).serializeArray();
226			var nspa = [];
227			$.each(spa, function(k,v) { if (v.value) nspa.push(v); } );
228			spa = (mode == 's') ? $.param(nspa) : nspa;
229		} else {
230			var spa = (mode == 's') ? $(formNode).serialize() : $(formNode).serializeArray();
231		}
232
233		return spa;
234
235	},
236	
237		
238	/**
239	* Querystring als Key/Value-Objekt zurueckliefern
240	* Verarbeitet auch Array-Parameter 
241	* Beispiel: ?La=1&NavID=1447.280&x1=2&x1=4&x2[]=1&x2[]=3&x3[bla]=check&x3[blubb]=super!&par=xyzüäß#test
242	*/
243	parseQuerystring : function(url) {
244		var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
245		var obj = {};
246		if (queryString) {
247			queryString = queryString.split('#')[0]; // Hash entfernen
248			var arr = queryString.split('&');
249			for (var i=0; i<arr.length; i++) {
250				var a = arr[i].split('=');
251
252				// Array-Parameter: key[]=value1&key[]=value2 usw.
253				var paramNum = undefined;
254				var paramName = a[0].replace(/\[.*?\]/, function(v) {
255					paramNum = v.slice(1,-1);
256					return '';
257				});
258
259				// Wert setzen, (empty = null)
260				var paramValue = typeof(a[1])==='undefined' ? null : a[1];
261				//console.log("parseQuerystring",paramName,paramNum,a);
262				
263				// gibt es schon, dann Array!
264				if (obj[paramName]) {
265					if (typeof obj[paramName] === 'string') obj[paramName] = [obj[paramName]];
266					if (!paramNum || typeof paramNum === 'undefined') obj[paramName].push(paramValue);
267					else obj[paramName][paramNum] = paramValue;
268				}
269				else {
270					if (paramNum) {
271						obj[paramName] = [];
272						obj[paramName][paramNum] = paramValue;
273					}
274					else obj[paramName] = paramValue;
275				}
276			}
277		}
278		return obj;
279	},
280
281
282	/**
283	* CRC32-Hash aus einem String ermitteln
284	* z.B. fuer Caching-Methoden etc.
285	*/
286	crc32 : function(str) {
287		var crcTable = window.crcTable || (window.crcTable = ikiss_basic.makeCRCTable());
288		var crc = 0 ^ (-1);
289
290		for (var i = 0; i < str.length; i++ ) {
291			crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF];
292		}
293
294		return (crc ^ (-1)) >>> 0;
295	},
296
297
298	/**
299	* Hilfsfunktion fuer Methode crc32() - erstellt die Basis-Hashtabelle
300	*/
301	makeCRCTable : function(){
302		var c;
303		var crcTable = [];
304		for(var n =0; n < 256; n++){
305			c = n;
306			for(var k =0; k < 8; k++){
307				c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
308			}
309			crcTable[n] = c;
310		}
311		return crcTable;
312	},
313
314
315	/**
316	* iKISS-Default-Alphanav
317	*/
318	setAlphanav : function(className) {
319		if (className) $('.' + className + ' a:not(.all)').click(function() {
320			$(this).closest('form').append('<input type="hidden" name="alpha" value="'+$(this).text()+'">').submit();
321			return false;
322		});
323	},
324
325
326	/**
327	* Skripte nacheinander laden
328	* ggf. vorher Skript-Caching aktivieren : $.ajaxSetup({ cache: true });
329	*
330	* @param {Array} scripts
331	* @param onReady auzufuehrende Methode nach dem Laden aller Skripte
332	*/
333	load : function(scripts,onReady,i) {
334		if (!scripts) return false;
335		if (!$.isArray(scripts)) scripts = [scripts];
336		if (typeof i === 'undefined' || i === null) var i = -1;
337		if (scripts[++i]) {
338			$.getScript( scripts[i] ).done(function( script, textStatus ) {
339				console.log('LOAD: ',i,scripts[i]);
340				ikiss_basic.load(scripts,onReady,i);
341			});
342		}
343		else if (onReady && typeof onReady === "function") onReady();
344	},
345
346
347	/**
348	 * Verzögerungsfunktion für z.B. asynchrone Requests (=> Autocomplete!)
349	 * @param fn
350	 * @param delay
351	 * @returns {function(): void}
352	 */
353	debounce : function (fn, delay) {
354		var timer = null;
355		return function () {
356			var context = this, args = arguments;
357			clearTimeout(timer);
358			timer = setTimeout(function () {
359				fn.apply(context, args);
360			}, delay);
361		}
362	},
363
364
365	/**
366	* Datumseingabe prüfen und ggf. korrigieren / formatieren -> #13157
367	* Es sind so auch Eingaben wie z.B. 3.9. oder 3 9 oder auch nur 3 möglich, diese werden dann auf den aktuellen Monat / das Jahr umgeformt
368	* Rückgabe erfolgt ISO 8601-konform im Format YYYY-MM-DD
369	* @param {string|object} obj Datumsstring oder DOM-Node auf das Input-Feld für die Datumseingabe
370	* @param dvo [optional] #DOM-ID des Eingabefeldes "Datum von" für die Prüfung, ob größer als "Datum bis"
371	* @param dbo [optional] #DOM-ID des Eingabefeldes "Datum bis"
372	* @returns {string} Wenn Übergabe als DOM-Node, wird auch der Wert des Feldes angepasst! => obj.value
373	*/
374	setDateValue : function (obj,dvo, dbo) {
375		var dval = null,
376			type = 0, // String (0) oder DOM-Node (1)
377			formatted = '',
378			utdv,utdb,tdv,tdb;
379
380		if (typeof obj === "string") dval = obj;
381		else if (typeof obj === "object" && obj.value) {
382			dval = obj.value
383			type = 1;
384		}
385		if (!dval) return '';
386
387		var d = new Date();
388		var sp = dval.split(/\D/);
389		if (sp[0].length === 4) sp = [sp[2],sp[1],sp[0]];
390		sp[0] = parseInt(sp[0],10) || d.getDate();
391		sp[1] = parseInt(sp[1],10) || (d.getMonth() + 1);
392		sp[2] = parseInt(sp[2],10) || d.getFullYear();
393		if (sp[2] < 100) sp[2] += 2000;
394		if (sp[2] < 2000) {
395			if (type) {
396				alert("Bitte geben Sie ein Datum im Format TT.MM oder TT.MM.JJ ein.");
397				obj.value = '';
398			}
399			return false;
400		}
401		d = new Date(sp[2],parseInt(sp[1],10)-1,parseInt(sp[0],10),12);
402		sp = [d.getDate(),d.getMonth()+1,d.getFullYear()];
403		formatted = sp[2]+ '-' + ((sp[1] < 10) ? '0'+sp[1] : sp[1]) + '-' + ((sp[0] < 10) ? '0'+sp[0] : sp[0]);
404		if (type) obj.value = formatted;
405
406		// von- und bis-Datum prüfen und tauschen, wenn bis kleiner von!
407		if (dvo && dbo) {
408			tdv = $(dvo).val();
409			tdb = $(dbo).val();
410			utdv = (tdv && new Date(tdv)) ? (new Date(tdv)).getTime() : null;
411			utdb = (tdb && new Date(tdb)) ? (new Date(tdb)).getTime() : null;
412			if (utdv && utdb && utdv > utdb) {
413				$(dvo).val(tdb);
414				$(dbo).val(tdv);
415			}
416		}
417		return formatted;
418	},
419
420
421	/*
422	Die Namen der zu speichernden Formularfelder müssen der Funktion übergeben werden. Beispielaufruf:
423	<button onclick='return ikiss_basic.form_storage_save("adr[Name]","adr[e-Mail]","adr[Straße]","adr[Ort]","adr[Bemerkungen]","booking[2787.140]","confirmed");'>Formulardaten speichern</button>
424	Statt <button> kann auch <input type="submit"> verwendet werden:
425	<input value="Speichern" type="submit" onclick="return ikiss_basic.form_storage_save('Textfeld','Auswahlfeld','radio','radio_umbruch');">
426	*/
427	form_storage_save: function (){//#11239
428		for(var i = 0; i < arguments.length; i++) {
429			var name = arguments[i];
430			var jquery_selector = "form textarea[name='" + name + "'], form select[name='" + name + "'], form input[name='" + name + "']";
431			var storage_key = "form_storage_" + name;
432
433			// Ungültige Namen
434			if($(jquery_selector).length < 1) continue;
435
436			// Gültige Namen
437			if($(jquery_selector).is(":checkbox")){
438				var value = ($(jquery_selector).is(":checked")) ? 1 : 0;
439			}
440			else if($(jquery_selector).is(":radio")){
441				var value = $(jquery_selector + ":checked").val();
442			}
443			else{
444				var value = $(jquery_selector).val();
445			}
446			sessionStorage.setItem(storage_key, value);
447		}
448		alert("Formulardaten sind gespeichert");
449		return false;//Damit ein Form nicht abgeschickt wird
450	},
451	/*
452	Die Namen der zu ladenden Formularfelder müssen der Funktion übergeben werden. Beispielaufruf:
453	<button onclick='return ikiss_basic.form_storage_load("adr[Name]","adr[e-Mail]","adr[Straße]","adr[Ort]","adr[Bemerkungen]","booking[2787.140]","confirmed");'>Formulardaten laden</button>
454	Statt <button> kann auch <input type="submit"> verwendet werden:
455	<input value="Laden" type="submit" onclick="return ikiss_basic.form_storage_load('Textfeld','Auswahlfeld','radio','radio_umbruch');">
456	*/
457	form_storage_load: function (){//#11239
458		for(var i = 0; i < arguments.length; i++) {
459			var name = arguments[i];
460			var jquery_selector = "form textarea[name='" + name + "'], form select[name='" + name + "'], form input[name='" + name + "']";
461			var storage_key = "form_storage_" + name;
462
463			// Ungültige Namen
464			if($(jquery_selector).length < 1) continue;
465
466			// Gültige Namen
467			var value = sessionStorage.getItem(storage_key);
468			if($(jquery_selector).is(":checkbox")){
469				$(jquery_selector).prop('checked', (value == 1));
470			}
471			else if($(jquery_selector).is(":radio")){
472				$(jquery_selector + "[value='" + value + "']").prop("checked",true);
473			}
474			else{
475				$(jquery_selector).val(value);
476			}
477		}
478		return false;//Damit ein Form nicht abgeschickt wird
479	}
480
481}
482
483// Kompatibilitaetsfunktion fuer alte iKISS-Systeme mit popup - Methode
484function popup(Url,xs,ys,opt,wname) { return ikiss_basic.popup(Url,xs,ys,opt,wname); }
485
486
487// String repeat
488String.prototype.repeat = function(num) {
489	return new Array( parseInt(num, 10) + 1 ).join(this);
490}
491
492/**
493* Berechnung des Bildschwerpunkts
494* Für den CSS-Wert "background-position" muss ein korrigierter Bildschwerpunkt berechnet werden, der sich je nach angezeigtem Bildausschnitt im umliegenenden div verändert.
495* Hierfür muss in einem div ein Bild als "background-image" eingebettet sein, die Klasse "js-adjust-focal", 
496* sowie die Werte für den Bildschwerpunkt als data-Attribute (data-focalx = "{itp:field _var:image:focalx}" data-focaly = "{itp:field _var:image:focaly}") vorhanden sein.
497* 
498* Beispiel aus Titelbildeinbindung:
499* <div class="bg-img{itp:field _var:titelbild::focalX|as:" js-adjust-focal"}" style="background-image:url('/output/img.php?id={itp:field _var:titelbild::FID}&amp;fm=g&amp;mfm=m');"{itp:if _var:titelbild::focalX} data-focalx="{itp:field _var:titelbild::focalX}" data-focaly="{itp:field _var:titelbild::focalY}"{/itp:if}>
500* 
501* Neu ab iKISS 8.4: Beispiel aus Themenboxen:
502* <img class="teaser-image{itp:field _var:image:class|delimit:" ",""}{itp:field _var:image:focalx|as:" js-adjust-focal"}" src="{itp:field _var:image:url}" alt="{itp:field _var:image:alt|empty:_var:image:title|quot}"{itp:if _var:image:focalx} data-sizex="{itp:field _var:image:sizex}" data-sizey="{itp:field _var:image:sizey}" data-focalx="{itp:field _var:image:focalx}" data-focaly="{itp:field _var:image:focaly}"{/itp:if}>
503* 
504*/
505jQuery(document).ready(function($) {
506	// Bildschwerpunkt mit JavaScript berechnen
507	window.ikissAdjustFocal = function (node,  retryCount = 0) {
508		const images = $('.js-adjust-focal', node || document.body);
509		const maxRetries = 3; 
510		const retryDelay = 150;  
511	
512		images.each(function () {
513			const self = this;
514			
515			// Ermittle, ob ein img-Element verwendet wird und ggf. Abbruch, wenn dieses nicht object-fit: cover nutzt
516            const isImgElement = self instanceof HTMLImageElement;
517            if (isImgElement && window.getComputedStyle(self).objectFit !== 'cover') {
518            	return;
519            }
520
521			// Ermittle, ob background-attachment: fixed verwendet wird
522			const isFixed = $(self).css('background-attachment') === 'fixed';
523			
524			// Bei fixed nehmen wir die Viewport-Dimensionen statt der Container-Dimensionen
525			const canvasWidth = isFixed ? window.innerWidth : $(self).parent().width();
526			const canvasHeight = isFixed ? window.innerHeight : $(self).parent().height();
527			
528			// Bild- und Focal-Werte aus den Attributen lesen (mit Standardwerten)
529			const originalWidth = parseFloat($(self).attr('data-sizex'));
530			const originalHeight = parseFloat($(self).attr('data-sizey'));
531			const focalx = parseFloat($(self).attr('data-focalx')) ?? 50;
532			const focaly = parseFloat($(self).attr('data-focaly')) ?? 50;
533			
534			let img;
535
536			// Wenn data-sizex nicht vorhanden, ermittle Bilddimensionen aus dem Bildobjekt.
537			if (!originalWidth) {
538				// Hintergrundbild-URL aus style-Attribut extrahieren
539				const backgroundImage = $(self).css('background-image');
540				let imgSrc = backgroundImage.match(/url\(["']?(.*?)["']?\)/)?.[1];
541		
542				// Falls keine Hintergrundbild-URL vorhanden ist, versuche das <img>-Tag als Fallback
543				if (!imgSrc) {
544					const imgElement = $(self).find('img');
545					imgSrc = imgElement.attr('src');
546				}
547		
548				// Prüfen, ob die Bildquelle existiert
549				if (!imgSrc) {
550					console.warn('Keine Bildquelle gefunden:', self);
551					return;
552				}
553		
554				// Bildobjekt erstellen und Quelle setzen
555				img = new Image();
556				img.src = imgSrc;
557			}
558			
559			// Berechnung des korrigierten Bildschwerpunktes
560			const calculateBackgroundPosition = (originalWidth, originalHeight, isImgElement) => {
561				const aspectWidth = canvasWidth;
562				const aspectHeight = canvasHeight;
563	
564				let background_position_x = 50; // Standardwert
565				let background_position_y = 50; // Standardwert
566	
567				// überprüfen, ob Originalmaße vorhanden sind. Falls der Bildrahmen durch falsches Timing die Größe 0px haben sollte, f?hre Funktion um 150ms verzögert aus (maximal 3 Versuche)
568				if ((aspectWidth == 0) || (aspectHeight == 0)) {
569					if (retryCount < maxRetries) {
570						setTimeout(() => {
571							window.ikissAdjustFocal(node, retryCount + 1);
572						}, retryDelay);
573					}
574					return;
575				}
576
577				// Verhältnis von Canvas und Bild bestimmen
578				if (aspectWidth / aspectHeight > originalWidth / originalHeight) {
579					// Hoch-/Runter-Verschiebung
580					if (focaly !== null) {
581						const zy = (aspectWidth / originalWidth) * (originalHeight / aspectHeight);
582						background_position_y = ((focaly - 50) * zy) / (zy - 1) + 50;
583						background_position_y = parseFloat(
584							Math.min(100, Math.max(0, background_position_y)).toFixed(2)
585						);
586					}
587				} else if (aspectWidth / aspectHeight < originalWidth / originalHeight) {
588					// Links-/Rechts-Verschiebung
589					if (focalx !== null) {
590						const zx = (originalWidth / aspectWidth) * (aspectHeight / originalHeight);
591						background_position_x = ((focalx - 50) * zx) / (zx - 1) + 50;
592						background_position_x = parseFloat(
593							Math.min(100, Math.max(0, background_position_x)).toFixed(2)
594						);
595					}
596				}
597	
598				// Hintergrundposition setzen
599				if (isImgElement) {
600            		self.style.objectPosition = `${background_position_x}% ${background_position_y}%`;
601            	} else {
602            		self.style.backgroundPosition = `${background_position_x}% ${background_position_y}%`;
603            	}
604			};
605			
606			if (!originalWidth) {
607				// Sobald das Bild geladen ist, Originalgröße auslesen und berechnen
608				img.onload = function () {
609				let originalWidth = img.naturalWidth;
610				let originalHeight = img.naturalHeight;
611
612				calculateBackgroundPosition(originalWidth, originalHeight, isImgElement);
613				};
614			} else {
615				calculateBackgroundPosition(originalWidth, originalHeight, isImgElement);
616			}
617
618		});
619	};
620	
621	// Funktion aufrufen
622	window.ikissAdjustFocal();
623
624	$(window).on('resize', function(ev) {
625		if (ev.target !== window)
626			return;
627		window.ikissAdjustFocal();
628	});
629});

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.