aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott González <scott.gonzalez@gmail.com>2012-04-03 16:51:22 -0400
committerScott González <scott.gonzalez@gmail.com>2012-04-03 16:51:22 -0400
commitd040b8f42cc28932deedddebe95473a9fd13d742 (patch)
treebb296c53d253f56417a518e536843714a855bfb1
parentfc6e72bf7399ecde5f15de88fd750a9a49b55b77 (diff)
downloadjquery-ui-d040b8f42cc28932deedddebe95473a9fd13d742.tar.gz
jquery-ui-d040b8f42cc28932deedddebe95473a9fd13d742.zip
Autocomplete: Move race condition logic from ajax requests to general response handler. Fixes #8234 - Autocomplete: Automatic race-condition handling for custom sources.
(cherry picked from commit 96f9c84b7b2149c6b93ac226a52065652f218e1e) Conflicts: tests/unit/autocomplete/autocomplete_core.js ui/jquery.ui.autocomplete.js
-rw-r--r--tests/unit/autocomplete/autocomplete_core.js31
-rw-r--r--ui/jquery.ui.autocomplete.js38
2 files changed, 50 insertions, 19 deletions
diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js
index fcd835d1a..84f26980f 100644
--- a/tests/unit/autocomplete/autocomplete_core.js
+++ b/tests/unit/autocomplete/autocomplete_core.js
@@ -69,4 +69,33 @@ test( "allow form submit on enter when menu is not active", function() {
ok( !event.isDefaultPrevented(), "default action is prevented" );
});
-})(jQuery);
+asyncTest( "handle race condition", function() {
+ expect( 3 );
+ var count = 0,
+ element = $( "#autocomplete" ).autocomplete({
+ source: function( request, response ) {
+ count++;
+ if ( request.term.length === 1 ) {
+ equal( count, 1, "request with 1 character is first" );
+ setTimeout(function() {
+ response([ "one" ]);
+ setTimeout( checkResults, 1 );
+ }, 1 );
+ return;
+ }
+ equal( count, 2, "request with 2 characters is second" );
+ response([ "two" ]);
+ }
+ });
+
+ element.autocomplete( "search", "a" );
+ element.autocomplete( "search", "ab" );
+
+ function checkResults() {
+ equal( element.autocomplete( "widget" ).find( ".ui-menu-item" ).text(), "two",
+ "correct results displayed" );
+ start();
+ }
+});
+
+}( jQuery ) );
diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js
index 72a69fb0e..5352c3432 100644
--- a/ui/jquery.ui.autocomplete.js
+++ b/ui/jquery.ui.autocomplete.js
@@ -131,9 +131,6 @@ $.widget( "ui.autocomplete", {
}, 150 );
});
this._initSource();
- this.response = function() {
- return self._response.apply( self, arguments );
- };
this.menu = $( "<ul></ul>" )
.addClass( "ui-autocomplete" )
.appendTo( $( this.options.appendTo || "body", doc )[0] )
@@ -268,18 +265,11 @@ $.widget( "ui.autocomplete", {
url: url,
data: request,
dataType: "json",
- context: {
- autocompleteRequest: ++requestIndex
- },
success: function( data, status ) {
- if ( this.autocompleteRequest === requestIndex ) {
- response( data );
- }
+ response( data );
},
error: function() {
- if ( this.autocompleteRequest === requestIndex ) {
- response( [] );
- }
+ response( [] );
}
});
};
@@ -310,10 +300,26 @@ $.widget( "ui.autocomplete", {
this.pending++;
this.element.addClass( "ui-autocomplete-loading" );
- this.source( { term: value }, this.response );
+ this.source( { term: value }, this._response() );
+ },
+
+ _response: function() {
+ var that = this,
+ index = ++requestIndex;
+
+ return function( content ) {
+ if ( index === requestIndex ) {
+ that.__response( content );
+ }
+
+ that.pending--;
+ if ( !that.pending ) {
+ that.element.removeClass( "ui-autocomplete-loading" );
+ }
+ };
},
- _response: function( content ) {
+ __response: function( content ) {
if ( !this.options.disabled && content && content.length ) {
content = this._normalize( content );
this._suggest( content );
@@ -321,10 +327,6 @@ $.widget( "ui.autocomplete", {
} else {
this.close();
}
- this.pending--;
- if ( !this.pending ) {
- this.element.removeClass( "ui-autocomplete-loading" );
- }
},
close: function( event ) {