PageSourceSearch

https://realsender.com/js/auto-complete.js?1789642913

js realsender.com collected 2026-10-09 04:48:14 UTC 14,111 bytes, 288 lines download raw bytes

1/*
2    JavaScript autoComplete v1.0.4+
3        McShelby/hugo-theme-relearn#155
4            - PR #46, PR #75: introducing selectorToInsert and anchor to it
5            - sticky dropdown on scrolling
6        McShelby/hugo-theme-relearn#387
7            - don't empty search input if no data-val is given
8            - don't delete search term but close suggestions when suggestions are open
9            - delete search term when suggestions are closed
10        McShelby/hugo-theme-relearn#452
11            - register focus event ignoring minChars because that doesn't make sense
12        McShelby/hugo-theme-relearn#452
13            - on ESC, close overlay without deleting search term if overlay is open
14            - on ESC, delete search term if overlay is closed
15            - on UP, preventDefault to keep cursor in position
16
17    Copyright (c) 2014 Simon Steinberger / Pixabay
18    GitHub: https://github.com/Pixabay/JavaScript-autoComplete
19    License: http://www.opensource.org/licenses/mit-license.php
20*/
21
22var autoComplete = (function(){
23    // "use strict";
24    function autoComplete(options){
25        if (!document.querySelector) return;
26
27        // helpers
28        function hasClass(el, className){ return el.classList ? el.classList.contains(className) : new RegExp('\\b'+ className+'\\b').test(el.className); }
29
30        function addEvent(el, type, handler){
31            if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
32        }
33        function removeEvent(el, type, handler){
34            if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
35        }
36        function live(elClass, event, cb, context){
37            addEvent(context || document, event, function(e){
38                var found, el = e.target || e.srcElement;
39                while (el && !(found = hasClass(el, elClass))) el = el.parentElement;
40                if (found) cb.call(el, e);
41            });
42        }
43
44        var o = {
45            selector: 0,
46            source: 0,
47            minChars: 3,
48            delay: 150,
49            offsetLeft: 0,
50            offsetTop: 1,
51            cache: 1,
52            menuClass: '',
53            selectorToInsert: 0,
54            renderItem: function (item, search){
55                // escape special characters
56                search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
57                var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
58                return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
59            },
60            onSelect: function(e, term, item){}
61        };
62        for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; }
63
64        // init
65        var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector);
66        for (var i=0; i<elems.length; i++) {
67            var that = elems[i];
68
69            // create suggestions container "sc"
70            that.sc = document.createElement('div');
71            that.sc.className = 'autocomplete-suggestions '+o.menuClass;
72
73            that.autocompleteAttr = that.getAttribute('autocomplete');
74            that.setAttribute('autocomplete', 'off');
75            that.cache = {};
76            that.last_val = '';
77
78			var parentElement;
79            if (typeof o.selectorToInsert === "string" && document.querySelector(o.selectorToInsert) instanceof HTMLElement) {
80				parentElement = document.querySelector(o.selectorToInsert);
81			}
82			that.updateSC = function(resize, next){
83                var rect = that.getBoundingClientRect();
84				var parentOffsetLeft = 0;
85                var parentOffsetTop = 0;
86                var pageXOffset = 0;
87                var pageYOffset = 0;
88                if (parentElement != false) {
89                    parentOffsetLeft = parentElement.getBoundingClientRect().left;
90                    parentOffsetTop = parentElement.getBoundingClientRect().top;
91                } else {
92                    pageXOffset = window.pageXOffset || document.documentElement.scrollLeft;
93                    pageYOffset = window.pageYOffset || document.documentElement.scrollTop;
94                }
95                // Is this really the job of the tool or should it be defered to the user?
96                // that.sc.style.left = Math.round(rect.left + pageXOffset + o.offsetLeft - parentOffsetLeft) + 'px';
97                // that.sc.style.top = Math.round(rect.bottom + pageYOffset + o.offsetTop - parentOffsetTop) + 'px';
98                // that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth
99                if (!resize) {
100                    that.sc.style.display = 'block';
101                    if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); }
102                    if (!that.sc.suggestionHeight) that.sc.suggestionHeight = that.sc.querySelector('.autocomplete-suggestion').offsetHeight;
103                    if (that.sc.suggestionHeight)
104                        if (!next) that.sc.scrollTop = 0;
105                        else {
106                            var scrTop = that.sc.scrollTop, selTop = next.getBoundingClientRect().top - that.sc.getBoundingClientRect().top;
107                            if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0)
108                                that.sc.scrollTop = selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight;
109                            else if (selTop < 0)
110                                that.sc.scrollTop = selTop + scrTop;
111                        }
112                }
113            }
114            addEvent(window, 'resize', that.updateSC);
115
116            if (typeof o.selectorToInsert === "string" && document.querySelector(o.selectorToInsert) instanceof HTMLElement) {
117                document.querySelector(o.selectorToInsert).appendChild(that.sc);
118            } else {
119                document.body.appendChild(that.sc);
120            }
121
122            live('autocomplete-suggestion', 'mouseleave', function(e){
123                var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
124                if (sel) setTimeout(function(){ sel.className = sel.className.replace('selected', ''); }, 20);
125            }, that.sc);
126
127            live('autocomplete-suggestion', 'mouseover', function(e){
128                var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
129                if (sel) sel.className = sel.className.replace('selected', '');
130                this.className += ' selected';
131            }, that.sc);
132
133            live('autocomplete-suggestion', 'mousedown', function(e){
134                if (hasClass(this, 'autocomplete-suggestion')) { // else outside click
135                    var v = this.getAttribute('data-val');
136                    that.value = v;
137                    o.onSelect(e, v, this);
138                    that.sc.style.display = 'none';
139                }
140            }, that.sc);
141
142            that.blurHandler = function(){
143                try { var over_sb = document.querySelector('.autocomplete-suggestions:hover'); } catch(e){ var over_sb = 0; }
144                if (!over_sb) {
145                    that.last_val = that.value;
146                    that.sc.style.display = 'none';
147                    setTimeout(function(){ that.sc.style.display = 'none'; }, 350); // hide suggestions on fast input
148                } else if (that !== document.activeElement) setTimeout(function(){ that.focus(); }, 20);
149            };
150            addEvent(that, 'blur', that.blurHandler);
151
152            var suggest = function(data){
153                var val = that.value;
154                that.cache[val] = data;
155                if (data.length && val.length >= o.minChars) {
156                    var s = '';
157                    for (var i=0;i<data.length;i++) s += o.renderItem(data[i], val);
158                    that.sc.innerHTML = s;
159                    that.updateSC(0);
160                }
161                else
162                    that.sc.style.display = 'none';
163            }
164
165            that.keydownHandler = function(e){
166                var key = window.event ? e.keyCode : e.which;
167                // down (40), up (38)
168                if ((key == 40 || key == 38) && that.sc.innerHTML) {
169                    e.preventDefault();
170                    var next, sel = that.sc.querySelector('.autocomplete-suggestion.selected');
171                    if (!sel) {
172                        next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last
173                        next.className += ' selected';
174                        if (next.getAttribute('data-val')) that.value = next.getAttribute('data-val');
175                    } else {
176                        next = (key == 40) ? sel.nextSibling : sel.previousSibling;
177                        if (next) {
178                            sel.className = sel.className.replace('selected', '');
179                            next.className += ' selected';
180                            if (next.getAttribute('data-val')) that.value = next.getAttribute('data-val');
181                        }
182                        else {
183                            sel.className = sel.className.replace('selected', '');
184                            that.value = that.last_val;
185                            next = 0;
186                        }
187                    }
188                    that.updateSC(0, next);
189                    return false;
190                }
191                // esc
192                else if (key == 27) {
193                    if (that.sc.style.display != 'none') {
194                        // just close the overlay if it's open, and prevent other listeners
195                        // from recognizing it; this is not for you!
196                        e.preventDefault();
197                        e.stopImmediatePropagation();
198                        that.sc.style.display = 'none';
199                        var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
200                        if (sel) {
201                            that.focus();
202                        }
203                    }
204                    else {
205                        // if no overlay is open, we want to remove the search term and also
206                        // want other listeners to recognize it
207                        that.value = '';
208                    }
209                }
210                // enter
211                else if (key == 13 || key == 9) {
212                    var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
213                    if (sel && that.sc.style.display != 'none') { o.onSelect(e, sel.getAttribute('data-val'), sel); setTimeout(function(){ that.sc.style.display = 'none'; }, 20); }
214                }
215            };
216            addEvent(that, 'keydown', that.keydownHandler);
217
218            that.keyupHandler = function(e){
219                var key = window.event ? e.keyCode : e.which;
220                if (!key || (key < 35 || key > 40) && key != 13 && key != 27) {
221                    var val = that.value;
222                    if (val.length >= o.minChars) {
223                        if (val != that.last_val) {
224                            that.last_val = val;
225                            clearTimeout(that.timer);
226                            if (o.cache) {
227                                if (val in that.cache) { suggest(that.cache[val]); return; }
228                                // no requests if previous suggestions were empty
229                                for (var i=1; i<val.length-o.minChars; i++) {
230                                    var part = val.slice(0, val.length-i);
231                                    if (part in that.cache && !that.cache[part].length) { suggest([]); return; }
232                                }
233                            }
234                            that.timer = setTimeout(function(){ o.source(val, suggest) }, o.delay);
235                        }
236                    } else {
237                        that.last_val = val;
238                        that.sc.style.display = 'none';
239                    }
240                }
241            };
242            addEvent(that, 'keyup', that.keyupHandler);
243
244            that.focusHandler = function(e){
245                that.last_val = '\n';
246                that.keyupHandler(e)
247            };
248            addEvent(that, 'focus', that.focusHandler);
249        }
250
251        // public destroy method
252        this.destroy = function(){
253            for (var i=0; i<elems.length; i++) {
254                var that = elems[i];
255                removeEvent(window, 'resize', that.updateSC);
256                removeEvent(that, 'blur', that.blurHandler);
257                removeEvent(that, 'focus', that.focusHandler);
258                removeEvent(that, 'keydown', that.keydownHandler);
259                removeEvent(that, 'keyup', that.keyupHandler);
260                if (that.autocompleteAttr)
261                    that.setAttribute('autocomplete', that.autocompleteAttr);
262                else
263                    that.removeAttribute('autocomplete');
264                try {
265                    if (o.selectorToInsert && document.querySelector(o.selectorToInsert).contains(that.sc)) {
266                        document.querySelector(o.selectorToInsert).removeChild(that.sc);
267                    } else {
268                        document.body.removeChild(that.sc);
269                    }
270                } catch (error) {
271                    console.log('Destroying error: can\'t find target selector', error);
272                    throw error;
273                }
274                that = null;
275            }
276        };
277    }
278    return autoComplete;
279})();
280
281(function(){
282    if (typeof define === 'function' && define.amd)
283        define('autoComplete', function () { return autoComplete; });
284    else if (typeof module !== 'undefined' && module.exports)
285        module.exports = autoComplete;
286    else
287        window.autoComplete = autoComplete;
288})();

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.