2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
9 * @description <p>The Button Control enables the creation of rich, graphical
10 * buttons that function like traditional HTML form buttons. <em>Unlike</em>
11 * tradition HTML form buttons, buttons created with the Button Control can have
12 * a label that is different from its value. With the inclusion of the optional
13 * <a href="module_menu.html">Menu Control</a>, the Button Control can also be
14 * used to create menu buttons and split buttons, controls that are not
15 * available natively in HTML. The Button Control can also be thought of as a
16 * way to create more visually engaging implementations of the browser's
17 * default radio-button and check-box controls.</p>
18 * <p>The Button Control supports the following types:</p>
21 * <dd>Basic push button that can execute a user-specified command when
24 * <dd>Navigates to a specified url when pressed.</dd>
26 * <dd>Submits the parent form when pressed.</dd>
28 * <dd>Resets the parent form when pressed.</dd>
30 * <dd>Maintains a "checked" state that can be toggled on and off.</dd>
32 * <dd>Maintains a "checked" state that can be toggled on and off. Use with
33 * the ButtonGroup class to create a set of controls that are mutually
34 * exclusive; checking one button in the set will uncheck all others in
37 * <dd>When pressed will show/hide a menu.</dd>
39 * <dd>Can execute a user-specified command or display a menu when pressed.</dd>
42 * @namespace YAHOO.widget
43 * @requires yahoo, dom, element, event
44 * @optional container, menu
53 * The Button class creates a rich, graphical button.
54 * @param {String} p_oElement String specifying the id attribute of the
55 * <code><input></code>, <code><button></code>,
56 * <code><a></code>, or <code><span></code> element to
57 * be used to create the button.
58 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
59 * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org
60 * /TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-34812697">
61 * HTMLButtonElement</a>|<a href="
62 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
63 * ID-33759296">HTMLElement</a>} p_oElement Object reference for the
64 * <code><input></code>, <code><button></code>,
65 * <code><a></code>, or <code><span></code> element to be
66 * used to create the button.
67 * @param {Object} p_oElement Object literal specifying a set of
68 * configuration attributes used to create the button.
69 * @param {Object} p_oAttributes Optional. Object literal specifying a set
70 * of configuration attributes used to create the button.
71 * @namespace YAHOO.widget
74 * @extends YAHOO.util.Element
79 // Shorthard for utilities
81 var Dom = YAHOO.util.Dom,
82 Event = YAHOO.util.Event,
84 Overlay = YAHOO.widget.Overlay,
85 Menu = YAHOO.widget.Menu,
88 // Private member variables
90 m_oButtons = {}, // Collection of all Button instances
91 m_oOverlayManager = null, // YAHOO.widget.OverlayManager instance
92 m_oSubmitTrigger = null, // The button that submitted the form
93 m_oFocusedButton = null; // The button that has focus
102 * @method createInputElement
103 * @description Creates an <code><input></code> element of the
106 * @param {String} p_sType String specifying the type of
107 * <code><input></code> element to create.
108 * @param {String} p_sName String specifying the name of
109 * <code><input></code> element to create.
110 * @param {String} p_sValue String specifying the value of
111 * <code><input></code> element to create.
112 * @param {String} p_bChecked Boolean specifying if the
113 * <code><input></code> element is to be checked.
114 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
115 * one-html.html#ID-6043025">HTMLInputElement</a>}
117 function createInputElement(p_sType, p_sName, p_sValue, p_bChecked) {
122 if (Lang.isString(p_sType) && Lang.isString(p_sName)) {
124 if (YAHOO.env.ua.ie) {
127 For IE it is necessary to create the element with the
128 "type," "name," "value," and "checked" properties set all
132 sInput = "<input type=\"" + p_sType + "\" name=\"" +
137 sInput += " checked";
143 oInput = document.createElement(sInput);
148 oInput = document.createElement("input");
149 oInput.name = p_sName;
150 oInput.type = p_sType;
154 oInput.checked = true;
160 oInput.value = p_sValue;
170 * @method setAttributesFromSrcElement
171 * @description Gets the values for all the attributes of the source element
172 * (either <code><input></code> or <code><a></code>) that
173 * map to Button configuration attributes and sets them into a collection
174 * that is passed to the Button constructor.
176 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
177 * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org/
178 * TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-
179 * 48250443">HTMLAnchorElement</a>} p_oElement Object reference to the HTML
180 * element (either <code><input></code> or <code><span>
181 * </code>) used to create the button.
182 * @param {Object} p_oAttributes Object reference for the collection of
183 * configuration attributes used to create the button.
185 function setAttributesFromSrcElement(p_oElement, p_oAttributes) {
187 var sSrcElementNodeName = p_oElement.nodeName.toUpperCase(),
195 * @method setAttributeFromDOMAttribute
196 * @description Gets the value of the specified DOM attribute and sets it
197 * into the collection of configuration attributes used to configure
200 * @param {String} p_sAttribute String representing the name of the
201 * attribute to retrieve from the DOM element.
203 function setAttributeFromDOMAttribute(p_sAttribute) {
205 if ( !(p_sAttribute in p_oAttributes) ) {
208 Need to use "getAttributeNode" instead of "getAttribute"
209 because using "getAttribute," IE will return the innerText
210 of a <code><button></code> for the value attribute
211 rather than the value of the "value" attribute.
214 oAttribute = p_oElement.getAttributeNode(p_sAttribute);
217 if (oAttribute && ("value" in oAttribute)) {
219 me.logger.log("Setting attribute \"" + p_sAttribute +
220 "\" using source element's attribute value of \"" +
221 oAttribute.value + "\"");
223 p_oAttributes[p_sAttribute] = oAttribute.value;
233 * @method setFormElementProperties
234 * @description Gets the value of the attributes from the form element
235 * and sets them into the collection of configuration attributes used to
236 * configure the button.
239 function setFormElementProperties() {
241 setAttributeFromDOMAttribute("type");
243 if (p_oAttributes.type == "button") {
245 p_oAttributes.type = "push";
249 if ( !("disabled" in p_oAttributes) ) {
251 p_oAttributes.disabled = p_oElement.disabled;
255 setAttributeFromDOMAttribute("name");
256 setAttributeFromDOMAttribute("value");
257 setAttributeFromDOMAttribute("title");
262 switch (sSrcElementNodeName) {
266 p_oAttributes.type = "link";
268 setAttributeFromDOMAttribute("href");
269 setAttributeFromDOMAttribute("target");
275 setFormElementProperties();
277 if ( !("checked" in p_oAttributes) ) {
279 p_oAttributes.checked = p_oElement.checked;
287 setFormElementProperties();
289 oRootNode = p_oElement.parentNode.parentNode;
291 if (Dom.hasClass(oRootNode, this.CSS_CLASS_NAME + "-checked")) {
293 p_oAttributes.checked = true;
297 if (Dom.hasClass(oRootNode, this.CSS_CLASS_NAME + "-disabled")) {
299 p_oAttributes.disabled = true;
303 p_oElement.removeAttribute("value");
305 p_oElement.setAttribute("type", "button");
311 p_oElement.removeAttribute("id");
312 p_oElement.removeAttribute("name");
314 if ( !("tabindex" in p_oAttributes) ) {
316 p_oAttributes.tabindex = p_oElement.tabIndex;
320 if ( !("label" in p_oAttributes) ) {
322 // Set the "label" property
324 sText = sSrcElementNodeName == "INPUT" ?
325 p_oElement.value : p_oElement.innerHTML;
328 if (sText && sText.length > 0) {
330 p_oAttributes.label = sText;
341 * @description Initializes the set of configuration attributes that are
342 * used to instantiate the button.
344 * @param {Object} Object representing the button's set of
345 * configuration attributes.
347 function initConfig(p_oConfig) {
349 var oAttributes = p_oConfig.attributes,
350 oSrcElement = oAttributes.srcelement,
351 sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
355 if (sSrcElementNodeName == this.NODE_NAME) {
357 p_oConfig.element = oSrcElement;
358 p_oConfig.id = oSrcElement.id;
360 Dom.getElementsBy(function (p_oElement) {
362 switch (p_oElement.nodeName.toUpperCase()) {
368 setAttributesFromSrcElement.call(me, p_oElement,
375 }, "*", oSrcElement);
380 switch (sSrcElementNodeName) {
386 setAttributesFromSrcElement.call(this, oSrcElement,
401 YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
403 var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
407 if (arguments.length == 1 && !Lang.isString(p_oElement) &&
408 !p_oElement.nodeName) {
410 if (!p_oElement.id) {
412 p_oElement.id = Dom.generateId();
414 YAHOO.log("No value specified for the button's \"id\" " +
415 "attribute. Setting button id to \"" + p_oElement.id +
420 this.logger = new YAHOO.widget.LogWriter("Button " + p_oElement.id);
422 this.logger.log("No source HTML element. Building the button " +
423 "using the set of configuration attributes.");
425 fnSuperClass.call(this,
426 (this.createButtonElement(p_oElement.type)),
432 oConfig = { element: null, attributes: (p_oAttributes || {}) };
435 if (Lang.isString(p_oElement)) {
437 oElement = Dom.get(p_oElement);
441 if (!oConfig.attributes.id) {
443 oConfig.attributes.id = p_oElement;
447 this.logger = new YAHOO.widget.LogWriter(
448 "Button " + oConfig.attributes.id);
450 this.logger.log("Building the button using an existing " +
451 "HTML element as a source element.");
454 oConfig.attributes.srcelement = oElement;
456 initConfig.call(this, oConfig);
459 if (!oConfig.element) {
461 this.logger.log("Source element could not be used " +
462 "as is. Creating a new HTML element for " +
466 this.createButtonElement(oConfig.attributes.type);
470 fnSuperClass.call(this, oConfig.element,
476 else if (p_oElement.nodeName) {
478 if (!oConfig.attributes.id) {
482 oConfig.attributes.id = p_oElement.id;
487 oConfig.attributes.id = Dom.generateId();
489 YAHOO.log("No value specified for the button's " +
490 "\"id\" attribute. Setting button id to \"" +
491 oConfig.attributes.id + "\".", "warn");
498 this.logger = new YAHOO.widget.LogWriter(
499 "Button " + oConfig.attributes.id);
501 this.logger.log("Building the button using an existing HTML " +
502 "element as a source element.");
505 oConfig.attributes.srcelement = p_oElement;
507 initConfig.call(this, oConfig);
510 if (!oConfig.element) {
512 this.logger.log("Source element could not be used as is." +
513 " Creating a new HTML element for the button.");
516 this.createButtonElement(oConfig.attributes.type);
520 fnSuperClass.call(this, oConfig.element, oConfig.attributes);
530 YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
533 // Protected properties
538 * @description Object reference to the button's internal
539 * <code><a></code> or <code><button></code> element.
542 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
543 * level-one-html.html#ID-48250443">HTMLAnchorElement</a>|<a href="
544 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
545 * #ID-34812697">HTMLButtonElement</a>
552 * @description Object reference to the button's menu.
555 * @type {<a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|
556 * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
562 * @property _hiddenFields
563 * @description Object reference to the <code><input></code>
564 * element, or array of HTML form elements used to represent the button
565 * when its parent form is submitted.
568 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
569 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array
575 * @property _onclickAttributeValue
576 * @description Object reference to the button's current value for the
577 * "onclick" configuration attribute.
582 _onclickAttributeValue: null,
586 * @property _activationKeyPressed
587 * @description Boolean indicating if the key(s) that toggle the button's
588 * "active" state have been pressed.
593 _activationKeyPressed: false,
597 * @property _activationButtonPressed
598 * @description Boolean indicating if the mouse button that toggles
599 * the button's "active" state has been pressed.
604 _activationButtonPressed: false,
608 * @property _hasKeyEventHandlers
609 * @description Boolean indicating if the button's "blur", "keydown" and
610 * "keyup" event handlers are assigned
615 _hasKeyEventHandlers: false,
619 * @property _hasMouseEventHandlers
620 * @description Boolean indicating if the button's "mouseout,"
621 * "mousedown," and "mouseup" event handlers are assigned
626 _hasMouseEventHandlers: false,
634 * @property NODE_NAME
635 * @description The name of the node to be used for the button's
645 * @property CHECK_ACTIVATION_KEYS
646 * @description Array of numbers representing keys that (when pressed)
647 * toggle the button's "checked" attribute.
652 CHECK_ACTIVATION_KEYS: [32],
656 * @property ACTIVATION_KEYS
657 * @description Array of numbers representing keys that (when presed)
658 * toggle the button's "active" state.
663 ACTIVATION_KEYS: [13, 32],
667 * @property OPTION_AREA_WIDTH
668 * @description Width (in pixels) of the area of a split button that
669 * when pressed will display a menu.
674 OPTION_AREA_WIDTH: 20,
678 * @property CSS_CLASS_NAME
679 * @description String representing the CSS class(es) to be applied to
680 * the button's root element.
681 * @default "yui-button"
685 CSS_CLASS_NAME: "yui-button",
689 * @property RADIO_DEFAULT_TITLE
690 * @description String representing the default title applied to buttons
692 * @default "Unchecked. Click to check."
696 RADIO_DEFAULT_TITLE: "Unchecked. Click to check.",
700 * @property RADIO_CHECKED_TITLE
701 * @description String representing the title applied to buttons of
702 * type "radio" when checked.
703 * @default "Checked. Click to uncheck."
707 RADIO_CHECKED_TITLE: "Checked. Click to uncheck.",
711 * @property CHECKBOX_DEFAULT_TITLE
712 * @description String representing the default title applied to
713 * buttons of type "checkbox."
714 * @default "Unchecked. Click to check."
718 CHECKBOX_DEFAULT_TITLE: "Unchecked. Click to check.",
722 * @property CHECKBOX_CHECKED_TITLE
723 * @description String representing the title applied to buttons of type
724 * "checkbox" when checked.
725 * @default "Checked. Click to uncheck."
729 CHECKBOX_CHECKED_TITLE: "Checked. Click to uncheck.",
733 * @property MENUBUTTON_DEFAULT_TITLE
734 * @description String representing the default title applied to
735 * buttons of type "menu."
736 * @default "Menu collapsed. Click to expand."
740 MENUBUTTON_DEFAULT_TITLE: "Menu collapsed. Click to expand.",
744 * @property MENUBUTTON_MENU_VISIBLE_TITLE
745 * @description String representing the title applied to buttons of type
746 * "menu" when the button's menu is visible.
747 * @default "Menu expanded. Click or press Esc to collapse."
751 MENUBUTTON_MENU_VISIBLE_TITLE:
752 "Menu expanded. Click or press Esc to collapse.",
756 * @property SPLITBUTTON_DEFAULT_TITLE
757 * @description String representing the default title applied to
758 * buttons of type "split."
759 * @default "Menu collapsed. Click inside option region or press
760 * Ctrl + Shift + M to show the menu."
764 SPLITBUTTON_DEFAULT_TITLE: ("Menu collapsed. Click inside option " +
765 "region or press Ctrl + Shift + M to show the menu."),
769 * @property SPLITBUTTON_OPTION_VISIBLE_TITLE
770 * @description String representing the title applied to buttons of type
771 * "split" when the button's menu is visible.
772 * @default "Menu expanded. Press Esc or Ctrl + Shift + M to hide
777 SPLITBUTTON_OPTION_VISIBLE_TITLE:
778 "Menu expanded. Press Esc or Ctrl + Shift + M to hide the menu.",
782 * @property SUBMIT_TITLE
783 * @description String representing the title applied to buttons of
785 * @default "Click to submit form."
789 SUBMIT_TITLE: "Click to submit form.",
793 // Protected attribute setter methods
798 * @description Sets the value of the button's "type" attribute.
800 * @param {String} p_sType String indicating the value for the button's
803 _setType: function (p_sType) {
805 if (p_sType == "split") {
807 this.on("option", this._onOption);
816 * @description Sets the value of the button's "label" attribute.
818 * @param {String} p_sLabel String indicating the value for the button's
821 _setLabel: function (p_sLabel) {
823 this._button.innerHTML = p_sLabel;
829 * @method _setTabIndex
830 * @description Sets the value of the button's "tabindex" attribute.
832 * @param {Number} p_nTabIndex Number indicating the value for the
833 * button's "tabindex" attribute.
835 _setTabIndex: function (p_nTabIndex) {
837 this._button.tabIndex = p_nTabIndex;
844 * @description Sets the value of the button's "title" attribute.
846 * @param {String} p_nTabIndex Number indicating the value for
847 * the button's "title" attribute.
849 _setTitle: function (p_sTitle) {
851 var sTitle = p_sTitle;
853 if (this.get("type") != "link") {
857 switch (this.get("type")) {
861 sTitle = this.RADIO_DEFAULT_TITLE;
867 sTitle = this.CHECKBOX_DEFAULT_TITLE;
873 sTitle = this.MENUBUTTON_DEFAULT_TITLE;
879 sTitle = this.SPLITBUTTON_DEFAULT_TITLE;
885 sTitle = this.SUBMIT_TITLE;
893 this._button.title = sTitle;
901 * @method _setDisabled
902 * @description Sets the value of the button's "disabled" attribute.
904 * @param {Boolean} p_bDisabled Boolean indicating the value for
905 * the button's "disabled" attribute.
907 _setDisabled: function (p_bDisabled) {
909 if (this.get("type") != "link") {
919 if (this.hasFocus()) {
925 this._button.setAttribute("disabled", "disabled");
927 this.addStateCSSClasses("disabled");
932 this._button.removeAttribute("disabled");
934 this.removeStateCSSClasses("disabled");
945 * @description Sets the value of the button's "href" attribute.
947 * @param {String} p_sHref String indicating the value for the button's
950 _setHref: function (p_sHref) {
952 if (this.get("type") == "link") {
954 this._button.href = p_sHref;
963 * @description Sets the value of the button's "target" attribute.
965 * @param {String} p_sTarget String indicating the value for the button's
966 * "target" attribute.
968 _setTarget: function (p_sTarget) {
970 if (this.get("type") == "link") {
972 this._button.setAttribute("target", p_sTarget);
980 * @method _setChecked
981 * @description Sets the value of the button's "target" attribute.
983 * @param {Boolean} p_bChecked Boolean indicating the value for
984 * the button's "checked" attribute.
986 _setChecked: function (p_bChecked) {
988 var sType = this.get("type"),
991 if (sType == "checkbox" || sType == "radio") {
995 this.addStateCSSClasses("checked");
997 sTitle = (sType == "radio") ?
998 this.RADIO_CHECKED_TITLE :
999 this.CHECKBOX_CHECKED_TITLE;
1004 this.removeStateCSSClasses("checked");
1006 sTitle = (sType == "radio") ?
1007 this.RADIO_DEFAULT_TITLE :
1008 this.CHECKBOX_DEFAULT_TITLE;
1012 this.set("title", sTitle);
1021 * @description Sets the value of the button's "menu" attribute.
1023 * @param {Object} p_oMenu Object indicating the value for the button's
1026 _setMenu: function (p_oMenu) {
1028 var bLazyLoad = this.get("lazyloadmenu"),
1029 oButtonElement = this.get("element"),
1032 Boolean indicating if the value of p_oMenu is an instance
1033 of YAHOO.widget.Menu or YAHOO.widget.Overlay.
1050 this.logger.log("YAHOO.widget.Overlay dependency not met.",
1060 this.logger.log("YAHOO.widget.Menu dependency not met.",
1068 function onAppendTo() {
1070 oMenu.render(oButtonElement.parentNode);
1072 this.removeListener("appendTo", onAppendTo);
1077 function initMenu() {
1081 Dom.addClass(oMenu.element, this.get("menuclassname"));
1082 Dom.addClass(oMenu.element,
1083 "yui-" + this.get("type") + "-button-menu");
1085 oMenu.showEvent.subscribe(this._onMenuShow, null, this);
1086 oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
1087 oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
1090 if (oMenu instanceof Menu) {
1092 oMenu.keyDownEvent.subscribe(this._onMenuKeyDown,
1095 oMenu.clickEvent.subscribe(this._onMenuClick,
1098 oMenu.itemAddedEvent.subscribe(this._onMenuItemAdded,
1101 oSrcElement = oMenu.srcElement;
1104 oSrcElement.nodeName.toUpperCase() == "SELECT") {
1106 oSrcElement.style.display = "none";
1107 oSrcElement.parentNode.removeChild(oSrcElement);
1112 else if (oMenu instanceof Overlay) {
1114 if (!m_oOverlayManager) {
1117 new YAHOO.widget.OverlayManager();
1121 m_oOverlayManager.register(oMenu);
1131 if (bLazyLoad && !(oMenu instanceof Menu)) {
1134 Mimic Menu's "lazyload" functionality by adding
1135 a "beforeshow" event listener that renders the
1136 Overlay instance before it is made visible by
1140 oMenu.beforeShowEvent.subscribe(
1141 this._onOverlayBeforeShow, null, this);
1144 else if (!bLazyLoad) {
1146 if (Dom.inDocument(oButtonElement)) {
1148 oMenu.render(oButtonElement.parentNode);
1153 this.on("appendTo", onAppendTo);
1166 if (p_oMenu && (p_oMenu instanceof Menu)) {
1169 aItems = oMenu.getItems();
1170 nItems = aItems.length;
1184 oItem.cfg.subscribeToConfigEvent("selected",
1185 this._onMenuItemSelected,
1196 initMenu.call(this);
1199 else if (p_oMenu && (p_oMenu instanceof Overlay)) {
1204 oMenu.cfg.setProperty("visible", false);
1205 oMenu.cfg.setProperty("context", [oButtonElement, "tl", "bl"]);
1207 initMenu.call(this);
1210 else if (Lang.isArray(p_oMenu)) {
1212 this.on("appendTo", function () {
1214 oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad,
1215 itemdata: p_oMenu });
1217 initMenu.call(this);
1222 else if (Lang.isString(p_oMenu)) {
1224 oMenuElement = Dom.get(p_oMenu);
1228 if (Dom.hasClass(oMenuElement,
1229 Menu.prototype.CSS_CLASS_NAME) ||
1230 oMenuElement.nodeName == "SELECT") {
1232 oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1234 initMenu.call(this);
1239 oMenu = new Overlay(p_oMenu, { visible: false,
1240 context: [oButtonElement, "tl", "bl"] });
1242 initMenu.call(this);
1249 else if (p_oMenu && p_oMenu.nodeName) {
1251 if (Dom.hasClass(p_oMenu, Menu.prototype.CSS_CLASS_NAME) ||
1252 p_oMenu.nodeName == "SELECT") {
1254 oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1256 initMenu.call(this);
1263 Dom.generateId(p_oMenu);
1267 oMenu = new Overlay(p_oMenu, { visible: false,
1268 context: [oButtonElement, "tl", "bl"] });
1270 initMenu.call(this);
1280 * @method _setOnClick
1281 * @description Sets the value of the button's "onclick" attribute.
1283 * @param {Object} p_oObject Object indicating the value for the button's
1284 * "onclick" attribute.
1286 _setOnClick: function (p_oObject) {
1289 Remove any existing listeners if a "click" event handler
1290 has already been specified.
1293 if (this._onclickAttributeValue &&
1294 (this._onclickAttributeValue != p_oObject)) {
1296 this.removeListener("click", this._onclickAttributeValue.fn);
1298 this._onclickAttributeValue = null;
1303 if (!this._onclickAttributeValue &&
1304 Lang.isObject(p_oObject) &&
1305 Lang.isFunction(p_oObject.fn)) {
1307 this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
1309 this._onclickAttributeValue = p_oObject;
1317 * @method _setSelectedMenuItem
1318 * @description Sets the value of the button's
1319 * "selectedMenuItem" attribute.
1321 * @param {Number} p_nIndex Number representing the index of the item
1322 * in the button's menu that is currently selected.
1324 _setSelectedMenuItem: function (p_nIndex) {
1326 var oMenu = this._menu,
1330 if (oMenu && oMenu instanceof Menu) {
1332 oMenuItem = oMenu.getItem(p_nIndex);
1335 if (oMenuItem && !oMenuItem.cfg.getProperty("selected")) {
1337 oMenuItem.cfg.setProperty("selected", true);
1346 // Protected methods
1351 * @method _isActivationKey
1352 * @description Determines if the specified keycode is one that toggles
1353 * the button's "active" state.
1355 * @param {Number} p_nKeyCode Number representing the keycode to
1359 _isActivationKey: function (p_nKeyCode) {
1361 var sType = this.get("type"),
1362 aKeyCodes = (sType == "checkbox" || sType == "radio") ?
1363 this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
1365 nKeyCodes = aKeyCodes.length,
1368 if (nKeyCodes > 0) {
1374 if (p_nKeyCode == aKeyCodes[i]) {
1389 * @method _isSplitButtonOptionKey
1390 * @description Determines if the specified keycode is one that toggles
1391 * the display of the split button's menu.
1393 * @param {Event} p_oEvent Object representing the DOM event object
1394 * passed back by the event utility (YAHOO.util.Event).
1397 _isSplitButtonOptionKey: function (p_oEvent) {
1399 return (p_oEvent.ctrlKey && p_oEvent.shiftKey &&
1400 Event.getCharCode(p_oEvent) == 77);
1406 * @method _addListenersToForm
1407 * @description Adds event handlers to the button's form.
1410 _addListenersToForm: function () {
1412 var oForm = this.getForm(),
1417 bHasKeyPressListener;
1422 Event.on(oForm, "reset", this._onFormReset, null, this);
1423 Event.on(oForm, "submit", this.createHiddenFields, null, this);
1425 oSrcElement = this.get("srcelement");
1428 if (this.get("type") == "submit" ||
1429 (oSrcElement && oSrcElement.type == "submit"))
1432 aListeners = Event.getListeners(oForm, "keypress");
1433 bHasKeyPressListener = false;
1437 nListeners = aListeners.length;
1439 if (nListeners > 0) {
1445 if (aListeners[i].fn ==
1446 YAHOO.widget.Button.onFormKeyPress)
1449 bHasKeyPressListener = true;
1462 if (!bHasKeyPressListener) {
1464 Event.on(oForm, "keypress",
1465 YAHOO.widget.Button.onFormKeyPress);
1476 _originalMaxHeight: -1,
1481 * @description Shows the button's menu.
1483 * @param {Event} p_oEvent Object representing the DOM event object
1484 * passed back by the event utility (YAHOO.util.Event) that triggered
1485 * the display of the menu.
1487 _showMenu: function (p_oEvent) {
1489 YAHOO.widget.MenuManager.hideVisible();
1491 if (m_oOverlayManager) {
1493 m_oOverlayManager.hideAll();
1498 var oMenu = this._menu,
1499 nViewportHeight = Dom.getViewportHeight(),
1505 if (oMenu && (oMenu instanceof Menu)) {
1507 oMenu.cfg.applyConfig({ context: [this.get("id"), "tl", "bl"],
1508 constraintoviewport: false,
1512 oMenu.cfg.fireQueue();
1514 oMenu.align("tl", "bl");
1517 Stop the propagation of the event so that the MenuManager
1518 doesn't blur the menu after it gets focus.
1521 if (p_oEvent.type == "mousedown") {
1523 Event.stopPropagation(p_oEvent);
1528 if (this.get("focusmenu")) {
1534 nMenuHeight = oMenu.element.offsetHeight;
1537 if ((oMenu.cfg.getProperty("y") + nMenuHeight) >
1540 this.logger.log("Current menu position will place a " +
1541 "portion, or the entire menu outside the boundary of " +
1542 "the viewport. Repositioning the menu to stay " +
1543 "inside the viewport.");
1545 oMenu.align("bl", "tl");
1547 nY = oMenu.cfg.getProperty("y");
1549 nScrollTop = Dom.getDocumentScrollTop();
1552 if (nScrollTop >= nY) {
1554 if (this._originalMaxHeight == -1) {
1556 this._originalMaxHeight =
1557 oMenu.cfg.getProperty("maxheight");
1561 oMenu.cfg.setProperty("maxheight",
1562 (nMenuHeight - ((nScrollTop - nY) + 20)));
1564 oMenu.align("bl", "tl");
1571 else if (oMenu && (oMenu instanceof Overlay)) {
1574 oMenu.align("tl", "bl");
1576 nMenuHeight = oMenu.element.offsetHeight;
1579 if ((oMenu.cfg.getProperty("y") + nMenuHeight) >
1582 this.logger.log("Current menu position will place a " +
1583 "portion, or the entire menu outside the boundary of " +
1584 "the viewport. Repositioning the menu to stay inside" +
1587 oMenu.align("bl", "tl");
1598 * @description Hides the button's menu.
1601 _hideMenu: function () {
1603 var oMenu = this._menu;
1616 // Protected event handlers
1620 * @method _onMouseOver
1621 * @description "mouseover" event handler for the button.
1623 * @param {Event} p_oEvent Object representing the DOM event object
1624 * passed back by the event utility (YAHOO.util.Event).
1626 _onMouseOver: function (p_oEvent) {
1628 if (!this._hasMouseEventHandlers) {
1630 this.on("mouseout", this._onMouseOut);
1631 this.on("mousedown", this._onMouseDown);
1632 this.on("mouseup", this._onMouseUp);
1634 this._hasMouseEventHandlers = true;
1638 this.addStateCSSClasses("hover");
1640 if (this._activationButtonPressed) {
1642 this.addStateCSSClasses("active");
1647 if (this._bOptionPressed) {
1649 this.addStateCSSClasses("activeoption");
1657 * @method _onMouseOut
1658 * @description "mouseout" event handler for the button.
1660 * @param {Event} p_oEvent Object representing the DOM event object
1661 * passed back by the event utility (YAHOO.util.Event).
1663 _onMouseOut: function (p_oEvent) {
1665 this.removeStateCSSClasses("hover");
1667 if (this.get("type") != "menu") {
1669 this.removeStateCSSClasses("active");
1673 if (this._activationButtonPressed || this._bOptionPressed) {
1675 Event.on(document, "mouseup", this._onDocumentMouseUp,
1684 * @method _onDocumentMouseUp
1685 * @description "mouseup" event handler for the button.
1687 * @param {Event} p_oEvent Object representing the DOM event object
1688 * passed back by the event utility (YAHOO.util.Event).
1690 _onDocumentMouseUp: function (p_oEvent) {
1692 this._activationButtonPressed = false;
1693 this._bOptionPressed = false;
1695 var sType = this.get("type");
1697 if (sType == "menu" || sType == "split") {
1699 this.removeStateCSSClasses(
1700 (sType == "menu" ? "active" : "activeoption"));
1706 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1712 * @method _onMouseDown
1713 * @description "mousedown" event handler for the button.
1715 * @param {Event} p_oEvent Object representing the DOM event object
1716 * passed back by the event utility (YAHOO.util.Event).
1718 _onMouseDown: function (p_oEvent) {
1726 function onMouseUp() {
1729 this.removeListener("mouseup", onMouseUp);
1734 if ((p_oEvent.which || p_oEvent.button) == 1) {
1737 if (!this.hasFocus()) {
1744 sType = this.get("type");
1747 if (sType == "split") {
1749 oElement = this.get("element");
1750 nX = Event.getPageX(p_oEvent) - Dom.getX(oElement);
1752 if ((oElement.offsetWidth - this.OPTION_AREA_WIDTH) < nX) {
1754 this.fireEvent("option", p_oEvent);
1759 this.addStateCSSClasses("active");
1761 this._activationButtonPressed = true;
1766 else if (sType == "menu") {
1768 if (this.isActive()) {
1772 this._activationButtonPressed = false;
1777 this._showMenu(p_oEvent);
1779 this._activationButtonPressed = true;
1786 this.addStateCSSClasses("active");
1788 this._activationButtonPressed = true;
1794 if (sType == "split" || sType == "menu") {
1798 this._hideMenuTimerId = window.setTimeout(function () {
1800 me.on("mouseup", onMouseUp);
1812 * @method _onMouseUp
1813 * @description "mouseup" event handler for the button.
1815 * @param {Event} p_oEvent Object representing the DOM event object
1816 * passed back by the event utility (YAHOO.util.Event).
1818 _onMouseUp: function (p_oEvent) {
1820 var sType = this.get("type");
1823 if (this._hideMenuTimerId) {
1825 window.clearTimeout(this._hideMenuTimerId);
1830 if (sType == "checkbox" || sType == "radio") {
1832 this.set("checked", !(this.get("checked")));
1837 this._activationButtonPressed = false;
1840 if (this.get("type") != "menu") {
1842 this.removeStateCSSClasses("active");
1851 * @description "focus" event handler for the button.
1853 * @param {Event} p_oEvent Object representing the DOM event object
1854 * passed back by the event utility (YAHOO.util.Event).
1856 _onFocus: function (p_oEvent) {
1860 this.addStateCSSClasses("focus");
1862 if (this._activationKeyPressed) {
1864 this.addStateCSSClasses("active");
1868 m_oFocusedButton = this;
1871 if (!this._hasKeyEventHandlers) {
1873 oElement = this._button;
1875 Event.on(oElement, "blur", this._onBlur, null, this);
1876 Event.on(oElement, "keydown", this._onKeyDown, null, this);
1877 Event.on(oElement, "keyup", this._onKeyUp, null, this);
1879 this._hasKeyEventHandlers = true;
1884 this.fireEvent("focus", p_oEvent);
1891 * @description "blur" event handler for the button.
1893 * @param {Event} p_oEvent Object representing the DOM event object
1894 * passed back by the event utility (YAHOO.util.Event).
1896 _onBlur: function (p_oEvent) {
1898 this.removeStateCSSClasses("focus");
1900 if (this.get("type") != "menu") {
1902 this.removeStateCSSClasses("active");
1906 if (this._activationKeyPressed) {
1908 Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
1913 m_oFocusedButton = null;
1915 this.fireEvent("blur", p_oEvent);
1921 * @method _onDocumentKeyUp
1922 * @description "keyup" event handler for the document.
1924 * @param {Event} p_oEvent Object representing the DOM event object
1925 * passed back by the event utility (YAHOO.util.Event).
1927 _onDocumentKeyUp: function (p_oEvent) {
1929 if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1931 this._activationKeyPressed = false;
1933 Event.removeListener(document, "keyup", this._onDocumentKeyUp);
1941 * @method _onKeyDown
1942 * @description "keydown" event handler for the button.
1944 * @param {Event} p_oEvent Object representing the DOM event object
1945 * passed back by the event utility (YAHOO.util.Event).
1947 _onKeyDown: function (p_oEvent) {
1949 var oMenu = this._menu;
1952 if (this.get("type") == "split" &&
1953 this._isSplitButtonOptionKey(p_oEvent)) {
1955 this.fireEvent("option", p_oEvent);
1958 else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1960 if (this.get("type") == "menu") {
1962 this._showMenu(p_oEvent);
1967 this._activationKeyPressed = true;
1969 this.addStateCSSClasses("active");
1976 if (oMenu && oMenu.cfg.getProperty("visible") &&
1977 Event.getCharCode(p_oEvent) == 27) {
1989 * @description "keyup" event handler for the button.
1991 * @param {Event} p_oEvent Object representing the DOM event object
1992 * passed back by the event utility (YAHOO.util.Event).
1994 _onKeyUp: function (p_oEvent) {
1998 if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
2000 sType = this.get("type");
2002 if (sType == "checkbox" || sType == "radio") {
2004 this.set("checked", !(this.get("checked")));
2008 this._activationKeyPressed = false;
2010 if (this.get("type") != "menu") {
2012 this.removeStateCSSClasses("active");
2023 * @description "click" event handler for the button.
2025 * @param {Event} p_oEvent Object representing the DOM event object
2026 * passed back by the event utility (YAHOO.util.Event).
2028 _onClick: function (p_oEvent) {
2030 var sType = this.get("type"),
2043 if (this.get("checked")) {
2045 sTitle = (sType == "radio") ?
2046 this.RADIO_CHECKED_TITLE :
2047 this.CHECKBOX_CHECKED_TITLE;
2052 sTitle = (sType == "radio") ?
2053 this.RADIO_DEFAULT_TITLE :
2054 this.CHECKBOX_DEFAULT_TITLE;
2058 this.set("title", sTitle);
2070 oForm = this.getForm();
2082 sTitle = this._menu.cfg.getProperty("visible") ?
2083 this.MENUBUTTON_MENU_VISIBLE_TITLE :
2084 this.MENUBUTTON_DEFAULT_TITLE;
2086 this.set("title", sTitle);
2092 oElement = this.get("element");
2093 nX = Event.getPageX(p_oEvent) - Dom.getX(oElement);
2095 if ((oElement.offsetWidth - this.OPTION_AREA_WIDTH) < nX) {
2104 oSrcElement = this.get("srcelement");
2106 if (oSrcElement && oSrcElement.type == "submit") {
2114 sTitle = this._menu.cfg.getProperty("visible") ?
2115 this.SPLITBUTTON_OPTION_VISIBLE_TITLE :
2116 this.SPLITBUTTON_DEFAULT_TITLE;
2118 this.set("title", sTitle);
2128 * @method _onAppendTo
2129 * @description "appendTo" event handler for the button.
2131 * @param {Event} p_oEvent Object representing the DOM event object
2132 * passed back by the event utility (YAHOO.util.Event).
2134 _onAppendTo: function (p_oEvent) {
2137 It is necessary to call "getForm" using "setTimeout" to make
2138 sure that the button's "form" property returns a node
2139 reference. Sometimes, if you try to get the reference
2140 immediately after appending the field, it is null.
2145 window.setTimeout(function () {
2147 me._addListenersToForm();
2155 * @method _onFormReset
2156 * @description "reset" event handler for the button's form.
2158 * @param {Event} p_oEvent Object representing the DOM event
2159 * object passed back by the event utility (YAHOO.util.Event).
2161 _onFormReset: function (p_oEvent) {
2163 var sType = this.get("type"),
2166 if (sType == "checkbox" || sType == "radio") {
2168 this.resetValue("checked");
2173 if (oMenu && (oMenu instanceof Menu)) {
2175 this.resetValue("selectedMenuItem");
2183 * @method _onDocumentMouseDown
2184 * @description "mousedown" event handler for the document.
2186 * @param {Event} p_oEvent Object representing the DOM event object
2187 * passed back by the event utility (YAHOO.util.Event).
2189 _onDocumentMouseDown: function (p_oEvent) {
2191 var oTarget = Event.getTarget(p_oEvent),
2192 oButtonElement = this.get("element"),
2193 oMenuElement = this._menu.element;
2195 if (oTarget != oButtonElement &&
2196 !Dom.isAncestor(oButtonElement, oTarget) &&
2197 oTarget != oMenuElement &&
2198 !Dom.isAncestor(oMenuElement, oTarget)) {
2202 Event.removeListener(document, "mousedown",
2203 this._onDocumentMouseDown);
2212 * @description "option" event handler for the button.
2214 * @param {Event} p_oEvent Object representing the DOM event object
2215 * passed back by the event utility (YAHOO.util.Event).
2217 _onOption: function (p_oEvent) {
2219 if (this.hasClass("yui-split-button-activeoption")) {
2223 this._bOptionPressed = false;
2228 this._showMenu(p_oEvent);
2230 this._bOptionPressed = true;
2238 * @method _onOverlayBeforeShow
2239 * @description "beforeshow" event handler for the
2240 * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a> instance
2241 * serving as the button's menu.
2243 * @param {String} p_sType String representing the name of the event
2246 _onOverlayBeforeShow: function (p_sType) {
2248 var oMenu = this._menu;
2250 oMenu.render(this.get("element").parentNode);
2252 oMenu.beforeShowEvent.unsubscribe(this._onOverlayBeforeShow);
2258 * @method _onMenuShow
2259 * @description "show" event handler for the button's menu.
2261 * @param {String} p_sType String representing the name of the event
2264 _onMenuShow: function (p_sType) {
2266 Event.on(document, "mousedown", this._onDocumentMouseDown,
2272 if (this.get("type") == "split") {
2274 sTitle = this.SPLITBUTTON_OPTION_VISIBLE_TITLE;
2275 sState = "activeoption";
2280 sTitle = this.MENUBUTTON_MENU_VISIBLE_TITLE;
2285 this.addStateCSSClasses(sState);
2286 this.set("title", sTitle);
2292 * @method _onMenuHide
2293 * @description "hide" event handler for the button's menu.
2295 * @param {String} p_sType String representing the name of the event
2298 _onMenuHide: function (p_sType) {
2300 var oMenu = this._menu,
2304 if (oMenu && (oMenu instanceof Menu) &&
2305 this._originalMaxHeight != -1) {
2307 this._menu.cfg.setProperty("maxheight",
2308 this._originalMaxHeight);
2313 if (this.get("type") == "split") {
2315 sTitle = this.SPLITBUTTON_DEFAULT_TITLE;
2316 sState = "activeoption";
2321 sTitle = this.MENUBUTTON_DEFAULT_TITLE;
2326 this.removeStateCSSClasses(sState);
2327 this.set("title", sTitle);
2330 if (this.get("type") == "split") {
2332 this._bOptionPressed = false;
2340 * @method _onMenuKeyDown
2341 * @description "keydown" event handler for the button's menu.
2343 * @param {String} p_sType String representing the name of the event
2345 * @param {Array} p_aArgs Array of arguments sent when the event
2348 _onMenuKeyDown: function (p_sType, p_aArgs) {
2350 var oEvent = p_aArgs[0];
2352 if (Event.getCharCode(oEvent) == 27) {
2356 if (this.get("type") == "split") {
2358 this._bOptionPressed = false;
2368 * @method _onMenuRender
2369 * @description "render" event handler for the button's menu.
2371 * @param {String} p_sType String representing the name of the
2372 * event thatwas fired.
2374 _onMenuRender: function (p_sType) {
2376 var oButtonElement = this.get("element"),
2377 oButtonParent = oButtonElement.parentNode,
2378 oMenuElement = this._menu.element;
2381 if (oButtonParent != oMenuElement.parentNode) {
2383 oButtonParent.appendChild(oMenuElement);
2387 this.set("selectedMenuItem", this.get("selectedMenuItem"));
2393 * @method _onMenuItemSelected
2394 * @description "selectedchange" event handler for each item in the
2397 * @param {String} p_sType String representing the name of the event
2399 * @param {Array} p_aArgs Array of arguments sent when the event
2401 * @param {Number} p_nItem Number representing the index of the menu
2402 * item that subscribed to the event.
2404 _onMenuItemSelected: function (p_sType, p_aArgs, p_nItem) {
2406 var bSelected = p_aArgs[0];
2410 this.set("selectedMenuItem", p_nItem);
2418 * @method _onMenuItemAdded
2419 * @description "itemadded" event handler for the button's menu.
2421 * @param {String} p_sType String representing the name of the event
2423 * @param {Array} p_aArgs Array of arguments sent when the event
2425 * @param {<a href="YAHOO.widget.MenuItem.html">
2426 * YAHOO.widget.MenuItem</a>} p_oItem Object representing the menu
2427 * item that subscribed to the event.
2429 _onMenuItemAdded: function (p_sType, p_aArgs, p_oItem) {
2431 var oItem = p_aArgs[0];
2433 oItem.cfg.subscribeToConfigEvent("selected",
2434 this._onMenuItemSelected,
2442 * @method _onMenuClick
2443 * @description "click" event handler for the button's menu.
2445 * @param {String} p_sType String representing the name of the event
2447 * @param {Array} p_aArgs Array of arguments sent when the event
2450 _onMenuClick: function (p_sType, p_aArgs) {
2452 var oItem = p_aArgs[1],
2457 oSrcElement = this.get("srcelement");
2459 if (oSrcElement && oSrcElement.type == "submit") {
2477 * @method createButtonElement
2478 * @description Creates the button's HTML elements.
2479 * @param {String} p_sType String indicating the type of element
2481 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2482 * level-one-html.html#ID-58190037">HTMLElement</a>}
2484 createButtonElement: function (p_sType) {
2486 var sNodeName = this.NODE_NAME,
2487 oElement = document.createElement(sNodeName);
2489 oElement.innerHTML = "<" + sNodeName + " class=\"first-child\">" +
2490 (p_sType == "link" ? "<a></a>" :
2491 "<button type=\"button\"></button>") + "</" + sNodeName + ">";
2499 * @method addStateCSSClasses
2500 * @description Appends state-specific CSS classes to the button's root
2503 addStateCSSClasses: function (p_sState) {
2505 var sType = this.get("type");
2507 if (Lang.isString(p_sState)) {
2509 if (p_sState != "activeoption") {
2511 this.addClass(this.CSS_CLASS_NAME + ("-" + p_sState));
2515 this.addClass("yui-" + sType + ("-button-" + p_sState));
2523 * @method removeStateCSSClasses
2524 * @description Removes state-specific CSS classes to the button's root
2527 removeStateCSSClasses: function (p_sState) {
2529 var sType = this.get("type");
2531 if (Lang.isString(p_sState)) {
2533 this.removeClass(this.CSS_CLASS_NAME + ("-" + p_sState));
2534 this.removeClass("yui-" + sType + ("-button-" + p_sState));
2542 * @method createHiddenFields
2543 * @description Creates the button's hidden form field and appends it
2544 * to its parent form.
2545 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2546 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
2548 createHiddenFields: function () {
2550 this.removeHiddenFields();
2552 var oForm = this.getForm(),
2563 if (oForm && !this.get("disabled")) {
2565 sType = this.get("type");
2566 bCheckable = (sType == "checkbox" || sType == "radio");
2569 if (bCheckable || (m_oSubmitTrigger == this)) {
2571 this.logger.log("Creating hidden field.");
2573 oButtonField = createInputElement(
2574 (bCheckable ? sType : "hidden"),
2577 this.get("checked"));
2584 oButtonField.style.display = "none";
2588 oForm.appendChild(oButtonField);
2598 if (oMenu && (oMenu instanceof Menu)) {
2600 this.logger.log("Creating hidden field for menu.");
2602 oMenuField = oMenu.srcElement;
2603 oMenuItem = oMenu.getItem(this.get("selectedMenuItem"));
2606 oMenuField.nodeName.toUpperCase() == "SELECT") {
2608 oForm.appendChild(oMenuField);
2609 oMenuField.selectedIndex = oMenuItem.index;
2614 oValue = (oMenuItem.value === null ||
2615 oMenuItem.value === "") ?
2616 oMenuItem.cfg.getProperty("text") :
2619 sName = this.get("name");
2621 if (oValue && sName) {
2623 oMenuField = createInputElement("hidden",
2624 (sName + "_options"),
2627 oForm.appendChild(oMenuField);
2636 if (oButtonField && oMenuField) {
2638 this._hiddenFields = [oButtonField, oMenuField];
2641 else if (!oButtonField && oMenuField) {
2643 this._hiddenFields = oMenuField;
2646 else if (oButtonField && !oMenuField) {
2648 this._hiddenFields = oButtonField;
2653 return this._hiddenFields;
2661 * @method removeHiddenFields
2662 * @description Removes the button's hidden form field(s) from its
2665 removeHiddenFields: function () {
2667 var oField = this._hiddenFields,
2671 function removeChild(p_oElement) {
2673 if (Dom.inDocument(p_oElement)) {
2675 p_oElement.parentNode.removeChild(p_oElement);
2684 if (Lang.isArray(oField)) {
2686 nFields = oField.length;
2694 removeChild(oField[i]);
2704 removeChild(oField);
2708 this._hiddenFields = null;
2716 * @method submitForm
2717 * @description Submits the form to which the button belongs. Returns
2718 * true if the form was submitted successfully, false if the submission
2723 submitForm: function () {
2725 var oForm = this.getForm(),
2727 oSrcElement = this.get("srcelement"),
2730 Boolean indicating if the event fired successfully
2731 (was not cancelled by any handlers)
2734 bSubmitForm = false,
2741 if (this.get("type") == "submit" ||
2742 (oSrcElement && oSrcElement.type == "submit"))
2745 m_oSubmitTrigger = this;
2750 if (YAHOO.env.ua.ie) {
2752 bSubmitForm = oForm.fireEvent("onsubmit");
2755 else { // Gecko, Opera, and Safari
2757 oEvent = document.createEvent("HTMLEvents");
2758 oEvent.initEvent("submit", true, true);
2760 bSubmitForm = oForm.dispatchEvent(oEvent);
2766 In IE and Safari, dispatching a "submit" event to a form
2767 WILL cause the form's "submit" event to fire, but WILL NOT
2768 submit the form. Therefore, we need to call the "submit"
2772 if ((YAHOO.env.ua.ie || YAHOO.env.ua.webkit) && bSubmitForm) {
2787 * @description The Button class's initialization method.
2788 * @param {String} p_oElement String specifying the id attribute of the
2789 * <code><input></code>, <code><button></code>,
2790 * <code><a></code>, or <code><span></code> element to
2791 * be used to create the button.
2792 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2793 * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://
2794 * www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
2795 * #ID-34812697">HTMLButtonElement</a>|<a href="http://www.w3.org/TR
2796 * /2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-33759296">
2797 * HTMLElement</a>} p_oElement Object reference for the
2798 * <code><input></code>, <code><button></code>,
2799 * <code><a></code>, or <code><span></code> element to be
2800 * used to create the button.
2801 * @param {Object} p_oElement Object literal specifying a set of
2802 * configuration attributes used to create the button.
2803 * @param {Object} p_oAttributes Optional. Object literal specifying a
2804 * set of configuration attributes used to create the button.
2806 init: function (p_oElement, p_oAttributes) {
2808 var sNodeName = p_oAttributes.type == "link" ? "A" : "BUTTON",
2809 oSrcElement = p_oAttributes.srcelement,
2810 oButton = p_oElement.getElementsByTagName(sNodeName)[0],
2816 oInput = p_oElement.getElementsByTagName("INPUT")[0];
2821 oButton = document.createElement("BUTTON");
2822 oButton.setAttribute("type", "button");
2824 oInput.parentNode.replaceChild(oButton, oInput);
2830 this._button = oButton;
2833 YAHOO.widget.Button.superclass.init.call(this, p_oElement,
2837 m_oButtons[this.get("id")] = this;
2840 this.addClass(this.CSS_CLASS_NAME);
2842 this.addClass("yui-" + this.get("type") + "-button");
2844 Event.on(this._button, "focus", this._onFocus, null, this);
2845 this.on("mouseover", this._onMouseOver);
2846 this.on("click", this._onClick);
2847 this.on("appendTo", this._onAppendTo);
2850 var oContainer = this.get("container"),
2851 oElement = this.get("element"),
2852 bElInDoc = Dom.inDocument(oElement),
2858 if (oSrcElement && oSrcElement != oElement) {
2860 oParentNode = oSrcElement.parentNode;
2864 oParentNode.removeChild(oSrcElement);
2870 if (Lang.isString(oContainer)) {
2872 Event.onContentReady(oContainer, function () {
2874 this.appendTo(oContainer);
2881 this.appendTo(oContainer);
2886 else if (!bElInDoc && oSrcElement && oSrcElement != oElement) {
2888 oParentNode = oSrcElement.parentNode;
2892 this.fireEvent("beforeAppendTo", {
2893 type: "beforeAppendTo",
2897 oParentNode.replaceChild(oElement, oSrcElement);
2899 this.fireEvent("appendTo", {
2907 else if (this.get("type") != "link" && bElInDoc && oSrcElement &&
2908 oSrcElement == oElement) {
2910 this._addListenersToForm();
2914 this.logger.log("Initialization completed.");
2920 * @method initAttributes
2921 * @description Initializes all of the configuration attributes used to
2922 * create the button.
2923 * @param {Object} p_oAttributes Object literal specifying a set of
2924 * configuration attributes used to create the button.
2926 initAttributes: function (p_oAttributes) {
2928 var oAttributes = p_oAttributes || {};
2930 YAHOO.widget.Button.superclass.initAttributes.call(this,
2936 * @description String specifying the button's type. Possible
2937 * values are: "push," "link," "submit," "reset," "checkbox,"
2938 * "radio," "menu," and "split."
2942 this.setAttributeConfig("type", {
2944 value: (oAttributes.type || "push"),
2945 validator: Lang.isString,
2947 method: this._setType
2954 * @description String specifying the button's text label
2959 this.setAttributeConfig("label", {
2961 value: oAttributes.label,
2962 validator: Lang.isString,
2963 method: this._setLabel
2970 * @description Object specifying the value for the button.
2974 this.setAttributeConfig("value", {
2976 value: oAttributes.value
2983 * @description String specifying the name for the button.
2987 this.setAttributeConfig("name", {
2989 value: oAttributes.name,
2990 validator: Lang.isString
2997 * @description Number specifying the tabindex for the button.
3001 this.setAttributeConfig("tabindex", {
3003 value: oAttributes.tabindex,
3004 validator: Lang.isNumber,
3005 method: this._setTabIndex
3012 * @description String specifying the title for the button.
3016 this.configureAttribute("title", {
3018 value: oAttributes.title,
3019 validator: Lang.isString,
3020 method: this._setTitle
3027 * @description Boolean indicating if the button should be disabled.
3028 * (Disabled buttons are dimmed and will not respond to user input
3029 * or fire events. Does not apply to button's of type "link.")
3033 this.setAttributeConfig("disabled", {
3035 value: (oAttributes.disabled || false),
3036 validator: Lang.isBoolean,
3037 method: this._setDisabled
3044 * @description String specifying the href for the button. Applies
3045 * only to buttons of type "link."
3048 this.setAttributeConfig("href", {
3050 value: oAttributes.href,
3051 validator: Lang.isString,
3052 method: this._setHref
3059 * @description String specifying the target for the button.
3060 * Applies only to buttons of type "link."
3063 this.setAttributeConfig("target", {
3065 value: oAttributes.target,
3066 validator: Lang.isString,
3067 method: this._setTarget
3074 * @description Boolean indicating if the button is checked.
3075 * Applies only to buttons of type "radio" and "checkbox."
3079 this.setAttributeConfig("checked", {
3081 value: (oAttributes.checked || false),
3082 validator: Lang.isBoolean,
3083 method: this._setChecked
3090 * @description HTML element reference or string specifying the id
3091 * attribute of the HTML element that the button's markup should be
3093 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3094 * level-one-html.html#ID-58190037">HTMLElement</a>|String
3097 this.setAttributeConfig("container", {
3099 value: oAttributes.container,
3106 * @config srcelement
3107 * @description Object reference to the HTML element (either
3108 * <code><input></code> or <code><span></code>)
3109 * used to create the button.
3110 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3111 * level-one-html.html#ID-58190037">HTMLElement</a>|String
3114 this.setAttributeConfig("srcelement", {
3116 value: oAttributes.srcelement,
3124 * @description Object specifying the menu for the button.
3125 * The value can be one of the following:
3127 * <li>Object specifying a <a href="YAHOO.widget.Menu.html">
3128 * YAHOO.widget.Menu</a> instance.</li>
3129 * <li>Object specifying a <a href="YAHOO.widget.Overlay.html">
3130 * YAHOO.widget.Overlay</a> instance.</li>
3131 * <li>String specifying the id attribute of the <code><div>
3132 * </code> element used to create the menu. By default the menu
3133 * will be created as an instance of
3134 * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>.
3135 * If the <a href="YAHOO.widget.Menu.html#CSS_CLASS_NAME">
3136 * default CSS class name for YAHOO.widget.Menu</a> is applied to
3137 * the <code><div></code> element, it will be created as an
3138 * instance of <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu
3139 * </a>.</li><li>String specifying the id attribute of the
3140 * <code><select></code> element used to create the menu.
3141 * </li><li>Object specifying the <code><div></code> element
3142 * used to create the menu.</li>
3143 * <li>Object specifying the <code><select></code> element
3144 * used to create the menu.</li>
3145 * <li>Array of object literals, each representing a set of
3146 * <a href="YAHOO.widget.MenuItem.html">YAHOO.widget.MenuItem</a>
3147 * configuration attributes.</li>
3148 * <li>Array of strings representing the text labels for each menu
3149 * item in the menu.</li>
3151 * @type <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>|<a
3152 * href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|<a
3153 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3154 * one-html.html#ID-58190037">HTMLElement</a>|String|Array
3157 this.setAttributeConfig("menu", {
3160 method: this._setMenu,
3167 * @config lazyloadmenu
3168 * @description Boolean indicating the value to set for the
3169 * <a href="YAHOO.widget.Menu.html#lazyLoad">"lazyload"</a>
3170 * configuration property of the button's menu. Setting
3171 * "lazyloadmenu" to <code>true </code> will defer rendering of
3172 * the button's menu until the first time it is made visible.
3173 * If "lazyloadmenu" is set to <code>false</code>, the button's
3174 * menu will be rendered immediately if the button is in the
3175 * document, or in response to the button's "appendTo" event if
3176 * the button is not yet in the document. In either case, the
3177 * menu is rendered into the button's parent HTML element.
3178 * <em>This attribute does not apply if a
3179 * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a> or
3180 * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>
3181 * instance is passed as the value of the button's "menu"
3182 * configuration attribute. <a href="YAHOO.widget.Menu.html">
3183 * YAHOO.widget.Menu</a> or <a href="YAHOO.widget.Overlay.html">
3184 * YAHOO.widget.Overlay</a> instances should be rendered before
3185 * being set as the value for the "menu" configuration
3190 this.setAttributeConfig("lazyloadmenu", {
3192 value: (oAttributes.lazyloadmenu === false ? false : true),
3193 validator: Lang.isBoolean,
3200 * @config menuclassname
3201 * @description String representing the CSS class name to be
3202 * applied to the root element of the button's menu.
3204 * @default "yui-button-menu"
3206 this.setAttributeConfig("menuclassname", {
3208 value: (oAttributes.menuclassname || "yui-button-menu"),
3209 validator: Lang.isString,
3210 method: this._setMenuClassName,
3217 * @config selectedMenuItem
3218 * @description Number representing the index of the item in the
3219 * button's menu that is currently selected.
3223 this.setAttributeConfig("selectedMenuItem", {
3226 validator: Lang.isNumber,
3227 method: this._setSelectedMenuItem
3234 * @description Object literal representing the code to be executed
3235 * when the button is clicked. Format:<br> <code> {<br>
3236 * <strong>fn:</strong> Function, // The handler to call
3237 * when the event fires.<br> <strong>obj:</strong> Object,
3238 * // An object to pass back to the handler.<br>
3239 * <strong>scope:</strong> Object // The object to use
3240 * for the scope of the handler.<br> } </code>
3244 this.setAttributeConfig("onclick", {
3246 value: oAttributes.onclick,
3247 method: this._setOnClick
3254 * @description Boolean indicating whether or not the button's menu
3255 * should be focused when it is made visible.
3259 this.setAttributeConfig("focusmenu", {
3261 value: (oAttributes.focusmenu === false ? false : true),
3262 validator: Lang.isBoolean
3271 * @description Causes the button to receive the focus and fires the
3272 * button's "focus" event.
3274 focus: function () {
3276 if (!this.get("disabled")) {
3278 this._button.focus();
3287 * @description Causes the button to lose focus and fires the button's
3292 if (!this.get("disabled")) {
3294 this._button.blur();
3303 * @description Returns a boolean indicating whether or not the button
3307 hasFocus: function () {
3309 return (m_oFocusedButton == this);
3316 * @description Returns a boolean indicating whether or not the button
3320 isActive: function () {
3322 return this.hasClass(this.CSS_CLASS_NAME + "-active");
3329 * @description Returns a reference to the button's menu.
3330 * @return {<a href="YAHOO.widget.Overlay.html">
3331 * YAHOO.widget.Overlay</a>|<a
3332 * href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
3334 getMenu: function () {
3343 * @description Returns a reference to the button's parent form.
3344 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-
3345 * 20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>}
3347 getForm: function () {
3349 return this._button.form;
3355 * @method getHiddenFields
3356 * @description Returns an <code><input></code> element or
3357 * array of form elements used to represent the button when its parent
3358 * form is submitted.
3359 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3360 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
3362 getHiddenFields: function () {
3364 return this._hiddenFields;
3371 * @description Removes the button's element from its parent element and
3372 * removes all event handlers.
3374 destroy: function () {
3376 this.logger.log("Destroying ...");
3378 var oElement = this.get("element"),
3379 oParentNode = oElement.parentNode,
3384 this.logger.log("Destroying menu.");
3390 this.logger.log("Removing DOM event handlers.");
3392 Event.purgeElement(oElement);
3393 Event.purgeElement(this._button);
3394 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
3395 Event.removeListener(document, "keyup", this._onDocumentKeyUp);
3396 Event.removeListener(document, "mousedown",
3397 this._onDocumentMouseDown);
3400 var oForm = this.getForm();
3404 Event.removeListener(oForm, "reset", this._onFormReset);
3405 Event.removeListener(oForm, "submit", this.createHiddenFields);
3410 oParentNode.removeChild(oElement);
3412 this.logger.log("Removing from document.");
3414 delete m_oButtons[this.get("id")];
3416 this.logger.log("Destroyed.");
3421 fireEvent: function (p_sType , p_aArgs) {
3423 // Disabled buttons should not respond to DOM events
3425 if (this.DOM_EVENTS[p_sType] && this.get("disabled")) {
3431 YAHOO.widget.Button.superclass.fireEvent.call(this, p_sType,
3439 * @description Returns a string representing the button.
3442 toString: function () {
3444 return ("Button " + this.get("id"));
3452 * @method YAHOO.widget.Button.onFormKeyPress
3453 * @description "keypress" event handler for the button's form.
3454 * @param {Event} p_oEvent Object representing the DOM event object passed
3455 * back by the event utility (YAHOO.util.Event).
3457 YAHOO.widget.Button.onFormKeyPress = function (p_oEvent) {
3459 var oTarget = Event.getTarget(p_oEvent),
3460 nCharCode = Event.getCharCode(p_oEvent),
3461 sNodeName = oTarget.nodeName && oTarget.nodeName.toUpperCase(),
3462 sType = oTarget.type,
3465 Boolean indicating if the form contains any enabled or
3466 disabled YUI submit buttons
3469 bFormContainsYUIButtons = false,
3473 oYUISubmitButton, // The form's first, enabled YUI submit button
3476 The form's first, enabled HTML submit button that precedes any
3480 oPrecedingSubmitButton,
3484 The form's first, enabled HTML submit button that follows a
3488 oFollowingSubmitButton;
3491 function isSubmitButton(p_oElement) {
3496 switch (p_oElement.nodeName.toUpperCase()) {
3501 if (p_oElement.type == "submit" && !p_oElement.disabled) {
3503 if (!bFormContainsYUIButtons &&
3504 !oPrecedingSubmitButton) {
3506 oPrecedingSubmitButton = p_oElement;
3510 if (oYUISubmitButton && !oFollowingSubmitButton) {
3512 oFollowingSubmitButton = p_oElement;
3523 sId = p_oElement.id;
3527 oButton = m_oButtons[sId];
3531 bFormContainsYUIButtons = true;
3533 if (!oButton.get("disabled")) {
3535 oSrcElement = oButton.get("srcelement");
3537 if (!oYUISubmitButton &&
3538 (oButton.get("type") == "submit" ||
3539 (oSrcElement && oSrcElement.type == "submit")))
3542 oYUISubmitButton = oButton;
3559 if (nCharCode == 13 && ((sNodeName == "INPUT" && (sType == "text" ||
3560 sType == "password" || sType == "checkbox" || sType == "radio" ||
3561 sType == "file") ) || sNodeName == "SELECT"))
3564 Dom.getElementsBy(isSubmitButton, "*", this);
3567 if (oPrecedingSubmitButton) {
3570 Need to set focus to the first enabled submit button
3571 to make sure that IE includes its name and value
3572 in the form's data set.
3575 oPrecedingSubmitButton.focus();
3578 else if (!oPrecedingSubmitButton && oYUISubmitButton) {
3580 if (oFollowingSubmitButton) {
3583 Need to call "preventDefault" to ensure that
3584 the name and value of the regular submit button
3585 following the YUI button doesn't get added to the
3586 form's data set when it is submitted.
3589 Event.preventDefault(p_oEvent);
3593 oYUISubmitButton.submitForm();
3603 * @method addHiddenFieldsToForm
3604 * @description Searches the specified form and adds hidden fields for
3605 * instances of YAHOO.widget.Button that are of type "radio," "checkbox,"
3606 * "menu," and "split."
3607 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3608 * one-html.html#ID-40002357">HTMLFormElement</a>} p_oForm Object reference
3609 * for the form to search.
3611 YAHOO.widget.Button.addHiddenFieldsToForm = function (p_oForm) {
3613 var aButtons = Dom.getElementsByClassName(
3614 YAHOO.widget.Button.prototype.CSS_CLASS_NAME,
3618 nButtons = aButtons.length,
3625 YAHOO.log("Form contains " + nButtons + " YUI buttons.");
3627 for (i = 0; i < nButtons; i++) {
3629 sId = aButtons[i].id;
3633 oButton = m_oButtons[sId];
3637 oButton.createHiddenFields();
3656 * @description Fires when the menu item receives focus. Passes back a
3657 * single object representing the original DOM event object passed back by
3658 * the event utility (YAHOO.util.Event) when the event was fired. See
3659 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a>
3660 * for more information on listening for this event.
3661 * @type YAHOO.util.CustomEvent
3667 * @description Fires when the menu item loses the input focus. Passes back
3668 * a single object representing the original DOM event object passed back by
3669 * the event utility (YAHOO.util.Event) when the event was fired. See
3670 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for
3671 * more information on listening for this event.
3672 * @type YAHOO.util.CustomEvent
3678 * @description Fires when the user invokes the button's option. Passes
3679 * back a single object representing the original DOM event (either
3680 * "mousedown" or "keydown") that caused the "option" event to fire. See
3681 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a>
3682 * for more information on listening for this event.
3683 * @type YAHOO.util.CustomEvent
3689 // Shorthard for utilities
3691 var Dom = YAHOO.util.Dom,
3692 Event = YAHOO.util.Event,
3694 Button = YAHOO.widget.Button,
3696 // Private collection of radio buttons
3703 * The ButtonGroup class creates a set of buttons that are mutually
3704 * exclusive; checking one button in the set will uncheck all others in the
3706 * @param {String} p_oElement String specifying the id attribute of the
3707 * <code><div></code> element of the button group.
3708 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3709 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
3710 * specifying the <code><div></code> element of the button group.
3711 * @param {Object} p_oElement Object literal specifying a set of
3712 * configuration attributes used to create the button group.
3713 * @param {Object} p_oAttributes Optional. Object literal specifying a set
3714 * of configuration attributes used to create the button group.
3715 * @namespace YAHOO.widget
3716 * @class ButtonGroup
3718 * @extends YAHOO.util.Element
3720 YAHOO.widget.ButtonGroup = function (p_oElement, p_oAttributes) {
3722 var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor,
3727 if (arguments.length == 1 && !Lang.isString(p_oElement) &&
3728 !p_oElement.nodeName) {
3730 if (!p_oElement.id) {
3732 sId = Dom.generateId();
3734 p_oElement.id = sId;
3736 YAHOO.log("No value specified for the button group's \"id\"" +
3737 " attribute. Setting button group id to \"" + sId + "\".",
3742 this.logger = new YAHOO.widget.LogWriter("ButtonGroup " + sId);
3744 this.logger.log("No source HTML element. Building the button " +
3745 "group using the set of configuration attributes.");
3747 fnSuperClass.call(this, (this._createGroupElement()), p_oElement);
3750 else if (Lang.isString(p_oElement)) {
3752 oElement = Dom.get(p_oElement);
3756 if (oElement.nodeName.toUpperCase() == this.NODE_NAME) {
3759 new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement);
3761 fnSuperClass.call(this, oElement, p_oAttributes);
3770 sNodeName = p_oElement.nodeName;
3772 if (sNodeName && sNodeName == this.NODE_NAME) {
3774 if (!p_oElement.id) {
3776 p_oElement.id = Dom.generateId();
3778 YAHOO.log("No value specified for the button group's" +
3779 " \"id\" attribute. Setting button group id " +
3780 "to \"" + p_oElement.id + "\".", "warn");
3785 new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement.id);
3787 fnSuperClass.call(this, p_oElement, p_oAttributes);
3796 YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {
3799 // Protected properties
3803 * @property _buttons
3804 * @description Array of buttons in the button group.
3817 * @property NODE_NAME
3818 * @description The name of the tag to be used for the button
3828 * @property CSS_CLASS_NAME
3829 * @description String representing the CSS class(es) to be applied
3830 * to the button group's element.
3831 * @default "yui-buttongroup"
3835 CSS_CLASS_NAME: "yui-buttongroup",
3839 // Protected methods
3843 * @method _createGroupElement
3844 * @description Creates the button group's element.
3846 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3847 * level-one-html.html#ID-22445964">HTMLDivElement</a>}
3849 _createGroupElement: function () {
3851 var oElement = document.createElement(this.NODE_NAME);
3859 // Protected attribute setter methods
3863 * @method _setDisabled
3864 * @description Sets the value of the button groups's
3865 * "disabled" attribute.
3867 * @param {Boolean} p_bDisabled Boolean indicating the value for
3868 * the button group's "disabled" attribute.
3870 _setDisabled: function (p_bDisabled) {
3872 var nButtons = this.getCount(),
3881 this._buttons[i].set("disabled", p_bDisabled);
3892 // Protected event handlers
3896 * @method _onKeyDown
3897 * @description "keydown" event handler for the button group.
3899 * @param {Event} p_oEvent Object representing the DOM event object
3900 * passed back by the event utility (YAHOO.util.Event).
3902 _onKeyDown: function (p_oEvent) {
3904 var oTarget = Event.getTarget(p_oEvent),
3905 nCharCode = Event.getCharCode(p_oEvent),
3906 sId = oTarget.parentNode.parentNode.id,
3907 oButton = m_oButtons[sId],
3911 if (nCharCode == 37 || nCharCode == 38) {
3913 nIndex = (oButton.index === 0) ?
3914 (this._buttons.length - 1) : (oButton.index - 1);
3917 else if (nCharCode == 39 || nCharCode == 40) {
3919 nIndex = (oButton.index === (this._buttons.length - 1)) ?
3920 0 : (oButton.index + 1);
3928 this.getButton(nIndex).focus();
3936 * @method _onAppendTo
3937 * @description "appendTo" event handler for the button group.
3939 * @param {Event} p_oEvent Object representing the event that was fired.
3941 _onAppendTo: function (p_oEvent) {
3943 var aButtons = this._buttons,
3944 nButtons = aButtons.length,
3947 for (i = 0; i < nButtons; i++) {
3949 aButtons[i].appendTo(this.get("element"));
3957 * @method _onButtonCheckedChange
3958 * @description "checkedChange" event handler for each button in the
3961 * @param {Event} p_oEvent Object representing the event that was fired.
3962 * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
3963 * p_oButton Object representing the button that fired the event.
3965 _onButtonCheckedChange: function (p_oEvent, p_oButton) {
3967 var bChecked = p_oEvent.newValue,
3968 oCheckedButton = this.get("checkedButton");
3970 if (bChecked && oCheckedButton != p_oButton) {
3972 if (oCheckedButton) {
3974 oCheckedButton.set("checked", false, true);
3978 this.set("checkedButton", p_oButton);
3979 this.set("value", p_oButton.get("value"));
3982 else if (oCheckedButton && !oCheckedButton.set("checked")) {
3984 oCheckedButton.set("checked", true, true);
3997 * @description The ButtonGroup class's initialization method.
3998 * @param {String} p_oElement String specifying the id attribute of the
3999 * <code><div></code> element of the button group.
4000 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4001 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
4002 * specifying the <code><div></code> element of the button group.
4003 * @param {Object} p_oElement Object literal specifying a set of
4004 * configuration attributes used to create the button group.
4005 * @param {Object} p_oAttributes Optional. Object literal specifying a
4006 * set of configuration attributes used to create the button group.
4008 init: function (p_oElement, p_oAttributes) {
4012 YAHOO.widget.ButtonGroup.superclass.init.call(this, p_oElement,
4015 this.addClass(this.CSS_CLASS_NAME);
4017 this.logger.log("Searching for child nodes with the class name " +
4018 "\"yui-radio-button\" to add to the button group.");
4020 var aButtons = this.getElementsByClassName("yui-radio-button");
4023 if (aButtons.length > 0) {
4025 this.logger.log("Found " + aButtons.length +
4026 " child nodes with the class name \"yui-radio-button.\"" +
4027 " Attempting to add to button group.");
4029 this.addButtons(aButtons);
4034 this.logger.log("Searching for child nodes with the type of " +
4035 " \"radio\" to add to the button group.");
4037 function isRadioButton(p_oElement) {
4039 return (p_oElement.type == "radio");
4044 Dom.getElementsBy(isRadioButton, "input", this.get("element"));
4047 if (aButtons.length > 0) {
4049 this.logger.log("Found " + aButtons.length + " child nodes" +
4050 " with the type of \"radio.\" Attempting to add to" +
4053 this.addButtons(aButtons);
4057 this.on("keydown", this._onKeyDown);
4058 this.on("appendTo", this._onAppendTo);
4061 var oContainer = this.get("container");
4065 if (Lang.isString(oContainer)) {
4067 Event.onContentReady(oContainer, function () {
4069 this.appendTo(oContainer);
4076 this.appendTo(oContainer);
4083 this.logger.log("Initialization completed.");
4089 * @method initAttributes
4090 * @description Initializes all of the configuration attributes used to
4091 * create the button group.
4092 * @param {Object} p_oAttributes Object literal specifying a set of
4093 * configuration attributes used to create the button group.
4095 initAttributes: function (p_oAttributes) {
4097 var oAttributes = p_oAttributes || {};
4099 YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
4105 * @description String specifying the name for the button group.
4106 * This name will be applied to each button in the button group.
4110 this.setAttributeConfig("name", {
4112 value: oAttributes.name,
4113 validator: Lang.isString
4120 * @description Boolean indicating if the button group should be
4121 * disabled. Disabling the button group will disable each button
4122 * in the button group. Disabled buttons are dimmed and will not
4123 * respond to user input or fire events.
4127 this.setAttributeConfig("disabled", {
4129 value: (oAttributes.disabled || false),
4130 validator: Lang.isBoolean,
4131 method: this._setDisabled
4138 * @description Object specifying the value for the button group.
4142 this.setAttributeConfig("value", {
4144 value: oAttributes.value
4151 * @description HTML element reference or string specifying the id
4152 * attribute of the HTML element that the button group's markup
4153 * should be rendered into.
4154 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4155 * level-one-html.html#ID-58190037">HTMLElement</a>|String
4158 this.setAttributeConfig("container", {
4160 value: oAttributes.container,
4167 * @config checkedButton
4168 * @description Reference for the button in the button group that
4170 * @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4173 this.setAttributeConfig("checkedButton", {
4184 * @description Adds the button to the button group.
4185 * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4186 * p_oButton Object reference for the <a href="YAHOO.widget.Button.html">
4187 * YAHOO.widget.Button</a> instance to be added to the button group.
4188 * @param {String} p_oButton String specifying the id attribute of the
4189 * <code><input></code> or <code><span></code> element
4190 * to be used to create the button to be added to the button group.
4191 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4192 * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
4193 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
4194 * ID-33759296">HTMLElement</a>} p_oButton Object reference for the
4195 * <code><input></code> or <code><span></code> element
4196 * to be used to create the button to be added to the button group.
4197 * @param {Object} p_oButton Object literal specifying a set of
4198 * <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>
4199 * configuration attributes used to configure the button to be added to
4201 * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4203 addButton: function (p_oButton) {
4213 if (p_oButton instanceof Button &&
4214 p_oButton.get("type") == "radio") {
4216 oButton = p_oButton;
4219 else if (!Lang.isString(p_oButton) && !p_oButton.nodeName) {
4221 p_oButton.type = "radio";
4223 oButton = new Button(p_oButton);
4228 oButton = new Button(p_oButton, { type: "radio" });
4235 nIndex = this._buttons.length;
4236 sButtonName = oButton.get("name");
4237 sGroupName = this.get("name");
4239 oButton.index = nIndex;
4241 this._buttons[nIndex] = oButton;
4242 m_oButtons[oButton.get("id")] = oButton;
4245 if (sButtonName != sGroupName) {
4247 oButton.set("name", sGroupName);
4252 if (this.get("disabled")) {
4254 oButton.set("disabled", true);
4259 if (oButton.get("checked")) {
4261 this.set("checkedButton", oButton);
4266 oButtonElement = oButton.get("element");
4267 oGroupElement = this.get("element");
4269 if (oButtonElement.parentNode != oGroupElement) {
4271 oGroupElement.appendChild(oButtonElement);
4276 oButton.on("checkedChange",
4277 this._onButtonCheckedChange, oButton, this);
4279 this.logger.log("Button " + oButton.get("id") + " added.");
4289 * @method addButtons
4290 * @description Adds the array of buttons to the button group.
4291 * @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
4292 * YAHOO.widget.Button</a> instances to be added
4293 * to the button group.
4294 * @param {Array} p_aButtons Array of strings specifying the id
4295 * attribute of the <code><input></code> or <code><span>
4296 * </code> elements to be used to create the buttons to be added to the
4298 * @param {Array} p_aButtons Array of object references for the
4299 * <code><input></code> or <code><span></code> elements
4300 * to be used to create the buttons to be added to the button group.
4301 * @param {Array} p_aButtons Array of object literals, each containing
4302 * a set of <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>
4303 * configuration attributes used to configure each button to be added
4304 * to the button group.
4307 addButtons: function (p_aButtons) {
4314 if (Lang.isArray(p_aButtons)) {
4316 nButtons = p_aButtons.length;
4321 for (i = 0; i < nButtons; i++) {
4323 oButton = this.addButton(p_aButtons[i]);
4327 aButtons[aButtons.length] = oButton;
4333 if (aButtons.length > 0) {
4335 this.logger.log(aButtons.length + " buttons added.");
4349 * @method removeButton
4350 * @description Removes the button at the specified index from the
4352 * @param {Number} p_nIndex Number specifying the index of the button
4353 * to be removed from the button group.
4355 removeButton: function (p_nIndex) {
4357 var oButton = this.getButton(p_nIndex),
4363 this.logger.log("Removing button " + oButton.get("id") + ".");
4365 this._buttons.splice(p_nIndex, 1);
4366 delete m_oButtons[oButton.get("id")];
4368 oButton.removeListener("checkedChange",
4369 this._onButtonCheckedChange);
4374 nButtons = this._buttons.length;
4378 i = this._buttons.length - 1;
4382 this._buttons[i].index = i;
4389 this.logger.log("Button " + oButton.get("id") + " removed.");
4398 * @description Returns the button at the specified index.
4399 * @param {Number} p_nIndex The index of the button to retrieve from the
4401 * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4403 getButton: function (p_nIndex) {
4405 if (Lang.isNumber(p_nIndex)) {
4407 return this._buttons[p_nIndex];
4415 * @method getButtons
4416 * @description Returns an array of the buttons in the button group.
4419 getButtons: function () {
4421 return this._buttons;
4428 * @description Returns the number of buttons in the button group.
4431 getCount: function () {
4433 return this._buttons.length;
4440 * @description Sets focus to the button at the specified index.
4441 * @param {Number} p_nIndex Number indicating the index of the button
4444 focus: function (p_nIndex) {
4450 if (Lang.isNumber(p_nIndex)) {
4452 oButton = this._buttons[p_nIndex];
4463 nButtons = this.getCount();
4465 for (i = 0; i < nButtons; i++) {
4467 oButton = this._buttons[i];
4469 if (!oButton.get("disabled")) {
4485 * @description Checks the button at the specified index.
4486 * @param {Number} p_nIndex Number indicating the index of the button
4489 check: function (p_nIndex) {
4491 var oButton = this.getButton(p_nIndex);
4495 oButton.set("checked", true);
4504 * @description Removes the button group's element from its parent
4505 * element and removes all event handlers.
4507 destroy: function () {
4509 this.logger.log("Destroying...");
4511 var nButtons = this._buttons.length,
4512 oElement = this.get("element"),
4513 oParentNode = oElement.parentNode,
4518 i = this._buttons.length - 1;
4522 this._buttons[i].destroy();
4529 this.logger.log("Removing DOM event handlers.");
4531 Event.purgeElement(oElement);
4533 this.logger.log("Removing from document.");
4535 oParentNode.removeChild(oElement);
4542 * @description Returns a string representing the button group.
4545 toString: function () {
4547 return ("ButtonGroup " + this.get("id"));
4554 YAHOO.register("button", YAHOO.widget.Button, {version: "2.3.0", build: "442"});