type: widget
release: TBD
status: in development - GitHub branch: menu
documentation: N/A
demo: http://view.jqueryui.com/menu/demos/menu/default.html
menus in labs:
http://jquery-ui.googlecode.com/svn/branches/labs/fg-menu/index.html
1 - Description:
Attaches a menu to any element, either as dropdown, context or statically rendered menu, takes well-formed markup -- an unordered list or select form control -- or JSON and converts it into a menu which takes one of several forms (either determined automatically by the structure or via options [the option is called 'type']):
NOTE: numbers in brackets reference visual designs.
Flat, non-hierarchical list (default when there are no nested lists)
- simple menu [D1] appears/acts like a customized dropdown list.
- popup menu [D8] appears/acts like a native Mac OS select list, where the the selected option appears boxed to the left of the trigger button, and the user can click either the selected option or button to open the menu. The menu is positioned so that the selected option always appears at the same place in the list; when the menu is open, if the selected option is third from the top, you'll see the first two options above the selection, and the rest below.
Hierarchical list:
- fly-out [D2 and D3], if the option is explicitly set or, as a best practice, if number of sub-levels limited to 2 or 3 (when 3+ submenus are showing, collision detection can become unwieldy depending on the available space in the viewport). Behaves similarly to Apple's OS menus where the main menu appears on click and sub-menus on hover; the current sub-menu remains open as long as the user's mouse is over it, otherwise it (and any other sub-menus) closes after a short delay. The user's path through the menu is marked with an "on" state.
- ipod-style/drilldown [D6 and D7], if the number of sub-levels is larger or unknown or if the option has been explicitely set. Mimics its namesake by showing a main menu, and as you choose options that navigate to deeper levels, the next menu slides to the left into view. By default a "back" link appears at the bottom of the menu, and when clicked, the visible menu slides to the right out of view. Options allow the user to:
- show a full breadcrumb in place of the back link
- change the location of the back link (above vs. below the menu)
- change the default back text (from "Back" to something else)
- set default breadcrumb text (i.e., "Choose an option:")
- select wether the menu should be context loaded, drop down or statically rendered
- menubar [E2], if the option is explicitly set (not automatic detection): the top-level menu options are arranged either horizontally or vertically in a row, and sub-menus appear either below or beside them, respectively. Sub-menus can be formatted as flat, ipod-style, or flyout. This menu could be used as standard global navigation, or as part of a toolbar. (The toolbar is a separate widget that groups navigation and form controls.)
Split buttons
Users should have the option to create split-buttons for any menu option, where the left button selects the node and the right button opens a sub-menu. The original design only spec'd split buttons for ipod style menu, but this could be useful to show link affordance in fly-outs as well.
Check and radio options
- a check or radio option is always a leaf node, never has a child menu
- check options can be toggled on/off one at a time; multiple check options can be selected/on in a single menu
- radio options are like their namesake in that you can choose one from a group. Example: EXT toolbar, "button with menu:" http://extjs.com/deploy/dev/examples/menu/menus.html
- radio options must be visually grouped together, either in a stand-alone menu or sub-menu, or set apart from other list items with a divider
- when one or more options has an check, radio, or custom icon, the entire menu -- parent menu plus all sub-menus -- is indented left so that the icons are easily scannable in a left "column"
Custom icons [D5]
Users could also specify unique icons that appear next to particular menu options.
Dividers
- dividers could be specified in the original (pre-menu widget) markup as:
- an empty list item. The menu widget could insert a horizontal rule for vertical menus, or a vertical rule for horizontal menus (menubars)
- a list item containing text (not linked) could be converted to a horizontal rule followed by a text label
- dividers/labels are not clickable
Sub-menu indicator arrows and icon alignment [D4]
- for vertical menus: Arrow icons which indicate sub-menus always appear in the right column. It may be problematic to flip the location of the arrows to the left side of the menu; doing so would only work when there are no left column check/radio icons, otherwise it may be visually noisy. Keeping the arrow icons on the right but flipping their direction to point left may also be confusing, as the arrow would be pointing back to the list item -- has anyone seen a menu behave this way? Using the Mac OS default behavior as a guide, it may be a safer bet to never flip the location or direction of the arrows and have them always stay in the right column and point right, which is the default direction of the menu, and reserve the left column for icons.
- for horizontal menus (top-level menubar buttons): An option could be set whether to show a "down" arrow to indicate sub-menus.
As decribed in the first paragraph, the behaviour/mode of the menu can be set to the following (the option for this is called 'mode'):
- dropdown, makes the element the menu is bound to to act like a button, therefore drops down the menu to one side of the original element (default is below, configurable via option 'direction')
- context, appears on right-click in a specified region by default, or the user can optionally make it appear on left click or a key + click combination [any suggestions for this option?]. The direction option can be used to set how it pops up, the default is "right below".
- static (default), simply takes the list or JSON and renders the menu statically (always visible) into the original element. If you don't specify the items option, it will search for the first ul that is a child of the selected element and transforms it automatically (this is specific to the selected mode).
One thing to consider for the grid (and many other future UI plugins) is that HTML 5 provides detailed specs for these widgets that we should seriously consider using as a blueprint for our plugins. If we shared similiar naming and conventions, it will provide a cleaner interface in the future when we all have to support both the HTML 5 version (where available) and the JS-based UI plugin verison on the same site (i.e. use the native HTML 5 if availble, fall back to JS if not supported). The other benefit is that these specs have been refined by a large group of people so they are fairly mature and there may be no need to reinvent the wheel. There is a menu spec here:
http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#menus
Many, many jQuery menu plugins already exist that we may be able to mine for ideas, or use as the basis for the jQuery widget. Several are listed below, but there may be others that look as/more promising (feel free to add to or edit this list):
Single or multi-level menus (dropdown, flyout, ipod-style)
Context menu
Enhance standard <select> into menu
http://www.givainc.com/labs/linkselect_jquery_plugin.htm
Filament flyout and iPod menus with ARIA and CSS framework support:
http://www.filamentgroup.com/lab/jquery_ipod_style_and_flyout_menus/
http://www.filamentgroup.com/examples/menus/index.html
Themeroller-based drilldown menu: http://www.matthewfeerick.com/jquery_menu/
For a very detailed description of menu design best practices and behavior, please review the Apple's UI guidelines for menus or Microsoft's Vista UI guide for menus.
2 - Visual Design:

