aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott González <scott.gonzalez@gmail.com>2015-10-15 10:11:14 -0400
committerScott González <scott.gonzalez@gmail.com>2015-10-16 14:09:05 -0400
commit548fbf570caa5fdee973bbbe8ac2d36b0338c2b9 (patch)
tree4d3dc28cd3084f62726b461855a156fb4d9aa46a
parent7df2f1905a1ec4727f00451f8d794aeb35ec4159 (diff)
downloadjquery-ui-548fbf570caa5fdee973bbbe8ac2d36b0338c2b9.tar.gz
jquery-ui-548fbf570caa5fdee973bbbe8ac2d36b0338c2b9.zip
Autocomplete: Close the menu on any outside interactions
This ensures that the menu will close if the user interacts with a draggable, resizable, etc. element since those interactions don't change focus. Ref #6642 Closes gh-1614
-rw-r--r--tests/unit/autocomplete/core.js24
-rw-r--r--ui/widgets/autocomplete.js41
2 files changed, 47 insertions, 18 deletions
diff --git a/tests/unit/autocomplete/core.js b/tests/unit/autocomplete/core.js
index 41be5ae6a..9cfac3917 100644
--- a/tests/unit/autocomplete/core.js
+++ b/tests/unit/autocomplete/core.js
@@ -398,4 +398,28 @@ asyncTest( "Search if the user retypes the same value (#7434)", function() {
} );
} );
+asyncTest( "Close on click outside when focus remains", function() {
+ expect( 2 );
+
+ var element = $( "#autocomplete" ).autocomplete( {
+ source: [ "java", "javascript" ],
+ delay: 0
+ } );
+ var menu = element.autocomplete( "widget" );
+
+ $( "body" ).on( "mousedown", function( event ) {
+ event.preventDefault();
+ } );
+
+ element.val( "j" ).autocomplete( "search", "j" );
+ setTimeout(function() {
+ ok( menu.is( ":visible" ), "menu displays initially" );
+ $( "body" ).simulate( "mousedown" );
+ setTimeout(function() {
+ ok( menu.is( ":hidden" ), "menu closes after clicking elsewhere" );
+ start();
+ } );
+ } );
+} );
+
} );
diff --git a/ui/widgets/autocomplete.js b/ui/widgets/autocomplete.js
index 4067f871f..20d6d2fdd 100644
--- a/ui/widgets/autocomplete.js
+++ b/ui/widgets/autocomplete.js
@@ -245,24 +245,6 @@ $.widget( "ui.autocomplete", {
this.element.trigger( "focus" );
}
} );
-
- // 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
- // the user clicks somewhere outside of the autocomplete
- var menuElement = this.menu.element[ 0 ];
- if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
- this._delay( function() {
- var that = this;
- this.document.one( "mousedown", function( event ) {
- if ( event.target !== that.element[ 0 ] &&
- event.target !== menuElement &&
- !$.contains( menuElement, event.target ) ) {
- that.close();
- }
- } );
- } );
- }
},
menufocus: function( event, ui ) {
var label, item;
@@ -368,6 +350,20 @@ $.widget( "ui.autocomplete", {
}
},
+ _isEventTargetInWidget: function( event ) {
+ var menuElement = this.menu.element[ 0 ];
+
+ return event.target === this.element[ 0 ] ||
+ event.target === menuElement ||
+ $.contains( menuElement, event.target );
+ },
+
+ _closeOnClickOutside: function( event ) {
+ if ( !this._isEventTargetInWidget( event ) ) {
+ this.close();
+ }
+ },
+
_appendTo: function() {
var element = this.options.appendTo;
@@ -496,6 +492,10 @@ $.widget( "ui.autocomplete", {
},
_close: function( event ) {
+
+ // Remove the handler that closes the menu on outside clicks
+ this._off( this.document, "mousedown" );
+
if ( this.menu.element.is( ":visible" ) ) {
this.menu.element.hide();
this.menu.blur();
@@ -546,6 +546,11 @@ $.widget( "ui.autocomplete", {
if ( this.options.autoFocus ) {
this.menu.next();
}
+
+ // Listen for interactions outside of the widget (#6642)
+ this._on( this.document, {
+ mousedown: "_closeOnClickOutside"
+ } );
},
_resizeMenu: function() {