From 34a0479d1cbb0acf5d86818506deec78bfbb373b Mon Sep 17 00:00:00 2001 From: Corey Frang Date: Thu, 22 Sep 2011 13:56:53 -0500 Subject: [PATCH] Menu: Refactoring the collapseAll to deal with some issues selecting - Updating unit tests. Thanks @kborchers --- tests/unit/menu/menu_events.js | 8 ++++- tests/unit/menu/menu_test_helpers.js | 2 +- ui/jquery.ui.menu.js | 46 +++++++++++++++------------- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/tests/unit/menu/menu_events.js b/tests/unit/menu/menu_events.js index 6d1b02b87..55ec1e2ff 100644 --- a/tests/unit/menu/menu_events.js +++ b/tests/unit/menu/menu_events.js @@ -99,7 +99,7 @@ asyncTest( "handle submenu auto collapse: mouseleave", function() { }); asyncTest( "handle custom menu item submenu auto collapse: mouseleave", function() { - expect( 4 ); + expect( 5 ); var $menu = $( "#menu5" ).menu( { items: "div" } ); $menu.children( ":nth-child(7)" ).trigger( "mouseover" ); @@ -110,6 +110,11 @@ asyncTest( "handle custom menu item submenu auto collapse: mouseleave", function equal( $menu.find( "div[aria-expanded='true']" ).length, 2, "second submenu expanded" ); $menu.find( "div[aria-expanded='true']:first" ).trigger( "mouseleave" ); equal( $menu.find( "div[aria-expanded='true']" ).length, 1, "second submenu collapsed" ); + + $menu.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN }); + ok( $menu.find( ".ui-state-active" ).is( "#menu5 :nth-child(7) a" ), + "down keypress selected an item from the first submenu" ); + $menu.trigger( "mouseleave" ); equal( $menu.find( "div[aria-expanded='true']" ).length, 0, "first submenu collapsed" ); start(); @@ -117,6 +122,7 @@ asyncTest( "handle custom menu item submenu auto collapse: mouseleave", function }, 200); }); + test("handle keyboard navigation on menu without scroll and without submenus", function() { expect(12); var element = $('#menu1').menu({ diff --git a/tests/unit/menu/menu_test_helpers.js b/tests/unit/menu/menu_test_helpers.js index 052c9226b..e83795e5a 100644 --- a/tests/unit/menu/menu_test_helpers.js +++ b/tests/unit/menu/menu_test_helpers.js @@ -5,7 +5,7 @@ function menu_log( message, clear ) { if ( message === undefined ) { message = $( "#log" ).data( "lastItem" ); } - $( "#log" ).prepend( message + "," ); + $( "#log" ).prepend( $.trim( message ) + "," ); } function menu_click( menu, item ) { diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 455a12184..6d9db8879 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -62,13 +62,19 @@ $.widget( "ui.menu", { target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); this.focus( event, target ); }, - "mouseleave": "_mouseleave", - "mouseleave .ui-menu": "_mouseleave", + "mouseleave": "collapseAll", + "mouseleave .ui-menu": "collapseAll", "mouseout .ui-menu-item": "blur", "focus": function( event ) { this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); }, - "blur": "collapseAll" + blur: function( event ) { + this._delay( function() { + if ( ! $.contains( this.element[0], document.activeElement ) ) { + this.collapseAll( event ); + } + }, 0); + } }); this.refresh(); @@ -341,25 +347,25 @@ $.widget( "ui.menu", { .position( position ); }, - collapseAll: function( event ) { - 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" ); - } + collapseAll: function( event, all ) { + + // if we were passed an event, look for the submenu that contains the event + var currentMenu = all ? this.element : + $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); + + // if we found no valid submenu ancestor, use the main menu to close all sub menus anyway + if ( !currentMenu.length ) { + currentMenu = this.element; } this._close( currentMenu ); - if ( !currentMenu ) { - this.blur( event ); - this.activeMenu = this.element; - } + this.blur( event ); + this.activeMenu = currentMenu; }, + // With no arguments, closes the currently active menu - if nothing is active + // it closes all menus. If passed an argument, it will search for menus BELOW _close: function( startMenu ) { if ( !startMenu ) { startMenu = this.active ? this.active.parent() : this.element; @@ -487,17 +493,13 @@ $.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 = { item: this.active }; - this.collapseAll( event ); + this.collapseAll( event, true ); this._trigger( "select", event, ui ); } }); -- 2.39.5