PageSourceSearch

https://www.oxfordms.net/templates/yoo_nano3/warp/vendor/uikit/js/components/autocomplete.js

js oxfordms.net collected 2026-10-02 11:09:33 UTC 9,683 bytes, 340 lines download raw bytes

1/*! UIkit 2.27.1 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
2(function(addon) {
3
4    var component;
5
6    if (window.UIkit) {
7        component = addon(UIkit);
8    }
9
10    if (typeof define == "function" && define.amd) {
11        define("uikit-autocomplete", ["uikit"], function(){
12            return component || addon(UIkit);
13        });
14    }
15
16})(function(UI){
17
18    "use strict";
19
20    var active;
21
22    UI.component('autocomplete', {
23
24        defaults: {
25            minLength: 3,
26            param: 'search',
27            method: 'post',
28            delay: 300,
29            loadingClass: 'uk-loading',
30            flipDropdown: false,
31            skipClass: 'uk-skip',
32            hoverClass: 'uk-active',
33            source: null,
34            renderer: null,
35
36            // template
37
38            template: '<ul class="uk-nav uk-nav-autocomplete uk-autocomplete-results">{{~items}}<li data-value="{{$item.value}}"><a>{{$item.value}}</a></li>{{/items}}</ul>'
39        },
40
41        visible  : false,
42        value    : null,
43        selected : null,
44
45        boot: function() {
46
47            // init code
48            UI.$html.on("focus.autocomplete.uikit", "[data-uk-autocomplete]", function(e) {
49
50                var ele = UI.$(this);
51
52                if (!ele.data("autocomplete")) {
53                    UI.autocomplete(ele, UI.Utils.options(ele.attr("data-uk-autocomplete")));
54                }
55            });
56
57            // register outer click for autocompletes
58            UI.$html.on("click.autocomplete.uikit", function(e) {
59                if (active && e.target!=active.input[0]) active.hide();
60            });
61        },
62
63        init: function() {
64
65            var $this   = this,
66                select  = false,
67                trigger = UI.Utils.debounce(function(e) {
68
69                    if (select) {
70                        return (select = false);
71                    }
72
73                    $this.handle();
74                }, this.options.delay);
75
76
77            this.dropdown = this.find('.uk-dropdown');
78            this.template = this.find('script[type="text/autocomplete"]').html();
79            this.template = UI.Utils.template(this.template || this.options.template);
80            this.input    = this.find("input:first").attr("autocomplete", "off");
81
82            if (!this.dropdown.length) {
83               this.dropdown = UI.$('<div class="uk-dropdown"></div>').appendTo(this.element);
84            }
85
86            if (this.options.flipDropdown) {
87                this.dropdown.addClass('uk-dropdown-flip');
88            }
89
90            this.dropdown.attr('aria-expanded', 'false');
91
92            this.input.on({
93
94                keydown: function(e) {
95
96                    if (e && e.which && !e.shiftKey && $this.visible) {
97
98                        switch (e.which) {
99                            case 13: // enter
100                                select = true;
101
102                                if ($this.selected) {
103                                    e.preventDefault();
104                                    $this.select();
105                                }
106                                break;
107                            case 38: // up
108                                e.preventDefault();
109                                $this.pick('prev', true);
110                                break;
111                            case 40: // down
112                                e.preventDefault();
113                                $this.pick('next', true);
114                                break;
115                            case 27:
116                            case 9: // esc, tab
117                                $this.hide();
118                                break;
119                            default:
120                                break;
121                        }
122                    }
123
124                },
125                
126                keyup: trigger
127            });
128
129            this.dropdown.on("click", ".uk-autocomplete-results > *", function(){
130                $this.select();
131            });
132
133            this.dropdown.on("mouseover", ".uk-autocomplete-results > *", function(){
134                $this.pick(UI.$(this));
135            });
136
137            this.triggercomplete = trigger;
138        },
139
140        handle: function() {
141
142            var $this = this, old = this.value;
143
144            this.value = this.input.val();
145
146            if (this.value.length < this.options.minLength) return this.hide();
147
148            if (this.value != old) {
149                $this.request();
150            }
151
152            return this;
153        },
154
155        pick: function(item, scrollinview) {
156
157            var $this    = this,
158                items    = UI.$(this.dropdown.find('.uk-autocomplete-results').children(':not(.'+this.options.skipClass+')')),
159                selected = false;
160
161            if (typeof item !== "string" && !item.hasClass(this.options.skipClass)) {
162                selected = item;
163            } else if (item == 'next' || item == 'prev') {
164
165                if (this.selected) {
166                    var index = items.index(this.selected);
167
168                    if (item == 'next') {
169                        selected = items.eq(index + 1 < items.length ? index + 1 : 0);
170                    } else {
171                        selected = items.eq(index - 1 < 0 ? items.length - 1 : index - 1);
172                    }
173
174                } else {
175                    selected = items[(item == 'next') ? 'first' : 'last']();
176                }
177
178                selected = UI.$(selected);
179            }
180
181            if (selected && selected.length) {
182                this.selected = selected;
183                items.removeClass(this.options.hoverClass);
184                this.selected.addClass(this.options.hoverClass);
185
186                // jump to selected if not in view
187                if (scrollinview) {
188
189                    var top       = selected.position().top,
190                        scrollTop = $this.dropdown.scrollTop(),
191                        dpheight  = $this.dropdown.height();
192
193                    if (top > dpheight ||  top < 0) {
194                        $this.dropdown.scrollTop(scrollTop + top);
195                    }
196                }
197            }
198        },
199
200        select: function() {
201
202            if(!this.selected) return;
203
204            var data = this.selected.data();
205
206            this.trigger("selectitem.uk.autocomplete", [data, this]);
207
208            if (data.value) {
209                this.input.val(data.value).trigger('change');
210            }
211
212            this.hide();
213        },
214
215        show: function() {
216
217            if (this.visible) return;
218
219            this.visible = true;
220            this.element.addClass("uk-open");
221
222            if (active && active!==this) {
223                active.hide();
224            }
225
226            active = this;
227
228            // Update aria
229            this.dropdown.attr('aria-expanded', 'true');
230
231            return this;
232        },
233
234        hide: function() {
235            if (!this.visible) return;
236            this.visible = false;
237            this.element.removeClass("uk-open");
238
239            if (active === this) {
240                active = false;
241            }
242
243            // Update aria
244            this.dropdown.attr('aria-expanded', 'false');
245
246            return this;
247        },
248
249        request: function() {
250
251            var $this   = this,
252                release = function(data) {
253
254                    if(data) {
255                        $this.render(data);
256                    }
257
258                    $this.element.removeClass($this.options.loadingClass);
259                };
260
261            this.element.addClass(this.options.loadingClass);
262
263            if (this.options.source) {
264
265                var source = this.options.source;
266
267                switch(typeof(this.options.source)) {
268                    case 'function':
269
270                        this.options.source.apply(this, [release]);
271
272                        break;
273
274                    case 'object':
275
276                        if(source.length) {
277
278                            var items = [];
279
280                            source.forEach(function(item){
281                                if(item.value && item.value.toLowerCase().indexOf($this.value.toLowerCase())!=-1) {
282                                    items.push(item);
283                                }
284                            });
285
286                            release(items);
287                        }
288
289                        break;
290
291                    case 'string':
292
293                        var params ={};
294
295                        params[this.options.param] = this.value;
296
297                        UI.$.ajax({
298                            url: this.options.source,
299                            data: params,
300                            type: this.options.method,
301                            dataType: 'json'
302                        }).done(function(json) {
303                            release(json || []);
304                        });
305
306                        break;
307
308                    default:
309                        release(null);
310                }
311
312            } else {
313                this.element.removeClass($this.options.loadingClass);
314            }
315        },
316
317        render: function(data) {
318
319            this.dropdown.empty();
320
321            this.selected = false;
322
323            if (this.options.renderer) {
324
325                this.options.renderer.apply(this, [data]);
326
327            } else if(data && data.length) {
328
329                this.dropdown.append(this.template({"items":data}));
330                this.show();
331
332                this.trigger('show.uk.autocomplete');
333            }
334
335            return this;
336        }
337    });
338
339    return UI.autocomplete;
340});

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.