Issues (4542)

js/autocomplete/jquery.autocomplete.js (3 issues)

1
/**
2
*  Ajax Autocomplete for jQuery, version 1.2.9
3
*  (c) 2013 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
10
/*jslint  browser: true, white: true, plusplus: true */
11
/*global define, window, document, jQuery */
12
13
// Expose plugin as an AMD module if AMD loader is present:
14
(function (factory) {
15
    'use strict';
16
    if (typeof define === 'function' && define.amd) {
17
        // AMD. Register as an anonymous module.
18
        define(['jquery'], factory);
19
    } else {
20
        // Browser globals
21
        factory(jQuery);
22
    }
23
}(function ($) {
24
    'use strict';
25
26
    var
27
        utils = (function () {
28
            return {
29
                escapeRegExChars: function (value) {
30
                    return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
31
                },
32
                createNode: function (containerClass) {
33
                    var div = document.createElement('div');
34
                    div.className = containerClass;
35
                    div.style.position = 'absolute';
36
                    div.style.display = 'none';
37
                    return div;
38
                }
39
            };
40
        }()),
41
42
        keys = {
43
            ESC: 27,
44
            TAB: 9,
45
            RETURN: 13,
46
            LEFT: 37,
47
            UP: 38,
48
            RIGHT: 39,
49
            DOWN: 40
50
        };
51
52
    function Autocomplete(el, options) {
53
        var noop = function () { },
54
            that = this,
55
            defaults = {
56
                autoSelectFirst: false,
57
                appendTo: 'body',
58
                serviceUrl: null,
59
                lookup: null,
60
                onSelect: null,
61
                width: 'auto',
62
                minChars: 1,
63
                maxHeight: 300,
64
                deferRequestBy: 0,
65
                params: {},
66
                formatResult: Autocomplete.formatResult,
67
                delimiter: null,
68
                zIndex: 9999,
69
                type: 'GET',
70
                noCache: false,
71
                onSearchStart: noop,
72
                onSearchComplete: noop,
73
                onSearchError: noop,
74
                containerClass: 'autocomplete-suggestions',
75
                tabDisabled: false,
76
                dataType: 'text',
77
                currentRequest: null,
78
                triggerSelectOnValidInput: true,
79
                preventBadQueries: true,
80
                lookupFilter: function (suggestion, originalQuery, queryLowerCase) {
81
                    return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
82
                },
83
                paramName: 'query',
84
                transformResult: function (response) {
85
                    return typeof response === 'string' ? $.parseJSON(response) : response;
86
                }
87
            };
88
89
        // Shared variables:
90
        that.element = el;
91
        that.el = $(el);
92
        that.suggestions = [];
93
        that.badQueries = [];
94
        that.selectedIndex = -1;
95
        that.currentValue = that.element.value;
96
        that.intervalId = 0;
97
        that.cachedResponse = {};
98
        that.onChangeInterval = null;
99
        that.onChange = null;
100
        that.isLocal = false;
101
        that.suggestionsContainer = null;
102
        that.options = $.extend({}, defaults, options);
103
        that.classes = {
104
            selected: 'autocomplete-selected',
105
            suggestion: 'autocomplete-suggestion'
106
        };
107
        that.hint = null;
108
        that.hintValue = '';
109
        that.selection = null;
110
111
        // Initialize and set options:
112
        that.initialize();
113
        that.setOptions(options);
114
    }
115
116
    Autocomplete.utils = utils;
117
118
    $.Autocomplete = Autocomplete;
119
120
    Autocomplete.formatResult = function (suggestion, currentValue) {
121
        var pattern = '(' + utils.escapeRegExChars(currentValue) + ')';
122
123
        return suggestion.value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
124
    };
125
126
    Autocomplete.prototype = {
127
128
        killerFn: null,
129
130
        initialize: function () {
131
            var that = this,
132
                suggestionSelector = '.' + that.classes.suggestion,
133
                selected = that.classes.selected,
134
                options = that.options,
135
                container;
136
137
            // Remove autocomplete attribute to prevent native suggestions:
138
            that.element.setAttribute('autocomplete', 'off');
139
140
            that.killerFn = function (e) {
141
                if ($(e.target).closest('.' + that.options.containerClass).length === 0) {
142
                    that.killSuggestions();
143
                    that.disableKillerFn();
144
                }
145
            };
146
147
            that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);
148
149
            container = $(that.suggestionsContainer);
150
151
            container.appendTo(options.appendTo);
152
153
            // Only set width if it was provided:
154
            if (options.width !== 'auto') {
155
                container.width(options.width);
156
            }
157
158
            // Listen for mouse over event on suggestions list:
159
            container.on('mouseover.autocomplete', suggestionSelector, function () {
160
                that.activate($(this).data('index'));
161
            });
162
163
            // Deselect Aktif element when mouse leaves suggestions container:
164
            container.on('mouseout.autocomplete', function () {
165
                that.selectedIndex = -1;
166
                container.children('.' + selected).removeClass(selected);
167
            });
168
169
            // Listen for click event on suggestions list:
170
            container.on('click.autocomplete', suggestionSelector, function () {
171
                that.select($(this).data('index'));
172
            });
173
174
            that.fixPosition();
175
176
            that.fixPositionCapture = function () {
177
                if (that.visible) {
178
                    that.fixPosition();
179
                }
180
            };
181
182
            $(window).on('resize.autocomplete', that.fixPositionCapture);
183
184
            that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); });
185
            that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); });
