YUI 3: MenuNav Node Plugin [beta]
The MenuNav Node Plugin makes it easy to transform existing list-based markup into traditional, drop down navigational menus that are both accessible and easy to customize, and only require a small set of dependencies. The MenuNav Node Plugin features:
- Progressive Enhancement
- The MenuNav Node Plugin is designed to support Progressive Enhancement, making it easy to transform simple, semantic markup into dynamic drop-down menus with just a few lines of JavaScript.
- Small footprint
- The MenuNav Node Plugin has a small footprint of ~5 KB (GZIP'd) and requires a minimal set of dependencies (YUI, Event, DOM, Node, OOP, ClassNameManager, and the Focus Manager Node Plugin).
- Accessibility & Usability Minded
- The MenuNav Node Plugin was built with both accessibility and usability in mind. The MenuNav Node Plugin implements established mouse and keyboard interaction patterns to deliver a user experience that is both familiar and easy to use. To that foundation the MenuNav Node plugin adds support for screen readers through the use of the WAI-ARIA Roles and States. Watch this video for a quick a demo of a menu created using the MenuNav Node Plugin using the WAI-ARIA Roles and States running in Firefox 3 using the Window-Eyes screen reader.
- Easy to style and configure
- The MenuNav Node Plugin is easy to configure. The visual presentation of menus is controlled completely via CSS. A handful of straightforward configuration attributes can be used to make common modifications to a menu's behavior.
<iframe>Shim for IE 6-
No menuing system would be complete without an
<iframe>to prevent<select>elements from poking through menus in IE 6.
More Information
- Examples: MenuNav Node Plugin in action.
- API Documentation: View the full API documentation for the MenuNav Node Plugin.
- Download: MenuNav Node Plugin as part of the full YUI Library.
- Free Hosting on our fast edge servers with combo-loading.
- License: BSD.
Getting Started
Include Dependencies
The easiest way to include the source files for MenuNav and its dependencies is to add the YUI seed file to your page, using the following script tag, and allow the YUI instance to download any additional files which may be required:
<script src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>
<script src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>The YUI instance will automatically pull down MenuNav's source files and any missing dependencies when the node-menunav module is used. This helps you avoid having to manually manage the list of files needed on your page to support multiple components while also optimizing your initial page weight by loading files only when they are required.
If you do want to include file dependencies manually on your page, the YUI Dependency Configurator can be used to determine the list of files you need to include in order to use MenuNav.
The YUI Instance
Once you have the YUI seed file on your page (yui-min.js), you can
create a new YUI instance for your application to use and populate it
with the modules you need, specified as the first set of arguments to the
use method:
// Create new YUI instance, and populate it with the required modules YUI().use('node-menunav', function(Y) { // MenuNav available, and ready for use. });
// Create new YUI instance, and populate it with the required modules YUI().use('node-menunav', function(Y) { // MenuNav available, and ready for use. });
The last argument passed to use is a callback function. The callback function will be invoked as soon as the YUI instance is done downloading any required files missing from your page. Once those files are loaded, your local YUI instance will be supplemented with the classes which make up the node-menunav module and any modules it depends on. A reference to the populated YUI instance (Y) is passed back to your callback function. Within your callback, then, you can start writing your application code based on your own custom instance of YUI.
For more information on creating instances of YUI and the
use method, see the
YUI Global object documentation.
Next, apply the yui-skin-sam class name to an element that is a
parent of the element in which the menu lives. You can usually accomplish this
simply by putting the class on the <body> tag:
<body class="yui-skin-sam">
<body class="yui-skin-sam">
For more information on skinning YUI components and making use of default skins, see our Understanding YUI Skins article.
Basic Setup
To create a menu using the MenuNav Node Plugin, start by including the required markup. The markup
for menus created using the MenuNav Node Plugin follows the same pattern established for Widgets,
with each menu's content box containing one or more <ul> elements:
Menu Markup Example
<div id="menu-1" class="yui-menu"><!-- Bounding box --> <div class="yui-menu-content"><!-- Content box --> <ul> <!-- Menu items --> </ul> </div> </div>
<div id="menu-1" class="yui-menu"><!-- Bounding box --> <div class="yui-menu-content"><!-- Content box --> <ul> <!-- Menu items --> </ul> </div> </div>
Menuitems also follow the Widget markup pattern, with root node defined using an
<li> element:
MenuItem Markup Example
<li class="yui-menuitem"><!-- Bounding box --> <a class="yui-menuitem-content" href="http://www.yahoo.com"><!-- Content box --> Yahoo! </a> </li>
<li class="yui-menuitem"><!-- Bounding box --> <a class="yui-menuitem-content" href="http://www.yahoo.com"><!-- Content box --> Yahoo! </a> </li>
Submenus are defined by wrapping the the menu markup in an <li> element. Each
submenu must have have a label. The label should preceed the menu markup, and the label's
href attribute should be set to the point to the id of its corresponding submenu.
Submenu Markup Example
<li> <a class="yui-menu-label" href="#submenu-1">Submenu Label</a><!-- Menu label --> <div id="submenu-1" class="yui-menu"><!-- Bounding box --> <div class="yui-menu-content"><!-- Content box --> <ul> <!-- Menu items --> </ul> </div> </div> </li>
<li> <a class="yui-menu-label" href="#submenu-1">Submenu Label</a><!-- Menu label --> <div id="submenu-1" class="yui-menu"><!-- Bounding box --> <div class="yui-menu-content"><!-- Content box --> <ul> <!-- Menu items --> </ul> </div> </div> </li>
Following the patterns illustrated above, the markup for a menu created using the MenuNav Node Plugin comes together as follows:
<div id="menu-1" class="yui-menu"><!-- Root menu bounding box --> <div class="yui-menu-content"><!-- Root menu content box --> <ul> <li class="yui-menuitem"><!-- Menuitem bounding box --> <a class="yui-menuitem-content" href="http://www.yahoo.com"><!-- Menuitem content box --> Yahoo! </a> </li> <li> <a class="yui-menu-label" href="#pim">PIM</a><!-- Submenu label --> <div id="pim" class="yui-menu"><!-- Submenu bounding box --> <div class="yui-menu-content"><!-- Submenu content box --> <ul> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://mail.yahoo.com">Yahoo! Mail</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://addressbook.yahoo.com">Yahoo! Address Book</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://calendar.yahoo.com">Yahoo! Calendar</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://notepad.yahoo.com">Yahoo! Notepad</a> </li> </ul> </div> </div> </li> </ul> </div> </div>
<div id="menu-1" class="yui-menu"><!-- Root menu bounding box --> <div class="yui-menu-content"><!-- Root menu content box --> <ul> <li class="yui-menuitem"><!-- Menuitem bounding box --> <a class="yui-menuitem-content" href="http://www.yahoo.com"><!-- Menuitem content box --> Yahoo! </a> </li> <li> <a class="yui-menu-label" href="#pim">PIM</a><!-- Submenu label --> <div id="pim" class="yui-menu"><!-- Submenu bounding box --> <div class="yui-menu-content"><!-- Submenu content box --> <ul> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://mail.yahoo.com">Yahoo! Mail</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://addressbook.yahoo.com">Yahoo! Address Book</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://calendar.yahoo.com">Yahoo! Calendar</a> </li> <li class="yui-menuitem"> <a class="yui-menuitem-content" href="http://notepad.yahoo.com">Yahoo! Notepad</a> </li> </ul> </div> </div> </li> </ul> </div> </div>
With the markup for the menu in place, simply get a Node reference for the root menu and then call
the plug method, passing in a reference to the MenuNav Node Plugin.
// Call the "use" method, passing in "node-menunav". This will load the // script and CSS for the MenuNav Node Plugin and all of the required // dependencies. YUI().use("node-menunav", function(Y) { // Use the "contentready" event to initialize the menu when the subtree of // element representing the root menu (<div id="menu-1">) is ready to // be scripted. Y.on("contentready", function () { // The scope of the callback will be a Node instance representing // the root menu (<div id="menu-1">). Therefore, since "this" // represents a Node instance, it is possible to just call "this.plug" // passing in a reference to the MenuNav Node Plugin. this.plug(Y.Plugin.NodeMenuNav); }, "#menu-1"); });
// Call the "use" method, passing in "node-menunav". This will load the // script and CSS for the MenuNav Node Plugin and all of the required // dependencies. YUI().use("node-menunav", function(Y) { // Use the "contentready" event to initialize the menu when the subtree of // element representing the root menu (<div id="menu-1">) is ready to // be scripted. Y.on("contentready", function () { // The scope of the callback will be a Node instance representing // the root menu (<div id="menu-1">). Therefore, since "this" // represents a Node instance, it is possible to just call "this.plug" // passing in a reference to the MenuNav Node Plugin. this.plug(Y.Plugin.NodeMenuNav); }, "#menu-1"); });
