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