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