From 62a70da959e71a2d5c8ecc27548ea38733ec3128 Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 31 Jan 2012 14:21:18 -0500 Subject: Autocomplete: Added test for close method. --- tests/unit/autocomplete/autocomplete_core.js | 4 ---- tests/unit/autocomplete/autocomplete_methods.js | 11 +++++++++-- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'tests/unit/autocomplete') diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index d98f56abf..bc61b9100 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -162,8 +162,4 @@ test( "allow form submit on enter when menu is not active", function() { } })(); -(function() { - -})(); - }( jQuery ) ); diff --git a/tests/unit/autocomplete/autocomplete_methods.js b/tests/unit/autocomplete/autocomplete_methods.js index 3fe035d28..1600d73dc 100644 --- a/tests/unit/autocomplete/autocomplete_methods.js +++ b/tests/unit/autocomplete/autocomplete_methods.js @@ -9,15 +9,19 @@ test( "destroy", function() { }); }); -test( "search", function() { - expect( 3 ); +test( "search, close", function() { + expect( 6 ); var data = [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl" ], element = $( "#autocomplete" ).autocomplete({ source: data, minLength: 0 }), menu = element.autocomplete( "widget" ); + + ok( menu.is( ":hidden" ), "menu is hidden on init" ); + element.autocomplete( "search" ); + ok( menu.is( ":visible" ), "menu is visible after search" ); equal( menu.find( ".ui-menu-item" ).length, data.length, "all items for a blank search" ); element.val( "has" ).autocomplete( "search" ); @@ -25,6 +29,9 @@ test( "search", function() { element.autocomplete( "search", "ja" ); equal( menu.find( ".ui-menu-item" ).length, 2, "only java and javascript for 'ja'" ); + + element.autocomplete( "close" ); + ok( menu.is( ":hidden" ), "menu is hidden after close" ); }); }( jQuery ) ); -- cgit v1.2.3 From 530d4cb40814c68163197f8091322e2258f0e57a Mon Sep 17 00:00:00 2001 From: Scott González Date: Sat, 11 Feb 2012 10:12:51 -0500 Subject: Autocomplete: Cancel search when closing the menu. Fixes #7523 - Autocomplete cancel pending request when text changes below minLength. --- tests/unit/autocomplete/autocomplete_options.js | 33 +++++++++++++++++++++++++ ui/jquery.ui.autocomplete.js | 8 +++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'tests/unit/autocomplete') diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index 114e9a42b..799a249d8 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -102,6 +102,39 @@ test( "minLength", function() { ok( menu.is( ":visible" ), "blank enough for minLength: 0" ); }); +asyncTest( "minLength, exceed then drop below", function() { + expect( 4 ); + var element = $( "#autocomplete" ).autocomplete({ + minLength: 2, + source: function( req, res ) { + equal( req.term, "12", "correct search term" ); + setTimeout(function() { + res([ "item" ]); + }, 1 ); + } + }), + menu = element.autocomplete( "widget" ); + + ok( menu.is( ":hidden" ), "menu is hidden before first search" ); + element.autocomplete( "search", "12" ); + + ok( menu.is( ":hidden" ), "menu is hidden before second search" ); + element.autocomplete( "search", "1" ); + + setTimeout(function() { + ok( menu.is( ":hidden" ), "menu is hidden after searches" ); + start(); + }, 50 ); +}); + +// TODO: figure out how to implement this test +// When fixing #7523, I couldn't figure out a test that would fail when +// calling .close() (instead of ._close()) from ._response(). +// Use the remote demo and type "je", delete, "a", you should get results for "ja" +// but if we call .close() from ._response() the results are ignored. +//asyncTest( "minLength, exceed then drop below", function() { +//}); + test( "source, local string array", function() { expect( 1 ); var element = $( "#autocomplete" ).autocomplete({ diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 14e8a2a86..ba0062410 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -383,7 +383,8 @@ $.widget( "ui.autocomplete", { this._suggest( content ); this._trigger( "open" ); } else { - this.close(); + // use ._close() instad of .close() so we don't cancel future searches + this._close(); } this.pending--; if ( !this.pending ) { @@ -392,6 +393,11 @@ $.widget( "ui.autocomplete", { }, close: function( event ) { + this.cancelSearch = true; + this._close( event ); + }, + + _close: function( event ) { clearTimeout( this.closing ); if ( this.menu.element.is(":visible") ) { this.menu.element.hide(); -- cgit v1.2.3 From f262a531fa0978c3aaa0cc1c0a75cb1b8fec0155 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 15 Feb 2012 11:41:30 -0500 Subject: Autocomplete: Added a test for exceeding minLength, then falling below, then exceeding again. --- tests/unit/autocomplete/autocomplete_options.js | 35 ++++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'tests/unit/autocomplete') diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index 799a249d8..1ab40f36c 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -127,13 +127,34 @@ asyncTest( "minLength, exceed then drop below", function() { }, 50 ); }); -// TODO: figure out how to implement this test -// When fixing #7523, I couldn't figure out a test that would fail when -// calling .close() (instead of ._close()) from ._response(). -// Use the remote demo and type "je", delete, "a", you should get results for "ja" -// but if we call .close() from ._response() the results are ignored. -//asyncTest( "minLength, exceed then drop below", function() { -//}); +test( "minLength, exceed then drop below then exceed", function() { + expect( 3 ); + var _res = [], + element = $( "#autocomplete" ).autocomplete({ + minLength: 2, + source: function( req, res ) { + _res.push( res ); + } + }), + menu = element.autocomplete( "widget" ); + + // trigger a valid search + ok( menu.is( ":hidden" ), "menu is hidden before first search" ); + element.autocomplete( "search", "12" ); + + // trigger a search below the minLength, to turn on cancelSearch flag + ok( menu.is( ":hidden" ), "menu is hidden before second search" ); + element.autocomplete( "search", "1" ); + + // trigger a valid search + element.autocomplete( "search", "13" ); + // react as if the first search was cancelled (default ajax behavior) + _res[ 0 ]([]); + // react to second search + _res[ 1 ]([ "13" ]); + + ok( menu.is( ":visible" ), "menu is visible after searches" ); +}); test( "source, local string array", function() { expect( 1 ); -- cgit v1.2.3 From f5b52a89a735082d06d6f6ea950efbccff0a227f Mon Sep 17 00:00:00 2001 From: Scott González Date: Sat, 11 Feb 2012 15:43:38 -0500 Subject: Autocomplete: Removed the timeout for the change event. Fixes #7550 - Autocomplete change event not triggered in time. Thanks spekary for finding a workaround for IE. --- tests/unit/autocomplete/autocomplete_core.js | 39 -------------------------- tests/unit/autocomplete/autocomplete_events.js | 5 +++- ui/jquery.ui.autocomplete.js | 29 +++++++++++-------- 3 files changed, 21 insertions(+), 52 deletions(-) (limited to 'tests/unit/autocomplete') diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index bc61b9100..ef6ea58af 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -2,45 +2,6 @@ module( "autocomplete: core" ); -asyncTest( "close-on-blur is properly delayed", function() { - expect( 3 ); - var element = $( "#autocomplete" ) - .autocomplete({ - source: [ "java", "javascript" ] - }) - .val( "ja" ) - .autocomplete( "search" ), - menu = element.autocomplete( "widget" ); - - ok( menu.is( ":visible" ) ); - element.blur(); - ok( menu.is( ":visible" ) ); - setTimeout(function() { - ok( menu.is( ":hidden") ); - start(); - }, 200 ); -}); - -asyncTest( "close-on-blur is cancelled when starting a search", function() { - expect( 3 ); - var element = $( "#autocomplete" ) - .autocomplete({ - source: [ "java", "javascript" ] - }) - .val( "ja" ) - .autocomplete( "search" ), - menu = element.autocomplete( "widget" ); - - ok( menu.is( ":visible" ) ); - element.blur(); - ok( menu.is( ":visible" ) ); - element.autocomplete( "search" ); - setTimeout(function() { - ok( menu.is( ":visible" ) ); - start(); - }, 200 ); -}); - test( "prevent form submit on enter when menu is active", function() { expect( 2 ); var event, diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index 7b51ec4c0..1c7ff7462 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -68,7 +68,10 @@ $.each([ ok( menu.is( ":visible" ), "menu is visible after delay" ); element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - element.simulate( "blur" ); + // blur must be async for IE to handle it properly + setTimeout(function() { + element.simulate( "blur" ); + }, 1 ); }, 50 ); }); }); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 5646eda7a..e261b9147 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -176,13 +176,14 @@ $.widget( "ui.autocomplete", { return; } + if ( self.cancelBlur ) { + delete self.cancelBlur; + return; + } + clearTimeout( self.searching ); - self.cancelSearch = true; - // clicks on the menu (or a button to trigger a search) will cause a blur event - self.closing = setTimeout(function() { - self.close( event ); - self._change( event ); - }, 150 ); + self.close( event ); + self._change( event ); }); this._initSource(); this.response = function() { @@ -193,6 +194,16 @@ $.widget( "ui.autocomplete", { .appendTo( this.document.find( this.options.appendTo || "body" )[0] ) // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) .mousedown(function( event ) { + // prevent moving focus out of the text field + event.preventDefault(); + + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + self.cancelBlur = true; + setTimeout(function() { + delete self.cancelBlur; + }, 1 ); + // clicking on the scrollbar causes focus to shift to the body // but we can't detect a mouseup or a click immediately afterward // so we have to track the next mousedown and close the menu if @@ -209,11 +220,6 @@ $.widget( "ui.autocomplete", { }); }, 1 ); } - - // use another timeout to make sure the blur-event-handler on the input was already triggered - setTimeout(function() { - clearTimeout( self.closing ); - }, 13); }) .menu({ // custom key handling for now @@ -358,7 +364,6 @@ $.widget( "ui.autocomplete", { return this.close( event ); } - clearTimeout( this.closing ); if ( this._trigger( "search", event ) === false ) { return; } -- cgit v1.2.3