Skip to content
Permalink
Browse files
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
  • Loading branch information
scottgonzalez committed Oct 16, 2015
1 parent 7df2f19 commit 548fbf570caa5fdee973bbbe8ac2d36b0338c2b9
Showing with 47 additions and 18 deletions.
  1. +24 −0 tests/unit/autocomplete/core.js
  2. +23 −18 ui/widgets/autocomplete.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();
} );
} );
} );

} );
@@ -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() {

0 comments on commit 548fbf5

Please sign in to comment.