2 Copyright (c) 2009, 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 * traditional 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
52 * The Button class creates a rich, graphical button.
53 * @param {String} p_oElement String specifying the id attribute of the
54 * <code><input></code>, <code><button></code>,
55 * <code><a></code>, or <code><span></code> element to
56 * be used to create the button.
57 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
58 * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org
59 * /TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-34812697">
60 * HTMLButtonElement</a>|<a href="
61 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
62 * ID-33759296">HTMLElement</a>} p_oElement Object reference for the
63 * <code><input></code>, <code><button></code>,
64 * <code><a></code>, or <code><span></code> element to be
65 * used to create the button.
66 * @param {Object} p_oElement Object literal specifying a set of
67 * configuration attributes used to create the button.
68 * @param {Object} p_oAttributes Optional. Object literal specifying a set
69 * of configuration attributes used to create the button.
70 * @namespace YAHOO.widget
73 * @extends YAHOO.util.Element
78 // Shorthard for utilities
80 var Dom = YAHOO.util.Dom,
81 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)) {
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(),
188 sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME),
196 * @method setAttributeFromDOMAttribute
197 * @description Gets the value of the specified DOM attribute and sets it
198 * into the collection of configuration attributes used to configure
201 * @param {String} p_sAttribute String representing the name of the
202 * attribute to retrieve from the DOM element.
204 function setAttributeFromDOMAttribute(p_sAttribute) {
206 if (!(p_sAttribute in p_oAttributes)) {
209 Need to use "getAttributeNode" instead of "getAttribute"
210 because using "getAttribute," IE will return the innerText
211 of a <code><button></code> for the value attribute
212 rather than the value of the "value" attribute.
215 oAttribute = p_oElement.getAttributeNode(p_sAttribute);
218 if (oAttribute && ("value" in oAttribute)) {
221 p_oAttributes[p_sAttribute] = oAttribute.value;
231 * @method setFormElementProperties
232 * @description Gets the value of the attributes from the form element
233 * and sets them into the collection of configuration attributes used to
234 * configure the button.
237 function setFormElementProperties() {
239 setAttributeFromDOMAttribute("type");
241 if (p_oAttributes.type == "button") {
243 p_oAttributes.type = "push";
247 if (!("disabled" in p_oAttributes)) {
249 p_oAttributes.disabled = p_oElement.disabled;
253 setAttributeFromDOMAttribute("name");
254 setAttributeFromDOMAttribute("value");
255 setAttributeFromDOMAttribute("title");
260 switch (sSrcElementNodeName) {
264 p_oAttributes.type = "link";
266 setAttributeFromDOMAttribute("href");
267 setAttributeFromDOMAttribute("target");
273 setFormElementProperties();
275 if (!("checked" in p_oAttributes)) {
277 p_oAttributes.checked = p_oElement.checked;
285 setFormElementProperties();
287 oRootNode = p_oElement.parentNode.parentNode;
289 if (Dom.hasClass(oRootNode, sClass + "-checked")) {
291 p_oAttributes.checked = true;
295 if (Dom.hasClass(oRootNode, sClass + "-disabled")) {
297 p_oAttributes.disabled = true;
301 p_oElement.removeAttribute("value");
303 p_oElement.setAttribute("type", "button");
309 p_oElement.removeAttribute("id");
310 p_oElement.removeAttribute("name");
312 if (!("tabindex" in p_oAttributes)) {
314 p_oAttributes.tabindex = p_oElement.tabIndex;
318 if (!("label" in p_oAttributes)) {
320 // Set the "label" property
322 sText = sSrcElementNodeName == "INPUT" ?
323 p_oElement.value : p_oElement.innerHTML;
326 if (sText && sText.length > 0) {
328 p_oAttributes.label = sText;
339 * @description Initializes the set of configuration attributes that are
340 * used to instantiate the button.
342 * @param {Object} Object representing the button's set of
343 * configuration attributes.
345 function initConfig(p_oConfig) {
347 var oAttributes = p_oConfig.attributes,
348 oSrcElement = oAttributes.srcelement,
349 sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
353 if (sSrcElementNodeName == this.NODE_NAME) {
355 p_oConfig.element = oSrcElement;
356 p_oConfig.id = oSrcElement.id;
358 Dom.getElementsBy(function (p_oElement) {
360 switch (p_oElement.nodeName.toUpperCase()) {
366 setAttributesFromSrcElement.call(me, p_oElement,
373 }, "*", oSrcElement);
378 switch (sSrcElementNodeName) {
384 setAttributesFromSrcElement.call(this, oSrcElement,
399 YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
401 if (!Overlay && YAHOO.widget.Overlay) {
403 Overlay = YAHOO.widget.Overlay;
408 if (!Menu && YAHOO.widget.Menu) {
410 Menu = YAHOO.widget.Menu;
415 var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
420 if (arguments.length == 1 && !Lang.isString(p_oElement) && !p_oElement.nodeName) {
422 if (!p_oElement.id) {
424 p_oElement.id = Dom.generateId();
430 fnSuperClass.call(this, (this.createButtonElement(p_oElement.type)), p_oElement);
435 oConfig = { element: null, attributes: (p_oAttributes || {}) };
438 if (Lang.isString(p_oElement)) {
440 oElement = Dom.get(p_oElement);
444 if (!oConfig.attributes.id) {
446 oConfig.attributes.id = p_oElement;
452 oConfig.attributes.srcelement = oElement;
454 initConfig.call(this, oConfig);
457 if (!oConfig.element) {
460 oConfig.element = this.createButtonElement(oConfig.attributes.type);
464 fnSuperClass.call(this, oConfig.element, oConfig.attributes);
469 else if (p_oElement.nodeName) {
471 if (!oConfig.attributes.id) {
475 oConfig.attributes.id = p_oElement.id;
480 oConfig.attributes.id = Dom.generateId();
489 oConfig.attributes.srcelement = p_oElement;
491 initConfig.call(this, oConfig);
494 if (!oConfig.element) {
497 oConfig.element = this.createButtonElement(oConfig.attributes.type);
501 fnSuperClass.call(this, oConfig.element, oConfig.attributes);
511 YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
514 // Protected properties
519 * @description Object reference to the button's internal
520 * <code><a></code> or <code><button></code> element.
523 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
524 * level-one-html.html#ID-48250443">HTMLAnchorElement</a>|<a href="
525 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
526 * #ID-34812697">HTMLButtonElement</a>
533 * @description Object reference to the button's menu.
536 * @type {<a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|
537 * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
543 * @property _hiddenFields
544 * @description Object reference to the <code><input></code>
545 * element, or array of HTML form elements used to represent the button
546 * when its parent form is submitted.
549 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
550 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array
556 * @property _onclickAttributeValue
557 * @description Object reference to the button's current value for the
558 * "onclick" configuration attribute.
563 _onclickAttributeValue: null,
567 * @property _activationKeyPressed
568 * @description Boolean indicating if the key(s) that toggle the button's
569 * "active" state have been pressed.
574 _activationKeyPressed: false,
578 * @property _activationButtonPressed
579 * @description Boolean indicating if the mouse button that toggles
580 * the button's "active" state has been pressed.
585 _activationButtonPressed: false,
589 * @property _hasKeyEventHandlers
590 * @description Boolean indicating if the button's "blur", "keydown" and
591 * "keyup" event handlers are assigned
596 _hasKeyEventHandlers: false,
600 * @property _hasMouseEventHandlers
601 * @description Boolean indicating if the button's "mouseout,"
602 * "mousedown," and "mouseup" event handlers are assigned
607 _hasMouseEventHandlers: false,
611 * @property _nOptionRegionX
612 * @description Number representing the X coordinate of the leftmost edge of the Button's
613 * option region. Applies only to Buttons of type "split".
625 * @property CLASS_NAME_PREFIX
626 * @description Prefix used for all class names applied to a Button.
631 CLASS_NAME_PREFIX: "yui-",
635 * @property NODE_NAME
636 * @description The name of the node to be used for the button's
646 * @property CHECK_ACTIVATION_KEYS
647 * @description Array of numbers representing keys that (when pressed)
648 * toggle the button's "checked" attribute.
653 CHECK_ACTIVATION_KEYS: [32],
657 * @property ACTIVATION_KEYS
658 * @description Array of numbers representing keys that (when presed)
659 * toggle the button's "active" state.
664 ACTIVATION_KEYS: [13, 32],
668 * @property OPTION_AREA_WIDTH
669 * @description Width (in pixels) of the area of a split button that
670 * when pressed will display a menu.
675 OPTION_AREA_WIDTH: 20,
679 * @property CSS_CLASS_NAME
680 * @description String representing the CSS class(es) to be applied to
681 * the button's root element.
686 CSS_CLASS_NAME: "button",
690 // Protected attribute setter methods
695 * @description Sets the value of the button's "type" attribute.
697 * @param {String} p_sType String indicating the value for the button's
700 _setType: function (p_sType) {
702 if (p_sType == "split") {
704 this.on("option", this._onOption);
713 * @description Sets the value of the button's "label" attribute.
715 * @param {String} p_sLabel String indicating the value for the button's
718 _setLabel: function (p_sLabel) {
720 this._button.innerHTML = p_sLabel;
724 Remove and add the default class name from the root element
725 for Gecko to ensure that the button shrinkwraps to the label.
726 Without this the button will not be rendered at the correct
727 width when the label changes. The most likely cause for this
728 bug is button's use of the Gecko-specific CSS display type of
729 "-moz-inline-box" to simulate "inline-block" supported by IE,
734 nGeckoVersion = UA.gecko;
737 if (nGeckoVersion && nGeckoVersion < 1.9 && Dom.inDocument(this.get("element"))) {
739 sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
741 this.removeClass(sClass);
743 Lang.later(0, this, this.addClass, sClass);
751 * @method _setTabIndex
752 * @description Sets the value of the button's "tabindex" attribute.
754 * @param {Number} p_nTabIndex Number indicating the value for the
755 * button's "tabindex" attribute.
757 _setTabIndex: function (p_nTabIndex) {
759 this._button.tabIndex = p_nTabIndex;
766 * @description Sets the value of the button's "title" attribute.
768 * @param {String} p_nTabIndex Number indicating the value for
769 * the button's "title" attribute.
771 _setTitle: function (p_sTitle) {
773 if (this.get("type") != "link") {
775 this._button.title = p_sTitle;
783 * @method _setDisabled
784 * @description Sets the value of the button's "disabled" attribute.
786 * @param {Boolean} p_bDisabled Boolean indicating the value for
787 * the button's "disabled" attribute.
789 _setDisabled: function (p_bDisabled) {
791 if (this.get("type") != "link") {
801 if (this.hasFocus()) {
807 this._button.setAttribute("disabled", "disabled");
809 this.addStateCSSClasses("disabled");
811 this.removeStateCSSClasses("hover");
812 this.removeStateCSSClasses("active");
813 this.removeStateCSSClasses("focus");
818 this._button.removeAttribute("disabled");
820 this.removeStateCSSClasses("disabled");
831 * @description Sets the value of the button's "href" attribute.
833 * @param {String} p_sHref String indicating the value for the button's
836 _setHref: function (p_sHref) {
838 if (this.get("type") == "link") {
840 this._button.href = p_sHref;
849 * @description Sets the value of the button's "target" attribute.
851 * @param {String} p_sTarget String indicating the value for the button's
852 * "target" attribute.
854 _setTarget: function (p_sTarget) {
856 if (this.get("type") == "link") {
858 this._button.setAttribute("target", p_sTarget);
866 * @method _setChecked
867 * @description Sets the value of the button's "target" attribute.
869 * @param {Boolean} p_bChecked Boolean indicating the value for
870 * the button's "checked" attribute.
872 _setChecked: function (p_bChecked) {
874 var sType = this.get("type");
876 if (sType == "checkbox" || sType == "radio") {
879 this.addStateCSSClasses("checked");
882 this.removeStateCSSClasses("checked");
892 * @description Sets the value of the button's "menu" attribute.
894 * @param {Object} p_oMenu Object indicating the value for the button's
897 _setMenu: function (p_oMenu) {
899 var bLazyLoad = this.get("lazyloadmenu"),
900 oButtonElement = this.get("element"),
904 Boolean indicating if the value of p_oMenu is an instance
905 of YAHOO.widget.Menu or YAHOO.widget.Overlay.
914 function onAppendTo() {
916 oMenu.render(oButtonElement.parentNode);
918 this.removeListener("appendTo", onAppendTo);
923 function setMenuContainer() {
925 oMenu.cfg.queueProperty("container", oButtonElement.parentNode);
927 this.removeListener("appendTo", setMenuContainer);
932 function initMenu() {
938 Dom.addClass(oMenu.element, this.get("menuclassname"));
939 Dom.addClass(oMenu.element, this.CLASS_NAME_PREFIX + this.get("type") + "-button-menu");
941 oMenu.showEvent.subscribe(this._onMenuShow, null, this);
942 oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
943 oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
946 if (Menu && oMenu instanceof Menu) {
950 oContainer = this.get("container");
954 oMenu.cfg.queueProperty("container", oContainer);
959 this.on("appendTo", setMenuContainer);
965 oMenu.cfg.queueProperty("clicktohide", false);
967 oMenu.keyDownEvent.subscribe(this._onMenuKeyDown, this, true);
968 oMenu.subscribe("click", this._onMenuClick, this, true);
970 this.on("selectedMenuItemChange", this._onSelectedMenuItemChange);
972 oSrcElement = oMenu.srcElement;
974 if (oSrcElement && oSrcElement.nodeName.toUpperCase() == "SELECT") {
976 oSrcElement.style.display = "none";
977 oSrcElement.parentNode.removeChild(oSrcElement);
982 else if (Overlay && oMenu instanceof Overlay) {
984 if (!m_oOverlayManager) {
986 m_oOverlayManager = new YAHOO.widget.OverlayManager();
990 m_oOverlayManager.register(oMenu);
998 if (!bInstance && !bLazyLoad) {
1000 if (Dom.inDocument(oButtonElement)) {
1002 oMenu.render(oButtonElement.parentNode);
1007 this.on("appendTo", onAppendTo);
1022 sMenuCSSClassName = Menu.prototype.CSS_CLASS_NAME;
1026 if (p_oMenu && Menu && (p_oMenu instanceof Menu)) {
1031 initMenu.call(this);
1034 else if (Overlay && p_oMenu && (p_oMenu instanceof Overlay)) {
1039 oMenu.cfg.queueProperty("visible", false);
1041 initMenu.call(this);
1044 else if (Menu && Lang.isArray(p_oMenu)) {
1046 oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad, itemdata: p_oMenu });
1050 this.on("appendTo", initMenu);
1053 else if (Lang.isString(p_oMenu)) {
1055 oMenuElement = Dom.get(p_oMenu);
1059 if (Menu && Dom.hasClass(oMenuElement, sMenuCSSClassName) ||
1060 oMenuElement.nodeName.toUpperCase() == "SELECT") {
1062 oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1064 initMenu.call(this);
1069 oMenu = new Overlay(p_oMenu, { visible: false });
1071 initMenu.call(this);
1078 else if (p_oMenu && p_oMenu.nodeName) {
1080 if (Menu && Dom.hasClass(p_oMenu, sMenuCSSClassName) ||
1081 p_oMenu.nodeName.toUpperCase() == "SELECT") {
1083 oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1085 initMenu.call(this);
1092 Dom.generateId(p_oMenu);
1096 oMenu = new Overlay(p_oMenu, { visible: false });
1098 initMenu.call(this);
1110 * @method _setOnClick
1111 * @description Sets the value of the button's "onclick" attribute.
1113 * @param {Object} p_oObject Object indicating the value for the button's
1114 * "onclick" attribute.
1116 _setOnClick: function (p_oObject) {
1119 Remove any existing listeners if a "click" event handler
1120 has already been specified.
1123 if (this._onclickAttributeValue &&
1124 (this._onclickAttributeValue != p_oObject)) {
1126 this.removeListener("click", this._onclickAttributeValue.fn);
1128 this._onclickAttributeValue = null;
1133 if (!this._onclickAttributeValue &&
1134 Lang.isObject(p_oObject) &&
1135 Lang.isFunction(p_oObject.fn)) {
1137 this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
1139 this._onclickAttributeValue = p_oObject;
1147 // Protected methods
1152 * @method _isActivationKey
1153 * @description Determines if the specified keycode is one that toggles
1154 * the button's "active" state.
1156 * @param {Number} p_nKeyCode Number representing the keycode to
1160 _isActivationKey: function (p_nKeyCode) {
1162 var sType = this.get("type"),
1163 aKeyCodes = (sType == "checkbox" || sType == "radio") ?
1164 this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
1166 nKeyCodes = aKeyCodes.length,
1171 if (nKeyCodes > 0) {
1177 if (p_nKeyCode == aKeyCodes[i]) {
1195 * @method _isSplitButtonOptionKey
1196 * @description Determines if the specified keycode is one that toggles
1197 * the display of the split button's menu.
1199 * @param {Event} p_oEvent Object representing the DOM event object
1200 * passed back by the event utility (YAHOO.util.Event).
1203 _isSplitButtonOptionKey: function (p_oEvent) {
1205 var bShowMenu = (Event.getCharCode(p_oEvent) == 40);
1208 var onKeyPress = function (p_oEvent) {
1210 Event.preventDefault(p_oEvent);
1212 this.removeListener("keypress", onKeyPress);
1217 // Prevent the browser from scrolling the window
1222 this.on("keypress", onKeyPress);
1226 Event.preventDefault(p_oEvent);
1235 * @method _addListenersToForm
1236 * @description Adds event handlers to the button's form.
1239 _addListenersToForm: function () {
1241 var oForm = this.getForm(),
1242 onFormKeyPress = YAHOO.widget.Button.onFormKeyPress,
1243 bHasKeyPressListener,
1252 Event.on(oForm, "reset", this._onFormReset, null, this);
1253 Event.on(oForm, "submit", this._onFormSubmit, null, this);
1255 oSrcElement = this.get("srcelement");
1258 if (this.get("type") == "submit" ||
1259 (oSrcElement && oSrcElement.type == "submit"))
1262 aListeners = Event.getListeners(oForm, "keypress");
1263 bHasKeyPressListener = false;
1267 nListeners = aListeners.length;
1269 if (nListeners > 0) {
1275 if (aListeners[i].fn == onFormKeyPress) {
1277 bHasKeyPressListener = true;
1290 if (!bHasKeyPressListener) {
1292 Event.on(oForm, "keypress", onFormKeyPress);
1306 * @description Shows the button's menu.
1308 * @param {Event} p_oEvent Object representing the DOM event object
1309 * passed back by the event utility (YAHOO.util.Event) that triggered
1310 * the display of the menu.
1312 _showMenu: function (p_oEvent) {
1314 if (YAHOO.widget.MenuManager) {
1315 YAHOO.widget.MenuManager.hideVisible();
1319 if (m_oOverlayManager) {
1320 m_oOverlayManager.hideAll();
1324 var oMenu = this._menu,
1325 aMenuAlignment = this.get("menualignment"),
1326 bFocusMenu = this.get("focusmenu"),
1330 if (this._renderedMenu) {
1332 oMenu.cfg.setProperty("context",
1333 [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1335 oMenu.cfg.setProperty("preventcontextoverlap", true);
1336 oMenu.cfg.setProperty("constraintoviewport", true);
1341 oMenu.cfg.queueProperty("context",
1342 [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1344 oMenu.cfg.queueProperty("preventcontextoverlap", true);
1345 oMenu.cfg.queueProperty("constraintoviewport", true);
1351 Refocus the Button before showing its Menu in case the call to
1352 YAHOO.widget.MenuManager.hideVisible() resulted in another element in the
1353 DOM being focused after another Menu was hidden.
1359 if (Menu && oMenu && (oMenu instanceof Menu)) {
1361 // Since Menus automatically focus themselves when made visible, temporarily
1362 // replace the Menu focus method so that the value of the Button's "focusmenu"
1363 // attribute determines if the Menu should be focus when made visible.
1365 fnFocusMethod = oMenu.focus;
1367 oMenu.focus = function () {};
1369 if (this._renderedMenu) {
1371 oMenu.cfg.setProperty("minscrollheight", this.get("menuminscrollheight"));
1372 oMenu.cfg.setProperty("maxheight", this.get("menumaxheight"));
1377 oMenu.cfg.queueProperty("minscrollheight", this.get("menuminscrollheight"));
1378 oMenu.cfg.queueProperty("maxheight", this.get("menumaxheight"));
1385 oMenu.focus = fnFocusMethod;
1391 Stop the propagation of the event so that the MenuManager
1392 doesn't blur the menu after it gets focus.
1395 if (p_oEvent.type == "mousedown") {
1396 Event.stopPropagation(p_oEvent);
1405 else if (Overlay && oMenu && (oMenu instanceof Overlay)) {
1407 if (!this._renderedMenu) {
1408 oMenu.render(this.get("element").parentNode);
1421 * @description Hides the button's menu.
1424 _hideMenu: function () {
1426 var oMenu = this._menu;
1439 // Protected event handlers
1443 * @method _onMouseOver
1444 * @description "mouseover" event handler for the button.
1446 * @param {Event} p_oEvent Object representing the DOM event object
1447 * passed back by the event utility (YAHOO.util.Event).
1449 _onMouseOver: function (p_oEvent) {
1451 var sType = this.get("type"),
1456 if (sType === "split") {
1458 oElement = this.get("element");
1460 (Dom.getX(oElement) + (oElement.offsetWidth - this.OPTION_AREA_WIDTH));
1462 this._nOptionRegionX = nOptionRegionX;
1467 if (!this._hasMouseEventHandlers) {
1469 if (sType === "split") {
1471 this.on("mousemove", this._onMouseMove);
1475 this.on("mouseout", this._onMouseOut);
1477 this._hasMouseEventHandlers = true;
1482 this.addStateCSSClasses("hover");
1485 if (sType === "split" && (Event.getPageX(p_oEvent) > nOptionRegionX)) {
1487 this.addStateCSSClasses("hoveroption");
1492 if (this._activationButtonPressed) {
1494 this.addStateCSSClasses("active");
1499 if (this._bOptionPressed) {
1501 this.addStateCSSClasses("activeoption");
1506 if (this._activationButtonPressed || this._bOptionPressed) {
1508 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1516 * @method _onMouseMove
1517 * @description "mousemove" event handler for the button.
1519 * @param {Event} p_oEvent Object representing the DOM event object
1520 * passed back by the event utility (YAHOO.util.Event).
1522 _onMouseMove: function (p_oEvent) {
1524 var nOptionRegionX = this._nOptionRegionX;
1526 if (nOptionRegionX) {
1528 if (Event.getPageX(p_oEvent) > nOptionRegionX) {
1530 this.addStateCSSClasses("hoveroption");
1535 this.removeStateCSSClasses("hoveroption");
1544 * @method _onMouseOut
1545 * @description "mouseout" event handler for the button.
1547 * @param {Event} p_oEvent Object representing the DOM event object
1548 * passed back by the event utility (YAHOO.util.Event).
1550 _onMouseOut: function (p_oEvent) {
1552 var sType = this.get("type");
1554 this.removeStateCSSClasses("hover");
1557 if (sType != "menu") {
1559 this.removeStateCSSClasses("active");
1564 if (this._activationButtonPressed || this._bOptionPressed) {
1566 Event.on(document, "mouseup", this._onDocumentMouseUp, null, this);
1571 if (sType === "split" && (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1573 this.removeStateCSSClasses("hoveroption");
1581 * @method _onDocumentMouseUp
1582 * @description "mouseup" event handler for the button.
1584 * @param {Event} p_oEvent Object representing the DOM event object
1585 * passed back by the event utility (YAHOO.util.Event).
1587 _onDocumentMouseUp: function (p_oEvent) {
1589 this._activationButtonPressed = false;
1590 this._bOptionPressed = false;
1592 var sType = this.get("type"),
1596 if (sType == "menu" || sType == "split") {
1598 oTarget = Event.getTarget(p_oEvent);
1599 oMenuElement = this._menu.element;
1601 if (oTarget != oMenuElement &&
1602 !Dom.isAncestor(oMenuElement, oTarget)) {
1604 this.removeStateCSSClasses((sType == "menu" ?
1605 "active" : "activeoption"));
1613 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1619 * @method _onMouseDown
1620 * @description "mousedown" event handler for the button.
1622 * @param {Event} p_oEvent Object representing the DOM event object
1623 * passed back by the event utility (YAHOO.util.Event).
1625 _onMouseDown: function (p_oEvent) {
1631 function onMouseUp() {
1634 this.removeListener("mouseup", onMouseUp);
1639 if ((p_oEvent.which || p_oEvent.button) == 1) {
1642 if (!this.hasFocus()) {
1649 sType = this.get("type");
1652 if (sType == "split") {
1654 if (Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1656 this.fireEvent("option", p_oEvent);
1662 this.addStateCSSClasses("active");
1664 this._activationButtonPressed = true;
1669 else if (sType == "menu") {
1671 if (this.isActive()) {
1675 this._activationButtonPressed = false;
1680 this._showMenu(p_oEvent);
1682 this._activationButtonPressed = true;
1689 this.addStateCSSClasses("active");
1691 this._activationButtonPressed = true;
1697 if (sType == "split" || sType == "menu") {
1699 this._hideMenuTimer = Lang.later(250, this, this.on, ["mouseup", onMouseUp]);
1711 * @method _onMouseUp
1712 * @description "mouseup" event handler for the button.
1714 * @param {Event} p_oEvent Object representing the DOM event object
1715 * passed back by the event utility (YAHOO.util.Event).
1717 _onMouseUp: function (p_oEvent) {
1719 var sType = this.get("type"),
1720 oHideMenuTimer = this._hideMenuTimer,
1724 if (oHideMenuTimer) {
1726 oHideMenuTimer.cancel();
1731 if (sType == "checkbox" || sType == "radio") {
1733 this.set("checked", !(this.get("checked")));
1738 this._activationButtonPressed = false;
1741 if (sType != "menu") {
1743 this.removeStateCSSClasses("active");
1748 if (sType == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1761 * @description "focus" event handler for the button.
1763 * @param {Event} p_oEvent Object representing the DOM event object
1764 * passed back by the event utility (YAHOO.util.Event).
1766 _onFocus: function (p_oEvent) {
1770 this.addStateCSSClasses("focus");
1772 if (this._activationKeyPressed) {
1774 this.addStateCSSClasses("active");
1778 m_oFocusedButton = this;
1781 if (!this._hasKeyEventHandlers) {
1783 oElement = this._button;
1785 Event.on(oElement, "blur", this._onBlur, null, this);
1786 Event.on(oElement, "keydown", this._onKeyDown, null, this);
1787 Event.on(oElement, "keyup", this._onKeyUp, null, this);
1789 this._hasKeyEventHandlers = true;
1794 this.fireEvent("focus", p_oEvent);
1801 * @description "blur" event handler for the button.
1803 * @param {Event} p_oEvent Object representing the DOM event object
1804 * passed back by the event utility (YAHOO.util.Event).
1806 _onBlur: function (p_oEvent) {
1808 this.removeStateCSSClasses("focus");
1810 if (this.get("type") != "menu") {
1812 this.removeStateCSSClasses("active");
1816 if (this._activationKeyPressed) {
1818 Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
1823 m_oFocusedButton = null;
1825 this.fireEvent("blur", p_oEvent);
1831 * @method _onDocumentKeyUp
1832 * @description "keyup" event handler for the document.
1834 * @param {Event} p_oEvent Object representing the DOM event object
1835 * passed back by the event utility (YAHOO.util.Event).
1837 _onDocumentKeyUp: function (p_oEvent) {
1839 if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1841 this._activationKeyPressed = false;
1843 Event.removeListener(document, "keyup", this._onDocumentKeyUp);
1851 * @method _onKeyDown
1852 * @description "keydown" event handler for the button.
1854 * @param {Event} p_oEvent Object representing the DOM event object
1855 * passed back by the event utility (YAHOO.util.Event).
1857 _onKeyDown: function (p_oEvent) {
1859 var oMenu = this._menu;
1862 if (this.get("type") == "split" &&
1863 this._isSplitButtonOptionKey(p_oEvent)) {
1865 this.fireEvent("option", p_oEvent);
1868 else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1870 if (this.get("type") == "menu") {
1872 this._showMenu(p_oEvent);
1877 this._activationKeyPressed = true;
1879 this.addStateCSSClasses("active");
1886 if (oMenu && oMenu.cfg.getProperty("visible") &&
1887 Event.getCharCode(p_oEvent) == 27) {
1899 * @description "keyup" event handler for the button.
1901 * @param {Event} p_oEvent Object representing the DOM event object
1902 * passed back by the event utility (YAHOO.util.Event).
1904 _onKeyUp: function (p_oEvent) {
1908 if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1910 sType = this.get("type");
1912 if (sType == "checkbox" || sType == "radio") {
1914 this.set("checked", !(this.get("checked")));
1918 this._activationKeyPressed = false;
1920 if (this.get("type") != "menu") {
1922 this.removeStateCSSClasses("active");
1933 * @description "click" event handler for the button.
1935 * @param {Event} p_oEvent Object representing the DOM event object
1936 * passed back by the event utility (YAHOO.util.Event).
1938 _onClick: function (p_oEvent) {
1940 var sType = this.get("type"),
1950 if (p_oEvent.returnValue !== false) {
1960 oForm = this.getForm();
1973 if (this._nOptionRegionX > 0 &&
1974 (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1983 oSrcElement = this.get("srcelement");
1985 if (oSrcElement && oSrcElement.type == "submit" &&
1986 p_oEvent.returnValue !== false) {
2004 * @method _onDblClick
2005 * @description "dblclick" event handler for the button.
2007 * @param {Event} p_oEvent Object representing the DOM event object
2008 * passed back by the event utility (YAHOO.util.Event).
2010 _onDblClick: function (p_oEvent) {
2012 var bReturnVal = true;
2014 if (this.get("type") == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
2026 * @method _onAppendTo
2027 * @description "appendTo" event handler for the button.
2029 * @param {Event} p_oEvent Object representing the DOM event object
2030 * passed back by the event utility (YAHOO.util.Event).
2032 _onAppendTo: function (p_oEvent) {
2035 It is necessary to call "_addListenersToForm" using
2036 "setTimeout" to make sure that the button's "form" property
2037 returns a node reference. Sometimes, if you try to get the
2038 reference immediately after appending the field, it is null.
2041 Lang.later(0, this, this._addListenersToForm);
2047 * @method _onFormReset
2048 * @description "reset" event handler for the button's form.
2050 * @param {Event} p_oEvent Object representing the DOM event
2051 * object passed back by the event utility (YAHOO.util.Event).
2053 _onFormReset: function (p_oEvent) {
2055 var sType = this.get("type"),
2058 if (sType == "checkbox" || sType == "radio") {
2060 this.resetValue("checked");
2065 if (Menu && oMenu && (oMenu instanceof Menu)) {
2067 this.resetValue("selectedMenuItem");
2075 * @method _onFormSubmit
2076 * @description "submit" event handler for the button's form.
2078 * @param {Event} p_oEvent Object representing the DOM event
2079 * object passed back by the event utility (YAHOO.util.Event).
2081 _onFormSubmit: function (p_oEvent) {
2083 this.createHiddenFields();
2089 * @method _onDocumentMouseDown
2090 * @description "mousedown" event handler for the document.
2092 * @param {Event} p_oEvent Object representing the DOM event object
2093 * passed back by the event utility (YAHOO.util.Event).
2095 _onDocumentMouseDown: function (p_oEvent) {
2097 var oTarget = Event.getTarget(p_oEvent),
2098 oButtonElement = this.get("element"),
2099 oMenuElement = this._menu.element;
2102 if (oTarget != oButtonElement &&
2103 !Dom.isAncestor(oButtonElement, oTarget) &&
2104 oTarget != oMenuElement &&
2105 !Dom.isAncestor(oMenuElement, oTarget)) {
2109 // In IE when the user mouses down on a focusable element
2110 // that element will be focused and become the "activeElement".
2111 // (http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
2112 // However, there is a bug in IE where if there is a
2113 // positioned element with a focused descendant that is
2114 // hidden in response to the mousedown event, the target of
2115 // the mousedown event will appear to have focus, but will
2116 // not be set as the activeElement. This will result
2117 // in the element not firing key events, even though it
2118 // appears to have focus. The following call to "setActive"
2121 if (UA.ie && oTarget.focus) {
2122 oTarget.setActive();
2125 Event.removeListener(document, "mousedown",
2126 this._onDocumentMouseDown);
2135 * @description "option" event handler for the button.
2137 * @param {Event} p_oEvent Object representing the DOM event object
2138 * passed back by the event utility (YAHOO.util.Event).
2140 _onOption: function (p_oEvent) {
2142 if (this.hasClass(this.CLASS_NAME_PREFIX + "split-button-activeoption")) {
2146 this._bOptionPressed = false;
2151 this._showMenu(p_oEvent);
2153 this._bOptionPressed = true;
2161 * @method _onMenuShow
2162 * @description "show" event handler for the button's menu.
2164 * @param {String} p_sType String representing the name of the event
2167 _onMenuShow: function (p_sType) {
2169 Event.on(document, "mousedown", this._onDocumentMouseDown,
2172 var sState = (this.get("type") == "split") ? "activeoption" : "active";
2174 this.addStateCSSClasses(sState);
2180 * @method _onMenuHide
2181 * @description "hide" event handler for the button's menu.
2183 * @param {String} p_sType String representing the name of the event
2186 _onMenuHide: function (p_sType) {
2188 var sState = (this.get("type") == "split") ? "activeoption" : "active";
2190 this.removeStateCSSClasses(sState);
2193 if (this.get("type") == "split") {
2195 this._bOptionPressed = false;
2203 * @method _onMenuKeyDown
2204 * @description "keydown" event handler for the button's menu.
2206 * @param {String} p_sType String representing the name of the event
2208 * @param {Array} p_aArgs Array of arguments sent when the event
2211 _onMenuKeyDown: function (p_sType, p_aArgs) {
2213 var oEvent = p_aArgs[0];
2215 if (Event.getCharCode(oEvent) == 27) {
2219 if (this.get("type") == "split") {
2221 this._bOptionPressed = false;
2231 * @method _onMenuRender
2232 * @description "render" event handler for the button's menu.
2234 * @param {String} p_sType String representing the name of the
2235 * event thatwas fired.
2237 _onMenuRender: function (p_sType) {
2239 var oButtonElement = this.get("element"),
2240 oButtonParent = oButtonElement.parentNode,
2242 oMenuElement = oMenu.element,
2243 oSrcElement = oMenu.srcElement,
2247 if (oButtonParent != oMenuElement.parentNode) {
2249 oButtonParent.appendChild(oMenuElement);
2253 this._renderedMenu = true;
2255 // If the user has designated an <option> of the Menu's source
2256 // <select> element to be selected, sync the selectedIndex with
2257 // the "selectedMenuItem" Attribute.
2260 oSrcElement.nodeName.toLowerCase() === "select" &&
2261 oSrcElement.value) {
2264 oItem = oMenu.getItem(oSrcElement.selectedIndex);
2266 // Set the value of the "selectedMenuItem" attribute
2267 // silently since this is the initial set--synchronizing
2268 // the value of the source <SELECT> element in the DOM with
2269 // its corresponding Menu instance.
2271 this.set("selectedMenuItem", oItem, true);
2273 // Call the "_onSelectedMenuItemChange" method since the
2274 // attribute was set silently.
2276 this._onSelectedMenuItemChange({ newValue: oItem });
2285 * @method _onMenuClick
2286 * @description "click" event handler for the button's menu.
2288 * @param {String} p_sType String representing the name of the event
2290 * @param {Array} p_aArgs Array of arguments sent when the event
2293 _onMenuClick: function (p_sType, p_aArgs) {
2295 var oItem = p_aArgs[1],
2300 this.set("selectedMenuItem", oItem);
2302 oSrcElement = this.get("srcelement");
2304 if (oSrcElement && oSrcElement.type == "submit") {
2318 * @method _onSelectedMenuItemChange
2319 * @description "selectedMenuItemChange" event handler for the Button's
2320 * "selectedMenuItem" attribute.
2321 * @param {Event} event Object representing the DOM event object
2322 * passed back by the event utility (YAHOO.util.Event).
2324 _onSelectedMenuItemChange: function (event) {
2326 var oSelected = event.prevValue,
2327 oItem = event.newValue,
2328 sPrefix = this.CLASS_NAME_PREFIX;
2331 Dom.removeClass(oSelected.element, (sPrefix + "button-selectedmenuitem"));
2335 Dom.addClass(oItem.element, (sPrefix + "button-selectedmenuitem"));
2342 * @method _onLabelClick
2343 * @description "click" event handler for the Button's
2344 * <code><label></code> element.
2345 * @param {Event} event Object representing the DOM event object
2346 * passed back by the event utility (YAHOO.util.Event).
2348 _onLabelClick: function (event) {
2352 var sType = this.get("type");
2354 if (sType == "radio" || sType == "checkbox") {
2355 this.set("checked", (!this.get("checked")));
2365 * @method createButtonElement
2366 * @description Creates the button's HTML elements.
2367 * @param {String} p_sType String indicating the type of element
2369 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2370 * level-one-html.html#ID-58190037">HTMLElement</a>}
2372 createButtonElement: function (p_sType) {
2374 var sNodeName = this.NODE_NAME,
2375 oElement = document.createElement(sNodeName);
2377 oElement.innerHTML = "<" + sNodeName + " class=\"first-child\">" +
2378 (p_sType == "link" ? "<a></a>" :
2379 "<button type=\"button\"></button>") + "</" + sNodeName + ">";
2387 * @method addStateCSSClasses
2388 * @description Appends state-specific CSS classes to the button's root
2391 addStateCSSClasses: function (p_sState) {
2393 var sType = this.get("type"),
2394 sPrefix = this.CLASS_NAME_PREFIX;
2396 if (Lang.isString(p_sState)) {
2398 if (p_sState != "activeoption" && p_sState != "hoveroption") {
2400 this.addClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2404 this.addClass(sPrefix + sType + ("-button-" + p_sState));
2412 * @method removeStateCSSClasses
2413 * @description Removes state-specific CSS classes to the button's root
2416 removeStateCSSClasses: function (p_sState) {
2418 var sType = this.get("type"),
2419 sPrefix = this.CLASS_NAME_PREFIX;
2421 if (Lang.isString(p_sState)) {
2423 this.removeClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2424 this.removeClass(sPrefix + sType + ("-button-" + p_sState));
2432 * @method createHiddenFields
2433 * @description Creates the button's hidden form field and appends it
2434 * to its parent form.
2435 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2436 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
2438 createHiddenFields: function () {
2440 this.removeHiddenFields();
2442 var oForm = this.getForm(),
2454 bMenuSrcElementIsSelect = false;
2457 if (oForm && !this.get("disabled")) {
2459 sType = this.get("type");
2460 bCheckable = (sType == "checkbox" || sType == "radio");
2463 if ((bCheckable && this.get("checked")) || (m_oSubmitTrigger == this)) {
2466 oButtonField = createInputElement((bCheckable ? sType : "hidden"),
2467 this.get("name"), this.get("value"), this.get("checked"));
2474 oButtonField.style.display = "none";
2478 oForm.appendChild(oButtonField);
2488 if (Menu && oMenu && (oMenu instanceof Menu)) {
2491 oMenuItem = this.get("selectedMenuItem");
2492 oMenuSrcElement = oMenu.srcElement;
2493 bMenuSrcElementIsSelect = (oMenuSrcElement &&
2494 oMenuSrcElement.nodeName.toUpperCase() == "SELECT");
2498 oValue = (oMenuItem.value === null || oMenuItem.value === "") ?
2499 oMenuItem.cfg.getProperty("text") : oMenuItem.value;
2501 sButtonName = this.get("name");
2504 if (bMenuSrcElementIsSelect) {
2506 sMenuFieldName = oMenuSrcElement.name;
2509 else if (sButtonName) {
2511 sMenuFieldName = (sButtonName + "_options");
2516 if (oValue && sMenuFieldName) {
2518 oMenuField = createInputElement("hidden", sMenuFieldName, oValue);
2519 oForm.appendChild(oMenuField);
2524 else if (bMenuSrcElementIsSelect) {
2526 oMenuField = oForm.appendChild(oMenuSrcElement);
2533 if (oButtonField && oMenuField) {
2535 this._hiddenFields = [oButtonField, oMenuField];
2538 else if (!oButtonField && oMenuField) {
2540 this._hiddenFields = oMenuField;
2543 else if (oButtonField && !oMenuField) {
2545 this._hiddenFields = oButtonField;
2549 oReturnVal = this._hiddenFields;
2559 * @method removeHiddenFields
2560 * @description Removes the button's hidden form field(s) from its
2563 removeHiddenFields: function () {
2565 var oField = this._hiddenFields,
2569 function removeChild(p_oElement) {
2571 if (Dom.inDocument(p_oElement)) {
2573 p_oElement.parentNode.removeChild(p_oElement);
2582 if (Lang.isArray(oField)) {
2584 nFields = oField.length;
2592 removeChild(oField[i]);
2602 removeChild(oField);
2606 this._hiddenFields = null;
2614 * @method submitForm
2615 * @description Submits the form to which the button belongs. Returns
2616 * true if the form was submitted successfully, false if the submission
2621 submitForm: function () {
2623 var oForm = this.getForm(),
2625 oSrcElement = this.get("srcelement"),
2628 Boolean indicating if the event fired successfully
2629 (was not cancelled by any handlers)
2632 bSubmitForm = false,
2639 if (this.get("type") == "submit" || (oSrcElement && oSrcElement.type == "submit")) {
2641 m_oSubmitTrigger = this;
2648 bSubmitForm = oForm.fireEvent("onsubmit");
2651 else { // Gecko, Opera, and Safari
2653 oEvent = document.createEvent("HTMLEvents");
2654 oEvent.initEvent("submit", true, true);
2656 bSubmitForm = oForm.dispatchEvent(oEvent);
2662 In IE and Safari, dispatching a "submit" event to a form
2663 WILL cause the form's "submit" event to fire, but WILL NOT
2664 submit the form. Therefore, we need to call the "submit"
2668 if ((UA.ie || UA.webkit) && bSubmitForm) {
2683 * @description The Button class's initialization method.
2684 * @param {String} p_oElement String specifying the id attribute of the
2685 * <code><input></code>, <code><button></code>,
2686 * <code><a></code>, or <code><span></code> element to
2687 * be used to create the button.
2688 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2689 * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://
2690 * www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
2691 * #ID-34812697">HTMLButtonElement</a>|<a href="http://www.w3.org/TR
2692 * /2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-33759296">
2693 * HTMLElement</a>} p_oElement Object reference for the
2694 * <code><input></code>, <code><button></code>,
2695 * <code><a></code>, or <code><span></code> element to be
2696 * used to create the button.
2697 * @param {Object} p_oElement Object literal specifying a set of
2698 * configuration attributes used to create the button.
2699 * @param {Object} p_oAttributes Optional. Object literal specifying a
2700 * set of configuration attributes used to create the button.
2702 init: function (p_oElement, p_oAttributes) {
2704 var sNodeName = p_oAttributes.type == "link" ? "a" : "button",
2705 oSrcElement = p_oAttributes.srcelement,
2706 oButton = p_oElement.getElementsByTagName(sNodeName)[0],
2712 oInput = p_oElement.getElementsByTagName("input")[0];
2717 oButton = document.createElement("button");
2718 oButton.setAttribute("type", "button");
2720 oInput.parentNode.replaceChild(oButton, oInput);
2726 this._button = oButton;
2729 YAHOO.widget.Button.superclass.init.call(this, p_oElement, p_oAttributes);
2732 var sId = this.get("id"),
2733 sButtonId = sId + "-button";
2736 oButton.id = sButtonId;
2743 var hasLabel = function (element) {
2745 return (element.htmlFor === sId);
2750 var setLabel = function () {
2752 oLabel.setAttribute((UA.ie ? "htmlFor" : "for"), sButtonId);
2757 if (oSrcElement && this.get("type") != "link") {
2759 aLabels = Dom.getElementsBy(hasLabel, "label");
2761 if (Lang.isArray(aLabels) && aLabels.length > 0) {
2763 oLabel = aLabels[0];
2770 m_oButtons[sId] = this;
2772 var sPrefix = this.CLASS_NAME_PREFIX;
2774 this.addClass(sPrefix + this.CSS_CLASS_NAME);
2775 this.addClass(sPrefix + this.get("type") + "-button");
2777 Event.on(this._button, "focus", this._onFocus, null, this);
2778 this.on("mouseover", this._onMouseOver);
2779 this.on("mousedown", this._onMouseDown);
2780 this.on("mouseup", this._onMouseUp);
2781 this.on("click", this._onClick);
2783 // Need to reset the value of the "onclick" Attribute so that any
2784 // handlers registered via the "onclick" Attribute are fired after
2785 // Button's default "_onClick" listener.
2787 var fnOnClick = this.get("onclick");
2789 this.set("onclick", null);
2790 this.set("onclick", fnOnClick);
2792 this.on("dblclick", this._onDblClick);
2799 if (this.get("replaceLabel")) {
2801 this.set("label", oLabel.innerHTML);
2803 oParentNode = oLabel.parentNode;
2805 oParentNode.removeChild(oLabel);
2810 this.on("appendTo", setLabel);
2812 Event.on(oLabel, "click", this._onLabelClick, null, this);
2814 this._label = oLabel;
2820 this.on("appendTo", this._onAppendTo);
2824 var oContainer = this.get("container"),
2825 oElement = this.get("element"),
2826 bElInDoc = Dom.inDocument(oElement);
2831 if (oSrcElement && oSrcElement != oElement) {
2833 oParentNode = oSrcElement.parentNode;
2837 oParentNode.removeChild(oSrcElement);
2843 if (Lang.isString(oContainer)) {
2845 Event.onContentReady(oContainer, this.appendTo, oContainer, this);
2850 this.on("init", function () {
2852 Lang.later(0, this, this.appendTo, oContainer);
2859 else if (!bElInDoc && oSrcElement && oSrcElement != oElement) {
2861 oParentNode = oSrcElement.parentNode;
2865 this.fireEvent("beforeAppendTo", {
2866 type: "beforeAppendTo",
2870 oParentNode.replaceChild(oElement, oSrcElement);
2872 this.fireEvent("appendTo", {
2880 else if (this.get("type") != "link" && bElInDoc && oSrcElement &&
2881 oSrcElement == oElement) {
2883 this._addListenersToForm();
2889 this.fireEvent("init", {
2898 * @method initAttributes
2899 * @description Initializes all of the configuration attributes used to
2900 * create the button.
2901 * @param {Object} p_oAttributes Object literal specifying a set of
2902 * configuration attributes used to create the button.
2904 initAttributes: function (p_oAttributes) {
2906 var oAttributes = p_oAttributes || {};
2908 YAHOO.widget.Button.superclass.initAttributes.call(this,
2914 * @description String specifying the button's type. Possible
2915 * values are: "push," "link," "submit," "reset," "checkbox,"
2916 * "radio," "menu," and "split."
2921 this.setAttributeConfig("type", {
2923 value: (oAttributes.type || "push"),
2924 validator: Lang.isString,
2926 method: this._setType
2933 * @description String specifying the button's text label
2938 this.setAttributeConfig("label", {
2940 value: oAttributes.label,
2941 validator: Lang.isString,
2942 method: this._setLabel
2949 * @description Object specifying the value for the button.
2953 this.setAttributeConfig("value", {
2955 value: oAttributes.value
2962 * @description String specifying the name for the button.
2966 this.setAttributeConfig("name", {
2968 value: oAttributes.name,
2969 validator: Lang.isString
2975 * @attribute tabindex
2976 * @description Number specifying the tabindex for the button.
2980 this.setAttributeConfig("tabindex", {
2982 value: oAttributes.tabindex,
2983 validator: Lang.isNumber,
2984 method: this._setTabIndex
2991 * @description String specifying the title for the button.
2995 this.configureAttribute("title", {
2997 value: oAttributes.title,
2998 validator: Lang.isString,
2999 method: this._setTitle
3005 * @attribute disabled
3006 * @description Boolean indicating if the button should be disabled.
3007 * (Disabled buttons are dimmed and will not respond to user input
3008 * or fire events. Does not apply to button's of type "link.")
3012 this.setAttributeConfig("disabled", {
3014 value: (oAttributes.disabled || false),
3015 validator: Lang.isBoolean,
3016 method: this._setDisabled
3023 * @description String specifying the href for the button. Applies
3024 * only to buttons of type "link."
3027 this.setAttributeConfig("href", {
3029 value: oAttributes.href,
3030 validator: Lang.isString,
3031 method: this._setHref
3038 * @description String specifying the target for the button.
3039 * Applies only to buttons of type "link."
3042 this.setAttributeConfig("target", {
3044 value: oAttributes.target,
3045 validator: Lang.isString,
3046 method: this._setTarget
3052 * @attribute checked
3053 * @description Boolean indicating if the button is checked.
3054 * Applies only to buttons of type "radio" and "checkbox."
3058 this.setAttributeConfig("checked", {
3060 value: (oAttributes.checked || false),
3061 validator: Lang.isBoolean,
3062 method: this._setChecked
3068 * @attribute container
3069 * @description HTML element reference or string specifying the id
3070 * attribute of the HTML element that the button's markup should be
3072 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3073 * level-one-html.html#ID-58190037">HTMLElement</a>|String
3077 this.setAttributeConfig("container", {
3079 value: oAttributes.container,
3086 * @attribute srcelement
3087 * @description Object reference to the HTML element (either
3088 * <code><input></code> or <code><span></code>)
3089 * used to create the button.
3090 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3091 * level-one-html.html#ID-58190037">HTMLElement</a>|String
3095 this.setAttributeConfig("srcelement", {
3097 value: oAttributes.srcelement,
3105 * @description Object specifying the menu for the button.
3106 * The value can be one of the following:
3108 * <li>Object specifying a rendered <a href="YAHOO.widget.Menu.html">
3109 * YAHOO.widget.Menu</a> instance.</li>
3110 * <li>Object specifying a rendered <a href="YAHOO.widget.Overlay.html">
3111 * YAHOO.widget.Overlay</a> instance.</li>
3112 * <li>String specifying the id attribute of the <code><div>
3113 * </code> element used to create the menu. By default the menu
3114 * will be created as an instance of
3115 * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>.
3116 * If the <a href="YAHOO.widget.Menu.html#CSS_CLASS_NAME">
3117 * default CSS class name for YAHOO.widget.Menu</a> is applied to
3118 * the <code><div></code> element, it will be created as an
3119 * instance of <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu
3120 * </a>.</li><li>String specifying the id attribute of the
3121 * <code><select></code> element used to create the menu.
3122 * </li><li>Object specifying the <code><div></code> element
3123 * used to create the menu.</li>
3124 * <li>Object specifying the <code><select></code> element
3125 * used to create the menu.</li>
3126 * <li>Array of object literals, each representing a set of
3127 * <a href="YAHOO.widget.MenuItem.html">YAHOO.widget.MenuItem</a>
3128 * configuration attributes.</li>
3129 * <li>Array of strings representing the text labels for each menu
3130 * item in the menu.</li>
3132 * @type <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>|<a
3133 * href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|<a
3134 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3135 * one-html.html#ID-58190037">HTMLElement</a>|String|Array
3139 this.setAttributeConfig("menu", {
3142 method: this._setMenu,
3149 * @attribute lazyloadmenu
3150 * @description Boolean indicating the value to set for the
3151 * <a href="YAHOO.widget.Menu.html#lazyLoad">"lazyload"</a>
3152 * configuration property of the button's menu. Setting
3153 * "lazyloadmenu" to <code>true </code> will defer rendering of
3154 * the button's menu until the first time it is made visible.
3155 * If "lazyloadmenu" is set to <code>false</code>, the button's
3156 * menu will be rendered immediately if the button is in the
3157 * document, or in response to the button's "appendTo" event if
3158 * the button is not yet in the document. In either case, the
3159 * menu is rendered into the button's parent HTML element.
3160 * <em>This attribute does not apply if a
3161 * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a> or
3162 * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>
3163 * instance is passed as the value of the button's "menu"
3164 * configuration attribute. <a href="YAHOO.widget.Menu.html">
3165 * YAHOO.widget.Menu</a> or <a href="YAHOO.widget.Overlay.html">
3166 * YAHOO.widget.Overlay</a> instances should be rendered before
3167 * being set as the value for the "menu" configuration
3173 this.setAttributeConfig("lazyloadmenu", {
3175 value: (oAttributes.lazyloadmenu === false ? false : true),
3176 validator: Lang.isBoolean,
3183 * @attribute menuclassname
3184 * @description String representing the CSS class name to be
3185 * applied to the root element of the button's menu.
3187 * @default "yui-button-menu"
3190 this.setAttributeConfig("menuclassname", {
3192 value: (oAttributes.menuclassname || (this.CLASS_NAME_PREFIX + "button-menu")),
3193 validator: Lang.isString,
3194 method: this._setMenuClassName,
3201 * @attribute menuminscrollheight
3202 * @description Number defining the minimum threshold for the "menumaxheight"
3203 * configuration attribute. When set this attribute is automatically applied
3208 this.setAttributeConfig("menuminscrollheight", {
3210 value: (oAttributes.menuminscrollheight || 90),
3211 validator: Lang.isNumber
3217 * @attribute menumaxheight
3218 * @description Number defining the maximum height (in pixels) for a menu's
3219 * body element (<code><div class="bd"<</code>). Once a menu's body
3220 * exceeds this height, the contents of the body are scrolled to maintain
3221 * this value. This value cannot be set lower than the value of the
3222 * "minscrollheight" configuration property.
3226 this.setAttributeConfig("menumaxheight", {
3228 value: (oAttributes.menumaxheight || 0),
3229 validator: Lang.isNumber
3235 * @attribute menualignment
3236 * @description Array defining how the Button's Menu is aligned to the Button.
3237 * The default value of ["tl", "bl"] aligns the Menu's top left corner to the Button's
3238 * bottom left corner.
3240 * @default ["tl", "bl"]
3242 this.setAttributeConfig("menualignment", {
3244 value: (oAttributes.menualignment || ["tl", "bl"]),
3245 validator: Lang.isArray
3251 * @attribute selectedMenuItem
3252 * @description Object representing the item in the button's menu
3253 * that is currently selected.
3254 * @type YAHOO.widget.MenuItem
3257 this.setAttributeConfig("selectedMenuItem", {
3265 * @attribute onclick
3266 * @description Object literal representing the code to be executed
3267 * when the button is clicked. Format:<br> <code> {<br>
3268 * <strong>fn:</strong> Function, // The handler to call
3269 * when the event fires.<br> <strong>obj:</strong> Object,
3270 * // An object to pass back to the handler.<br>
3271 * <strong>scope:</strong> Object // The object to use
3272 * for the scope of the handler.<br> } </code>
3276 this.setAttributeConfig("onclick", {
3278 value: oAttributes.onclick,
3279 method: this._setOnClick
3285 * @attribute focusmenu
3286 * @description Boolean indicating whether or not the button's menu
3287 * should be focused when it is made visible.
3291 this.setAttributeConfig("focusmenu", {
3293 value: (oAttributes.focusmenu === false ? false : true),
3294 validator: Lang.isBoolean
3300 * @attribute replaceLabel
3301 * @description Boolean indicating whether or not the text of the
3302 * button's <code><label></code> element should be used as
3303 * the source for the button's label configuration attribute and
3304 * removed from the DOM.
3308 this.setAttributeConfig("replaceLabel", {
3311 validator: Lang.isBoolean,
3321 * @description Causes the button to receive the focus and fires the
3322 * button's "focus" event.
3324 focus: function () {
3326 if (!this.get("disabled")) {
3328 this._button.focus();
3337 * @description Causes the button to lose focus and fires the button's
3342 if (!this.get("disabled")) {
3344 this._button.blur();
3353 * @description Returns a boolean indicating whether or not the button
3357 hasFocus: function () {
3359 return (m_oFocusedButton == this);
3366 * @description Returns a boolean indicating whether or not the button
3370 isActive: function () {
3372 return this.hasClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME + "-active");
3379 * @description Returns a reference to the button's menu.
3380 * @return {<a href="YAHOO.widget.Overlay.html">
3381 * YAHOO.widget.Overlay</a>|<a
3382 * href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
3384 getMenu: function () {
3393 * @description Returns a reference to the button's parent form.
3394 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-
3395 * 20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>}
3397 getForm: function () {
3399 var oButton = this._button,
3404 oForm = oButton.form;
3414 * @method getHiddenFields
3415 * @description Returns an <code><input></code> element or
3416 * array of form elements used to represent the button when its parent
3417 * form is submitted.
3418 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3419 * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
3421 getHiddenFields: function () {
3423 return this._hiddenFields;
3430 * @description Removes the button's element from its parent element and
3431 * removes all event handlers.
3433 destroy: function () {
3436 var oElement = this.get("element"),
3438 oLabel = this._label,
3445 if (m_oOverlayManager && m_oOverlayManager.find(oMenu)) {
3447 m_oOverlayManager.remove(oMenu);
3456 Event.purgeElement(oElement);
3457 Event.purgeElement(this._button);
3458 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
3459 Event.removeListener(document, "keyup", this._onDocumentKeyUp);
3460 Event.removeListener(document, "mousedown", this._onDocumentMouseDown);
3465 Event.removeListener(oLabel, "click", this._onLabelClick);
3467 oParentNode = oLabel.parentNode;
3468 oParentNode.removeChild(oLabel);
3473 var oForm = this.getForm();
3477 Event.removeListener(oForm, "reset", this._onFormReset);
3478 Event.removeListener(oForm, "submit", this._onFormSubmit);
3483 this.unsubscribeAll();
3485 oParentNode = oElement.parentNode;
3489 oParentNode.removeChild(oElement);
3494 delete m_oButtons[this.get("id")];
3496 var sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
3498 aButtons = Dom.getElementsByClassName(sClass,
3499 this.NODE_NAME, oForm);
3501 if (Lang.isArray(aButtons) && aButtons.length === 0) {
3503 Event.removeListener(oForm, "keypress",
3504 YAHOO.widget.Button.onFormKeyPress);
3512 fireEvent: function (p_sType , p_aArgs) {
3514 var sType = arguments[0];
3516 // Disabled buttons should not respond to DOM events
3518 if (this.DOM_EVENTS[sType] && this.get("disabled")) {
3524 return YAHOO.widget.Button.superclass.fireEvent.apply(this, arguments);
3531 * @description Returns a string representing the button.
3534 toString: function () {
3536 return ("Button " + this.get("id"));
3544 * @method YAHOO.widget.Button.onFormKeyPress
3545 * @description "keypress" event handler for the button's form.
3546 * @param {Event} p_oEvent Object representing the DOM event object passed
3547 * back by the event utility (YAHOO.util.Event).
3549 YAHOO.widget.Button.onFormKeyPress = function (p_oEvent) {
3551 var oTarget = Event.getTarget(p_oEvent),
3552 nCharCode = Event.getCharCode(p_oEvent),
3553 sNodeName = oTarget.nodeName && oTarget.nodeName.toUpperCase(),
3554 sType = oTarget.type,
3557 Boolean indicating if the form contains any enabled or
3558 disabled YUI submit buttons
3561 bFormContainsYUIButtons = false,
3565 oYUISubmitButton, // The form's first, enabled YUI submit button
3568 The form's first, enabled HTML submit button that precedes any
3572 oPrecedingSubmitButton,
3577 function isSubmitButton(p_oElement) {
3582 switch (p_oElement.nodeName.toUpperCase()) {
3587 if (p_oElement.type == "submit" && !p_oElement.disabled) {
3589 if (!bFormContainsYUIButtons && !oPrecedingSubmitButton) {
3591 oPrecedingSubmitButton = p_oElement;
3602 sId = p_oElement.id;
3606 oButton = m_oButtons[sId];
3610 bFormContainsYUIButtons = true;
3612 if (!oButton.get("disabled")) {
3614 oSrcElement = oButton.get("srcelement");
3616 if (!oYUISubmitButton && (oButton.get("type") == "submit" ||
3617 (oSrcElement && oSrcElement.type == "submit"))) {
3619 oYUISubmitButton = oButton;
3636 if (nCharCode == 13 && ((sNodeName == "INPUT" && (sType == "text" ||
3637 sType == "password" || sType == "checkbox" || sType == "radio" ||
3638 sType == "file")) || sNodeName == "SELECT")) {
3640 Dom.getElementsBy(isSubmitButton, "*", this);
3643 if (oPrecedingSubmitButton) {
3646 Need to set focus to the first enabled submit button
3647 to make sure that IE includes its name and value
3648 in the form's data set.
3651 oPrecedingSubmitButton.focus();
3654 else if (!oPrecedingSubmitButton && oYUISubmitButton) {
3657 Need to call "preventDefault" to ensure that the form doesn't end up getting
3661 Event.preventDefault(p_oEvent);
3666 oYUISubmitButton.get("element").fireEvent("onclick");
3671 oEvent = document.createEvent("HTMLEvents");
3672 oEvent.initEvent("click", true, true);
3675 if (UA.gecko < 1.9) {
3677 oYUISubmitButton.fireEvent("click", oEvent);
3682 oYUISubmitButton.get("element").dispatchEvent(oEvent);
3696 * @method YAHOO.widget.Button.addHiddenFieldsToForm
3697 * @description Searches the specified form and adds hidden fields for
3698 * instances of YAHOO.widget.Button that are of type "radio," "checkbox,"
3699 * "menu," and "split."
3700 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3701 * one-html.html#ID-40002357">HTMLFormElement</a>} p_oForm Object reference
3702 * for the form to search.
3704 YAHOO.widget.Button.addHiddenFieldsToForm = function (p_oForm) {
3706 var proto = YAHOO.widget.Button.prototype,
3707 aButtons = Dom.getElementsByClassName(
3708 (proto.CLASS_NAME_PREFIX + proto.CSS_CLASS_NAME),
3712 nButtons = aButtons.length,
3720 for (i = 0; i < nButtons; i++) {
3722 sId = aButtons[i].id;
3726 oButton = m_oButtons[sId];
3730 oButton.createHiddenFields();
3744 * @method YAHOO.widget.Button.getButton
3745 * @description Returns a button with the specified id.
3746 * @param {String} p_sId String specifying the id of the root node of the
3747 * HTML element representing the button to be retrieved.
3748 * @return {YAHOO.widget.Button}
3750 YAHOO.widget.Button.getButton = function (p_sId) {
3752 return m_oButtons[p_sId];
3762 * @description Fires when the menu item receives focus. Passes back a
3763 * single object representing the original DOM event object passed back by
3764 * the event utility (YAHOO.util.Event) when the event was fired. See
3765 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a>
3766 * for more information on listening for this event.
3767 * @type YAHOO.util.CustomEvent
3773 * @description Fires when the menu item loses the input focus. Passes back
3774 * a single object representing the original DOM event object passed back by
3775 * the event utility (YAHOO.util.Event) when the event was fired. See
3776 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for
3777 * more information on listening for this event.
3778 * @type YAHOO.util.CustomEvent
3784 * @description Fires when the user invokes the button's option. Passes
3785 * back a single object representing the original DOM event (either
3786 * "mousedown" or "keydown") that caused the "option" event to fire. See
3787 * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a>
3788 * for more information on listening for this event.
3789 * @type YAHOO.util.CustomEvent
3795 // Shorthard for utilities
3797 var Dom = YAHOO.util.Dom,
3798 Event = YAHOO.util.Event,
3800 Button = YAHOO.widget.Button,
3802 // Private collection of radio buttons
3809 * The ButtonGroup class creates a set of buttons that are mutually
3810 * exclusive; checking one button in the set will uncheck all others in the
3812 * @param {String} p_oElement String specifying the id attribute of the
3813 * <code><div></code> element of the button group.
3814 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3815 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
3816 * specifying the <code><div></code> element of the button group.
3817 * @param {Object} p_oElement Object literal specifying a set of
3818 * configuration attributes used to create the button group.
3819 * @param {Object} p_oAttributes Optional. Object literal specifying a set
3820 * of configuration attributes used to create the button group.
3821 * @namespace YAHOO.widget
3822 * @class ButtonGroup
3824 * @extends YAHOO.util.Element
3826 YAHOO.widget.ButtonGroup = function (p_oElement, p_oAttributes) {
3828 var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor,
3833 if (arguments.length == 1 && !Lang.isString(p_oElement) &&
3834 !p_oElement.nodeName) {
3836 if (!p_oElement.id) {
3838 sId = Dom.generateId();
3840 p_oElement.id = sId;
3847 fnSuperClass.call(this, (this._createGroupElement()), p_oElement);
3850 else if (Lang.isString(p_oElement)) {
3852 oElement = Dom.get(p_oElement);
3856 if (oElement.nodeName.toUpperCase() == this.NODE_NAME) {
3859 fnSuperClass.call(this, oElement, p_oAttributes);
3868 sNodeName = p_oElement.nodeName.toUpperCase();
3870 if (sNodeName && sNodeName == this.NODE_NAME) {
3872 if (!p_oElement.id) {
3874 p_oElement.id = Dom.generateId();
3880 fnSuperClass.call(this, p_oElement, p_oAttributes);
3889 YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {
3892 // Protected properties
3896 * @property _buttons
3897 * @description Array of buttons in the button group.
3910 * @property NODE_NAME
3911 * @description The name of the tag to be used for the button
3921 * @property CLASS_NAME_PREFIX
3922 * @description Prefix used for all class names applied to a ButtonGroup.
3927 CLASS_NAME_PREFIX: "yui-",
3931 * @property CSS_CLASS_NAME
3932 * @description String representing the CSS class(es) to be applied
3933 * to the button group's element.
3934 * @default "buttongroup"
3938 CSS_CLASS_NAME: "buttongroup",
3942 // Protected methods
3946 * @method _createGroupElement
3947 * @description Creates the button group's element.
3949 * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3950 * level-one-html.html#ID-22445964">HTMLDivElement</a>}
3952 _createGroupElement: function () {
3954 var oElement = document.createElement(this.NODE_NAME);
3962 // Protected attribute setter methods
3966 * @method _setDisabled
3967 * @description Sets the value of the button groups's
3968 * "disabled" attribute.
3970 * @param {Boolean} p_bDisabled Boolean indicating the value for
3971 * the button group's "disabled" attribute.
3973 _setDisabled: function (p_bDisabled) {
3975 var nButtons = this.getCount(),
3984 this._buttons[i].set("disabled", p_bDisabled);
3995 // Protected event handlers
3999 * @method _onKeyDown
4000 * @description "keydown" event handler for the button group.
4002 * @param {Event} p_oEvent Object representing the DOM event object
4003 * passed back by the event utility (YAHOO.util.Event).
4005 _onKeyDown: function (p_oEvent) {
4007 var oTarget = Event.getTarget(p_oEvent),
4008 nCharCode = Event.getCharCode(p_oEvent),
4009 sId = oTarget.parentNode.parentNode.id,
4010 oButton = m_oButtons[sId],
4014 if (nCharCode == 37 || nCharCode == 38) {
4016 nIndex = (oButton.index === 0) ?
4017 (this._buttons.length - 1) : (oButton.index - 1);
4020 else if (nCharCode == 39 || nCharCode == 40) {
4022 nIndex = (oButton.index === (this._buttons.length - 1)) ?
4023 0 : (oButton.index + 1);
4031 this.getButton(nIndex).focus();
4039 * @method _onAppendTo
4040 * @description "appendTo" event handler for the button group.
4042 * @param {Event} p_oEvent Object representing the event that was fired.
4044 _onAppendTo: function (p_oEvent) {
4046 var aButtons = this._buttons,
4047 nButtons = aButtons.length,
4050 for (i = 0; i < nButtons; i++) {
4052 aButtons[i].appendTo(this.get("element"));
4060 * @method _onButtonCheckedChange
4061 * @description "checkedChange" event handler for each button in the
4064 * @param {Event} p_oEvent Object representing the event that was fired.
4065 * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4066 * p_oButton Object representing the button that fired the event.
4068 _onButtonCheckedChange: function (p_oEvent, p_oButton) {
4070 var bChecked = p_oEvent.newValue,
4071 oCheckedButton = this.get("checkedButton");
4073 if (bChecked && oCheckedButton != p_oButton) {
4075 if (oCheckedButton) {
4077 oCheckedButton.set("checked", false, true);
4081 this.set("checkedButton", p_oButton);
4082 this.set("value", p_oButton.get("value"));
4085 else if (oCheckedButton && !oCheckedButton.set("checked")) {
4087 oCheckedButton.set("checked", true, true);
4100 * @description The ButtonGroup class's initialization method.
4101 * @param {String} p_oElement String specifying the id attribute of the
4102 * <code><div></code> element of the button group.
4103 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4104 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
4105 * specifying the <code><div></code> element of the button group.
4106 * @param {Object} p_oElement Object literal specifying a set of
4107 * configuration attributes used to create the button group.
4108 * @param {Object} p_oAttributes Optional. Object literal specifying a
4109 * set of configuration attributes used to create the button group.
4111 init: function (p_oElement, p_oAttributes) {
4115 YAHOO.widget.ButtonGroup.superclass.init.call(this, p_oElement,
4118 this.addClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
4121 var sClass = (YAHOO.widget.Button.prototype.CLASS_NAME_PREFIX + "radio-button"),
4122 aButtons = this.getElementsByClassName(sClass);
4126 if (aButtons.length > 0) {
4129 this.addButtons(aButtons);
4135 function isRadioButton(p_oElement) {
4137 return (p_oElement.type == "radio");
4142 Dom.getElementsBy(isRadioButton, "input", this.get("element"));
4145 if (aButtons.length > 0) {
4148 this.addButtons(aButtons);
4152 this.on("keydown", this._onKeyDown);
4153 this.on("appendTo", this._onAppendTo);
4156 var oContainer = this.get("container");
4160 if (Lang.isString(oContainer)) {
4162 Event.onContentReady(oContainer, function () {
4164 this.appendTo(oContainer);
4171 this.appendTo(oContainer);
4183 * @method initAttributes
4184 * @description Initializes all of the configuration attributes used to
4185 * create the button group.
4186 * @param {Object} p_oAttributes Object literal specifying a set of
4187 * configuration attributes used to create the button group.
4189 initAttributes: function (p_oAttributes) {
4191 var oAttributes = p_oAttributes || {};
4193 YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
4199 * @description String specifying the name for the button group.
4200 * This name will be applied to each button in the button group.
4204 this.setAttributeConfig("name", {
4206 value: oAttributes.name,
4207 validator: Lang.isString
4213 * @attribute disabled
4214 * @description Boolean indicating if the button group should be
4215 * disabled. Disabling the button group will disable each button
4216 * in the button group. Disabled buttons are dimmed and will not
4217 * respond to user input or fire events.
4221 this.setAttributeConfig("disabled", {
4223 value: (oAttributes.disabled || false),
4224 validator: Lang.isBoolean,
4225 method: this._setDisabled
4232 * @description Object specifying the value for the button group.
4236 this.setAttributeConfig("value", {
4238 value: oAttributes.value
4244 * @attribute container
4245 * @description HTML element reference or string specifying the id
4246 * attribute of the HTML element that the button group's markup
4247 * should be rendered into.
4248 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4249 * level-one-html.html#ID-58190037">HTMLElement</a>|String
4253 this.setAttributeConfig("container", {
4255 value: oAttributes.container,
4262 * @attribute checkedButton
4263 * @description Reference for the button in the button group that
4265 * @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4268 this.setAttributeConfig("checkedButton", {
4279 * @description Adds the button to the button group.
4280 * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4281 * p_oButton Object reference for the <a href="YAHOO.widget.Button.html">
4282 * YAHOO.widget.Button</a> instance to be added to the button group.
4283 * @param {String} p_oButton String specifying the id attribute of the
4284 * <code><input></code> or <code><span></code> element
4285 * to be used to create the button to be added to the button group.
4286 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4287 * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
4288 * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
4289 * ID-33759296">HTMLElement</a>} p_oButton Object reference for the
4290 * <code><input></code> or <code><span></code> element
4291 * to be used to create the button to be added to the button group.
4292 * @param {Object} p_oButton Object literal specifying a set of
4293 * <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>
4294 * configuration attributes used to configure the button to be added to
4296 * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4298 addButton: function (p_oButton) {
4308 if (p_oButton instanceof Button &&
4309 p_oButton.get("type") == "radio") {
4311 oButton = p_oButton;
4314 else if (!Lang.isString(p_oButton) && !p_oButton.nodeName) {
4316 p_oButton.type = "radio";
4318 oButton = new Button(p_oButton);
4323 oButton = new Button(p_oButton, { type: "radio" });
4330 nIndex = this._buttons.length;
4331 sButtonName = oButton.get("name");
4332 sGroupName = this.get("name");
4334 oButton.index = nIndex;
4336 this._buttons[nIndex] = oButton;
4337 m_oButtons[oButton.get("id")] = oButton;
4340 if (sButtonName != sGroupName) {
4342 oButton.set("name", sGroupName);
4347 if (this.get("disabled")) {
4349 oButton.set("disabled", true);
4354 if (oButton.get("checked")) {
4356 this.set("checkedButton", oButton);
4361 oButtonElement = oButton.get("element");
4362 oGroupElement = this.get("element");
4364 if (oButtonElement.parentNode != oGroupElement) {
4366 oGroupElement.appendChild(oButtonElement);
4371 oButton.on("checkedChange",
4372 this._onButtonCheckedChange, oButton, this);
4383 * @method addButtons
4384 * @description Adds the array of buttons to the button group.
4385 * @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
4386 * YAHOO.widget.Button</a> instances to be added
4387 * to the button group.
4388 * @param {Array} p_aButtons Array of strings specifying the id
4389 * attribute of the <code><input></code> or <code><span>
4390 * </code> elements to be used to create the buttons to be added to the
4392 * @param {Array} p_aButtons Array of object references for the
4393 * <code><input></code> or <code><span></code> elements
4394 * to be used to create the buttons to be added to the button group.
4395 * @param {Array} p_aButtons Array of object literals, each containing
4396 * a set of <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>
4397 * configuration attributes used to configure each button to be added
4398 * to the button group.
4401 addButtons: function (p_aButtons) {
4408 if (Lang.isArray(p_aButtons)) {
4410 nButtons = p_aButtons.length;
4415 for (i = 0; i < nButtons; i++) {
4417 oButton = this.addButton(p_aButtons[i]);
4421 aButtons[aButtons.length] = oButton;
4437 * @method removeButton
4438 * @description Removes the button at the specified index from the
4440 * @param {Number} p_nIndex Number specifying the index of the button
4441 * to be removed from the button group.
4443 removeButton: function (p_nIndex) {
4445 var oButton = this.getButton(p_nIndex),
4452 this._buttons.splice(p_nIndex, 1);
4453 delete m_oButtons[oButton.get("id")];
4455 oButton.removeListener("checkedChange",
4456 this._onButtonCheckedChange);
4461 nButtons = this._buttons.length;
4465 i = this._buttons.length - 1;
4469 this._buttons[i].index = i;
4484 * @description Returns the button at the specified index.
4485 * @param {Number} p_nIndex The index of the button to retrieve from the
4487 * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4489 getButton: function (p_nIndex) {
4491 return this._buttons[p_nIndex];
4497 * @method getButtons
4498 * @description Returns an array of the buttons in the button group.
4501 getButtons: function () {
4503 return this._buttons;
4510 * @description Returns the number of buttons in the button group.
4513 getCount: function () {
4515 return this._buttons.length;
4522 * @description Sets focus to the button at the specified index.
4523 * @param {Number} p_nIndex Number indicating the index of the button
4526 focus: function (p_nIndex) {
4532 if (Lang.isNumber(p_nIndex)) {
4534 oButton = this._buttons[p_nIndex];
4545 nButtons = this.getCount();
4547 for (i = 0; i < nButtons; i++) {
4549 oButton = this._buttons[i];
4551 if (!oButton.get("disabled")) {
4567 * @description Checks the button at the specified index.
4568 * @param {Number} p_nIndex Number indicating the index of the button
4571 check: function (p_nIndex) {
4573 var oButton = this.getButton(p_nIndex);
4577 oButton.set("checked", true);
4586 * @description Removes the button group's element from its parent
4587 * element and removes all event handlers.
4589 destroy: function () {
4592 var nButtons = this._buttons.length,
4593 oElement = this.get("element"),
4594 oParentNode = oElement.parentNode,
4599 i = this._buttons.length - 1;
4603 this._buttons[i].destroy();
4611 Event.purgeElement(oElement);
4614 oParentNode.removeChild(oElement);
4621 * @description Returns a string representing the button group.
4624 toString: function () {
4626 return ("ButtonGroup " + this.get("id"));
4633 YAHOO.register("button", YAHOO.widget.Button, {version: "2.8.0r4", build: "2449"});