3 - Functional Specifications/Requirements:
Options:
- input (Selector, default: the selected element itself)
- The element to handle keyboard events for controlling the menu
- If not specified, the selected element will handle keyboard events, it'll get tabIndex=0 to be keyboard focussable
- A button opening a menu can be the target for this option: Tab to the button, hit space to open the menu, keep the focus on the button to navigate the menu
Methods:
- refresh
- Renders all non-menu-items as menu-items, called once by _create
- Call whenever adding or replacing items in the menu via DOM operations, eg. via menu.append("<li><a href='#'>new item</a></li>").menu("refresh")
- activate(event, item)
- activate an item, by deactivating the current item, scrolling the new one into view if necessary, making it the active item and triggering a focus event
- deactivate
- Clear the current selection
- Useful when reopening a menu which had previously an item selected
- next
- Selects the next item based on the active one
- Selects the first if
- none is active
- the last one is active
- previous
- Selects the previos item based on the active one
- Selects the last if
- none is active
- the first one is active
- nextPage
- Similar to next, but jumps a whole page
- prevPage
- Similar to previous, but jumps a whole page
- first
- Returns true if the first item is active
- last
- Returns true if the last item is active
- select
- Select the active item, triggering the select event for that item
- Useful for custom keyboard handling
Events:
- focus
- Triggered when a menu item gets mouse (on hover) or keyboard (navigation with cursor keys) focus
- ui.item refers to a jQuery object containing the focused menu item (a li-element)
- blur
- Triggered a menu item looses focus
- select
- Triggered when a menu item was selected
- ui.item refers to a jQuery object containing the selected menu item (a li-element)
There is no API for binding data to each item that menu provides. Instead, jQuery's data API can be used to bind whatever necessary to each menu item and retrieve that within the select-event via ui.item. Autocomplete does exactly that.
4 - Markup & Style:
4.1 Initial markup examples
Any unordered list:
<ul>
<li><a href="http://google.com">Google</a></li>
<li><a href="http://yahoo.com">Yahoo</a></li>
<li><a href="http://msn.com">MSN</a></li>
<li><a href="http://ask.com">Ask</a></li>
<li><a href="http://aol.com">AOL</a></li>
</ul>
For nested menus, nested unordered lists:
<ul>
<li><a href="http://google.com">Google</a></li>
<li><a href="http://yahoo.com">Yahoo</a></li>
<li><a href="http://msn.com">MSN</a>
<ul>
<li><a href="htp://sub1.example.com">sub-level</a></li>
<li><a href="http://sub2.example.com">sub-level</a></li>
</ul>
</li>
<li><a href="http://ask.com">Ask</a></li>
<li><a href="http://aol.com">AOL</a></li>
</ul>
4.2 Recommended transformed HTML markup
4.3 Accessibility recommendations
TODO specify use of ARIA attributes like role="menu" and active-descendent=...
4.4 CSS & Theme
TODO
5 - Latest version of plugin:
http://view.jqueryui.com/menu/tests/visual/menu/menu.html
6 - Open issues being discussed
Move standard key handling to base menu plugin:
- up moves to the previous item, triggers focus event
- up on first item triggers underflow event, does nothing
- down moves to the next item, triggers focus event
- down on last item triggers overflow event, does nothing
- right triggers overflow event, does nothing
- left triggers underflow event, does nothing
Looping:
- up underflow focuses last item
- down overflow focuses first item
Nested menu:
- right on item with submenu opens submenu
- right on item with no subment triggers overflow
- left on submenu triggers focus on parent menu
- left on top menu triggers underflow
Autocomplete:
- up underflow focuses text field
- down overflow focuses text field
Menu bar:
- right overflow focuses next menu bar item
- left underflow focuses previous menu bar item
Prove extensibiility by building examples of:
- autocomplete
- nested menu
- combobox
- menu bar
Todos:
- Implement menu-overlay handling in widget: bind click to some trigger, usually a button to open and close it, and have the menu close on any click outside the menu, but not (necessarily) on the menu itself
Comments (24)
hugh.lomas said
at 3:08 pm on Jul 17, 2009
One thing that I have often wanted in a menu is the ability to pop out an input directly in the menu, and type into it. Like
File->Search->[input], without it opening a "dialog" or whatever. The [input] should grab focus, and the menu should stay open.
Damir Sečki said
at 7:02 am on Jun 15, 2010
I would like to request a feature:
imagine data in a table (cms administration area).
Now you list about 20 rows of data (or more)...
The most useful thing I would need is the ability to append at least one "action" menu per row
(this menu would include edit, delete, rename, etc - for that specific row) now the best way it would be to add a UL list at the end of the table in this way
<ul id="action_menu">
<li><a href="/users/delete/?id={id}">Delete user</a></li>
<li><a href="/users/edit/?id={id}">Update user datar</a></li>
<li><a href="/users/rename/?id={id}">Rename user</a></li>
</ul>
and each row in the table would have a cell with an image for example, or a button or whatever.. that on click, would show this action menu right beside it... and would populate the {id} portion with proper id
Obviously you could use other fields beside {id} too
The only thing I couldn't figure out is how to extract the data from the table row, since you could also need fields that you are even not showing in your table...
one way it would be to populate a JSON with row data and then assign an id to each row like this:
<script ....>
$(document).ready(function(){
$('.action_menu').menu({
"type":action, "row_id_prefix":"user_", "data":users_json, "open_method":"on_hover", "open_delay":500});
});
</script>
<tr id="user_<?php echo $USER["id"];?>">
<td>.....</td>
<td><img src="media/admin_arrow_down.png" alt="action menu" class="action_menu" /></td>
</tr>
Something like this
Benjamin Neau said
at 11:18 am on Jun 15, 2010
Hi Damir,
I think you can already do what you want to do. Considering your request, you may do the following:
1/ bind an onclick event handler to your image/button which :
a/ sets a temporary global variable to the value of $(event.target).closest("tr").attr("id") (Note: you can probably find a cleaner way, I'm trying to tell you the easiest way that came to mind...)
b/ open the menu (myUL.menu("open"))
2/ Bind a selectedmenu event handler to your menu which
a/ looks up which menu item was clicked (using the event handler second parameter: data; which will contains an "item" object: the clicked menu item as a DOM Node (IIRC))
b/ redirects the user to the page according to which menu item was clicked and the global variable set earlier when the button was clicked (the latter containing your user ID)
If there is anything more I can do for you, do not hesitate to ask here, or on the Developping jQuery UI forum (http://forum.jquery.com/developing-jquery-ui).
Damir Sečki said
at 11:44 am on Jun 15, 2010
Hello, I know I can do all this and I already did, several times...
but it would be nice to have this functionality in jquery UI, since it is something very usefull, productive, user friendly, etc, etc
Scott González said
at 6:09 pm on Jul 1, 2010
From Michael Lang (forum post: http://forum.jquery.com/topic/jquery-ui-1-9-milestone-2-does-menu-support-nested-menus#14737000001100447):
Here is a url to the latest flyout menu and toolbar demo. It has two menus to ensure they do not conflict with each other, then a toolbar which also has flyout menu's tied to both toolbar buttons.
http://nexul.com/prototypes/toolbar/demo.html
I will maintain the demo at this link at least until jquery ui supports these features and has them documented on the main jquery UI documentation site.
As of now all the toolbar menu item handling is not perfect, but I will continue to refine it. I'll move any further discussion on this to the menu wiki page. (http://wiki.jqueryui.com/Menu)
Michael Lang said
at 10:23 pm on Jul 1, 2010
Thanks for copying that post here.
Michael Lang said
at 10:43 pm on Jul 1, 2010
I could use some advice on using position. The toolbar tries to position the "cities" button sub-menu top left to the bottom left of the button. But it appears down and to the right a varying amount depending on where on the page viewport the button is located. The menu always appears to the right of the left edge of the button by the same number of pixels the left edge of the button is from the left side of the viewport, and it appears under the button by the same number of pixels as the button is from the top edge of the viewport. Is this due to a mix of absolute and relative positioned entities?
Michael Lang said
at 11:02 am on Jul 2, 2010
answered on the forum: http://forum.jquery.com/topic/jquery-ui-1-9-milestone-2-does-menu-support-nested-menus
The advice worked, use position after show.
Michael Lang said
at 10:43 pm on Jul 1, 2010
I'm planning on creating a new menubar widget that does what is currently in the demo.html file. It registers the button elements as button elements, and then takes the next ul child after the button and assumes that is the menu to be displayed for the button. It then does all the click and other menu hiding logic. So then from the page all you'll have to do is register a single container element as a menubar.
What about this structure for the markup that is turned into a menubar:
<span id="toolbar" class="ui-widget-header ui-corner-all">
<button id="city-menu-button">cities</button>
<ul id="city-list3">
<li><a href="#" id="Amsterdam3">Amsterdam</a></li>
<li><a href="#">Anaheim</a></li>
<li><a href="#">Cologne</a></li>
<li><a href="#">Frankfurt</a></li>
<li><a href="#">Magdeburg</a></li>
<li><a href="#">Munich</a></li>
<li><a href="#">Utrecht</a></li>
<li><a href="#">Zurich</a></li>
</ul>
</span>
The outer element could be any container (div, span, other?). But it would need to contain elements that define the buttons (and could be either a button or an anchor tag?). If there is a ul tag immediately after the button it will turn that into a flyout menu for the button. If the next element is anything else, then the button will not get a flyout menu. That pattern can repeat as needed. Note the flyout menu definition already matches the specification in section 4 (markup & style) above.
If there is a flyout, should it just always add a down arrow per the E2 visual design using the appropriate themeroller style name? Any recommendations on how someone should be able to specify other images for the menu bar button, or should they just then use an anchor tag with a contained image?
what css class should be applied to the menubar container element. Should I use something existing like just ui-widget, or does this call for a new style name?
Michael Lang said
at 11:32 am on Jul 2, 2010
Button icon reference: http://jqueryui.com/demos/button/#icons
This does show how you can use the button plugin to define a primary and secondary icon. Since this toolbar widget will set the secondary icon to 'ui-icon-triangle-1-s' per the example, the question remains how someone creating a toolbar widget on the container would specify the primary icon for each button. It should probably be left as a secondary exercise of the person creating the toolbar to also set the primary icon of each button that needs one using something like this:
$(".toolbarselector" ).toolbar(...);
$( ".buttonselector" ).button( "option", "icons", {primary:'ui-icon-gear'} );
At this point I am just assuming the setting of the icons property will not change the secondary icon if it is not supplied. I'll have to look into that further.
Michael Lang said
at 2:46 pm on Jul 2, 2010
http://forum.jquery.com/topic/setting-partial-options-using-the-property-setter
verbose option to set primary button:
$("#city-menu-button").button( "option", "icons", {
primary:'ui-icon-gear',
secondary:$("#city-menu-button").button( "option", "icons").secondary
});
Michael Lang said
at 10:59 pm on Jul 1, 2010
I'd like to add a new requirement to this plugin. The base menu plugin, and the flyoutmenu extenstion I referenced above already supports it, but many other jquery menus out there do not. A developer should be able to bind an event such as click to the anchor in a menu item, and then after the item is included as part of a list turned into a menu, the click event should still fire when an end user clicks on the menu item representing that list item. A number of menus do not support is because they create new divs representing the list structure and put them in some hidden container div at the end of the document.
The reason this is needed is for C#, ASP.NET developers (such as myself) who want an anchor tag to trigger a form post to the server using helper method __doPostBack(name, arg). So the link that is clicked on not only needs to fire any jQuery events that were bound to it, but if the anchor tag was inside a form element at some level defined inside the menu then that form tag needs to remain active for that menu item.
Jörn Zaefferer said
at 4:02 am on Jul 2, 2010
Are you saying we should just put that into the spec, as its implemented right now? I agree with that, just need to figure out where to put it.
Jörn Zaefferer said
at 4:05 am on Jul 2, 2010
Actually I don't think we need to put that in the spec, as thats part of the general progressive enhancement requirement that stands for all jQuery UI widgets. See the Progressive Enhancement sction here: http://wiki.jqueryui.com/VisionAndGoals
Michael Lang said
at 10:43 am on Jul 2, 2010
Ok. That makes sense.
Michael Lang said
at 10:51 am on Jul 2, 2010
I've run across a line of code in the base menu widget that appears to break progressive enhancement. In the activate function it removes the existing id on child elements and sets it to a specific value when it is selected. Then we de-selected the id attribute is removed and the element is left with no id attribute.
this.active = item.eq(0)
.children("a")
.addClass("ui-state-hover")
.attr("id", "ui-active-menuitem")
.end();
Shouldn't this be done by applying the class 'ui-active-menuitem' to the element?
I found this when on the select event handler for my menu, I tried to output the id along with the text of the menu item, so I could tell in the log which menu control the selection was from. I also see needing this to get rid of ambiguity when multiple menu items (maybe at different nested levels) have the same text.
Michael Lang said
at 10:54 am on Jul 2, 2010
sorry for the typo. The last sentence of the first paragraph should be:
"Then when de-selected the id attribute is removed and the element is left with no id attribute."
It would be nice if posts in the wiki could be edited by the author.
Michael Lang said
at 4:51 pm on Jul 2, 2010
I've completed a preliminary menubar widget. It relies on the flyoutmenu widget (included) and the current jQueryUI button widget. All you need to do to invoke it is:
$("#toolbar").menubar();
There are no options, there is one event 'select'. See it here:
http://nexul.com/prototypes/toolbar/demo.html
There are a couple outstanding issues to discuss
1) bug: keyboard navigation to sub-menus of a menu opened by a menubar button does not work. The keyboard navigation for flyout menus created outside of a menubar. I have not found the cause. Any help is appreciated
2) discuss: a menu item that has a custom click handler associated to the anchor tag does not trigger the select event on the menu when it is clicked. It does fire the select event when you select it by pressing enter. I have not tested if select still fires if I handle the keypress on the menu item anchor. Since the user is then handling that item click separately, is this ok? Or does select need to fire also.
Eric H said
at 4:30 pm on Aug 16, 2010
I've been working with this; thank you.
My requirement is for an application-style menu bar; visual style E2 above. The button widget in this preliminary version of a menu bar doesn't work for me. It has the right interactions, but an unacceptable visual style relative to my requirement. I'm currently in the process of ripping out code from the button widget to make a minimal version of it that's suitable for my immediate needs. I mention this because a production version of a menu bar will likely need something similar. My suggestion, based on what I've been doing, is that the button widget derive from a new widget, say, named "clickable", that has the interaction code only. Instantiation of the menubar can then accept a clickable widget parametrically to anchor its flyout menu, allowing both button bars and application menu bars easily.
Less importantly, I changed the input syntax in mine to use only <ul>, <li>, and <a> tags. I got annoyed at the syntax checker in Eclipse warning about <ul> inside <span>.
Michael Lang said
at 5:02 pm on Jul 2, 2010
I've completed a preliminary flyout menu widget. It relies on the jQueryUI menu widget in 1.9 milestone 2. All you need to do to invoke it is:
$("#menu-top2").flyoutmenu();
Demo: http://nexul.com/prototypes/toolbar/demo.html
It supports the input option, and select event. It has methods for hide, show, left, right, up, down, pageup, pagedown, and activate.
What do you think about the z-ordering index among different menus. Right now, sub-menus are created at the same time as the parent menu it is associated with. So if you create two or more menus, it is possible that the sub-menu of the earlier menu will partially overlap the other main menu. If the overlapped main menu was created last, it will appear on top of the sub-menu being shown. That seems undesirable to me. I'm thinking of updating the flyoutmenu prototype so that it only builds the main menu portion at initialization, then only creates sub-menu instances as they are shown for the first time. That way the z-order of the sub-menus should be on top of all main menus. Does that make sense?
Michael Lang said
at 2:52 pm on Jul 4, 2010
As another alternative to the z-index issue, how about update the z-index of the each menu when it's show method is called.
http://www.west-wind.com/Weblog/posts/876332.aspx
or
http://plugins.jquery.com/taxonomy/term/2836
Is there another preferred method in the jQueryUI team?
Rhodry Korb said
at 11:52 pm on Jul 15, 2010
I am using the Filament iPod drilldown with Breadcrumbs, and want to know how to make the height variable on the second/third bread crumb, anyone achieved this?
Thanks in advance
GWBasic said
at 4:32 pm on Jul 28, 2010
I couldn't get the button example (http://view.jqueryui.com/menu/demos/menu/contextmenu.html) to work in my code. Anyway, in my opinion, it's really too much code to attach a context menu to a button. (In my case, I'm porting some apple-style context menus where there's a little button with an arrow instead of "right-click.")
I ended up writing a plugin that works with milestone 2 to get the kind of menus that I want. Basically, instead of $('.menu').menu(), my plugin is $('.menu').contextMenu(). As a result, it's much easier to set up a button-based context menu.
My plugin is at http://appfeeds.appfeeds.com/Lifestream/quickanddirtycontextbutton.page, and the sample is at http://appfeeds.appfeeds.com/jquery_contextButton/example_jqueryui.html. Feel free to integrate my ideas into jqueryui's menu system.
Michael Lang said
at 9:47 pm on Aug 3, 2010
your menu is not appearing directly under the button that opens it in firefox. It does not appear to work at all in IE8.
The menubar widget does exactly what you are looking for. My example shows multiple items on the menu bar, but if you put just one button on the menu bar container it does what you are looking for. See the source of this demo: http://nexul.com/prototypes/toolbar/demo.html
You don't have permission to comment on this page.