YUI Library Home

Site Search (YDN & YUIBlog):

# YUI Library Examples: Button Control: Using A Menu Button To Replace A <select> Element

# Button Control: Using A Menu Button To Replace A <select> Element

This example illustrates how to use Button to mimic the behavior of an HTML `<select>` element.

View example in new window.

With A Default Value
Using Existing Markup
Lazy load on Choose a value:
Lazy load off Choose a value:
Without Existing Markup
Lazy load on Choose a value:
Lazy load off Choose a value:
Without A Default Value
Using Existing Markup
Lazy load on Choose a value:
Lazy load off Choose a value
Without Existing Markup
Lazy load on Choose a value:
Lazy load off Choose a value:

By including the Menu family of controls, it is possible to create menu buttons that mimic the behavior of HTML `<select>` elements.

## Basic Setup

Menu buttons can either replace existing `<select>` elements or can be created completely from script.

### Using Existing Markup

To replace an existing `<select>` element with a menu button, simply set the Button's `menu` attribute to the id of the `<select>` element using an object literal passed to the Button's constructor. In this example, the following snippets of HTML and JavaScript are used to transform the first `<select>` element into a menu button.

<select id="select-1" name="select-1"> <option value="select-1-1" selected>Option 1</option> <option value="select-1-2">Option 2</option> <option value="select-1-3">Option 3</option> </select> var oMenuButton1 = new Button({ id: "menubutton-1", name: "menubutton-1", label: "<em class=\"yui-button-label\">Option 1</em>", type: "menu", menu: "select-1", container: "select-1-container" });

### Without Existing Markup

To create a menu button without existing markup, simply set the `menu` configuration property to an array of MenuItem configuration properties, as illustrated by the code used to create the third menu button in this example:

var aMenuButton3MenuData = [ { text: "Option 1", value: "menubutton-3-1" }, { text: "Option 2", value: "menubutton-3-2" }, { text: "Option 3", value: "menubutton-3-3" } ]; var oMenuButton3 = new Button({ id: "menubutton-3", name: "menubutton-3", label: "<em class=\"yui-button-label\">Option 1</em>", type: "menu", menu: aMenuButton3MenuData, container: "menubutton-3-container" });

## `<select>` Behavior & Style Customizations

To mimic the behavior of an HTML `<select>` element, the label of the Button needs to reflect the currently selected MenuItem in the Button's Menu. To update the Button's `label` attribute when the user clicks on a MenuItem, simply register a listener for the Button's `selectedMenuItemChange` event that sets the value of the Button's `label` attribute to the value of the `text` configuration property of the selected MenuItem instance. The following example illustrates how a `selectedMenuItemChange` event listener is added to the first Button in this example.

// "selectedMenuItemChange" event handler for a Button that will set // the Button's "label" attribute to the value of the "text" // configuration property of the MenuItem that was clicked. var onSelectedMenuItemChange = function (event) { var oMenuItem = event.newValue; this.set("label", ("<em class=\"yui-button-label\">" + oMenuItem.cfg.getProperty("text") + "</em>")); }; // Register a "selectedMenuItemChange" event handler that will sync the // Button's "label" attribute to the MenuItem that was clicked. oMenuButton1.on("selectedMenuItemChange", onSelectedMenuItemChange);

It is also necessary to customize the style of the menu button, to indicate the currently selected item in each Button's menu. When the value of the Button's `selectedMenuItem` attribute changes, Button adds a class named "yui-button-selectedmenuitem" to the `<li>` element of the currently selected MenuItem. This class can be used to provide a custom style to the currently selected MenuItem in a Button's Menu. In this example, a Button's currently selected MenuItem is rendered with a check mark to the left of its text label.

In addition to styling a Button's selected MenuItem, the label of each Button in this example is set to a fixed width. This is is accomplished by wrapping the text label of each Button in an `<em>` tag and setting the `<em>`'s `width` property to `5em`, and the `overflow` property to `hidden`.

.yui-menu-button em.yui-button-label { font-style: normal; display: block; text-align: left; white-space: nowrap; /* Restrict the width of the label to 5em. */ width: 5em; /* Hide the overflow if the text label exceeds 5em in width. */ overflow: hidden; /* IE, Safari and Opera support the ability to add ellipsis when the text label exceeds 10em in width. */ text-overflow: ellipsis; -o-text-overflow: ellipsis; } li.yui-button-selectedmenuitem { background: url(../button/assets/checkbox.png) left center no-repeat; }

## Creating Menu Buttons With A Default Value

In HTML, it is possible to specify a default value for a `<select>` element by applying the `selected` attribute to one of the `<select>`'s `<option>` elements. If a menu button is replacing an existing `<select>` element, the default value will automatically be interpreted from the `<select>`'s `<option>` elements.

If a default value is desired for a menu button built completely from script, it is necessary to specify the default value by setting the `selectedMenuItem` attribute. The following code illustrates how a default value was specified for the the fourth Button in this example.

var aMenuButton4MenuData = [ { text: "Option 1", value: "menubutton-4-1" }, { text: "Option 2", value: "menubutton-4-2" }, { text: "Option 3", value: "menubutton-4-3" } ]; var oMenuButton4 = new Button({ id: "menubutton-4", name: "menubutton-4", label: "<em class=\"yui-button-label\">Option 1</em>", type: "menu", lazyloadmenu: false, menu: aMenuButton4MenuData, container: "menubutton-4-container" }); var oMenuButton4Menu = oMenuButton4.getMenu(); // "render" event handler for a Button's Menu - responsible for setting // the default value for the Button's "selectedMenuItem" attribute. var onMenuRender = function (type, args, button) { button.set("selectedMenuItem", this.getItem(0)); }; // If a Button's "selectedMenuItem" attribute is set, the selected // MenuItem's name and value will be part of the form's data set // when its parent form is submitted. For Buttons with Menus built // entirely from script, the "selectedMenuItem" property is not set by // default. To set the "selectedMenuItem" to a default value, simply // register a "render" event handler for the Button's Menu that sets // the Button's "selectedMenuItem" attribute to the desired item in // the Menu. oMenuButton4Menu.subscribe("render", onMenuRender, oMenuButton4);

