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