PageSourceSearch

https://www.float-schwabing.de/wp-content/themes/pure-fashion-floa…/js/vendor/jquery.autocomplete.js?ver=1.3.4

js float-schwabing.de collected 2026-10-06 13:17:59 UTC 33,171 bytes, 999 lines download raw bytes

1/**
2*  Ajax Autocomplete for jQuery, version 1.4.1
3*  (c) 2017 Tomas Kirda
4*
5*  Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
6*  For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
7*/
8
9/*jslint  browser: true, white: true, single: true, this: true, multivar: true */
10/*global define, window, document, jQuery, exports, require */
11
12// Expose plugin as an AMD module if AMD loader is present:
13(function (factory) {
14    "use strict";
15    if (typeof define === 'function' && define.amd) {
16        // AMD. Register as an anonymous module.
17        define(['jquery'], factory);
18    } else if (typeof exports === 'object' && typeof require === 'function') {
19        // Browserify
20        factory(require('jquery'));
21    } else {
22        // Browser globals
23        factory(jQuery);
24    }
25}(function ($) {
26    'use strict';
27
28    var
29        utils = (function () {
30            return {
31                escapeRegExChars: function (value) {
32                    return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
33                },
34                createNode: function (containerClass) {
35                    var div = document.createElement('ul');
36                    div.classList.add(containerClass);
37                    div.classList.add('product_list_widget');
38                    div.style.display = 'none';
39                    return div;
40                }
41            };
42        }()),
43
44        keys = {
45            ESC: 27,
46            TAB: 9,
47            RETURN: 13,
48            LEFT: 37,
49            UP: 38,
50            RIGHT: 39,
51            DOWN: 40
52        },
53
54        noop = $.noop;
55
56    function Autocomplete(el, options) {
57        var that = this;
58
59        // Shared variables:
60        that.element = el;
61        that.el = $(el);
62        that.suggestions = [];
63        that.badQueries = [];
64        that.selectedIndex = -1;
65        that.currentValue = that.element.value;
66        that.timeoutId = null;
67        that.cachedResponse = {};
68        that.onChangeTimeout = null;
69        that.onChange = null;
70        that.isLocal = false;
71        that.suggestionsContainer = null;
72        that.noSuggestionsContainer = null;
73        that.options = $.extend({}, Autocomplete.defaults, options);
74        that.classes = {
75            selected: 'autocomplete-selected',
76            suggestion: 'autocomplete-suggestion'
77        };
78        that.hint = null;
79        that.hintValue = '';
80        that.selection = null;
81
82        // Initialize and set options:
83        that.initialize();
84        that.setOptions(options);
85    }
86
87    Autocomplete.utils = utils;
88
89    $.Autocomplete = Autocomplete;
90
91    Autocomplete.defaults = {
92            ajaxSettings: {},
93            autoSelectFirst: false,
94            appendTo: 'body',
95            serviceUrl: null,
96            lookup: null,
97            onSelect: null,
98            width: 'auto',
99            minChars: 1,
100            maxHeight: 300,
101            deferRequestBy: 0,
102            params: {},
103            formatResult: _formatResult,
104            formatGroup: _formatGroup,
105            delimiter: null,
106            zIndex: 9999,
107            type: 'GET',
108            noCache: false,
109            onSearchStart: noop,
110            onSearchComplete: noop,
111            onSearchError: noop,
112            preserveInput: false,
113            containerClass: 'autocomplete-suggestions',
114            tabDisabled: false,
115            dataType: 'text',
116            currentRequest: null,
117            triggerSelectOnValidInput: true,
118            preventBadQueries: true,
119            lookupFilter: _lookupFilter,
120            paramName: 'query',
121            transformResult: _transformResult,
122            showNoSuggestionNotice: false,
123            noSuggestionNotice: 'No results',
124            orientation: 'bottom',
125            forceFixPosition: false
126    };
127
128    function _lookupFilter(suggestion, originalQuery, queryLowerCase) {
129        return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
130    };
131
132    function _transformResult(response) {
133        return typeof response === 'string' ? $.parseJSON(response) : response;
134    };
135
136    function _formatResult(suggestion, currentValue) {
137        // Do not replace anything if the current value is empty
138        if (!currentValue) {
139            return suggestion.value;
140        }
141
142        var pattern = '(' + utils.escapeRegExChars(currentValue) + ')';
143
144        return suggestion.value
145            .replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>')
146            .replace(/&/g, '&amp;')
147            .replace(/</g, '&lt;')
148            .replace(/>/g, '&gt;')
149            .replace(/"/g, '&quot;')
150            .replace(/&lt;(\/?strong)&gt;/g, '<$1>');
151    };
152
153    function _formatGroup(suggestion, category) {
154        return '<div class="autocomplete-group">' + category + '</div>';
155    };
156
157    Autocomplete.prototype = {
158
159        initialize: function () {
160            var that = this,
161                suggestionSelector = '.' + that.classes.suggestion,
162                selected = that.classes.selected,
163                options = that.options,
164                container;
165
166            // Remove autocomplete attribute to prevent native suggestions:
167            that.element.setAttribute('autocomplete', 'off' );
168
169            // html() deals with many types: htmlString or Element or Array or jQuery
170            that.noSuggestionsContainer = $('<div class="autocomplete-no-suggestion post"></div>')
171                                          .html(this.options.noSuggestionNotice).get(0);
172
173            that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);
174
175            container = $(that.suggestionsContainer);
176            container.appendTo(options.appendTo || 'body');
177
178            // Only set width if it was provided:
179            if (options.width !== 'auto') {
180                container.css('width', options.width);
181            }
182
183            // Listen for mouse over event on suggestions list:
184            container.on('mouseover.autocomplete', suggestionSelector, function () {
185                that.activate($(this).data('index'));
186            });
187
188            // Deselect active element when mouse leaves suggestions container:
189            container.on('mouseout.autocomplete', function () {
190                that.selectedIndex = -1;
191                container.children('.' + selected).removeClass(selected);
192            });
193
194
195            // Listen for click event on suggestions list:
196            container.on('click.autocomplete', suggestionSelector, function () {
197                that.select($(this).data('index'));
198            });
199
200            container.on('click.autocomplete', function () {
201                clearTimeout(that.blurTimeoutId);
202            });
203
204            that.fixPositionCapture = function () {
205                if (that.visible) {
206                    that.fixPosition();
207                }
208            };
209
210            $(window).on('resize.autocomplete', that.fixPositionCapture);
211
212            that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); });
213            that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); });
214            that.el.on('blur.autocomplete', function () { that.onBlur(); });
215            that.el.on('focus.autocomplete', function () { that.onFocus(); });
216            that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); });
217            that.el.on('input.autocomplete', function (e) { that.onKeyUp(e); });
218        },
219
220        onFocus: function () {
221            var that = this;
222            if (that.disabled) {
223                return;
224            }
225            that.fixPosition();
226
227            if (that.el.val().length >= that.options.minChars) {
228                that.onValueChange();
229            }
230        },
231
232        onBlur: function () {
233          var that = this,
234              options = that.options,
235              value = that.el.val(),
236              query = that.getQuery(value);
237
238          // If user clicked on a suggestion, hide() will
239          // be canceled, otherwise close suggestions
240          that.blurTimeoutId = setTimeout(function () {
241              that.hide();
242
243              if (that.selection && that.currentValue !== query) {
244                  (options.onInvalidateSelection || $.noop).call(that.element);
245              }
246          }, 200);
247        },
248
249        abortAjax: function () {
250            var that = this;
251            if (that.currentRequest) {
252                that.currentRequest.abort();
253                that.currentRequest = null;
254            }
255        },
256
257        setOptions: function (suppliedOptions) {
258            var that = this,
259                options = that.options;
260
261            this.options = $.extend({}, options, suppliedOptions);
262
263            that.isLocal = $.isArray(options.lookup);
264
265            if (that.isLocal) {
266                options.lookup = that.verifySuggestionsFormat(options.lookup);
267            }
268
269            options.orientation = that.validateOrientation(options.orientation, 'bottom');
270
271            // Adjust height, width and z-index:
272            /*
273            $(that.suggestionsContainer).css({
274                'max-height': options.maxHeight + 'px',
275                'width': options.width + 'px',
276                'z-index': options.zIndex
277            });
278            */
279        },
280
281
282        clearCache: function () {
283            this.cachedResponse = {};
284            this.badQueries = [];
285        },
286
287        clear: function () {
288            this.clearCache();
289            this.currentValue = '';
290            this.suggestions = [];
291        },
292
293        disable: function () {
294            var that = this;
295            that.disabled = true;
296            clearTimeout(that.onChangeTimeout);
297            that.abortAjax();
298        },
299
300        enable: function () {
301            this.disabled = false;
302        },
303
304        fixPosition: function () {
305            // Use only when container has already its content
306
307            var that = this,
308                $container = $(that.suggestionsContainer),
309                containerParent = $container.parent().get(0);
310            // Fix position automatically when appended to body.
311            // In other cases force parameter must be given.
312            if (containerParent !== document.body && !that.options.forceFixPosition) {
313                return;
314            }
315
316            // Choose orientation
317            var orientation = that.options.orientation,
318                containerHeight = $container.outerHeight(),
319                height = that.el.outerHeight(),
320                offset = that.el.offset(),
321                styles = { 'top': offset.top, 'left': offset.left };
322
323            if (orientation === 'auto') {
324                var viewPortHeight = $(window).height(),
325                    scrollTop = $(window).scrollTop(),
326                    topOverflow = -scrollTop + offset.top - containerHeight,
327                    bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
328
329                orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow) ? 'top' : 'bottom';
330            }
331
332            if (orientation === 'top') {
333                styles.top += -containerHeight;
334            } else {
335                styles.top += height;
336            }
337
338            // If container is not positioned to body,
339            // correct its position using offset parent offset
340            if(containerParent !== document.body) {
341                var opacity = $container.css('opacity'),
342                    parentOffsetDiff;
343
344                    if (!that.visible){
345                        $container.css('opacity', 0).show();
346                    }
347
348                parentOffsetDiff = $container.offsetParent().offset();
349                styles.top -= parentOffsetDiff.top;
350                styles.left -= parentOffsetDiff.left;
351
352                if (!that.visible){
353                    $container.css('opacity', opacity).hide();
354                }
355            }
356
357            if (that.options.width === 'auto') {
358                styles.width = that.el.outerWidth() + 'px';
359            }
360
361            $container.css(styles);
362        },
363
364        isCursorAtEnd: function () {
365            var that = this,
366                valLength = that.el.val().length,
367                selectionStart = that.element.selectionStart,
368                range;
369
370            if (typeof selectionStart === 'number') {
371                return selectionStart === valLength;
372            }
373            if (document.selection) {
374                range = document.selection.createRange();
375                range.moveStart('character', -valLength);
376                return valLength === range.text.length;
377            }
378            return true;
379        },
380
381        onKeyPress: function (e) {
382            var that = this;
383
384            // If suggestions are hidden and user presses arrow down, display suggestions:
385            if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) {
386                that.suggest();
387                return;
388            }
389
390            if (that.disabled || !that.visible) {
391                return;
392            }
393
394            switch (e.which) {
395                case keys.ESC:
396                    that.el.val(that.currentValue);
397                    $('.results-found').remove();
398                    that.hide();
399                    break;
400                case keys.RIGHT:
401                    if (that.hint && that.options.onHint && that.isCursorAtEnd()) {
402                        that.selectHint();
403                        break;
404                    }
405                    return;
406                case keys.TAB:
407                    if (that.hint && that.options.onHint) {
408                        that.selectHint();
409                        return;
410                    }
411                    if (that.selectedIndex === -1) {
412                        that.hide();
413                        return;
414                    }
415                    that.select(that.selectedIndex);
416                    if (that.options.tabDisabled === false) {
417                        return;
418                    }
419                    break;
420                case keys.RETURN:
421                    if (that.selectedIndex === -1) {
422                        that.hide();
423                        return;
424                    }
425                    that.select(that.selectedIndex);
426                    break;
427                case keys.UP:
428                    that.moveUp();
429                    break;
430                case keys.DOWN:
431                    that.moveDown();
432                    break;
433                default:
434                    return;
435            }
436
437            // Cancel event if function did not return:
438            e.stopImmediatePropagation();
439            e.preventDefault();
440        },
441
442        onKeyUp: function (e) {
443            var that = this;
444
445            if (that.disabled) {
446                return;
447            }
448
449            switch (e.which) {
450                case keys.UP:
451                case keys.DOWN:
452                    return;
453            }
454
455            clearTimeout(that.onChangeTimeout);
456
457            if (that.currentValue !== that.el.val()) {
458                that.findBestHint();
459                if (that.options.deferRequestBy > 0) {
460                    // Defer lookup in case when value changes very quickly:
461                    that.onChangeTimeout = setTimeout(function () {
462                        that.onValueChange();
463                    }, that.options.deferRequestBy);
464                } else {
465                    that.onValueChange();
466                }
467            }
468        },
469
470        onValueChange: function () {
471            var that = this,
472                options = that.options,
473                value = that.el.val(),
474                query = that.getQuery(value);
475
476            if (that.selection && that.currentValue !== query) {
477                that.selection = null;
478                (options.onInvalidateSelection || $.noop).call(that.element);
479            }
480
481            clearTimeout(that.onChangeTimeout);
482            that.currentValue = value;
483            that.selectedIndex = -1;
484
485            // Check existing suggestion for the match before proceeding:
486            if (options.triggerSelectOnValidInput && that.isExactMatch(query)) {
487                that.select(0);
488                return;
489            }
490
491            if (query.length < options.minChars) {
492                that.hide();
493            } else {
494                that.getSuggestions(query);
495            }
496        },
497
498        isExactMatch: function (query) {
499            var suggestions = this.suggestions;
500
501            return (suggestions.length === 1 && suggestions[0].value.toLowerCase() === query.toLowerCase());
502        },
503
504        getQuery: function (value) {
505            var delimiter = this.options.delimiter,
506                parts;
507
508            if (!delimiter) {
509                return value;
510            }
511            parts = value.split(delimiter);
512            return $.trim(parts[parts.length - 1]);
513        },
514
515        getSuggestionsLocal: function (query) {
516            var that = this,
517                options = that.options,
518                queryLowerCase = query.toLowerCase(),
519                filter = options.lookupFilter,
520                limit = parseInt(options.lookupLimit, 10),
521                data;
522
523            data = {
524                suggestions: $.grep(options.lookup, function (suggestion) {
525                    return filter(suggestion, query, queryLowerCase);
526                })
527            };
528
529            if (limit && data.suggestions.length > limit) {
530                data.suggestions = data.suggestions.slice(0, limit);
531            }
532
533            return data;
534        },
535
536        getSuggestions: function (q) {
537            var response,
538                that = this,
539                options = that.options,
540                serviceUrl = options.serviceUrl,
541                params,
542                cacheKey,
543                ajaxSettings;
544
545            options.params[options.paramName] = q;
546
547            if (options.onSearchStart.call(that.element, options.params) === false) {
548                return;
549            }
550
551            params = options.ignoreParams ? null : options.params;
552
553            if ($.isFunction(options.lookup)){
554                options.lookup(q, function (data) {
555                    that.suggestions = data.suggestions;
556                    that.suggest();
557                    options.onSearchComplete.call(that.element, q, data.suggestions);
558                });
559                return;
560            }
561
562            if (that.isLocal) {
563                response = that.getSuggestionsLocal(q);
564            } else {
565                if ($.isFunction(serviceUrl)) {
566                    serviceUrl = serviceUrl.call(that.element, q);
567                }
568                cacheKey = serviceUrl + '?' + $.param(params || {});
569                response = that.cachedResponse[cacheKey];
570            }
571
572            if (response && $.isArray(response.suggestions)) {
573                that.suggestions = response.suggestions;
574                that.suggest();
575                options.onSearchComplete.call(that.element, q, response.suggestions);
576            } else if (!that.isBadQuery(q)) {
577                that.abortAjax();
578
579                ajaxSettings = {
580                    url: serviceUrl,
581                    data: params,
582                    type: options.type,
583                    dataType: options.dataType
584                };
585
586                $.extend(ajaxSettings, options.ajaxSettings);
587
588                that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
589                    var result;
590                    that.currentRequest = null;
591                    result = options.transformResult(data, q);
592                    that.processResponse(result, q, cacheKey);
593                    options.onSearchComplete.call(that.element, q, result.suggestions);
594                }).fail(function (jqXHR, textStatus, errorThrown) {
595                    options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
596                });
597            } else {
598                options.onSearchComplete.call(that.element, q, []);
599            }
600        },
601
602        isBadQuery: function (q) {
603            if (!this.options.preventBadQueries){
604                return false;
605            }
606
607            var badQueries = this.badQueries,
608                i = badQueries.length;
609
610            while (i--) {
611                if (q.indexOf(badQueries[i]) === 0) {
612                    return true;
613                }
614            }
615
616            return false;
617        },
618
619        hide: function () {
620            var that = this,
621                container = $(that.suggestionsContainer);
622
623            if ($.isFunction(that.options.onHide) && that.visible) {
624                that.options.onHide.call(that.element, container);
625            }
626
627            that.visible = false;
628            that.selectedIndex = -1;
629            clearTimeout(that.onChangeTimeout);
630            $(that.suggestionsContainer).hide();
631            that.signalHint(null);
632        },
633
634        suggest: function () {
635            if (!this.suggestions.length) {
636                if (this.options.showNoSuggestionNotice) {
637                    this.noSuggestions();
638                } else {
639                    this.hide();
640                }
641                return;
642            }
643
644            var that = this,
645                options = that.options,
646                groupBy = options.groupBy,
647                formatResult = options.formatResult,
648                value = that.getQuery(that.currentValue),
649                className = that.classes.suggestion,
650                classSelected = that.classes.selected,
651                container = $(that.suggestionsContainer),
652                noSuggestionsContainer = $(that.noSuggestionsContainer),
653                beforeRender = options.beforeRender,
654                html = '',
655                category,
656                formatGroup = function (suggestion, index) {
657                        var currentCategory = suggestion.data[groupBy];
658
659                        if (category === currentCategory){
660                            return '';
661                        }
662
663                        category = currentCategory;
664
665                        return options.formatGroup(suggestion, category);
666                    };
667
668            if (options.triggerSelectOnValidInput && that.isExactMatch(value)) {
669                that.select(0);
670                return;
671            }
672
673            // Build suggestions inner HTML:
674
675            $.each(that.suggestions, function (i, suggestion) {
676                if (groupBy){
677                    html += formatGroup(suggestion, value, i);
678                }
679
680                html += '<li class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value, i) + '</li>';
681            });
682
683            this.adjustContainerWidth();
684
685            noSuggestionsContainer.detach();
686            container.html(html);
687
688            if ($.isFunction(beforeRender)) {
689                beforeRender.call(that.element, container, that.suggestions);
690            }
691
692            that.fixPosition();
693            container.show();
694
695            // Select first value by default:
696            if (options.autoSelectFirst) {
697                that.selectedIndex = 0;
698                container.scrollTop(0);
699                container.children('.' + className).first().addClass(classSelected);
700            }
701
702            that.visible = true;
703            that.findBestHint();
704        },
705
706        noSuggestions: function() {
707             var that = this,
708                 beforeRender = that.options.beforeRender,
709                 container = $(that.suggestionsContainer),
710                 noSuggestionsContainer = $(that.noSuggestionsContainer);
711
712            this.adjustContainerWidth();
713
714            // Some explicit steps. Be careful here as it easy to get
715            // noSuggestionsContainer removed from DOM if not detached properly.
716            noSuggestionsContainer.detach();
717
718            // clean suggestions if any
719            $('.results-found').remove();
720            container.empty();
721            container.append(noSuggestionsContainer);
722
723            if ($.isFunction(beforeRender)) {
724                beforeRender.call(that.element, container, that.suggestions);
725            }
726
727            that.fixPosition();
728
729            container.show();
730            that.visible = true;
731        },
732
733        adjustContainerWidth: function() {
734            var that = this,
735                options = that.options,
736                width,
737                container = $(that.suggestionsContainer);
738
739            // If width is auto, adjust width before displaying suggestions,
740            // because if instance was created before input had width, it will be zero.
741            // Also it adjusts if input width has changed.
742            if (options.width === 'auto') {
743                width = that.el.outerWidth();
744                container.css('width', width > 0 ? width : 300);
745            } else if(options.width === 'flex') {
746                // Trust the source! Unset the width property so it will be the max length
747                // the containing elements.
748                container.css('width', '');
749            }
750        },
751
752        findBestHint: function () {
753            var that = this,
754                value = that.el.val().toLowerCase(),
755                bestMatch = null;
756
757            if (!value) {
758                return;
759            }
760
761            $.each(that.suggestions, function (i, suggestion) {
762                var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0;
763                if (foundMatch) {
764                    bestMatch = suggestion;
765                }
766                return !foundMatch;
767            });
768
769            that.signalHint(bestMatch);
770        },
771
772        signalHint: function (suggestion) {
773            var hintValue = '',
774                that = this;
775            if (suggestion) {
776                hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length);
777            }
778            if (that.hintValue !== hintValue) {
779                that.hintValue = hintValue;
780                that.hint = suggestion;
781                (this.options.onHint || $.noop)(hintValue);
782            }
783        },
784
785        verifySuggestionsFormat: function (suggestions) {
786            // If suggestions is string array, convert them to supported format:
787            if (suggestions.length && typeof suggestions[0] === 'string') {
788                return $.map(suggestions, function (value) {
789                    return { value: value, data: null };
790                });
791            }
792
793            return suggestions;
794        },
795
796        validateOrientation: function(orientation, fallback) {
797            orientation = $.trim(orientation || '').toLowerCase();
798
799            if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){
800                orientation = fallback;
801            }
802
803            return orientation;
804        },
805
806        processResponse: function (result, originalQuery, cacheKey) {
807            var that = this,
808                options = that.options;
809
810            result.suggestions = that.verifySuggestionsFormat(result.suggestions);
811
812            // Cache results if cache is not disabled:
813            if (!options.noCache) {
814                that.cachedResponse[cacheKey] = result;
815                if (options.preventBadQueries && !result.suggestions.length) {
816                    that.badQueries.push(originalQuery);
817                }
818            }
819
820            // Return if originalQuery is not matching current query:
821            if (originalQuery !== that.getQuery(that.currentValue)) {
822                return;
823            }
824
825            that.suggestions = result.suggestions;
826            that.suggest();
827        },
828
829        activate: function (index) {
830            var that = this,
831                activeItem,
832                selected = that.classes.selected,
833                container = $(that.suggestionsContainer),
834                children = container.find('.' + that.classes.suggestion);
835
836            container.find('.' + selected).removeClass(selected);
837
838            that.selectedIndex = index;
839
840            if (that.selectedIndex !== -1 && children.length > that.selectedIndex) {
841                activeItem = children.get(that.selectedIndex);
842                $(activeItem).addClass(selected);
843                return activeItem;
844            }
845
846            return null;
847        },
848
849        selectHint: function () {
850            var that = this,
851                i = $.inArray(that.hint, that.suggestions);
852
853            that.select(i);
854        },
855
856        select: function (i) {
857            var that = this;
858            that.hide();
859            that.onSelect(i);
860        },
861
862        moveUp: function () {
863            var that = this;
864
865            if (that.selectedIndex === -1) {
866                return;
867            }
868
869            if (that.selectedIndex === 0) {
870                $(that.suggestionsContainer).children().first().removeClass(that.classes.selected);
871                that.selectedIndex = -1;
872                that.el.val(that.currentValue);
873                that.findBestHint();
874                return;
875            }
876
877            that.adjustScroll(that.selectedIndex - 1);
878        },
879
880        moveDown: function () {
881            var that = this;
882
883            if (that.selectedIndex === (that.suggestions.length - 1)) {
884                return;
885            }
886
887            that.adjustScroll(that.selectedIndex + 1);
888        },
889
890        adjustScroll: function (index) {
891            var that = this,
892                activeItem = that.activate(index);
893
894            if (!activeItem) {
895                return;
896            }
897
898            var offsetTop,
899                upperBound,
900                lowerBound,
901                heightDelta = $(activeItem).outerHeight();
902
903            offsetTop = activeItem.offsetTop;
904            upperBound = $(that.suggestionsContainer).scrollTop();
905            lowerBound = upperBound + that.options.maxHeight - heightDelta;
906
907            if (offsetTop < upperBound) {
908                $(that.suggestionsContainer).scrollTop(offsetTop);
909            } else if (offsetTop > lowerBound) {
910                $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta);
911            }
912
913            if (!that.options.preserveInput) {
914                that.el.val(that.getValue(that.suggestions[index].value));
915            }
916            that.signalHint(null);
917        },
918
919        onSelect: function (index) {
920            var that = this,
921                onSelectCallback = that.options.onSelect,
922                suggestion = that.suggestions[index];
923
924            that.currentValue = that.getValue(suggestion.value);
925
926            if (that.currentValue !== that.el.val() && !that.options.preserveInput) {
927                that.el.val(that.currentValue);
928            }
929
930            that.signalHint(null);
931            that.suggestions = [];
932            that.selection = suggestion;
933
934            if ($.isFunction(onSelectCallback)) {
935                onSelectCallback.call(that.element, suggestion);
936            }
937        },
938
939        getValue: function (value) {
940            var that = this,
941                delimiter = that.options.delimiter,
942                currentValue,
943                parts;
944
945            if (!delimiter) {
946                return value;
947            }
948
949            currentValue = that.currentValue;
950            parts = currentValue.split(delimiter);
951
952            if (parts.length === 1) {
953                return value;
954            }
955
956            return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value;
957        },
958
959        dispose: function () {
960            var that = this;
961            that.el.off('.autocomplete').removeData('autocomplete');
962            $(window).off('resize.autocomplete', that.fixPositionCapture);
963            $(that.suggestionsContainer).remove();
964        }
965    };
966
967    // Create chainable jQuery plugin:
968    $.fn.devbridgeAutocomplete = function (options, args) {
969        var dataKey = 'autocomplete';
970        // If function invoked without argument return
971        // instance of the first matched element:
972        if (!arguments.length) {
973            return this.first().data(dataKey);
974        }
975
976        return this.each(function () {
977            var inputElement = $(this),
978                instance = inputElement.data(dataKey);
979
980            if (typeof options === 'string') {
981                if (instance && typeof instance[options] === 'function') {
982                    instance[options](args);
983                }
984            } else {
985                // If instance already exists, destroy it:
986                if (instance && instance.dispose) {
987                    instance.dispose();
988                }
989                instance = new Autocomplete(this, options);
990                inputElement.data(dataKey, instance);
991            }
992        });
993    };
994
995    // Don't overwrite if it already exists
996    if (!$.fn.autocomplete) {
997        $.fn.autocomplete = $.fn.devbridgeAutocomplete;
998    }
999}));

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.