1/* 2 JavaScript autoComplete v1.0.4 3 Copyright (c) 2014 Simon Steinberger / Pixabay 4 GitHub: https://github.com/Pixabay/JavaScript-autoComplete 5 License: http://www.opensource.org/licenses/mit-license.php 6*/ 7 8var autoComplete = (function(){ 9 // "use strict"; 10 function autoComplete(options){ 11 if (!document.querySelector) return; 12 13 // helpers 14 function hasClass(el, className){ return el.classList ? el.classList.contains(className) : new RegExp('\\b'+ className+'\\b').test(el.className); } 15 16 function addEvent(el, type, handler){ 17 if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler); 18 } 19 function removeEvent(el, type, handler){ 20 // if (el.removeEventListener) not working in IE11 21 if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler); 22 } 23 function live(elClass, event, cb, context){ 24 addEvent(context || document, event, function(e){ 25 var found, el = e.target || e.srcElement; 26 while (el && !(found = hasClass(el, elClass))) el = el.parentElement; 27 if (found) cb.call(el, e); 28 }); 29 } 30 31 var o = { 32 selector: 0, 33 source: 0, 34 minChars: 3, 35 delay: 150, 36 offsetLeft: 0, 37 offsetTop: 1, 38 cache: 1, 39 menuClass: '', 40 renderItem: function (item, search){ 41 // escape special characters 42 search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 43 var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi"); 44 return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>'; 45 }, 46 onSelect: function(e, term, item){} 47 }; 48 for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; } 49 50 // init 51 var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector); 52 for (var i=0; i<elems.length; i++) { 53 var that = elems[i]; 54 55 // create suggestions container "sc" 56 that.sc = document.createElement('div'); 57 that.sc.className = 'autocomplete-suggestions '+o.menuClass; 58 59 that.autocompleteAttr = that.getAttribute('autocomplete'); 60 that.setAttribute('autocomplete', 'off'); 61 that.cache = {}; 62 that.last_val = ''; 63 64 that.updateSC = function(resize, next){ 65 var rect = that.getBoundingClientRect(); 66 that.sc.style.left = Math.round(rect.left + (window.pageXOffset || document.documentElement.scrollLeft) + o.offsetLeft) + 'px'; 67 that.sc.style.top = Math.round(rect.bottom + (window.pageYOffset || document.documentElement.scrollTop) + o.offsetTop) + 'px'; 68 that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth 69 if (!resize) { 70 that.sc.style.display = 'block'; 71 $('.popup-regionality__searcher-no-result').removeClass('--open') 72 if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); } 73 if (!that.sc.suggestionHeight) that.sc.suggestionHeight = that.sc.querySelector('.autocomplete-suggestion').offsetHeight; 74 if (that.sc.suggestionHeight) 75 if (!next) that.sc.scrollTop = 0; 76 else { 77 var scrTop = that.sc.scrollTop, selTop = next.getBoundingClientRect().top - that.sc.getBoundingClientRect().top; 78 if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0) 79 that.sc.scrollTop = selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight; 80 else if (selTop < 0) 81 that.sc.scrollTop = selTop + scrTop; 82 } 83 } 84 } 85 addEvent(window, 'resize', that.updateSC); 86 document.body.appendChild(that.sc); 87 88 live('autocomplete-suggestion', 'mouseleave', function(e){ 89 var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); 90 if (sel) setTimeout(function(){ sel.className = sel.className.replace('selected', ''); }, 20); 91 }, that.sc); 92 93 live('autocomplete-suggestion', 'mouseover', function(e){ 94 var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); 95 if (sel) sel.className = sel.className.replace('selected', ''); 96 this.className += ' selected'; 97 }, that.sc); 98 99 live('autocomplete-suggestion', 'mousedown', function(e){ 100 if (hasClass(this, 'autocomplete-suggestion')) { // else outside click 101 var v = this.getAttribute('data-val'); 102 that.value = v; 103 o.onSelect(e, v, this); 104 that.sc.style.display = 'none'; 105 $('.popup-regionality__searcher-no-result').addClass('--open') 106 } 107 }, that.sc); 108 109 that.blurHandler = function(){ 110 try { var over_sb = document.querySelector('.autocomplete-suggestions:hover'); } catch(e){ var over_sb = 0; } 111 if (!over_sb) { 112 that.last_val = that.value; 113 that.sc.style.display = 'none'; 114 setTimeout(function(){ that.sc.style.display = 'none'; }, 350); // hide suggestions on fast input 115 } else if (that !== document.activeElement) setTimeout(function(){ that.focus(); }, 20); 116 }; 117 addEvent(that, 'blur', that.blurHandler); 118 119 var suggest = function(data){ 120 var val = that.value; 121 that.cache[val] = data; 122 if (data.length && val.length >= o.minChars) { 123 var s = ''; 124 for (var i=0;i<data.length;i++) s += o.renderItem(data[i], val); 125 that.sc.innerHTML = s; 126 that.updateSC(0); 127 } 128 else 129 that.sc.style.display = 'none'; 130 } 131 132 that.keydownHandler = function(e){ 133 var key = window.event ? e.keyCode : e.which; 134 // down (40), up (38) 135 if ((key == 40 || key == 38) && that.sc.innerHTML) { 136 var next, sel = that.sc.querySelector('.autocomplete-suggestion.selected'); 137 if (!sel) { 138 next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last 139 next.className += ' selected'; 140 that.value = next.getAttribute('data-val'); 141 } else { 142 next = (key == 40) ? sel.nextSibling : sel.previousSibling; 143 if (next) { 144 sel.className = sel.className.replace('selected', ''); 145 next.className += ' selected'; 146 that.value = next.getAttribute('data-val'); 147 } 148 else { sel.className = sel.className.replace('selected', ''); that.value = that.last_val; next = 0; } 149 } 150 that.updateSC(0, next); 151 return false;
152 } 153 // esc 154 else if (key == 27) { that.value = that.last_val; that.sc.style.display = 'none'; } 155 // enter 156 else if (key == 13 || key == 9) { 157 var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); 158 if (sel && that.sc.style.display != 'none') { o.onSelect(e, sel.getAttribute('data-val'), sel); setTimeout(function(){ that.sc.style.display = 'none'; }, 20); } 159 } 160 }; 161 addEvent(that, 'keydown', that.keydownHandler); 162 163 that.keyupHandler = function(e){ 164 var key = window.event ? e.keyCode : e.which; 165 if (!key || (key < 35 || key > 40) && key != 13 && key != 27) { 166 var val = that.value; 167 if (val.length >= o.minChars) { 168 if (val != that.last_val) { 169 that.last_val = val; 170 clearTimeout(that.timer); 171 if (o.cache) { 172 if (val in that.cache) { suggest(that.cache[val]); return; } 173 // no requests if previous suggestions were empty 174 for (var i=1; i<val.length-o.minChars; i++) { 175 var part = val.slice(0, val.length-i); 176 if (part in that.cache && !that.cache[part].length) { suggest([]); return; } 177 } 178 } 179 that.timer = setTimeout(function(){ o.source(val, suggest) }, o.delay); 180 } 181 } else { 182 that.last_val = val; 183 that.sc.style.display = 'none'; 184 $('.popup-regionality__searcher-no-result').addClass('--open') 185 } 186 } 187 }; 188 addEvent(that, 'keyup', that.keyupHandler); 189 190 that.focusHandler = function(e){ 191 that.last_val = '\n'; 192 that.keyupHandler(e) 193 }; 194 if (!o.minChars) addEvent(that, 'focus', that.focusHandler); 195 } 196 197 // public destroy method 198 this.destroy = function(){ 199 for (var i=0; i<elems.length; i++) { 200 var that = elems[i]; 201 removeEvent(window, 'resize', that.updateSC); 202 removeEvent(that, 'blur', that.blurHandler); 203 removeEvent(that, 'focus', that.focusHandler); 204 removeEvent(that, 'keydown', that.keydownHandler); 205 removeEvent(that, 'keyup', that.keyupHandler); 206 if (that.autocompleteAttr) 207 that.setAttribute('autocomplete', that.autocompleteAttr); 208 else 209 that.removeAttribute('autocomplete'); 210 document.body.removeChild(that.sc); 211 that = null; 212 } 213 }; 214 } 215 return autoComplete; 216})(); 217 218(function(){ 219 if (typeof define === 'function' && define.amd) 220 define('autoComplete', function () { return autoComplete; }); 221 else if (typeof module !== 'undefined' && module.exports) 222 module.exports = autoComplete; 223 else 224 window.autoComplete = autoComplete; 225})();
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.