For performance, a Button's Menu is lazy loaded by default — the MenuItems are initialized and the Menu's HTML is rendered to the page the first time the Button is clicked. If the user never clicks on the Button, its Menu will never be rendered, meaning the `render` event handler used to set the default value of the `selectedMenuItem` attribute will never be called. In such cases it is necessary to add a `submit` event handler to the Button's parent form that will render the Menu if the Button's `selectedMenuItem` attribute is not set. The following code illustrates how a `submit` event handler is added to the parent form of the third button in this example.

// "render" event handler for a Button's Menu - responsible for setting // the default value for the Button's "selectedMenuItem" attribute. var onMenuRender = function (type, args, button) { button.set("selectedMenuItem", this.getItem(0)); }; // "selectedMenuItemChange" event handler for a Button that will set // the Button's "label" attribute to the value of the "text" // configuration property of the MenuItem that was clicked. var onSelectedMenuItemChange = function (event) { var oMenuItem = event.newValue; this.set("label", ("<em class=\"yui-button-label\">" + oMenuItem.cfg.getProperty("text") + "</em>")); }; // "submit" event handler for a Button's parent form - repsonsible for // rendering a Menu that was to be lazy loaded, but never clicked on, // and therefore never rendered. var onFormSubmit = function (event, button) { var oMenuItem = button.get("selectedMenuItem"), UA = YAHOO.env.ua, oEvent, oMenu; if (!oMenuItem) { // Pause submission of the form until the Button's Menu // is rendered YAHOO.util.Event.preventDefault(event); oMenu = button.getMenu(); oMenu.addItems(oMenu.itemData); oMenu.subscribe("render", function () { var bSubmitForm; if (UA.ie) { bSubmitForm = this.fireEvent("onsubmit"); } else { // Gecko, Opera, and Safari oEvent = document.createEvent("HTMLEvents"); oEvent.initEvent("submit", true, true); bSubmitForm = this.dispatchEvent(oEvent); } // In IE and Safari, dispatching a "submit" event to a form // WILL cause the form's "submit" event to fire, but WILL // NOT submit the form. Therefore, we need to call the // "submit" method as well. if ((UA.ie || UA.webkit) && bSubmitForm) { this.submit(); } }, this, true); oMenu.render(oMenu.cfg.getProperty("container")); } }; var aMenuButton3MenuData = [ { text: "Option 1", value: "menubutton-3-1" }, { text: "Option 2", value: "menubutton-3-2" }, { text: "Option 3", value: "menubutton-3-3" } ]; var oMenuButton3 = new Button({ id: "menubutton-3", name: "menubutton-3", label: "<em class=\"yui-button-label\">Option 1</em>", type: "menu", menu: aMenuButton3MenuData, container: "menubutton-3-container" }); // Register a "selectedMenuItemChange" event handler that will sync the // Button's "label" attribute to the MenuItem that was clicked. oMenuButton3.on("selectedMenuItemChange", onSelectedMenuItemChange); oMenuButton3.on("appendTo", function () { var oMenu = this.getMenu(); // If a Button's "selectedMenuItem" attribute is set, the selected // MenuItem's name and value will be part of the form's data set // when its parent form is submitted. For Buttons with Menus built // entirely from script, the "selectedMenuItem" property is not // set by default. To set the "selectedMenuItem" to a default // value, simply register a "render" event handler for the Button's // Menu that sets the Button's "selectedMenuItem" attribute to the // desired item in the Menu. oMenu.subscribe("render", onMenuRender, this); // The items in a Button's Menu are lazy loaded by default: loaded // when the Button is initially clicked. If the user never clicks // on the Button, its Menu will never be rendered, meaning the // "render" event handler registered above will never be called, // and the default value for the Button's "selectMenuItem" // attribute will never be set. Therefore, add a "submit" event // handler to the Button's parent form that will render the Menu // if the Button's "selectedMenuItem" attribute is not set. YAHOO.util.Event.on(this.getForm(), "submit", onFormSubmit, this); });

## Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

### YUI Logger Output:

Note: You are viewing this example in debug mode with logging enabled. This can significantly slow performance.

Reload with logging
and debugging disabled.

### Button Control Examples:

- Push Buttons
- Link Buttons
- Checkbox Buttons
- Radio Buttons
- Submit Buttons
- Reset Buttons
- Menu Buttons
- Split Buttons
- Simple Calendar Menu Button
- Calendar Menu Button with Date on Button Face
- Color Picker Button
- Fixed Width Menu Button
- Glowing Button
- Slider Button
- Using the Button ARIA Plugin
- Using A Menu Button To Replace A <select> Element
- Replacing the content of a Button's Menu
- Combobox, with CSS for Multiple Stacked Instances (included with examples for AutoComplete Control)
- Showing, Hiding, and Reordering Columns. (included with examples for DataTable Control)
- Getting CSS Style Sheets (included with examples for Get Utility)
- Complex Application (included with examples for Layout Manager)

### More Button Control Resources:

- User's Guide (external)
- API Documentation
- Cheat Sheet PDF (external)

Copyright © 2010 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings