Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Menu: Added autoCollapse as the default #440

Merged
merged 1 commit into from

2 participants

@kborchers
Owner

Menu: Added autoCollapse as the default

ui/jquery.ui.menu.js
@@ -250,6 +250,12 @@ $.widget( "ui.menu", {
.prepend( '<span class="ui-menu-icon ui-icon ui-icon-carat-1-e"></span>' );
menu.attr( "aria-labelledby", item.attr( "id" ) );
});
+
+ submenus.add( this.element ).bind( "mouseleave.menu", function( event ) {
@jzaefferer Owner

Would be nice if we could use event delegation here as well, doing the binding just once in _create. Should then also use _bind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ui/jquery.ui.menu.js
@@ -346,21 +352,21 @@ $.widget( "ui.menu", {
},
collapseAll: function( event ) {
- this.element
- .find( "ul" )
- .hide()
- .attr( "aria-hidden", "true" )
- .attr( "aria-expanded", "false" )
- .end()
- .find( "a.ui-state-active" )
- .removeClass( "ui-state-active" );
+ var currentMenu = event ? $( event.target ).is( ".ui-menu" ) ? $( event.target ) : $( event.target ).closest( ".ui-menu" ).length ? $( event.target ).closest( ".ui-menu" ) : false : false;
@jzaefferer Owner

This line needs some refactoring or at least formatting. Too many ternaries. Too much duplicated, e.g. this happens three times: $( event.target ).closest( ".ui-menu" )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jzaefferer
Owner

Works really well for the menubar, gets us pretty close to the behaviour of the OSX menubar.

Some code issues still need to be resolved, see above.

Also: Can we add unit tests for this?

@kborchers
Owner

@jzaefferer Made modifications and added a unit test. Still getting the hang of QUnit so let me know if anything needs to change there or if you have any thoughts on my changes based on your comments.

ui/jquery.ui.menu.js
@@ -45,6 +45,10 @@ $.widget( "ui.menu", {
event.preventDefault();
}
});
+ var mouseleaveHandler = function( event ) {
@jzaefferer Owner

Should move this on the prototype, e.g. as _mouseleave, and use this instead of self. this points to the instance when using _bind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@kborchers
Owner

@jzaefferer How's that look?

@jzaefferer jzaefferer merged commit 94317d7 into jquery:master
@jzaefferer
Owner

Looking good. Just landed it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 48 additions and 16 deletions.
  1. +19 −0 tests/unit/menu/menu_events.js
  2. +29 −16 ui/jquery.ui.menu.js
View
19 tests/unit/menu/menu_events.js
@@ -41,6 +41,25 @@ test( "handle blur: click", function() {
$("#remove").remove();
});
+asyncTest( "handle submenu auto collapse: mouseleave", function() {
+ expect( 4 );
+ var $menu = $( "#menu2" ).menu();
+
+ $menu.find( "li:nth-child(7)" ).trigger( "mouseover" );
+ setTimeout(function() {
+ equal( $menu.find( "ul[aria-expanded='true']" ).length, 1, "first submenu expanded" );
+ $menu.find( "li:nth-child(7) li:first" ).trigger( "mouseover" );
+ setTimeout(function() {
+ equal( $menu.find( "ul[aria-expanded='true']" ).length, 2, "second submenu expanded" );
+ $menu.find( "ul[aria-expanded='true']:first" ).trigger( "mouseleave" );
+ equal( $menu.find( "ul[aria-expanded='true']" ).length, 1, "second submenu collapsed" );
+ $menu.trigger( "mouseleave" );
+ equal( $menu.find( "ul[aria-expanded='true']" ).length, 0, "first submenu collapsed" );
+ start();
+ }, 400);
+ }, 200);
+});
+
test("handle keyboard navigation on menu without scroll and without submenus", function() {
expect(12);
var element = $('#menu1').menu({
View
45 ui/jquery.ui.menu.js
@@ -62,6 +62,8 @@ $.widget( "ui.menu", {
target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
this.focus( event, target );
},
+ "mouseleave": "_mouseleave",
+ "mouseleave .ui-menu": "_mouseleave",
"mouseout .ui-menu-item": "blur",
"focus": function( event ) {
this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) );
@@ -346,21 +348,30 @@ $.widget( "ui.menu", {
},
collapseAll: function( event ) {
- this.element
- .find( "ul" )
- .hide()
- .attr( "aria-hidden", "true" )
- .attr( "aria-expanded", "false" )
- .end()
- .find( "a.ui-state-active" )
- .removeClass( "ui-state-active" );
+ var currentMenu = false;
+ if ( event ) {
+ var target = $( event.target );
+ if ( target.is( "ui.menu" ) ) {
+ currentMenu = target;
+ } else if ( target.closest( ".ui-menu" ).length ) {
+ currentMenu = target.closest( ".ui-menu" );
+ }
+ }
- this.blur( event );
- this.activeMenu = this.element;
+ this._close( currentMenu );
+
+ if( !currentMenu ) {
+ this.blur( event );
+ this.activeMenu = this.element;
+ }
},
- _close: function() {
- this.active.parent()
+ _close: function( startMenu ) {
+ if( !startMenu ) {
+ startMenu = this.active ? this.active.parent() : this.element;
+ }
+
+ startMenu
.find( "ul" )
.hide()
.attr( "aria-hidden", "true" )
@@ -373,10 +384,7 @@ $.widget( "ui.menu", {
collapse: function( event ) {
var newItem = this.active && this.active.parents("li:not(.ui-menubar-item)").first();
if ( newItem && newItem.length ) {
- this.active.parent()
- .attr("aria-hidden", "true")
- .attr("aria-expanded", "false")
- .hide();
+ this._close();
this.focus( event, newItem );
return true;
}
@@ -486,6 +494,11 @@ $.widget( "ui.menu", {
return this.element.height() < this.element.prop( "scrollHeight" );
},
+ _mouseleave: function( event ) {
+ this.collapseAll( event );
+ this.blur();
+ },
+
select: function( event ) {
// save active reference before collapseAll triggers blur
var ui = {
Something went wrong with that request. Please try again.