PageSourceSearch

https://www.korbach.de/output/js/ikiss/ikissKeepFocus.js

js korbach.de collected 2026-10-02 17:50:08 UTC 4,714 bytes, 192 lines download raw bytes

1/*
2Beispieleinbindung:
3
4<script src="/output/js/ikiss/ikissKeepFocus.js"></script>
5<script>
6	$(function() {
7		$.fn.ikissKeepFocus({
8			elements: [
9				{ selector: '#layer1' },
10				{ selector: '#layer2', onKeyDown: function() { return $('.suche-fullscreen').hasClass('flex'); }  },
11				{
12					selector: '#leyer3',
13					isVisible: function() { return $('#layer3').hasClass('show-layer'); },
14					//Extraelemente, welche ausshalb des eigentlichen Elements liegen, aber der Tastaursteueung mit einbezogen werden sollen
15					extraElements: function() {
16						return $('.suhe-btn');
17					}
18
19				}
20			]
21		});
22	});
23<script>
24*/
25
26;(function ($) {
27	
28	$.fn.ikissKeepFocus = function(config) {
29		return new ikissKeepFocus(config);
30	};
31	
32	var ikissKeepFocus = function(config) {
33		this.elements = config.elements;
34		this.init();
35		return this;
36	};
37	
38	ikissKeepFocus.prototype = {
39		
40		focusSet: false,
41		
42		init: function() {
43			this.elements.forEach(this.initElement, this);
44		},
45		
46		initElement: function(elCfg, idx, arr) {
47			var el = arr[idx];
48				
49			if (!el.$el) 
50				el.$el = $(elCfg.selector);
51			
52			if (el.$el.length) {
53				el.$el[0].ikissKeepFocusIndex = idx;
54				el.$el.on('keydown', this.onElKeyDown.bind(this)); 
55				
56				if (!this.focusSet && this.isVisible(el)) {
57					if (el.$el.attr('tabindex') == undefined) {
58                        el.$el.attr('tabindex', '0');
59                    }
60					el.$el.focus();
61					this.focusSet = true;
62				}
63			} else {
64				delete el.$el;	
65			}
66		},
67		
68		setFocus: function(el, mode) {
69			var tabbable = this.getTabbableElements(el),
70				target;
71
72			if (mode === 'first') {
73				target = tabbable.first()[0];
74			} else {
75				var extra = this.getExtraTabbableElements(el[0]);
76				target = (extra && extra.length) ? extra.last()[0] : tabbable.last()[0];
77			}
78
79			if (!target) return;
80
81			target.focus();
82			if (document.activeElement !== target) {
83				requestAnimationFrame(function() { target.focus(); });
84			}
85		},
86		
87		getTabbableElements: function(el) {
88			return $(el).find('select, input, textarea, button, a').not('.no-keep-focus').filter(':visible');
89		},
90
91		getExtraTabbableElements: function(el) {
92			var me 		= this,
93				idxEl 	= el && this.elements[el.ikissKeepFocusIndex];
94
95			if (idxEl && idxEl.extraElements) {
96				var addEls = idxEl.extraElements();
97				if (addEls.length) {
98					addEls.each(function(idx) {
99						$(this)
100							.off('keydown.ikisskeepfocus')
101							.on('keydown.ikisskeepfocus', { rootEl: el, idx: idx }, me.onElKeyDown.bind(me))
102							.data('ikisskeepfocus-keytrigger', '1');
103					});
104					return addEls;
105				}
106			}
107			return false;
108		},
109		
110		findElement: function(node, direction) {
111			var cIndex	= node.ikissKeepFocusIndex,
112				dir		= (direction == 'next') ? 1 : -1,
113				marker	= this.moveMarker(cIndex, dir),
114				els		= this.elements,
115				el;
116			
117			while (marker != cIndex) {
118				el = els[marker];
119				if(this.isVisible(el)) 
120					return el.$el;	
121				marker = this.moveMarker(marker, dir);	
122			}
123			return els[marker].$el;
124		},
125		
126		moveMarker: function(idx, direction) {
127			var els = this.elements;
128			return (idx + els.length + direction) % els.length;
129		},
130		
131		isVisible: function(el) {
132			return el.$el ? (typeof el.isVisible == 'function') ? el.isVisible() : el.$el.is(':visible') : false;	
133		},
134		
135		onElKeyDown: function(ev) {
136
137			if (ev.which !== 9)
138				return;
139
140			var data	= ev.data,
141				el 		= (data && data.rootEl) ? data.rootEl : ev.currentTarget,
142				idxEl 	= this.elements[el.ikissKeepFocusIndex];
143			
144			//Prüfen, ob der Fokus überhaupt gefangen werden soll
145			if (idxEl && idxEl.onKeyDown && idxEl.onKeyDown() === false)
146				return;
147
148			var	tabbable 		= this.getTabbableElements(el),
149				extraTabbable	= this.getExtraTabbableElements(el),
150				firstTabbable 	= tabbable.first(),
151				lastTabbable 	= tabbable.last(),
152				trg 			= ev.target, 
153				sk 				= ev.shiftKey; 
154
155			//Wir sind in einem Extralement ausserhalb des eigentlichen Fokus-Elements, z.B. Suchbutton
156			if (data && data.rootEl) {
157
158				if (!this.isVisible(idxEl)) {
159					return;
160				}
161
162				if (!sk && trg === (extraTabbable.last())[0]) {
163					ev.preventDefault();
164					this.setFocus(this.findElement(el, 'next'), 'first');
165					return;
166				}
167
168				if (sk && trg === (extraTabbable.first())[0]) {
169					ev.preventDefault();
170					this.setFocus(el, 'last');
171					return;
172				}
173
174			}
175
176
177			if (!sk && trg === lastTabbable[0] && extraTabbable && extraTabbable.length) {
178				ev.preventDefault();
179				extraTabbable.first().focus();
180				return;
181			}
182
183
184			if ((!sk && trg == lastTabbable[0]) || (sk && trg == firstTabbable[0])) {
185				ev.preventDefault();
186				this.setFocus(this.findElement(el, sk ? 'prev' : 'next'), sk ? 'last' :'first');
187			}
188		}
189		
190	};
191	
192})(jQuery);

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