(For more resources on YUI, see here.)
Common navigation structures
All but the most limited of websites must have a mechanism by which visitors can navigate around the pages of the site from the home page. In order to meet accessibility guidelines, several methods of navigation will usually be available, including at least a navigation menu and a site map.
There have been many different implementation styles that have been popular over the years. Before anyone really worried about accessibility or standards compliance, a common way of designing a navigation menu was to use a series of images that linked to other pages of the site, and there was also the popular frame-based navigation structure. While these methods saved the designer a lot of time, effort, and any real skill, they led to hugely increased page load times and a legacy of bad coding practice.
Thankfully, those days have long since passed, and with the continued development of CSS, it’s now possible to design an effective navigation structure based on semantic HTML and styled with CSS.
Designing a navigation menu that is effective, robust, and presented effectively can still pose a challenge, and troubleshooting the compatibility of a menu between different browsers can be a very time-consuming process. This is where the YUI steps in.
Instant menus—just add water (or a Menu Control)
The Menu Control is used to add one of several different menus to your website, saving you the chore of adding this almost essential feature yourself. It’s another control that takes a complex, difficult, or time-consuming task, and one which is an almost inherent requirement of any website, and packages it up into a convenient and easy-to-use module. The three different types of menu you can create are:
- A standard navigation menu
- An application-style menu bar
- A right-click context menu
The navigation menu can be implemented as either a vertical or horizontal menu and generates a clean and attractive interface, which your visitors can use to navigate to different areas of your site. The navigation model of any site is key to whether using the site is easy and enjoyable; nothing turns off visitors more than a poorly designed or inconsistent navigation structure.
Another type of menu that the Menu Control is able to create is an application-style menu bar, which stretches across the screen horizontally, building on the current trend in the online world to blur the distinction between the browser and the desktop.
As well as taking care of navigation for you, it can also be used to add right-click context (pop-up) menus to any part of your web application, which again can give a web application a definite desktop feel to it.
We’ll be looking at implementing each of the different types of menu ourselves in just a moment. Before we do this, let’s take a quick look at the classes that go together to make the Menu Control.
The Menu classes
This component is made up of a small family of different types of menu. There is a range of different classes that work together to bring the functionality of the different types of menu to you.
The three main classes behind the Menu family are:
Menu is a subclass of Overlay, part of the Container family, and the other two are subclasses of Menu. Just as each TabView is made of several Tabs, each kind of Menu has a different class for its items:
ContextMenuItem is simply an alias for MenuItem created just for the sake of symmetry. All types of menu items can have a Menu as a submenu; neither ContextMenu nor MenuBar can be nested in a menu item, they are only good at the outermost level.
All the menus are coordinated by YAHOO.widget.MenuManager, which listens to events at the document body level and dispatches them to the corresponding menus or menu items using the technique of Event Delegation to the limit; after all, the document body is the furthest out an event can bubble.
Like the other members of the Container family, the constructor for Menu and its subclasses take two arguments; first a reference to existing markup or, if built via code, the id we want the Menu to have once rendered. The second argument takes the configuration options, if any, and accepts any configuration attribute as would be expected. However, in Menu, it can also take a couple of properties: itemData and lazyLoad, while MenuItem can also take value. We will see what they can be used for shortly.
The markup will usually consist of a series of unordered lists
Just as with any container, Menus have to be rendered. ContextMenus are usually rendered into document.body, as they have no place in the normal flow of the page. If the menu structure is too complex and takes too long to render, the lazyLoad option tells the Menu to render just the first level of items, those that would be visible initially, postponing rendering the rest until needed.
The ContextMenu is a specialized version of the control that provides a menu hidden from view until the element that it is associated with (the trigger element) is clicked with the right mouse button (except in Opera on Windows and OS X which requires the left-click + Ctrl key combination). The trigger element is defined using the trigger configuration attribute; this is the only configuration attribute natively defined by the ContextMenu class, all others are inherited.
The MenuBar is similar to the standard Menu, but is horizontal instead of vertical. It can behave like an application-style menu bar, where the top-level menu items must be clicked in order for them to expand, or it can behave more like a web menu where the menu items expand on a simple mouse over and have submenu indicators. This is controlled with the autosubmenudisplay Boolean configuration attribute.
The MenuItem class
Each menu type has a subclass representing the individual menu items that form choices within the menu. They will be created automatically when a Menu is built from existing markup or by setting the itemData configuration option to a menu description. You will only create individual MenuItems when extending the functionality of an existing menu.
MenuItems have several interesting configuration attributes:
- checked: Shows a checkmark to the left of the label, useful for items that toggle in between two states.
- classname: Added to the existing if any further styling is required. It can read this from existing markup.
- disabled: This item cannot be selected and will be grayed out. When built from markup, it can read this attribute from an tag.
- keylistener: The key combination (Shift, Control, or Alt + character) that will trigger this item. It can be read from markup.
- onclick: The method to be called when this item is clicked.
- text: A string to be shown in the label.
- url, target: The destination page for this item when not handled via code.
- selected: The item shows highlighted.
- submenu: A nested instance of Menu, an object description of a nested Menu, or a reference to the markup that would produce it.
- value: A value associated with this item.
The two subclasses YAHOO.widget.ContextMenuItem and YAHOO.widget. MenuBarItem both extend the MenuItem class, providing a constructor and some basic properties and methods for programmatically working with individual ContextMenu or MenuBar menu items.
As a matter of fact ConextMenuItem is simply an alias for MenuItem. MenuBarItem has different defaults than MenuItem to suit the different layout of the MenuBar.
Creating a Basic Navigation Menu
Let’s put together a basic navigation menu.
Our menu will be built from underlying HTML rather than from script.
We’ll be enhancing the example of the image portfolio by first providing a landing, home page that will welcome us. We’ll later add a context menu to the image portfolio itself so that instead of adding an extra button (like Rate!) for each option, we’ll handle them via menus. Once complete, our landing page should appear like this: