PageSourceSearch

https://www.sironaconsulting.com/auto-complete.js

js sironaconsulting.com collected 2026-10-03 21:37:40 UTC 10,654 bytes, 215 lines download raw bytes

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.