PageSourceSearch

https://w3.sdu.edu.tr/assets/js/jquery.autocomplete.js

js sdu.edu.tr collected 2026-09-24 09:03:42 UTC 34,039 bytes, 979 lines download raw bytes

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

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.