mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-11-21 11:04:24 +00:00
Menu: Add support for structures other than UL/LI plus visual and unit tests
This commit is contained in:
parent
cedac75bcc
commit
9e617bbad1
@ -207,6 +207,44 @@
|
|||||||
<li class="foo"><a class="foo" href="#">Amesville</a></li>
|
<li class="foo"><a class="foo" href="#">Amesville</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div id="menu5">
|
||||||
|
<blockquote><a href="#">Aberdeen</a></blockquote>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Adamsville</a></blockquote>
|
||||||
|
<blockquote><a href="#">Addyston</a></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Salzburg</a>
|
||||||
|
<div>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><a href="#">Perch</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,6 +5,7 @@ commonWidgetTests( "menu", {
|
|||||||
my: "left top",
|
my: "left top",
|
||||||
at: "right top"
|
at: "right top"
|
||||||
},
|
},
|
||||||
|
items: "ul",
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
create: null
|
create: null
|
||||||
|
@ -21,6 +21,23 @@ test("handle click on menu", function() {
|
|||||||
equals( $("#log").html(), "1,3,2,afterclick,1,click,", "Click order not valid.");
|
equals( $("#log").html(), "1,3,2,afterclick,1,click,", "Click order not valid.");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("handle click on custom item menu", function() {
|
||||||
|
expect(1);
|
||||||
|
var ac = $('#menu5').menu({
|
||||||
|
select: function(event, ui) {
|
||||||
|
menu_log();
|
||||||
|
},
|
||||||
|
items: "div"
|
||||||
|
});
|
||||||
|
menu_log("click",true);
|
||||||
|
menu_click($('#menu5'),"1");
|
||||||
|
menu_log("afterclick");
|
||||||
|
menu_click( ac,"2");
|
||||||
|
menu_click($('#menu5'),"3");
|
||||||
|
menu_click( ac,"1");
|
||||||
|
equals( $("#log").html(), "1,3,2,afterclick,1,click,", "Click order not valid.");
|
||||||
|
});
|
||||||
|
|
||||||
test( "handle blur: click", function() {
|
test( "handle blur: click", function() {
|
||||||
expect( 4 );
|
expect( 4 );
|
||||||
var $menu = $( "#menu1" ).menu({
|
var $menu = $( "#menu1" ).menu({
|
||||||
@ -41,6 +58,27 @@ test( "handle blur: click", function() {
|
|||||||
$("#remove").remove();
|
$("#remove").remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test( "handle blur on custom item menu: click", function() {
|
||||||
|
expect( 4 );
|
||||||
|
var $menu = $( "#menu5" ).menu({
|
||||||
|
focus: function( event, ui ) {
|
||||||
|
equal( event.originalEvent.type, "click", "focus triggered 'click'" );
|
||||||
|
equal( event.type, "menufocus", "focus event.type is 'menufocus'" );
|
||||||
|
|
||||||
|
},
|
||||||
|
blur: function( event, ui ) {
|
||||||
|
equal( event.originalEvent.type, "click", "blur triggered 'click'" );
|
||||||
|
equal( event.type, "menublur", "blur event.type is 'menublur'" );
|
||||||
|
},
|
||||||
|
items: "div"
|
||||||
|
});
|
||||||
|
|
||||||
|
menu_click($('#menu5'),"1");
|
||||||
|
$( "<a>", { id: "remove"} ).appendTo("body").trigger( "click" );
|
||||||
|
|
||||||
|
$("#remove").remove();
|
||||||
|
});
|
||||||
|
|
||||||
asyncTest( "handle submenu auto collapse: mouseleave", function() {
|
asyncTest( "handle submenu auto collapse: mouseleave", function() {
|
||||||
expect( 4 );
|
expect( 4 );
|
||||||
var $menu = $( "#menu2" ).menu();
|
var $menu = $( "#menu2" ).menu();
|
||||||
@ -60,6 +98,25 @@ asyncTest( "handle submenu auto collapse: mouseleave", function() {
|
|||||||
}, 200);
|
}, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTest( "handle custom menu item submenu auto collapse: mouseleave", function() {
|
||||||
|
expect( 4 );
|
||||||
|
var $menu = $( "#menu5" ).menu( { items: "div" } );
|
||||||
|
|
||||||
|
$menu.children( ":nth-child(7)" ).trigger( "mouseover" );
|
||||||
|
setTimeout(function() {
|
||||||
|
equal( $menu.find( "div[aria-expanded='true']" ).length, 1, "first submenu expanded" );
|
||||||
|
$menu.children( ":nth-child(7)" ).find( "div:first" ).children( ":first" ).trigger( "mouseover" );
|
||||||
|
setTimeout(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.trigger( "mouseleave" );
|
||||||
|
equal( $menu.find( "div[aria-expanded='true']" ).length, 0, "first submenu collapsed" );
|
||||||
|
start();
|
||||||
|
}, 400);
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
|
||||||
test("handle keyboard navigation on menu without scroll and without submenus", function() {
|
test("handle keyboard navigation on menu without scroll and without submenus", function() {
|
||||||
expect(12);
|
expect(12);
|
||||||
var element = $('#menu1').menu({
|
var element = $('#menu1').menu({
|
||||||
|
@ -10,5 +10,5 @@ function menu_log( message, clear ) {
|
|||||||
|
|
||||||
function menu_click( menu, item ) {
|
function menu_click( menu, item ) {
|
||||||
$( "#log" ).data( "lastItem", item );
|
$( "#log" ).data( "lastItem", item );
|
||||||
menu.find( "li:eq(" + item + ") a" ).trigger( "click" );
|
menu.children( ":eq(" + item + ")" ).find( "a:first" ).trigger( "click" );
|
||||||
}
|
}
|
@ -23,6 +23,20 @@
|
|||||||
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
|
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#menu5").menu({
|
||||||
|
select: function(event, ui) {
|
||||||
|
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
|
||||||
|
},
|
||||||
|
items: "div"
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#menu6").menu({
|
||||||
|
select: function(event, ui) {
|
||||||
|
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
|
||||||
|
},
|
||||||
|
items: ".menuElement"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var menus = $("#menu1, #menu2, #menu3, .menu4");
|
var menus = $("#menu1, #menu2, #menu3, .menu4");
|
||||||
@ -42,6 +56,9 @@
|
|||||||
body { font-size:62.5%; }
|
body { font-size:62.5%; }
|
||||||
.ui-menu { width: 200px; margin-bottom: 2em; }
|
.ui-menu { width: 200px; margin-bottom: 2em; }
|
||||||
.menu4 { height: 200px; overflow: auto; }
|
.menu4 { height: 200px; overflow: auto; }
|
||||||
|
.address-item { border-bottom: 1px solid #999; }
|
||||||
|
.address-header { display: block; margin-bottom: .2em; font-weight: bold; }
|
||||||
|
.address-content { display: block; margin-bottom: .2em; padding-left: 10px; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -173,6 +190,87 @@
|
|||||||
<li><a href="#">Amesville</a></li>
|
<li><a href="#">Amesville</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div id="menu5">
|
||||||
|
<blockquote><a href="#">Aberdeen</a></blockquote>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Adamsville</a></blockquote>
|
||||||
|
<blockquote><a href="#">Addyston</a></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Salzburg</a>
|
||||||
|
<div>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<a href="#">Delphi</a>
|
||||||
|
<div>
|
||||||
|
<blockquote><a href="#">Ada</a></blockquote>
|
||||||
|
<blockquote><a href="#">Saarland</a></blockquote>
|
||||||
|
<blockquote><a href="#">Salzburg</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><a href="#">Perch</a></blockquote>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menuElement" id="menu6">
|
||||||
|
<div class="address-item">
|
||||||
|
<a href="#">
|
||||||
|
<span class="address-header">John Doe</span>
|
||||||
|
<span class="address-content">78 West Main St Apt 3A</span>
|
||||||
|
<span class="address-content">Bloomsburg, PA 12345</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="address-item">
|
||||||
|
<a href="#">
|
||||||
|
<span class="address-header">Jane Doe</span>
|
||||||
|
<span class="address-content">78 West Main St Apt 3A</span>
|
||||||
|
<span class="address-content">Bloomsburg, PA 12345</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="address-item">
|
||||||
|
<a href="#">
|
||||||
|
<span class="address-header">James Doe</span>
|
||||||
|
<span class="address-content">78 West Main St Apt 3A</span>
|
||||||
|
<span class="address-content">Bloomsburg, PA 12345</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="address-item">
|
||||||
|
<a href="#">
|
||||||
|
<span class="address-header">Jenny Doe</span>
|
||||||
|
<span class="address-content">78 West Main St Apt 3A</span>
|
||||||
|
<span class="address-content">Bloomsburg, PA 12345</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="address-item">
|
||||||
|
<a href="#">
|
||||||
|
<span class="address-header">John Doe</span>
|
||||||
|
<span class="address-content">78 West Main St Apt 3A</span>
|
||||||
|
<span class="address-content">Bloomsburg, PA 12345</span>
|
||||||
|
</a>
|
||||||
|
<div class="menuElement">
|
||||||
|
<div><a href="#">Ada</a></div>
|
||||||
|
<div><a href="#">Saarland</a></div>
|
||||||
|
<div><a href="#">Salzburg</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="ui-widget" style="clear: left; margin-top:2em; font-family:Arial">
|
<div class="ui-widget" style="clear: left; margin-top:2em; font-family:Arial">
|
||||||
Log:
|
Log:
|
||||||
<div id="log" style="height: 400px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
|
<div id="log" style="height: 400px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
|
||||||
|
23
ui/jquery.ui.menu.js
vendored
23
ui/jquery.ui.menu.js
vendored
@ -20,6 +20,7 @@ $.widget( "ui.menu", {
|
|||||||
defaultElement: "<ul>",
|
defaultElement: "<ul>",
|
||||||
delay: 150,
|
delay: 150,
|
||||||
options: {
|
options: {
|
||||||
|
items: "ul",
|
||||||
position: {
|
position: {
|
||||||
my: "left top",
|
my: "left top",
|
||||||
at: "right top"
|
at: "right top"
|
||||||
@ -194,7 +195,7 @@ $.widget( "ui.menu", {
|
|||||||
//destroy (sub)menus
|
//destroy (sub)menus
|
||||||
this.element
|
this.element
|
||||||
.removeAttr( "aria-activedescendant" )
|
.removeAttr( "aria-activedescendant" )
|
||||||
.find( "ul" )
|
.find( ".ui-menu" )
|
||||||
.andSelf()
|
.andSelf()
|
||||||
.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
|
.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
|
||||||
.removeAttr( "role" )
|
.removeAttr( "role" )
|
||||||
@ -221,7 +222,7 @@ $.widget( "ui.menu", {
|
|||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
// initialize nested menus
|
// initialize nested menus
|
||||||
var submenus = this.element.find( "ul:not(.ui-menu)" )
|
var submenus = this.element.find( this.options.items + ":not( .ui-menu )" )
|
||||||
.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
|
.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
|
||||||
.attr( "role", "menu" )
|
.attr( "role", "menu" )
|
||||||
.hide()
|
.hide()
|
||||||
@ -230,7 +231,7 @@ $.widget( "ui.menu", {
|
|||||||
|
|
||||||
// don't refresh list items that are already adapted
|
// don't refresh list items that are already adapted
|
||||||
var menuId = this.menuId;
|
var menuId = this.menuId;
|
||||||
submenus.add( this.element ).children( "li:not(.ui-menu-item):has(a)" )
|
submenus.add( this.element ).children( ":not( .ui-menu-item ):has( a )" )
|
||||||
.addClass( "ui-menu-item" )
|
.addClass( "ui-menu-item" )
|
||||||
.attr( "role", "presentation" )
|
.attr( "role", "presentation" )
|
||||||
.children( "a" )
|
.children( "a" )
|
||||||
@ -273,16 +274,16 @@ $.widget( "ui.menu", {
|
|||||||
.children( "a" )
|
.children( "a" )
|
||||||
.addClass( "ui-state-focus" )
|
.addClass( "ui-state-focus" )
|
||||||
.end();
|
.end();
|
||||||
this.element.attr( "aria-activedescendant", this.active.children("a").attr("id") );
|
this.element.attr( "aria-activedescendant", this.active.children( "a" ).attr( "id" ) );
|
||||||
|
|
||||||
// highlight active parent menu item, if any
|
// highlight active parent menu item, if any
|
||||||
this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active");
|
this.active.parent().closest( ".ui-menu-item" ).children( "a:first" ).addClass( "ui-state-active" );
|
||||||
|
|
||||||
this.timer = this._delay( function() {
|
this.timer = this._delay( function() {
|
||||||
this._close();
|
this._close();
|
||||||
}, this.delay );
|
}, this.delay );
|
||||||
|
|
||||||
var nested = $( ">ul", item );
|
var nested = $( "> .ui-menu", item );
|
||||||
if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
|
if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
|
||||||
this._startOpening(nested);
|
this._startOpening(nested);
|
||||||
}
|
}
|
||||||
@ -353,19 +354,19 @@ $.widget( "ui.menu", {
|
|||||||
|
|
||||||
this._close( currentMenu );
|
this._close( currentMenu );
|
||||||
|
|
||||||
if( !currentMenu ) {
|
if ( !currentMenu ) {
|
||||||
this.blur( event );
|
this.blur( event );
|
||||||
this.activeMenu = this.element;
|
this.activeMenu = this.element;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_close: function( startMenu ) {
|
_close: function( startMenu ) {
|
||||||
if( !startMenu ) {
|
if ( !startMenu ) {
|
||||||
startMenu = this.active ? this.active.parent() : this.element;
|
startMenu = this.active ? this.active.parent() : this.element;
|
||||||
}
|
}
|
||||||
|
|
||||||
startMenu
|
startMenu
|
||||||
.find( "ul" )
|
.find( ".ui-menu" )
|
||||||
.hide()
|
.hide()
|
||||||
.attr( "aria-hidden", "true" )
|
.attr( "aria-hidden", "true" )
|
||||||
.attr( "aria-expanded", "false" )
|
.attr( "aria-expanded", "false" )
|
||||||
@ -375,7 +376,7 @@ $.widget( "ui.menu", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
collapse: function( event ) {
|
collapse: function( event ) {
|
||||||
var newItem = this.active && this.active.parents("li:not(.ui-menubar-item)").first();
|
var newItem = this.active && this.active.parent().closest( ".ui-menu-item", this.element );
|
||||||
if ( newItem && newItem.length ) {
|
if ( newItem && newItem.length ) {
|
||||||
this._close();
|
this._close();
|
||||||
this.focus( event, newItem );
|
this.focus( event, newItem );
|
||||||
@ -384,7 +385,7 @@ $.widget( "ui.menu", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
expand: function( event ) {
|
expand: function( event ) {
|
||||||
var newItem = this.active && this.active.children("ul").children("li").first();
|
var newItem = this.active && this.active.children( ".ui-menu " ).children( ".ui-menu-item" ).first();
|
||||||
|
|
||||||
if ( newItem && newItem.length ) {
|
if ( newItem && newItem.length ) {
|
||||||
this._open( newItem.parent() );
|
this._open( newItem.parent() );
|
||||||
|
Loading…
Reference in New Issue
Block a user