186
            that.el.on('blur.autocomplete', function () { that.onBlur(); });
187
            that.el.on('focus.autocomplete', function () { that.onFocus(); });
188
            that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); });
189
        },
190
191
        onFocus: function () {
192
            var that = this;
193
            that.fixPosition();
194
            if (that.options.minChars <= that.el.val().length) {
195
                that.onValueChange();
196
            }
197
        },
198
199
        onBlur: function () {
200
            this.enableKillerFn();
201
        },
202
203
        setOptions: function (suppliedOptions) {
204
            var that = this,
205
                options = that.options;
206
207
            $.extend(options, suppliedOptions);
208
209
            that.isLocal = $.isArray(options.lookup);
210
211
            if (that.isLocal) {
212
                options.lookup = that.verifySuggestionsFormat(options.lookup);
213
            }
214
215
            // Adjust height, width and z-index:
216
            $(that.suggestionsContainer).css({
217
                'max-height': options.maxHeight + 'px',
218
                'width': options.width + 'px',
219
                'z-index': options.zIndex
220
            });
221
        },
222
223
        clearCache: function () {
224
            this.cachedResponse = {};
225
            this.badQueries = [];
226
        },
227
228
        clear: function () {
229
            this.clearCache();
230
            this.currentValue = '';
231
            this.suggestions = [];
232
        },
233
234
        disable: function () {
235
            var that = this;
236
            that.disabled = true;
237
            if (that.currentRequest) {
238
                that.currentRequest.abort();
239
            }
240
        },
241
242
        enable: function () {
243
            this.disabled = false;
244
        },
245
246
        fixPosition: function () {
247
            var that = this,
248
                offset,
249
                styles;
250
251
            // Don't adjsut position if custom container has been specified:
252
            if (that.options.appendTo !== 'body') {
253
                return;
254
            }
255
256
            offset = that.el.offset();
257
258
            styles = {
259
                top: (offset.top + that.el.outerHeight()) + 'px',
260
                left: offset.left + 'px'
261
            };
262
263
            if (that.options.width === 'auto') {
264
                styles.width = (that.el.outerWidth() - 2) + 'px';
265
            }
266
267
            $(that.suggestionsContainer).css(styles);
268
        },
269
270
        enableKillerFn: function () {
271
            var that = this;
272
            $(document).on('click.autocomplete', that.killerFn);
273
        },
274
275
        disableKillerFn: function () {
276
            var that = this;
277
            $(document).off('click.autocomplete', that.killerFn);
278
        },
279
280
        killSuggestions: function () {
281
            var that = this;
282
            that.stopKillSuggestions();
283
            that.intervalId = window.setInterval(function () {
284
                that.hide();
285
                that.stopKillSuggestions();
286
            }, 50);
287
        },
288
289
        stopKillSuggestions: function () {
290
            window.clearInterval(this.intervalId);
291
        },
292
293
        isCursorAtEnd: function () {
294
            var that = this,
295
                valLength = that.el.val().length,
296
                selectionStart = that.element.selectionStart,
297
                range;
298
299
            if (typeof selectionStart === 'number') {
300
                return selectionStart === valLength;
301
            }
302
            if (document.selection) {
303
                range = document.selection.createRange();
304
                range.moveStart('character', -valLength);
305
                return valLength === range.text.length;
306
            }
307
            return true;
308
        },
309
310
        onKeyPress: function (e) {
311
            var that = this;
312
313
            // If suggestions are hidden and user presses arrow down, display suggestions:
314
            if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) {
315
                that.suggest();
316
                return;
317
            }
318
319
            if (that.disabled || !that.visible) {
320
                return;
321
            }
322
323
            switch (e.which) {
324
                case keys.ESC:
325
                    that.el.val(that.currentValue);
326
                    that.hide();
327
                    break;
328
                case keys.RIGHT:
329
                    if (that.hint && that.options.onHint && that.isCursorAtEnd()) {
330
                        that.selectHint();
331
                        break;
332
                    }
333
                    return;
334
                case keys.TAB:
335
                    if (that.hint && that.options.onHint) {
336
                        that.selectHint();
337
                        return;
338
                    }
0 ignored issues
show
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
339
                    // Fall through to RETURN
340
                case keys.RETURN:
341
                    if (that.selectedIndex === -1) {
342
                        that.hide();
343
                        return;
344
                    }
345
                    that.select(that.selectedIndex);
346
                    if (e.which === keys.TAB && that.options.tabDisabled === false) {
347
                        return;
348
                    }
349
                    break;
350
                case keys.UP:
351
                    that.moveUp();
352
                    break;
353
                case keys.DOWN:
354
                    that.moveDown();
355
                    break;
356
                default:
357
                    return;
358
            }
359
360
            // Cancel event if function did not return:
361
            e.stopImmediatePropagation();
362
            e.preventDefault();
363
        },
364
365
        onKeyUp: function (e) {
366
            var that = this;
367
368
            if (that.disabled) {
369
                return;
370
            }
371
372
            switch (e.which) {
373
                case keys.UP:
374
                case keys.DOWN:
375
                    return;
376
            }
377
378
            clearInterval(that.onChangeInterval);
379
380
            if (that.currentValue !== that.el.val()) {
381
                that.findBestHint();
382
                if (that.options.deferRequestBy > 0) {
383
                    // Defer lookup in case when value changes very quickly:
384
                    that.onChangeInterval = setInterval(function () {
385
                        that.onValueChange();
386
                    }, that.options.deferRequestBy);
387
                } else {
388
                    that.onValueChange();
389
                }
390
            }
391
        },
392
393
        onValueChange: function () {
394
            var that = this,
395
                options = that.options,
396
                value = that.el.val(),
397
                query = that.getQuery(value),
398
                index;
399
400
            if (that.selection) {
401
                that.selection = null;
402
                (options.onInvalidateSelection || $.noop).call(that.element);
403
            }
404
405
            clearInterval(that.onChangeInterval);
406
            that.currentValue = value;
407
            that.selectedIndex = -1;
408
409
            // Check existing suggestion for the match before proceeding:
410
            if (options.triggerSelectOnValidInput) {
411
                index = that.findSuggestionIndex(query);
412
                if (index !== -1) {
413
                    that.select(index);
414
                    return;
415
                }
416
            }
417
418
            if (query.length < options.minChars) {
419
                that.hide();
420
            } else {
421
                that.getSuggestions(query);
422
            }
423
        },
