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.