wp/wp-includes/js/jquery/ui/autocomplete.js
changeset 18 be944660c56a
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
       
     1 /*!
       
     2  * jQuery UI Autocomplete 1.12.1
       
     3  * http://jqueryui.com
       
     4  *
       
     5  * Copyright jQuery Foundation and other contributors
       
     6  * Released under the MIT license.
       
     7  * http://jquery.org/license
       
     8  */
       
     9 
       
    10 //>>label: Autocomplete
       
    11 //>>group: Widgets
       
    12 //>>description: Lists suggested words as the user is typing.
       
    13 //>>docs: http://api.jqueryui.com/autocomplete/
       
    14 //>>demos: http://jqueryui.com/autocomplete/
       
    15 //>>css.structure: ../../themes/base/core.css
       
    16 //>>css.structure: ../../themes/base/autocomplete.css
       
    17 //>>css.theme: ../../themes/base/theme.css
       
    18 
       
    19 ( function( factory ) {
       
    20 	if ( typeof define === "function" && define.amd ) {
       
    21 
       
    22 		// AMD. Register as an anonymous module.
       
    23 		define( [
       
    24 			"jquery",
       
    25 			"./menu",
       
    26 			"./core"
       
    27 		], factory );
       
    28 	} else {
       
    29 
       
    30 		// Browser globals
       
    31 		factory( jQuery );
       
    32 	}
       
    33 }( function( $ ) {
       
    34 
       
    35 $.widget( "ui.autocomplete", {
       
    36 	version: "1.12.1",
       
    37 	defaultElement: "<input>",
       
    38 	options: {
       
    39 		appendTo: null,
       
    40 		autoFocus: false,
       
    41 		delay: 300,
       
    42 		minLength: 1,
       
    43 		position: {
       
    44 			my: "left top",
       
    45 			at: "left bottom",
       
    46 			collision: "none"
       
    47 		},
       
    48 		source: null,
       
    49 
       
    50 		// Callbacks
       
    51 		change: null,
       
    52 		close: null,
       
    53 		focus: null,
       
    54 		open: null,
       
    55 		response: null,
       
    56 		search: null,
       
    57 		select: null
       
    58 	},
       
    59 
       
    60 	requestIndex: 0,
       
    61 	pending: 0,
       
    62 
       
    63 	_create: function() {
       
    64 
       
    65 		// Some browsers only repeat keydown events, not keypress events,
       
    66 		// so we use the suppressKeyPress flag to determine if we've already
       
    67 		// handled the keydown event. #7269
       
    68 		// Unfortunately the code for & in keypress is the same as the up arrow,
       
    69 		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
       
    70 		// events when we know the keydown event was used to modify the
       
    71 		// search term. #7799
       
    72 		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
       
    73 			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
       
    74 			isTextarea = nodeName === "textarea",
       
    75 			isInput = nodeName === "input";
       
    76 
       
    77 		// Textareas are always multi-line
       
    78 		// Inputs are always single-line, even if inside a contentEditable element
       
    79 		// IE also treats inputs as contentEditable
       
    80 		// All other element types are determined by whether or not they're contentEditable
       
    81 		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
       
    82 
       
    83 		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
       
    84 		this.isNewMenu = true;
       
    85 
       
    86 		this._addClass( "ui-autocomplete-input" );
       
    87 		this.element.attr( "autocomplete", "off" );
       
    88 
       
    89 		this._on( this.element, {
       
    90 			keydown: function( event ) {
       
    91 				if ( this.element.prop( "readOnly" ) ) {
       
    92 					suppressKeyPress = true;
       
    93 					suppressInput = true;
       
    94 					suppressKeyPressRepeat = true;
       
    95 					return;
       
    96 				}
       
    97 
       
    98 				suppressKeyPress = false;
       
    99 				suppressInput = false;
       
   100 				suppressKeyPressRepeat = false;
       
   101 				var keyCode = $.ui.keyCode;
       
   102 				switch ( event.keyCode ) {
       
   103 				case keyCode.PAGE_UP:
       
   104 					suppressKeyPress = true;
       
   105 					this._move( "previousPage", event );
       
   106 					break;
       
   107 				case keyCode.PAGE_DOWN:
       
   108 					suppressKeyPress = true;
       
   109 					this._move( "nextPage", event );
       
   110 					break;
       
   111 				case keyCode.UP:
       
   112 					suppressKeyPress = true;
       
   113 					this._keyEvent( "previous", event );
       
   114 					break;
       
   115 				case keyCode.DOWN:
       
   116 					suppressKeyPress = true;
       
   117 					this._keyEvent( "next", event );
       
   118 					break;
       
   119 				case keyCode.ENTER:
       
   120 
       
   121 					// when menu is open and has focus
       
   122 					if ( this.menu.active ) {
       
   123 
       
   124 						// #6055 - Opera still allows the keypress to occur
       
   125 						// which causes forms to submit
       
   126 						suppressKeyPress = true;
       
   127 						event.preventDefault();
       
   128 						this.menu.select( event );
       
   129 					}
       
   130 					break;
       
   131 				case keyCode.TAB:
       
   132 					if ( this.menu.active ) {
       
   133 						this.menu.select( event );
       
   134 					}
       
   135 					break;
       
   136 				case keyCode.ESCAPE:
       
   137 					if ( this.menu.element.is( ":visible" ) ) {
       
   138 						if ( !this.isMultiLine ) {
       
   139 							this._value( this.term );
       
   140 						}
       
   141 						this.close( event );
       
   142 
       
   143 						// Different browsers have different default behavior for escape
       
   144 						// Single press can mean undo or clear
       
   145 						// Double press in IE means clear the whole form
       
   146 						event.preventDefault();
       
   147 					}
       
   148 					break;
       
   149 				default:
       
   150 					suppressKeyPressRepeat = true;
       
   151 
       
   152 					// search timeout should be triggered before the input value is changed
       
   153 					this._searchTimeout( event );
       
   154 					break;
       
   155 				}
       
   156 			},
       
   157 			keypress: function( event ) {
       
   158 				if ( suppressKeyPress ) {
       
   159 					suppressKeyPress = false;
       
   160 					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
       
   161 						event.preventDefault();
       
   162 					}
       
   163 					return;
       
   164 				}
       
   165 				if ( suppressKeyPressRepeat ) {
       
   166 					return;
       
   167 				}
       
   168 
       
   169 				// Replicate some key handlers to allow them to repeat in Firefox and Opera
       
   170 				var keyCode = $.ui.keyCode;
       
   171 				switch ( event.keyCode ) {
       
   172 				case keyCode.PAGE_UP:
       
   173 					this._move( "previousPage", event );
       
   174 					break;
       
   175 				case keyCode.PAGE_DOWN:
       
   176 					this._move( "nextPage", event );
       
   177 					break;
       
   178 				case keyCode.UP:
       
   179 					this._keyEvent( "previous", event );
       
   180 					break;
       
   181 				case keyCode.DOWN:
       
   182 					this._keyEvent( "next", event );
       
   183 					break;
       
   184 				}
       
   185 			},
       
   186 			input: function( event ) {
       
   187 				if ( suppressInput ) {
       
   188 					suppressInput = false;
       
   189 					event.preventDefault();
       
   190 					return;
       
   191 				}
       
   192 				this._searchTimeout( event );
       
   193 			},
       
   194 			focus: function() {
       
   195 				this.selectedItem = null;
       
   196 				this.previous = this._value();
       
   197 			},
       
   198 			blur: function( event ) {
       
   199 				if ( this.cancelBlur ) {
       
   200 					delete this.cancelBlur;
       
   201 					return;
       
   202 				}
       
   203 
       
   204 				clearTimeout( this.searching );
       
   205 				this.close( event );
       
   206 				this._change( event );
       
   207 			}
       
   208 		} );
       
   209 
       
   210 		this._initSource();
       
   211 		this.menu = $( "<ul>" )
       
   212 			.appendTo( this._appendTo() )
       
   213 			.menu( {
       
   214 
       
   215 				// disable ARIA support, the live region takes care of that
       
   216 				role: null
       
   217 			} )
       
   218 			.hide()
       
   219 			.menu( "instance" );
       
   220 
       
   221 		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
       
   222 		this._on( this.menu.element, {
       
   223 			mousedown: function( event ) {
       
   224 
       
   225 				// prevent moving focus out of the text field
       
   226 				event.preventDefault();
       
   227 
       
   228 				// IE doesn't prevent moving focus even with event.preventDefault()
       
   229 				// so we set a flag to know when we should ignore the blur event
       
   230 				this.cancelBlur = true;
       
   231 				this._delay( function() {
       
   232 					delete this.cancelBlur;
       
   233 
       
   234 					// Support: IE 8 only
       
   235 					// Right clicking a menu item or selecting text from the menu items will
       
   236 					// result in focus moving out of the input. However, we've already received
       
   237 					// and ignored the blur event because of the cancelBlur flag set above. So
       
   238 					// we restore focus to ensure that the menu closes properly based on the user's
       
   239 					// next actions.
       
   240 					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
       
   241 						this.element.trigger( "focus" );
       
   242 					}
       
   243 				} );
       
   244 			},
       
   245 			menufocus: function( event, ui ) {
       
   246 				var label, item;
       
   247 
       
   248 				// support: Firefox
       
   249 				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
       
   250 				if ( this.isNewMenu ) {
       
   251 					this.isNewMenu = false;
       
   252 					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
       
   253 						this.menu.blur();
       
   254 
       
   255 						this.document.one( "mousemove", function() {
       
   256 							$( event.target ).trigger( event.originalEvent );
       
   257 						} );
       
   258 
       
   259 						return;
       
   260 					}
       
   261 				}
       
   262 
       
   263 				item = ui.item.data( "ui-autocomplete-item" );
       
   264 				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
       
   265 
       
   266 					// use value to match what will end up in the input, if it was a key event
       
   267 					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
       
   268 						this._value( item.value );
       
   269 					}
       
   270 				}
       
   271 
       
   272 				// Announce the value in the liveRegion
       
   273 				label = ui.item.attr( "aria-label" ) || item.value;
       
   274 				if ( label && $.trim( label ).length ) {
       
   275 					this.liveRegion.children().hide();
       
   276 					$( "<div>" ).text( label ).appendTo( this.liveRegion );
       
   277 				}
       
   278 			},
       
   279 			menuselect: function( event, ui ) {
       
   280 				var item = ui.item.data( "ui-autocomplete-item" ),
       
   281 					previous = this.previous;
       
   282 
       
   283 				// Only trigger when focus was lost (click on menu)
       
   284 				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
       
   285 					this.element.trigger( "focus" );
       
   286 					this.previous = previous;
       
   287 
       
   288 					// #6109 - IE triggers two focus events and the second
       
   289 					// is asynchronous, so we need to reset the previous
       
   290 					// term synchronously and asynchronously :-(
       
   291 					this._delay( function() {
       
   292 						this.previous = previous;
       
   293 						this.selectedItem = item;
       
   294 					} );
       
   295 				}
       
   296 
       
   297 				if ( false !== this._trigger( "select", event, { item: item } ) ) {
       
   298 					this._value( item.value );
       
   299 				}
       
   300 
       
   301 				// reset the term after the select event
       
   302 				// this allows custom select handling to work properly
       
   303 				this.term = this._value();
       
   304 
       
   305 				this.close( event );
       
   306 				this.selectedItem = item;
       
   307 			}
       
   308 		} );
       
   309 
       
   310 		this.liveRegion = $( "<div>", {
       
   311 			role: "status",
       
   312 			"aria-live": "assertive",
       
   313 			"aria-relevant": "additions"
       
   314 		} )
       
   315 			.appendTo( this.document[ 0 ].body );
       
   316 
       
   317 		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
       
   318 
       
   319 		// Turning off autocomplete prevents the browser from remembering the
       
   320 		// value when navigating through history, so we re-enable autocomplete
       
   321 		// if the page is unloaded before the widget is destroyed. #7790
       
   322 		this._on( this.window, {
       
   323 			beforeunload: function() {
       
   324 				this.element.removeAttr( "autocomplete" );
       
   325 			}
       
   326 		} );
       
   327 	},
       
   328 
       
   329 	_destroy: function() {
       
   330 		clearTimeout( this.searching );
       
   331 		this.element.removeAttr( "autocomplete" );
       
   332 		this.menu.element.remove();
       
   333 		this.liveRegion.remove();
       
   334 	},
       
   335 
       
   336 	_setOption: function( key, value ) {
       
   337 		this._super( key, value );
       
   338 		if ( key === "source" ) {
       
   339 			this._initSource();
       
   340 		}
       
   341 		if ( key === "appendTo" ) {
       
   342 			this.menu.element.appendTo( this._appendTo() );
       
   343 		}
       
   344 		if ( key === "disabled" && value && this.xhr ) {
       
   345 			this.xhr.abort();
       
   346 		}
       
   347 	},
       
   348 
       
   349 	_isEventTargetInWidget: function( event ) {
       
   350 		var menuElement = this.menu.element[ 0 ];
       
   351 
       
   352 		return event.target === this.element[ 0 ] ||
       
   353 			event.target === menuElement ||
       
   354 			$.contains( menuElement, event.target );
       
   355 	},
       
   356 
       
   357 	_closeOnClickOutside: function( event ) {
       
   358 		if ( !this._isEventTargetInWidget( event ) ) {
       
   359 			this.close();
       
   360 		}
       
   361 	},
       
   362 
       
   363 	_appendTo: function() {
       
   364 		var element = this.options.appendTo;
       
   365 
       
   366 		if ( element ) {
       
   367 			element = element.jquery || element.nodeType ?
       
   368 				$( element ) :
       
   369 				this.document.find( element ).eq( 0 );
       
   370 		}
       
   371 
       
   372 		if ( !element || !element[ 0 ] ) {
       
   373 			element = this.element.closest( ".ui-front, dialog" );
       
   374 		}
       
   375 
       
   376 		if ( !element.length ) {
       
   377 			element = this.document[ 0 ].body;
       
   378 		}
       
   379 
       
   380 		return element;
       
   381 	},
       
   382 
       
   383 	_initSource: function() {
       
   384 		var array, url,
       
   385 			that = this;
       
   386 		if ( $.isArray( this.options.source ) ) {
       
   387 			array = this.options.source;
       
   388 			this.source = function( request, response ) {
       
   389 				response( $.ui.autocomplete.filter( array, request.term ) );
       
   390 			};
       
   391 		} else if ( typeof this.options.source === "string" ) {
       
   392 			url = this.options.source;
       
   393 			this.source = function( request, response ) {
       
   394 				if ( that.xhr ) {
       
   395 					that.xhr.abort();
       
   396 				}
       
   397 				that.xhr = $.ajax( {
       
   398 					url: url,
       
   399 					data: request,
       
   400 					dataType: "json",
       
   401 					success: function( data ) {
       
   402 						response( data );
       
   403 					},
       
   404 					error: function() {
       
   405 						response( [] );
       
   406 					}
       
   407 				} );
       
   408 			};
       
   409 		} else {
       
   410 			this.source = this.options.source;
       
   411 		}
       
   412 	},
       
   413 
       
   414 	_searchTimeout: function( event ) {
       
   415 		clearTimeout( this.searching );
       
   416 		this.searching = this._delay( function() {
       
   417 
       
   418 			// Search if the value has changed, or if the user retypes the same value (see #7434)
       
   419 			var equalValues = this.term === this._value(),
       
   420 				menuVisible = this.menu.element.is( ":visible" ),
       
   421 				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
       
   422 
       
   423 			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
       
   424 				this.selectedItem = null;
       
   425 				this.search( null, event );
       
   426 			}
       
   427 		}, this.options.delay );
       
   428 	},
       
   429 
       
   430 	search: function( value, event ) {
       
   431 		value = value != null ? value : this._value();
       
   432 
       
   433 		// Always save the actual value, not the one passed as an argument
       
   434 		this.term = this._value();
       
   435 
       
   436 		if ( value.length < this.options.minLength ) {
       
   437 			return this.close( event );
       
   438 		}
       
   439 
       
   440 		if ( this._trigger( "search", event ) === false ) {
       
   441 			return;
       
   442 		}
       
   443 
       
   444 		return this._search( value );
       
   445 	},
       
   446 
       
   447 	_search: function( value ) {
       
   448 		this.pending++;
       
   449 		this._addClass( "ui-autocomplete-loading" );
       
   450 		this.cancelSearch = false;
       
   451 
       
   452 		this.source( { term: value }, this._response() );
       
   453 	},
       
   454 
       
   455 	_response: function() {
       
   456 		var index = ++this.requestIndex;
       
   457 
       
   458 		return $.proxy( function( content ) {
       
   459 			if ( index === this.requestIndex ) {
       
   460 				this.__response( content );
       
   461 			}
       
   462 
       
   463 			this.pending--;
       
   464 			if ( !this.pending ) {
       
   465 				this._removeClass( "ui-autocomplete-loading" );
       
   466 			}
       
   467 		}, this );
       
   468 	},
       
   469 
       
   470 	__response: function( content ) {
       
   471 		if ( content ) {
       
   472 			content = this._normalize( content );
       
   473 		}
       
   474 		this._trigger( "response", null, { content: content } );
       
   475 		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
       
   476 			this._suggest( content );
       
   477 			this._trigger( "open" );
       
   478 		} else {
       
   479 
       
   480 			// use ._close() instead of .close() so we don't cancel future searches
       
   481 			this._close();
       
   482 		}
       
   483 	},
       
   484 
       
   485 	close: function( event ) {
       
   486 		this.cancelSearch = true;
       
   487 		this._close( event );
       
   488 	},
       
   489 
       
   490 	_close: function( event ) {
       
   491 
       
   492 		// Remove the handler that closes the menu on outside clicks
       
   493 		this._off( this.document, "mousedown" );
       
   494 
       
   495 		if ( this.menu.element.is( ":visible" ) ) {
       
   496 			this.menu.element.hide();
       
   497 			this.menu.blur();
       
   498 			this.isNewMenu = true;
       
   499 			this._trigger( "close", event );
       
   500 		}
       
   501 	},
       
   502 
       
   503 	_change: function( event ) {
       
   504 		if ( this.previous !== this._value() ) {
       
   505 			this._trigger( "change", event, { item: this.selectedItem } );
       
   506 		}
       
   507 	},
       
   508 
       
   509 	_normalize: function( items ) {
       
   510 
       
   511 		// assume all items have the right format when the first item is complete
       
   512 		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
       
   513 			return items;
       
   514 		}
       
   515 		return $.map( items, function( item ) {
       
   516 			if ( typeof item === "string" ) {
       
   517 				return {
       
   518 					label: item,
       
   519 					value: item
       
   520 				};
       
   521 			}
       
   522 			return $.extend( {}, item, {
       
   523 				label: item.label || item.value,
       
   524 				value: item.value || item.label
       
   525 			} );
       
   526 		} );
       
   527 	},
       
   528 
       
   529 	_suggest: function( items ) {
       
   530 		var ul = this.menu.element.empty();
       
   531 		this._renderMenu( ul, items );
       
   532 		this.isNewMenu = true;
       
   533 		this.menu.refresh();
       
   534 
       
   535 		// Size and position menu
       
   536 		ul.show();
       
   537 		this._resizeMenu();
       
   538 		ul.position( $.extend( {
       
   539 			of: this.element
       
   540 		}, this.options.position ) );
       
   541 
       
   542 		if ( this.options.autoFocus ) {
       
   543 			this.menu.next();
       
   544 		}
       
   545 
       
   546 		// Listen for interactions outside of the widget (#6642)
       
   547 		this._on( this.document, {
       
   548 			mousedown: "_closeOnClickOutside"
       
   549 		} );
       
   550 	},
       
   551 
       
   552 	_resizeMenu: function() {
       
   553 		var ul = this.menu.element;
       
   554 		ul.outerWidth( Math.max(
       
   555 
       
   556 			// Firefox wraps long text (possibly a rounding bug)
       
   557 			// so we add 1px to avoid the wrapping (#7513)
       
   558 			ul.width( "" ).outerWidth() + 1,
       
   559 			this.element.outerWidth()
       
   560 		) );
       
   561 	},
       
   562 
       
   563 	_renderMenu: function( ul, items ) {
       
   564 		var that = this;
       
   565 		$.each( items, function( index, item ) {
       
   566 			that._renderItemData( ul, item );
       
   567 		} );
       
   568 	},
       
   569 
       
   570 	_renderItemData: function( ul, item ) {
       
   571 		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
       
   572 	},
       
   573 
       
   574 	_renderItem: function( ul, item ) {
       
   575 		return $( "<li>" )
       
   576 			.append( $( "<div>" ).text( item.label ) )
       
   577 			.appendTo( ul );
       
   578 	},
       
   579 
       
   580 	_move: function( direction, event ) {
       
   581 		if ( !this.menu.element.is( ":visible" ) ) {
       
   582 			this.search( null, event );
       
   583 			return;
       
   584 		}
       
   585 		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
       
   586 				this.menu.isLastItem() && /^next/.test( direction ) ) {
       
   587 
       
   588 			if ( !this.isMultiLine ) {
       
   589 				this._value( this.term );
       
   590 			}
       
   591 
       
   592 			this.menu.blur();
       
   593 			return;
       
   594 		}
       
   595 		this.menu[ direction ]( event );
       
   596 	},
       
   597 
       
   598 	widget: function() {
       
   599 		return this.menu.element;
       
   600 	},
       
   601 
       
   602 	_value: function() {
       
   603 		return this.valueMethod.apply( this.element, arguments );
       
   604 	},
       
   605 
       
   606 	_keyEvent: function( keyEvent, event ) {
       
   607 		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
       
   608 			this._move( keyEvent, event );
       
   609 
       
   610 			// Prevents moving cursor to beginning/end of the text field in some browsers
       
   611 			event.preventDefault();
       
   612 		}
       
   613 	},
       
   614 
       
   615 	// Support: Chrome <=50
       
   616 	// We should be able to just use this.element.prop( "isContentEditable" )
       
   617 	// but hidden elements always report false in Chrome.
       
   618 	// https://code.google.com/p/chromium/issues/detail?id=313082
       
   619 	_isContentEditable: function( element ) {
       
   620 		if ( !element.length ) {
       
   621 			return false;
       
   622 		}
       
   623 
       
   624 		var editable = element.prop( "contentEditable" );
       
   625 
       
   626 		if ( editable === "inherit" ) {
       
   627 		  return this._isContentEditable( element.parent() );
       
   628 		}
       
   629 
       
   630 		return editable === "true";
       
   631 	}
       
   632 } );
       
   633 
       
   634 $.extend( $.ui.autocomplete, {
       
   635 	escapeRegex: function( value ) {
       
   636 		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
       
   637 	},
       
   638 	filter: function( array, term ) {
       
   639 		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
       
   640 		return $.grep( array, function( value ) {
       
   641 			return matcher.test( value.label || value.value || value );
       
   642 		} );
       
   643 	}
       
   644 } );
       
   645 
       
   646 // Live region extension, adding a `messages` option
       
   647 // NOTE: This is an experimental API. We are still investigating
       
   648 // a full solution for string manipulation and internationalization.
       
   649 $.widget( "ui.autocomplete", $.ui.autocomplete, {
       
   650 	options: {
       
   651 		messages: {
       
   652 			noResults: "No search results.",
       
   653 			results: function( amount ) {
       
   654 				return amount + ( amount > 1 ? " results are" : " result is" ) +
       
   655 					" available, use up and down arrow keys to navigate.";
       
   656 			}
       
   657 		}
       
   658 	},
       
   659 
       
   660 	__response: function( content ) {
       
   661 		var message;
       
   662 		this._superApply( arguments );
       
   663 		if ( this.options.disabled || this.cancelSearch ) {
       
   664 			return;
       
   665 		}
       
   666 		if ( content && content.length ) {
       
   667 			message = this.options.messages.results( content.length );
       
   668 		} else {
       
   669 			message = this.options.messages.noResults;
       
   670 		}
       
   671 		this.liveRegion.children().hide();
       
   672 		$( "<div>" ).text( message ).appendTo( this.liveRegion );
       
   673 	}
       
   674 } );
       
   675 
       
   676 return $.ui.autocomplete;
       
   677 
       
   678 } ) );