424
425
        findSuggestionIndex: function (query) {
426
            var that = this,
427
                index = -1,
428
                queryLowerCase = query.toLowerCase();
429
430
            $.each(that.suggestions, function (i, suggestion) {
431
                if (suggestion.value.toLowerCase() === queryLowerCase) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if suggestion.value.toLowerCase() === queryLowerCase is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
432
                    index = i;
433
                    return false;
434
                }
435
            });
436
437
            return index;
438
        },
439
440
        getQuery: function (value) {
441
            var delimiter = this.options.delimiter,
442
                parts;
443
444
            if (!delimiter) {
445
                return value;
446
            }
447
            parts = value.split(delimiter);
448
            return $.trim(parts[parts.length - 1]);
449
        },
450
451
        getSuggestionsLocal: function (query) {
452
            var that = this,
453
                options = that.options,
454
                queryLowerCase = query.toLowerCase(),
455
                filter = options.lookupFilter,
456
                limit = parseInt(options.lookupLimit, 10),
457
                data;
458
459
            data = {
460
                suggestions: $.grep(options.lookup, function (suggestion) {
461
                    return filter(suggestion, query, queryLowerCase);
462
                })
463
            };
464
465
            if (limit && data.suggestions.length > limit) {
466
                data.suggestions = data.suggestions.slice(0, limit);
467
            }
468
469
            return data;
470
        },
471
472
        getSuggestions: function (q) {
473
            var response,
474
                that = this,
475
                options = that.options,
476
                serviceUrl = options.serviceUrl,
477
                params,
478
                cacheKey;
479
480
            options.params[options.paramName] = q;
481
            params = options.ignoreParams ? null : options.params;
482
483
            if (that.isLocal) {
484
                response = that.getSuggestionsLocal(q);
485
            } else {
486
                if ($.isFunction(serviceUrl)) {
487
                    serviceUrl = serviceUrl.call(that.element, q);
488
                }
489
                cacheKey = serviceUrl + '?' + $.param(params || {});
490
                response = that.cachedResponse[cacheKey];
491
            }
492
493
            if (response && $.isArray(response.suggestions)) {
494
                that.suggestions = response.suggestions;
495
                that.suggest();
496
            } else if (!that.isBadQuery(q)) {
497
                if (options.onSearchStart.call(that.element, options.params) === false) {
498
                    return;
499
                }
500
                if (that.currentRequest) {
501
                    that.currentRequest.abort();
502
                }
503
                that.currentRequest = $.ajax({
504
                    url: serviceUrl,
505
                    data: params,
506
                    type: options.type,
507
                    dataType: options.dataType
508
                }).done(function (data) {
509
                    var result;
510
                    that.currentRequest = null;
511
                    result = options.transformResult(data);
512
                    that.processResponse(result, q, cacheKey);
0 ignored issues
show
The variable cacheKey seems to not be initialized for all possible execution paths. Are you sure processResponse handles undefined variables?
Loading history...
513
                    options.onSearchComplete.call(that.element, q, result.suggestions);
514
                }).fail(function (jqXHR, textStatus, errorThrown) {
515
                    options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
516
                });
517
            }
518
        },
519
520
        isBadQuery: function (q) {
521
            if (!this.options.preventBadQueries){
522
                return false;
523
            }
524
525
            var badQueries = this.badQueries,
526
                i = badQueries.length;
527
528
            while (i--) {
529
                if (q.indexOf(badQueries[i]) === 0) {
530
                    return true;
531
                }
532
            }
533
534
            return false;
535
        },
536
537
        hide: function () {
538
            var that = this;
539
            that.visible = false;
540
            that.selectedIndex = -1;
541
            $(that.suggestionsContainer).hide();
542
            that.signalHint(null);
543
        },
544
545
        suggest: function () {
546
            if (this.suggestions.length === 0) {
547
                this.hide();
548
                return;
549
            }
550
551
            var that = this,
552
                options = that.options,
553
                formatResult = options.formatResult,
554
                value = that.getQuery(that.currentValue),
555
                className = that.classes.suggestion,
556
                classSelected = that.classes.selected,
557
                container = $(that.suggestionsContainer),
558
                beforeRender = options.beforeRender,
559
                html = '',
560
                index,
561
                width;
562
563
            if (options.triggerSelectOnValidInput) {
564
                index = that.findSuggestionIndex(value);
565
                if (index !== -1) {
566
                    that.select(index);
567
                    return;
568
                }
569
            }
570
571
            // Build suggestions inner HTML:
572
            $.each(that.suggestions, function (i, suggestion) {
573
                html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value) + '</div>';
574
            });
575
576
            // If width is auto, adjust width before displaying suggestions,
577
            // because if instance was created before input had width, it will be zero.
578
            // Also it adjusts if input width has changed.
579
            // -2px to account for suggestions border.
580
            if (options.width === 'auto') {
581
                width = that.el.outerWidth() - 2;
582
                container.width(width > 0 ? width : 300);
583
            }
584
585
            container.html(html);
586
587
            // Select first value by default:
588
            if (options.autoSelectFirst) {
589
                that.selectedIndex = 0;
590
                container.children().first().addClass(classSelected);
591
            }
592
593
            if ($.isFunction(beforeRender)) {
594
                beforeRender.call(that.element, container);
595
            }
596
597
            container.show();
598
            that.visible = true;
599
600
            that.findBestHint();
601
        },
602
603
        findBestHint: function () {
604
            var that = this,
605
                value = that.el.val().toLowerCase(),
606
                bestMatch = null;
607
608
            if (!value) {
609
                return;
610
            }
611
612
            $.each(that.suggestions, function (i, suggestion) {
613
                var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0;
614
                if (foundMatch) {
615
                    bestMatch = suggestion;
616
                }
617
                return !foundMatch;
618
            });
619
620
            that.signalHint(bestMatch);
621
        },
622
623
        signalHint: function (suggestion) {
624
            var hintValue = '',
625
                that = this;
626
            if (suggestion) {
627
                hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length);
628
            }
629
            if (that.hintValue !== hintValue) {
630
                that.hintValue = hintValue;
631
                that.hint = suggestion;
632
                (this.options.onHint || $.noop)(hintValue);
633
            }
634
        },
635
636
        verifySuggestionsFormat: function (suggestions) {
637
            // If suggestions is string array, convert them to supported format:
638
            if (suggestions.length && typeof suggestions[0] === 'string') {
639
                return $.map(suggestions, function (value) {
640
                    return { value: value, data: null };
641
                });
642
            }
643
644
            return suggestions;
645
        },
646
647
        processResponse: function (result, originalQuery, cacheKey) {
648
            var that = this,
649
                options = that.options;
650
651
            result.suggestions = that.verifySuggestionsFormat(result.suggestions);
652
653
            // Cache results if cache is not disabled:
654
            if (!options.noCache) {
655
                that.cachedResponse[cacheKey] = result;
656
                if (options.preventBadQueries && result.suggestions.length === 0) {
657
                    that.badQueries.push(originalQuery);
658
                }
659
            }
660
661
            // Return if originalQuery is not matching current query:
662
            if (originalQuery !== that.getQuery(that.currentValue)) {
663
                return;
664
            }
665
666
            that.suggestions = result.suggestions;
667
            that.suggest();
668
        },
669
670
        activate: function (index) {
671
            var that = this,
672
                AktifItem,
673
                selected = that.classes.selected,
674
                container = $(that.suggestionsContainer),
675
                children = container.children();
676
677
            container.children('.' + selected).removeClass(selected);
678
679
            that.selectedIndex = index;
680
681
            if (that.selectedIndex !== -1 && children.length > that.selectedIndex) {
682
                AktifItem = children.get(that.selectedIndex);
683
                $(AktifItem).addClass(selected);
684
                return AktifItem;
685
            }
686
687
            return null;
688
        },
689
690
        selectHint: function () {
691
            var that = this,
692
                i = $.inArray(that.hint, that.suggestions);
693
694
            that.select(i);
695
        },
696
697
        select: function (i) {
698
            var that = this;
699
            that.hide();
700
            that.onSelect(i);
701
        },
702
703
        moveUp: function () {
704
            var that = this;
705
706
            if (that.selectedIndex === -1) {
707
                return;
708
            }
709
710
            if (that.selectedIndex === 0) {
711
                $(that.suggestionsContainer).children().first().removeClass(that.classes.selected);
712
                that.selectedIndex = -1;
713
                that.el.val(that.currentValue);
714
                that.findBestHint();
715
                return;
716
            }
717
718
            that.adjustScroll(that.selectedIndex - 1);
719
        },
720
721
        moveDown: function () {
722
            var that = this;
723
724
            if (that.selectedIndex === (that.suggestions.length - 1)) {
725
                return;
726
            }
727
728
            that.adjustScroll(that.selectedIndex + 1);
729
        },
730
731
        adjustScroll: function (index) {
732
            var that = this,
733
                AktifItem = that.activate(index),
734
                offsetTop,
735
                upperBound,
736
                lowerBound,
737
                heightDelta = 25;
738
739
            if (!AktifItem) {
740
                return;
741
            }
742
743
            offsetTop = AktifItem.offsetTop;
744
            upperBound = $(that.suggestionsContainer).scrollTop();
745
            lowerBound = upperBound + that.options.maxHeight - heightDelta;
746
747
            if (offsetTop < upperBound) {
748
                $(that.suggestionsContainer).scrollTop(offsetTop);
749
            } else if (offsetTop > lowerBound) {
750
                $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta);
751
            }
752
753
            that.el.val(that.getValue(that.suggestions[index].value));
754
            that.signalHint(null);
755
        },
756
757
        onSelect: function (index) {
758
            var that = this,
759
                onSelectCallback = that.options.onSelect,
760
                suggestion = that.suggestions[index];
761
762
            that.currentValue = that.getValue(suggestion.value);
763
764
            if (that.currentValue !== that.el.val()) {
765
                that.el.val(that.currentValue);
766
            }
767
768
            that.signalHint(null);
769
            that.suggestions = [];
770
            that.selection = suggestion;
771
772
            if ($.isFunction(onSelectCallback)) {
773
                onSelectCallback.call(that.element, suggestion);
774
            }
775
        },
776
777
        getValue: function (value) {
778
            var that = this,
779
                delimiter = that.options.delimiter,
780
                currentValue,
781
                parts;
782
783
            if (!delimiter) {
784
                return value;
785
            }
786
787
            currentValue = that.currentValue;
788
            parts = currentValue.split(delimiter);
789
790
            if (parts.length === 1) {
791
                return value;
792
            }
793
794
            return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value;
795
        },
796
797
        dispose: function () {
798
            var that = this;
799
            that.el.off('.autocomplete').removeData('autocomplete');
800
            that.disableKillerFn();
801
            $(window).off('resize.autocomplete', that.fixPositionCapture);
802
            $(that.suggestionsContainer).remove();
803
        }
804
    };
805
806
    // Create chainable jQuery plugin:
807
    $.fn.autocomplete = function (options, args) {
808
        var dataKey = 'autocomplete';
809
        // If function invoked without argument return
810
        // instance of the first matched element:
811
        if (arguments.length === 0) {
812
            return this.first().data(dataKey);
813
        }
814
815
        return this.each(function () {
816
            var inputElement = $(this),
817
                instance = inputElement.data(dataKey);
818
819
            if (typeof options === 'string') {
820
                if (instance && typeof instance[options] === 'function') {
821
                    instance[options](args);
822
                }
823
            } else {
824
                // If instance already exists, destroy it:
825
                if (instance && instance.dispose) {
826
                    instance.dispose();
827
                }
828
                instance = new Autocomplete(this, options);
829
                inputElement.data(dataKey, instance);
830
            }
831
        });
832
    };
833
}));
834