]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/yui/build/button/button.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / yui / build / button / button.js
1 /*
2 Copyright (c) 2011, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 2.9.0
6 */
7 /**
8 * @module button
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>
19 * <dl>
20 * <dt>push</dt>
21 * <dd>Basic push button that can execute a user-specified command when 
22 * pressed.</dd>
23 * <dt>link</dt>
24 * <dd>Navigates to a specified url when pressed.</dd>
25 * <dt>submit</dt>
26 * <dd>Submits the parent form when pressed.</dd>
27 * <dt>reset</dt>
28 * <dd>Resets the parent form when pressed.</dd>
29 * <dt>checkbox</dt>
30 * <dd>Maintains a "checked" state that can be toggled on and off.</dd>
31 * <dt>radio</dt>
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 
35 * the group.</dd>
36 * <dt>menu</dt>
37 * <dd>When pressed will show/hide a menu.</dd>
38 * <dt>split</dt>
39 * <dd>Can execute a user-specified command or display a menu when pressed.</dd>
40 * </dl>
41 * @title Button
42 * @namespace YAHOO.widget
43 * @requires yahoo, dom, element, event
44 * @optional container, menu
45 */
46
47
48 (function () {
49
50
51     /**
52     * The Button class creates a rich, graphical button.
53     * @param {String} p_oElement String specifying the id attribute of the 
54     * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
55     * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</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>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
64     * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</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
71     * @class Button
72     * @constructor
73     * @extends YAHOO.util.Element
74     */
75
76
77
78     // Shorthard for utilities
79
80     var Dom = YAHOO.util.Dom,
81         Event = YAHOO.util.Event,
82         Lang = YAHOO.lang,
83         UA = YAHOO.env.ua,
84         Overlay = YAHOO.widget.Overlay,
85         Menu = YAHOO.widget.Menu,
86     
87     
88         // Private member variables
89     
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
94
95
96
97     // Private methods
98
99     
100     
101     /**
102     * @method createInputElement
103     * @description Creates an <code>&#60;input&#62;</code> element of the 
104     * specified type.
105     * @private
106     * @param {String} p_sType String specifying the type of 
107     * <code>&#60;input&#62;</code> element to create.
108     * @param {String} p_sName String specifying the name of 
109     * <code>&#60;input&#62;</code> element to create.
110     * @param {String} p_sValue String specifying the value of 
111     * <code>&#60;input&#62;</code> element to create.
112     * @param {String} p_bChecked Boolean specifying if the  
113     * <code>&#60;input&#62;</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>}
116     */
117     function createInputElement(p_sType, p_sName, p_sValue, p_bChecked) {
118     
119         var oInput,
120             sInput;
121     
122         if (Lang.isString(p_sType) && Lang.isString(p_sName)) {
123         
124             if (UA.ie && (UA.ie < 9)) {
125         
126                 /*
127                     For IE it is necessary to create the element with the 
128                     "type," "name," "value," and "checked" properties set all 
129                     at once.
130                 */
131             
132                 sInput = "<input type=\"" + p_sType + "\" name=\"" + 
133                     p_sName + "\"";
134         
135                 if (p_bChecked) {
136         
137                     sInput += " checked";
138                 
139                 }
140                 
141                 sInput += ">";
142         
143                 oInput = document.createElement(sInput);
144         
145                 oInput.value = p_sValue;
146
147             } else {
148             
149                 oInput = document.createElement("input");
150                 oInput.name = p_sName;
151                 oInput.type = p_sType;
152                 oInput.value = p_sValue;
153         
154                 if (p_bChecked) {
155         
156                     oInput.checked = true;
157                 
158                 }
159         
160             }
161         
162         
163         }
164
165                 return oInput;
166     
167     }
168     
169     
170     /**
171     * @method setAttributesFromSrcElement
172     * @description Gets the values for all the attributes of the source element 
173     * (either <code>&#60;input&#62;</code> or <code>&#60;a&#62;</code>) that 
174     * map to Button configuration attributes and sets them into a collection 
175     * that is passed to the Button constructor.
176     * @private
177     * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
178     * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org/
179     * TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-
180     * 48250443">HTMLAnchorElement</a>} p_oElement Object reference to the HTML 
181     * element (either <code>&#60;input&#62;</code> or <code>&#60;span&#62;
182     * </code>) used to create the button.
183     * @param {Object} p_oAttributes Object reference for the collection of 
184     * configuration attributes used to create the button.
185     */
186     function setAttributesFromSrcElement(p_oElement, p_oAttributes) {
187     
188         var sSrcElementNodeName = p_oElement.nodeName.toUpperCase(),
189                         sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME),
190             me = this,
191             oAttribute,
192             oRootNode,
193             sText;
194             
195     
196         /**
197         * @method setAttributeFromDOMAttribute
198         * @description Gets the value of the specified DOM attribute and sets it 
199         * into the collection of configuration attributes used to configure 
200         * the button.
201         * @private
202         * @param {String} p_sAttribute String representing the name of the 
203         * attribute to retrieve from the DOM element.
204         */
205         function setAttributeFromDOMAttribute(p_sAttribute) {
206     
207             if (!(p_sAttribute in p_oAttributes)) {
208     
209                 /*
210                     Need to use "getAttributeNode" instead of "getAttribute" 
211                     because using "getAttribute," IE will return the innerText 
212                     of a <code>&#60;button&#62;</code> for the value attribute  
213                     rather than the value of the "value" attribute.
214                 */
215         
216                 oAttribute = p_oElement.getAttributeNode(p_sAttribute);
217         
218     
219                 if (oAttribute && ("value" in oAttribute)) {
220     
221     
222                     p_oAttributes[p_sAttribute] = oAttribute.value;
223     
224                 }
225     
226             }
227         
228         }
229     
230     
231         /**
232         * @method setFormElementProperties
233         * @description Gets the value of the attributes from the form element  
234         * and sets them into the collection of configuration attributes used to 
235         * configure the button.
236         * @private
237         */
238         function setFormElementProperties() {
239     
240             setAttributeFromDOMAttribute("type");
241     
242             if (p_oAttributes.type == "button") {
243             
244                 p_oAttributes.type = "push";
245             
246             }
247     
248             if (!("disabled" in p_oAttributes)) {
249     
250                 p_oAttributes.disabled = p_oElement.disabled;
251     
252             }
253     
254             setAttributeFromDOMAttribute("name");
255             setAttributeFromDOMAttribute("value");
256             setAttributeFromDOMAttribute("title");
257     
258         }
259
260     
261         switch (sSrcElementNodeName) {
262         
263         case "A":
264             
265             p_oAttributes.type = "link";
266             
267             setAttributeFromDOMAttribute("href");
268             setAttributeFromDOMAttribute("target");
269         
270             break;
271     
272         case "INPUT":
273
274             setFormElementProperties();
275
276             if (!("checked" in p_oAttributes)) {
277     
278                 p_oAttributes.checked = p_oElement.checked;
279     
280             }
281
282             break;
283
284         case "BUTTON":
285
286             setFormElementProperties();
287
288             oRootNode = p_oElement.parentNode.parentNode;
289
290             if (Dom.hasClass(oRootNode, sClass + "-checked")) {
291             
292                 p_oAttributes.checked = true;
293             
294             }
295
296             if (Dom.hasClass(oRootNode, sClass + "-disabled")) {
297
298                 p_oAttributes.disabled = true;
299             
300             }
301
302             p_oElement.removeAttribute("value");
303
304             p_oElement.setAttribute("type", "button");
305
306             break;
307         
308         }
309
310         p_oElement.removeAttribute("id");
311         p_oElement.removeAttribute("name");
312         
313         if (!("tabindex" in p_oAttributes)) {
314
315             p_oAttributes.tabindex = p_oElement.tabIndex;
316
317         }
318     
319         if (!("label" in p_oAttributes)) {
320     
321             // Set the "label" property
322         
323             sText = sSrcElementNodeName == "INPUT" ? 
324                             p_oElement.value : p_oElement.innerHTML;
325         
326     
327             if (sText && sText.length > 0) {
328                 
329                 p_oAttributes.label = sText;
330                 
331             } 
332     
333         }
334     
335     }
336     
337     
338     /**
339     * @method initConfig
340     * @description Initializes the set of configuration attributes that are 
341     * used to instantiate the button.
342     * @private
343     * @param {Object} Object representing the button's set of 
344     * configuration attributes.
345     */
346     function initConfig(p_oConfig) {
347     
348         var oAttributes = p_oConfig.attributes,
349             oSrcElement = oAttributes.srcelement,
350             sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
351             me = this;
352     
353     
354         if (sSrcElementNodeName == this.NODE_NAME) {
355     
356             p_oConfig.element = oSrcElement;
357             p_oConfig.id = oSrcElement.id;
358
359             Dom.getElementsBy(function (p_oElement) {
360             
361                 switch (p_oElement.nodeName.toUpperCase()) {
362                 
363                 case "BUTTON":
364                 case "A":
365                 case "INPUT":
366
367                     setAttributesFromSrcElement.call(me, p_oElement, 
368                         oAttributes);
369
370                     break;                        
371                 
372                 }
373             
374             }, "*", oSrcElement);
375         
376         }
377         else {
378     
379             switch (sSrcElementNodeName) {
380
381             case "BUTTON":
382             case "A":
383             case "INPUT":
384
385                 setAttributesFromSrcElement.call(this, oSrcElement, 
386                     oAttributes);
387
388                 break;
389
390             }
391         
392         }
393     
394     }
395
396
397
398     //  Constructor
399
400     YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
401     
402                 if (!Overlay && YAHOO.widget.Overlay) {
403                 
404                         Overlay = YAHOO.widget.Overlay;
405                 
406                 }
407
408
409                 if (!Menu && YAHOO.widget.Menu) {
410                 
411                         Menu = YAHOO.widget.Menu;
412                 
413                 }
414
415
416         var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
417             oConfig,
418             oElement;
419     
420
421         if (arguments.length == 1 && !Lang.isString(p_oElement) && !p_oElement.nodeName) {
422     
423             if (!p_oElement.id) {
424     
425                 p_oElement.id = Dom.generateId();
426     
427     
428             }
429     
430     
431             fnSuperClass.call(this, (this.createButtonElement(p_oElement.type)), p_oElement);
432     
433         }
434         else {
435     
436             oConfig = { element: null, attributes: (p_oAttributes || {}) };
437     
438     
439             if (Lang.isString(p_oElement)) {
440     
441                 oElement = Dom.get(p_oElement);
442     
443                 if (oElement) {
444
445                     if (!oConfig.attributes.id) {
446                     
447                         oConfig.attributes.id = p_oElement;
448                     
449                     }
450     
451                 
452                 
453                     oConfig.attributes.srcelement = oElement;
454                 
455                     initConfig.call(this, oConfig);
456                 
457                 
458                     if (!oConfig.element) {
459                 
460                 
461                         oConfig.element = this.createButtonElement(oConfig.attributes.type);
462                 
463                     }
464                 
465                     fnSuperClass.call(this, oConfig.element, oConfig.attributes);
466     
467                 }
468     
469             }
470             else if (p_oElement.nodeName) {
471     
472                 if (!oConfig.attributes.id) {
473     
474                     if (p_oElement.id) {
475         
476                         oConfig.attributes.id = p_oElement.id;
477                     
478                     }
479                     else {
480         
481                         oConfig.attributes.id = Dom.generateId();
482         
483         
484                     }
485     
486                 }
487     
488     
489     
490                 oConfig.attributes.srcelement = p_oElement;
491         
492                 initConfig.call(this, oConfig);
493         
494         
495                 if (!oConfig.element) {
496     
497             
498                     oConfig.element = this.createButtonElement(oConfig.attributes.type);
499             
500                 }
501             
502                 fnSuperClass.call(this, oConfig.element, oConfig.attributes);
503             
504             }
505     
506         }
507     
508     };
509
510
511
512     YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
513     
514     
515         // Protected properties
516         
517         
518         /** 
519         * @property _button
520         * @description Object reference to the button's internal 
521         * <code>&#60;a&#62;</code> or <code>&#60;button&#62;</code> element.
522         * @default null
523         * @protected
524         * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
525         * level-one-html.html#ID-48250443">HTMLAnchorElement</a>|<a href="
526         * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
527         * #ID-34812697">HTMLButtonElement</a>
528         */
529         _button: null,
530         
531         
532         /** 
533         * @property _menu
534         * @description Object reference to the button's menu.
535         * @default null
536         * @protected
537         * @type {<a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|
538         * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
539         */
540         _menu: null,
541         
542         
543         /** 
544         * @property _hiddenFields
545         * @description Object reference to the <code>&#60;input&#62;</code>  
546         * element, or array of HTML form elements used to represent the button
547         *  when its parent form is submitted.
548         * @default null
549         * @protected
550         * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
551         * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array
552         */
553         _hiddenFields: null,
554         
555         
556         /** 
557         * @property _onclickAttributeValue
558         * @description Object reference to the button's current value for the 
559         * "onclick" configuration attribute.
560         * @default null
561         * @protected
562         * @type Object
563         */
564         _onclickAttributeValue: null,
565         
566         
567         /** 
568         * @property _activationKeyPressed
569         * @description Boolean indicating if the key(s) that toggle the button's 
570         * "active" state have been pressed.
571         * @default false
572         * @protected
573         * @type Boolean
574         */
575         _activationKeyPressed: false,
576         
577         
578         /** 
579         * @property _activationButtonPressed
580         * @description Boolean indicating if the mouse button that toggles 
581         * the button's "active" state has been pressed.
582         * @default false
583         * @protected
584         * @type Boolean
585         */
586         _activationButtonPressed: false,
587         
588         
589         /** 
590         * @property _hasKeyEventHandlers
591         * @description Boolean indicating if the button's "blur", "keydown" and 
592         * "keyup" event handlers are assigned
593         * @default false
594         * @protected
595         * @type Boolean
596         */
597         _hasKeyEventHandlers: false,
598         
599         
600         /** 
601         * @property _hasMouseEventHandlers
602         * @description Boolean indicating if the button's "mouseout," 
603         * "mousedown," and "mouseup" event handlers are assigned
604         * @default false
605         * @protected
606         * @type Boolean
607         */
608         _hasMouseEventHandlers: false,
609
610
611         /** 
612         * @property _nOptionRegionX
613         * @description Number representing the X coordinate of the leftmost edge of the Button's 
614         * option region.  Applies only to Buttons of type "split".
615         * @default 0
616         * @protected
617         * @type Number
618         */        
619         _nOptionRegionX: 0,
620         
621
622
623         // Constants
624
625         /**
626         * @property CLASS_NAME_PREFIX
627         * @description Prefix used for all class names applied to a Button.
628         * @default "yui-"
629         * @final
630         * @type String
631         */
632         CLASS_NAME_PREFIX: "yui-",
633         
634         
635         /**
636         * @property NODE_NAME
637         * @description The name of the node to be used for the button's 
638         * root element.
639         * @default "SPAN"
640         * @final
641         * @type String
642         */
643         NODE_NAME: "SPAN",
644         
645         
646         /**
647         * @property CHECK_ACTIVATION_KEYS
648         * @description Array of numbers representing keys that (when pressed) 
649         * toggle the button's "checked" attribute.
650         * @default [32]
651         * @final
652         * @type Array
653         */
654         CHECK_ACTIVATION_KEYS: [32],
655         
656         
657         /**
658         * @property ACTIVATION_KEYS
659         * @description Array of numbers representing keys that (when presed) 
660         * toggle the button's "active" state.
661         * @default [13, 32]
662         * @final
663         * @type Array
664         */
665         ACTIVATION_KEYS: [13, 32],
666         
667         
668         /**
669         * @property OPTION_AREA_WIDTH
670         * @description Width (in pixels) of the area of a split button that  
671         * when pressed will display a menu.
672         * @default 20
673         * @final
674         * @type Number
675         */
676         OPTION_AREA_WIDTH: 20,
677         
678         
679         /**
680         * @property CSS_CLASS_NAME
681         * @description String representing the CSS class(es) to be applied to  
682         * the button's root element.
683         * @default "button"
684         * @final
685         * @type String
686         */
687         CSS_CLASS_NAME: "button",
688         
689         
690         
691         // Protected attribute setter methods
692         
693         
694         /**
695         * @method _setType
696         * @description Sets the value of the button's "type" attribute.
697         * @protected
698         * @param {String} p_sType String indicating the value for the button's 
699         * "type" attribute.
700         */
701         _setType: function (p_sType) {
702         
703             if (p_sType == "split") {
704         
705                 this.on("option", this._onOption);
706         
707             }
708         
709         },
710         
711         
712         /**
713         * @method _setLabel
714         * @description Sets the value of the button's "label" attribute.
715         * @protected
716         * @param {HTML} p_sLabel String indicating the value for the button's 
717         * "label" attribute.
718         */
719         _setLabel: function (p_sLabel) {
720
721             this._button.innerHTML = p_sLabel;
722
723             
724             /*
725                 Remove and add the default class name from the root element
726                 for Gecko to ensure that the button shrinkwraps to the label.
727                 Without this the button will not be rendered at the correct 
728                 width when the label changes.  The most likely cause for this 
729                 bug is button's use of the Gecko-specific CSS display type of 
730                 "-moz-inline-box" to simulate "inline-block" supported by IE, 
731                 Safari and Opera.
732             */
733             
734             var sClass,
735                 nGeckoVersion = UA.gecko;
736                                 
737             
738             if (nGeckoVersion && nGeckoVersion < 1.9 && Dom.inDocument(this.get("element"))) {
739             
740                 sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
741
742                 this.removeClass(sClass);
743                 
744                 Lang.later(0, this, this.addClass, sClass);
745
746             }
747         
748         },
749         
750         
751         /**
752         * @method _setTabIndex
753         * @description Sets the value of the button's "tabindex" attribute.
754         * @protected
755         * @param {Number} p_nTabIndex Number indicating the value for the 
756         * button's "tabindex" attribute.
757         */
758         _setTabIndex: function (p_nTabIndex) {
759         
760             this._button.tabIndex = p_nTabIndex;
761         
762         },
763         
764         
765         /**
766         * @method _setTitle
767         * @description Sets the value of the button's "title" attribute.
768         * @protected
769         * @param {String} p_nTabIndex Number indicating the value for 
770         * the button's "title" attribute.
771         */
772         _setTitle: function (p_sTitle) {
773         
774             if (this.get("type") != "link") {
775         
776                 this._button.title = p_sTitle;
777         
778             }
779         
780         },
781         
782         
783         /**
784         * @method _setDisabled
785         * @description Sets the value of the button's "disabled" attribute.
786         * @protected
787         * @param {Boolean} p_bDisabled Boolean indicating the value for 
788         * the button's "disabled" attribute.
789         */
790         _setDisabled: function (p_bDisabled) {
791         
792             if (this.get("type") != "link") {
793         
794                 if (p_bDisabled) {
795         
796                     if (this._menu) {
797         
798                         this._menu.hide();
799         
800                     }
801         
802                     if (this.hasFocus()) {
803                     
804                         this.blur();
805                     
806                     }
807         
808                     this._button.setAttribute("disabled", "disabled");
809         
810                     this.addStateCSSClasses("disabled");
811
812                     this.removeStateCSSClasses("hover");
813                     this.removeStateCSSClasses("active");
814                     this.removeStateCSSClasses("focus");
815         
816                 }
817                 else {
818         
819                     this._button.removeAttribute("disabled");
820         
821                     this.removeStateCSSClasses("disabled");
822                 
823                 }
824         
825             }
826         
827         },
828
829         
830         /**
831         * @method _setHref
832         * @description Sets the value of the button's "href" attribute.
833         * @protected
834         * @param {String} p_sHref String indicating the value for the button's 
835         * "href" attribute.
836         */
837         _setHref: function (p_sHref) {
838         
839             if (this.get("type") == "link") {
840         
841                 this._button.href = p_sHref;
842             
843             }
844         
845         },
846         
847         
848         /**
849         * @method _setTarget
850         * @description Sets the value of the button's "target" attribute.
851         * @protected
852         * @param {String} p_sTarget String indicating the value for the button's 
853         * "target" attribute.
854         */
855         _setTarget: function (p_sTarget) {
856         
857             if (this.get("type") == "link") {
858         
859                 this._button.setAttribute("target", p_sTarget);
860             
861             }
862         
863         },
864         
865         
866         /**
867         * @method _setChecked
868         * @description Sets the value of the button's "target" attribute.
869         * @protected
870         * @param {Boolean} p_bChecked Boolean indicating the value for  
871         * the button's "checked" attribute.
872         */
873         _setChecked: function (p_bChecked) {
874         
875             var sType = this.get("type");
876         
877             if (sType == "checkbox" || sType == "radio") {
878         
879                 if (p_bChecked) {
880                     this.addStateCSSClasses("checked");
881                 }
882                 else {
883                     this.removeStateCSSClasses("checked");
884                 }
885         
886             }
887         
888         },
889
890         
891         /**
892         * @method _setMenu
893         * @description Sets the value of the button's "menu" attribute.
894         * @protected
895         * @param {Object} p_oMenu Object indicating the value for the button's 
896         * "menu" attribute.
897         */
898         _setMenu: function (p_oMenu) {
899
900             var bLazyLoad = this.get("lazyloadmenu"),
901                 oButtonElement = this.get("element"),
902                 sMenuCSSClassName,
903         
904                 /*
905                     Boolean indicating if the value of p_oMenu is an instance 
906                     of YAHOO.widget.Menu or YAHOO.widget.Overlay.
907                 */
908         
909                 bInstance = false,
910                 oMenu,
911                 oMenuElement,
912                 oSrcElement;
913         
914
915                         function onAppendTo() {
916
917                                 oMenu.render(oButtonElement.parentNode);
918                                 
919                                 this.removeListener("appendTo", onAppendTo);
920                         
921                         }
922                         
923                         
924                         function setMenuContainer() {
925
926                                 oMenu.cfg.queueProperty("container", oButtonElement.parentNode);
927                                 
928                                 this.removeListener("appendTo", setMenuContainer);
929                         
930                         }
931
932
933                         function initMenu() {
934                 
935                                 var oContainer;
936                 
937                                 if (oMenu) {
938
939                                         Dom.addClass(oMenu.element, this.get("menuclassname"));
940                                         Dom.addClass(oMenu.element, this.CLASS_NAME_PREFIX + this.get("type") + "-button-menu");
941
942                                         oMenu.showEvent.subscribe(this._onMenuShow, null, this);
943                                         oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
944                                         oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
945
946
947                                         if (Menu && oMenu instanceof Menu) {
948
949                                                 if (bLazyLoad) {
950
951                                                         oContainer = this.get("container");
952
953                                                         if (oContainer) {
954
955                                                                 oMenu.cfg.queueProperty("container", oContainer);
956
957                                                         }
958                                                         else {
959
960                                                                 this.on("appendTo", setMenuContainer);
961
962                                                         }
963
964                                                 }
965
966                                                 oMenu.cfg.queueProperty("clicktohide", false);
967
968                                                 oMenu.keyDownEvent.subscribe(this._onMenuKeyDown, this, true);
969                                                 oMenu.subscribe("click", this._onMenuClick, this, true);
970
971                                                 this.on("selectedMenuItemChange", this._onSelectedMenuItemChange);
972                 
973                                                 oSrcElement = oMenu.srcElement;
974                 
975                                                 if (oSrcElement && oSrcElement.nodeName.toUpperCase() == "SELECT") {
976
977                                                         oSrcElement.style.display = "none";
978                                                         oSrcElement.parentNode.removeChild(oSrcElement);
979                 
980                                                 }
981                 
982                                         }
983                                         else if (Overlay && oMenu instanceof Overlay) {
984                 
985                                                 if (!m_oOverlayManager) {
986                 
987                                                         m_oOverlayManager = new YAHOO.widget.OverlayManager();
988                                                 
989                                                 }
990                                                 
991                                                 m_oOverlayManager.register(oMenu);
992                                                 
993                                         }
994                 
995                 
996                                         this._menu = oMenu;
997
998                 
999                                         if (!bInstance && !bLazyLoad) {
1000                 
1001                                                 if (Dom.inDocument(oButtonElement)) {
1002         
1003                                                         oMenu.render(oButtonElement.parentNode);
1004                                                 
1005                                                 }
1006                                                 else {
1007                 
1008                                                         this.on("appendTo", onAppendTo);
1009                                                 
1010                                                 }
1011                                         
1012                                         }
1013                 
1014                                 }
1015                 
1016                         }
1017
1018         
1019             if (Overlay) {
1020         
1021                                 if (Menu) {
1022                                 
1023                                         sMenuCSSClassName = Menu.prototype.CSS_CLASS_NAME;
1024                                 
1025                                 }
1026                         
1027                                 if (p_oMenu && Menu && (p_oMenu instanceof Menu)) {
1028                         
1029                                         oMenu = p_oMenu;
1030                                         bInstance = true;
1031                         
1032                                         initMenu.call(this);
1033                         
1034                                 }
1035                                 else if (Overlay && p_oMenu && (p_oMenu instanceof Overlay)) {
1036                         
1037                                         oMenu = p_oMenu;
1038                                         bInstance = true;
1039                         
1040                                         oMenu.cfg.queueProperty("visible", false);
1041                         
1042                                         initMenu.call(this);
1043                         
1044                                 }
1045                                 else if (Menu && Lang.isArray(p_oMenu)) {
1046
1047                                         oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad, itemdata: p_oMenu });
1048                                                 
1049                                         this._menu = oMenu;
1050                         
1051                                         this.on("appendTo", initMenu);
1052                         
1053                                 }
1054                                 else if (Lang.isString(p_oMenu)) {
1055                         
1056                                         oMenuElement = Dom.get(p_oMenu);
1057                         
1058                                         if (oMenuElement) {
1059                         
1060                                                 if (Menu && Dom.hasClass(oMenuElement, sMenuCSSClassName) || 
1061                                                         oMenuElement.nodeName.toUpperCase() == "SELECT") {
1062                                 
1063                                                         oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1064                                 
1065                                                         initMenu.call(this);
1066                                 
1067                                                 }
1068                                                 else if (Overlay) {
1069                         
1070                                                         oMenu = new Overlay(p_oMenu, { visible: false });
1071                                 
1072                                                         initMenu.call(this);
1073                                 
1074                                                 }
1075                         
1076                                         }
1077                         
1078                                 }
1079                                 else if (p_oMenu && p_oMenu.nodeName) {
1080                         
1081                                         if (Menu && Dom.hasClass(p_oMenu, sMenuCSSClassName) || 
1082                                                         p_oMenu.nodeName.toUpperCase() == "SELECT") {
1083                         
1084                                                 oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1085                                         
1086                                                 initMenu.call(this);
1087                         
1088                                         }
1089                                         else if (Overlay) {
1090                         
1091                                                 if (!p_oMenu.id) {
1092                                                 
1093                                                         Dom.generateId(p_oMenu);
1094                                                 
1095                                                 }
1096                         
1097                                                 oMenu = new Overlay(p_oMenu, { visible: false });
1098                         
1099                                                 initMenu.call(this);
1100                                         
1101                                         }
1102                                 
1103                                 }
1104             
1105             }
1106         
1107         },
1108         
1109         
1110         /**
1111         * @method _setOnClick
1112         * @description Sets the value of the button's "onclick" attribute.
1113         * @protected
1114         * @param {Object} p_oObject Object indicating the value for the button's 
1115         * "onclick" attribute.
1116         */
1117         _setOnClick: function (p_oObject) {
1118         
1119             /*
1120                 Remove any existing listeners if a "click" event handler 
1121                 has already been specified.
1122             */
1123         
1124             if (this._onclickAttributeValue && 
1125                 (this._onclickAttributeValue != p_oObject)) {
1126         
1127                 this.removeListener("click", this._onclickAttributeValue.fn);
1128         
1129                 this._onclickAttributeValue = null;
1130         
1131             }
1132         
1133         
1134             if (!this._onclickAttributeValue && 
1135                 Lang.isObject(p_oObject) && 
1136                 Lang.isFunction(p_oObject.fn)) {
1137         
1138                 this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
1139         
1140                 this._onclickAttributeValue = p_oObject;
1141         
1142             }
1143         
1144         },
1145
1146         
1147         
1148         // Protected methods
1149
1150         
1151         
1152         /**
1153         * @method _isActivationKey
1154         * @description Determines if the specified keycode is one that toggles  
1155         * the button's "active" state.
1156         * @protected
1157         * @param {Number} p_nKeyCode Number representing the keycode to 
1158         * be evaluated.
1159         * @return {Boolean}
1160         */
1161         _isActivationKey: function (p_nKeyCode) {
1162         
1163             var sType = this.get("type"),
1164                 aKeyCodes = (sType == "checkbox" || sType == "radio") ? 
1165                     this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
1166         
1167                 nKeyCodes = aKeyCodes.length,
1168                 bReturnVal = false,
1169                 i;
1170         
1171
1172             if (nKeyCodes > 0) {
1173         
1174                 i = nKeyCodes - 1;
1175         
1176                 do {
1177         
1178                     if (p_nKeyCode == aKeyCodes[i]) {
1179         
1180                         bReturnVal = true;
1181                         break;
1182         
1183                     }
1184         
1185                 }
1186                 while (i--);
1187             
1188             }
1189             
1190             return bReturnVal;
1191         
1192         },
1193         
1194         
1195         /**
1196         * @method _isSplitButtonOptionKey
1197         * @description Determines if the specified keycode is one that toggles  
1198         * the display of the split button's menu.
1199         * @protected
1200         * @param {Event} p_oEvent Object representing the DOM event object  
1201         * passed back by the event utility (YAHOO.util.Event).
1202         * @return {Boolean}
1203         */
1204         _isSplitButtonOptionKey: function (p_oEvent) {
1205
1206                         var bShowMenu = (Event.getCharCode(p_oEvent) == 40);
1207
1208
1209                         var onKeyPress = function (p_oEvent) {
1210
1211                                 Event.preventDefault(p_oEvent);
1212
1213                                 this.removeListener("keypress", onKeyPress);
1214                         
1215                         };
1216
1217
1218                         // Prevent the browser from scrolling the window
1219                         if (bShowMenu) {
1220
1221                                 if (UA.opera) {
1222         
1223                                         this.on("keypress", onKeyPress);
1224         
1225                                 }
1226
1227                                 Event.preventDefault(p_oEvent);
1228                         }
1229
1230             return bShowMenu;
1231         
1232         },
1233         
1234         
1235         /**
1236         * @method _addListenersToForm
1237         * @description Adds event handlers to the button's form.
1238         * @protected
1239         */
1240         _addListenersToForm: function () {
1241         
1242             var oForm = this.getForm(),
1243                 onFormKeyPress = YAHOO.widget.Button.onFormKeyPress,
1244                 bHasKeyPressListener,
1245                 oSrcElement,
1246                 aListeners,
1247                 nListeners,
1248                 i;
1249         
1250         
1251             if (oForm) {
1252         
1253                 Event.on(oForm, "reset", this._onFormReset, null, this);
1254                 Event.on(oForm, "submit", this._onFormSubmit, null, this);
1255         
1256                 oSrcElement = this.get("srcelement");
1257         
1258         
1259                 if (this.get("type") == "submit" || 
1260                     (oSrcElement && oSrcElement.type == "submit")) 
1261                 {
1262                 
1263                     aListeners = Event.getListeners(oForm, "keypress");
1264                     bHasKeyPressListener = false;
1265             
1266                     if (aListeners) {
1267             
1268                         nListeners = aListeners.length;
1269         
1270                         if (nListeners > 0) {
1271             
1272                             i = nListeners - 1;
1273                             
1274                             do {
1275                
1276                                 if (aListeners[i].fn == onFormKeyPress) {
1277                 
1278                                     bHasKeyPressListener = true;
1279                                     break;
1280                                 
1281                                 }
1282                 
1283                             }
1284                             while (i--);
1285                         
1286                         }
1287                     
1288                     }
1289             
1290             
1291                     if (!bHasKeyPressListener) {
1292                
1293                         Event.on(oForm, "keypress", onFormKeyPress);
1294             
1295                     }
1296         
1297                 }
1298             
1299             }
1300         
1301         },
1302         
1303         
1304         
1305         /**
1306         * @method _showMenu
1307         * @description Shows the button's menu.
1308         * @protected
1309         * @param {Event} p_oEvent Object representing the DOM event object 
1310         * passed back by the event utility (YAHOO.util.Event) that triggered 
1311         * the display of the menu.
1312         */
1313         _showMenu: function (p_oEvent) {
1314
1315             if (YAHOO.widget.MenuManager) {
1316                 YAHOO.widget.MenuManager.hideVisible();
1317             }
1318
1319         
1320             if (m_oOverlayManager) {
1321                 m_oOverlayManager.hideAll();
1322             }
1323
1324
1325             var oMenu = this._menu,
1326                 aMenuAlignment = this.get("menualignment"),
1327                 bFocusMenu = this.get("focusmenu"),
1328                                 fnFocusMethod;
1329
1330
1331                         if (this._renderedMenu) {
1332
1333                                 oMenu.cfg.setProperty("context", 
1334                                                                 [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1335         
1336                                 oMenu.cfg.setProperty("preventcontextoverlap", true);
1337                                 oMenu.cfg.setProperty("constraintoviewport", true);
1338
1339                         }
1340                         else {
1341
1342                                 oMenu.cfg.queueProperty("context", 
1343                                                                 [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1344         
1345                                 oMenu.cfg.queueProperty("preventcontextoverlap", true);
1346                                 oMenu.cfg.queueProperty("constraintoviewport", true);
1347                         
1348                         }
1349
1350
1351                         /*
1352                                  Refocus the Button before showing its Menu in case the call to 
1353                                  YAHOO.widget.MenuManager.hideVisible() resulted in another element in the 
1354                                  DOM being focused after another Menu was hidden.
1355                         */
1356                         
1357                         this.focus();
1358
1359
1360             if (Menu && oMenu && (oMenu instanceof Menu)) {
1361
1362                                 // Since Menus automatically focus themselves when made visible, temporarily 
1363                                 // replace the Menu focus method so that the value of the Button's "focusmenu"
1364                                 // attribute determines if the Menu should be focus when made visible.
1365
1366                                 fnFocusMethod = oMenu.focus;
1367
1368                                 oMenu.focus = function () {};
1369
1370                                 if (this._renderedMenu) {
1371
1372                                         oMenu.cfg.setProperty("minscrollheight", this.get("menuminscrollheight"));
1373                                         oMenu.cfg.setProperty("maxheight", this.get("menumaxheight"));
1374                                 
1375                                 }
1376                                 else {
1377
1378                                         oMenu.cfg.queueProperty("minscrollheight", this.get("menuminscrollheight"));
1379                                         oMenu.cfg.queueProperty("maxheight", this.get("menumaxheight"));
1380                                 
1381                                 }
1382
1383
1384                 oMenu.show();
1385
1386                         oMenu.focus = fnFocusMethod;
1387
1388                                 oMenu.align();
1389         
1390
1391                 /*
1392                     Stop the propagation of the event so that the MenuManager 
1393                     doesn't blur the menu after it gets focus.
1394                 */
1395         
1396                 if (p_oEvent.type == "mousedown") {
1397                     Event.stopPropagation(p_oEvent);
1398                 }
1399
1400         
1401                 if (bFocusMenu) { 
1402                     oMenu.focus();
1403                 }
1404
1405             }
1406             else if (Overlay && oMenu && (oMenu instanceof Overlay)) {
1407
1408                                 if (!this._renderedMenu) {
1409                             oMenu.render(this.get("element").parentNode);
1410                                 }
1411
1412                 oMenu.show();
1413                                 oMenu.align();
1414
1415             }
1416         
1417         },
1418         
1419         
1420         /**
1421         * @method _hideMenu
1422         * @description Hides the button's menu.
1423         * @protected
1424         */
1425         _hideMenu: function () {
1426         
1427             var oMenu = this._menu;
1428         
1429             if (oMenu) {
1430         
1431                 oMenu.hide();
1432         
1433             }
1434         
1435         },
1436         
1437         
1438         
1439         
1440         // Protected event handlers
1441         
1442         
1443         /**
1444         * @method _onMouseOver
1445         * @description "mouseover" event handler for the button.
1446         * @protected
1447         * @param {Event} p_oEvent Object representing the DOM event object  
1448         * passed back by the event utility (YAHOO.util.Event).
1449         */
1450         _onMouseOver: function (p_oEvent) {
1451         
1452                 var sType = this.get("type"),
1453                         oElement,
1454                                 nOptionRegionX;
1455
1456
1457                         if (sType === "split") {
1458
1459                                 oElement = this.get("element");
1460                                 nOptionRegionX = 
1461                                         (Dom.getX(oElement) + (oElement.offsetWidth - this.OPTION_AREA_WIDTH));
1462                                         
1463                                 this._nOptionRegionX = nOptionRegionX;
1464                         
1465                         }
1466         
1467
1468             if (!this._hasMouseEventHandlers) {
1469         
1470                                 if (sType === "split") {
1471         
1472                                 this.on("mousemove", this._onMouseMove);
1473
1474                         }
1475
1476                 this.on("mouseout", this._onMouseOut);
1477         
1478                 this._hasMouseEventHandlers = true;
1479         
1480             }
1481         
1482
1483             this.addStateCSSClasses("hover");
1484
1485
1486                         if (sType === "split" && (Event.getPageX(p_oEvent) > nOptionRegionX)) {
1487         
1488                                 this.addStateCSSClasses("hoveroption");
1489         
1490                         }
1491
1492         
1493             if (this._activationButtonPressed) {
1494         
1495                 this.addStateCSSClasses("active");
1496         
1497             }
1498         
1499         
1500             if (this._bOptionPressed) {
1501         
1502                 this.addStateCSSClasses("activeoption");
1503             
1504             }
1505
1506
1507             if (this._activationButtonPressed || this._bOptionPressed) {
1508         
1509                 Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1510         
1511             }
1512
1513         },
1514
1515
1516         /**
1517         * @method _onMouseMove
1518         * @description "mousemove" event handler for the button.
1519         * @protected
1520         * @param {Event} p_oEvent Object representing the DOM event object  
1521         * passed back by the event utility (YAHOO.util.Event).
1522         */        
1523         _onMouseMove: function (p_oEvent) {
1524         
1525                 var nOptionRegionX = this._nOptionRegionX;
1526         
1527                 if (nOptionRegionX) {
1528
1529                                 if (Event.getPageX(p_oEvent) > nOptionRegionX) {
1530                                         
1531                                         this.addStateCSSClasses("hoveroption");
1532         
1533                                 }
1534                                 else {
1535
1536                                         this.removeStateCSSClasses("hoveroption");
1537                                 
1538                                 }
1539                                 
1540                 }
1541         
1542         },
1543         
1544         /**
1545         * @method _onMouseOut
1546         * @description "mouseout" event handler for the button.
1547         * @protected
1548         * @param {Event} p_oEvent Object representing the DOM event object  
1549         * passed back by the event utility (YAHOO.util.Event).
1550         */
1551         _onMouseOut: function (p_oEvent) {
1552
1553                         var sType = this.get("type");
1554         
1555             this.removeStateCSSClasses("hover");
1556         
1557
1558             if (sType != "menu") {
1559         
1560                 this.removeStateCSSClasses("active");
1561         
1562             }
1563         
1564
1565             if (this._activationButtonPressed || this._bOptionPressed) {
1566         
1567                 Event.on(document, "mouseup", this._onDocumentMouseUp, null, this);
1568         
1569             }
1570
1571
1572                         if (sType === "split" && (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1573                         
1574                                 this.removeStateCSSClasses("hoveroption");
1575         
1576                         }
1577             
1578         },
1579         
1580         
1581         /**
1582         * @method _onDocumentMouseUp
1583         * @description "mouseup" event handler for the button.
1584         * @protected
1585         * @param {Event} p_oEvent Object representing the DOM event object  
1586         * passed back by the event utility (YAHOO.util.Event).
1587         */
1588         _onDocumentMouseUp: function (p_oEvent) {
1589         
1590             this._activationButtonPressed = false;
1591             this._bOptionPressed = false;
1592         
1593             var sType = this.get("type"),
1594                 oTarget,
1595                 oMenuElement;
1596         
1597             if (sType == "menu" || sType == "split") {
1598
1599                 oTarget = Event.getTarget(p_oEvent);
1600                 oMenuElement = this._menu.element;
1601         
1602                 if (oTarget != oMenuElement && 
1603                     !Dom.isAncestor(oMenuElement, oTarget)) {
1604
1605                     this.removeStateCSSClasses((sType == "menu" ? 
1606                         "active" : "activeoption"));
1607             
1608                     this._hideMenu();
1609
1610                 }
1611         
1612             }
1613         
1614             Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1615         
1616         },
1617         
1618         
1619         /**
1620         * @method _onMouseDown
1621         * @description "mousedown" event handler for the button.
1622         * @protected
1623         * @param {Event} p_oEvent Object representing the DOM event object  
1624         * passed back by the event utility (YAHOO.util.Event).
1625         */
1626         _onMouseDown: function (p_oEvent) {
1627
1628             var sType,
1629                 bReturnVal = true;
1630         
1631         
1632             function onMouseUp() {
1633             
1634                 this._hideMenu();
1635                 this.removeListener("mouseup", onMouseUp);
1636             
1637             }
1638         
1639         
1640             if ((p_oEvent.which || p_oEvent.button) == 1) {
1641         
1642         
1643                 if (!this.hasFocus()) {
1644                     Lang.later(0, this, this.focus);
1645                     //this.focus();
1646                 }
1647         
1648         
1649                 sType = this.get("type");
1650         
1651         
1652                 if (sType == "split") {
1653                 
1654                     if (Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1655                         
1656                         this.fireEvent("option", p_oEvent);
1657                                                 bReturnVal = false;
1658         
1659                     }
1660                     else {
1661         
1662                         this.addStateCSSClasses("active");
1663         
1664                         this._activationButtonPressed = true;
1665         
1666                     }
1667         
1668                 }
1669                 else if (sType == "menu") {
1670         
1671                     if (this.isActive()) {
1672         
1673                         this._hideMenu();
1674         
1675                         this._activationButtonPressed = false;
1676         
1677                     }
1678                     else {
1679         
1680                         this._showMenu(p_oEvent);
1681         
1682                         this._activationButtonPressed = true;
1683                     
1684                     }
1685         
1686                 }
1687                 else {
1688         
1689                     this.addStateCSSClasses("active");
1690         
1691                     this._activationButtonPressed = true;
1692                 
1693                 }
1694         
1695         
1696         
1697                 if (sType == "split" || sType == "menu") {
1698
1699                     this._hideMenuTimer = Lang.later(250, this, this.on, ["mouseup", onMouseUp]);
1700         
1701                 }
1702         
1703             }
1704             
1705             return bReturnVal;
1706             
1707         },
1708         
1709         
1710         /**
1711         * @method _onMouseUp
1712         * @description "mouseup" event handler for the button.
1713         * @protected
1714         * @param {Event} p_oEvent Object representing the DOM event object  
1715         * passed back by the event utility (YAHOO.util.Event).
1716         */
1717         _onMouseUp: function (p_oEvent) {
1718             this.inMouseDown = false;
1719         
1720             var sType = this.get("type"),
1721                 oHideMenuTimer = this._hideMenuTimer,
1722                 bReturnVal = true;
1723         
1724         
1725             if (oHideMenuTimer) {
1726   
1727                                 oHideMenuTimer.cancel();
1728         
1729             }
1730         
1731         
1732             if (sType == "checkbox" || sType == "radio") {
1733                 if ((p_oEvent.which || p_oEvent.button) != 1) {
1734                     return;
1735                 }
1736
1737                 this.set("checked", !(this.get("checked")));
1738             
1739             }
1740         
1741         
1742             this._activationButtonPressed = false;
1743             
1744         
1745             if (sType != "menu") {
1746         
1747                 this.removeStateCSSClasses("active");
1748             
1749             }
1750
1751                 
1752                         if (sType == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1753                                 
1754                                 bReturnVal = false;
1755
1756                         }
1757
1758                         return bReturnVal;
1759             
1760         },
1761         
1762         
1763         /**
1764         * @method _onFocus
1765         * @description "focus" event handler for the button.
1766         * @protected
1767         * @param {Event} p_oEvent Object representing the DOM event object  
1768         * passed back by the event utility (YAHOO.util.Event).
1769         */
1770         _onFocus: function (p_oEvent) {
1771         
1772             var oElement;
1773         
1774             this.addStateCSSClasses("focus");
1775         
1776             if (this._activationKeyPressed) {
1777         
1778                 this.addStateCSSClasses("active");
1779            
1780             }
1781         
1782             m_oFocusedButton = this;
1783         
1784         
1785             if (!this._hasKeyEventHandlers) {
1786         
1787                 oElement = this._button;
1788         
1789                 Event.on(oElement, "blur", this._onBlur, null, this);
1790                 Event.on(oElement, "keydown", this._onKeyDown, null, this);
1791                 Event.on(oElement, "keyup", this._onKeyUp, null, this);
1792         
1793                 this._hasKeyEventHandlers = true;
1794         
1795             }
1796         
1797         
1798             this.fireEvent("focus", p_oEvent);
1799         
1800         },
1801         
1802         
1803         /**
1804         * @method _onBlur
1805         * @description "blur" event handler for the button.
1806         * @protected
1807         * @param {Event} p_oEvent Object representing the DOM event object  
1808         * passed back by the event utility (YAHOO.util.Event).
1809         */
1810         _onBlur: function (p_oEvent) {
1811         
1812             this.removeStateCSSClasses("focus");
1813         
1814             if (this.get("type") != "menu") {
1815         
1816                 this.removeStateCSSClasses("active");
1817
1818             }    
1819         
1820             if (this._activationKeyPressed) {
1821         
1822                 Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
1823         
1824             }
1825         
1826         
1827             m_oFocusedButton = null;
1828         
1829             this.fireEvent("blur", p_oEvent);
1830            
1831         },
1832         
1833         
1834         /**
1835         * @method _onDocumentKeyUp
1836         * @description "keyup" event handler for the document.
1837         * @protected
1838         * @param {Event} p_oEvent Object representing the DOM event object  
1839         * passed back by the event utility (YAHOO.util.Event).
1840         */
1841         _onDocumentKeyUp: function (p_oEvent) {
1842         
1843             if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1844         
1845                 this._activationKeyPressed = false;
1846                 
1847                 Event.removeListener(document, "keyup", this._onDocumentKeyUp);
1848             
1849             }
1850         
1851         },
1852         
1853         
1854         /**
1855         * @method _onKeyDown
1856         * @description "keydown" event handler for the button.
1857         * @protected
1858         * @param {Event} p_oEvent Object representing the DOM event object  
1859         * passed back by the event utility (YAHOO.util.Event).
1860         */
1861         _onKeyDown: function (p_oEvent) {
1862         
1863             var oMenu = this._menu;
1864         
1865         
1866             if (this.get("type") == "split" && 
1867                 this._isSplitButtonOptionKey(p_oEvent)) {
1868         
1869                 this.fireEvent("option", p_oEvent);
1870         
1871             }
1872             else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1873         
1874                 if (this.get("type") == "menu") {
1875         
1876                     this._showMenu(p_oEvent);
1877         
1878                 }
1879                 else {
1880         
1881                     this._activationKeyPressed = true;
1882                     
1883                     this.addStateCSSClasses("active");
1884                 
1885                 }
1886             
1887             }
1888         
1889         
1890             if (oMenu && oMenu.cfg.getProperty("visible") && 
1891                 Event.getCharCode(p_oEvent) == 27) {
1892             
1893                 oMenu.hide();
1894                 this.focus();
1895             
1896             }
1897         
1898         },
1899         
1900         
1901         /**
1902         * @method _onKeyUp
1903         * @description "keyup" event handler for the button.
1904         * @protected
1905         * @param {Event} p_oEvent Object representing the DOM event object  
1906         * passed back by the event utility (YAHOO.util.Event).
1907         */
1908         _onKeyUp: function (p_oEvent) {
1909         
1910             var sType;
1911         
1912             if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1913         
1914                 sType = this.get("type");
1915         
1916                 if (sType == "checkbox" || sType == "radio") {
1917         
1918                     this.set("checked", !(this.get("checked")));
1919                 
1920                 }
1921         
1922                 this._activationKeyPressed = false;
1923         
1924                 if (this.get("type") != "menu") {
1925         
1926                     this.removeStateCSSClasses("active");
1927         
1928                 }
1929         
1930             }
1931         
1932         },
1933         
1934         
1935         /**
1936         * @method _onClick
1937         * @description "click" event handler for the button.
1938         * @protected
1939         * @param {Event} p_oEvent Object representing the DOM event object  
1940         * passed back by the event utility (YAHOO.util.Event).
1941         */
1942         _onClick: function (p_oEvent) {
1943         
1944             var sType = this.get("type"),
1945                 oForm,
1946                 oSrcElement,
1947                 bReturnVal;
1948         
1949
1950                         switch (sType) {
1951
1952                         case "submit":
1953
1954                                 if (p_oEvent.returnValue !== false) {
1955
1956                                         this.submitForm();
1957
1958                                 }
1959
1960                                 break;
1961
1962                         case "reset":
1963
1964                                 oForm = this.getForm();
1965
1966                                 if (oForm) {
1967
1968                                         oForm.reset();
1969
1970                                 }
1971
1972                                 break;
1973
1974
1975                         case "split":
1976
1977                                 if (this._nOptionRegionX > 0 && 
1978                                                 (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1979
1980                                         bReturnVal = false;
1981
1982                                 }
1983                                 else {
1984
1985                                         this._hideMenu();
1986
1987                                         oSrcElement = this.get("srcelement");
1988
1989                                         if (oSrcElement && oSrcElement.type == "submit" && 
1990                                                         p_oEvent.returnValue !== false) {
1991
1992                                                 this.submitForm();
1993
1994                                         }
1995
1996                                 }
1997
1998                                 break;
1999
2000                         }
2001
2002                         return bReturnVal;
2003         
2004         },
2005         
2006         
2007         /**
2008         * @method _onDblClick
2009         * @description "dblclick" event handler for the button.
2010         * @protected
2011         * @param {Event} p_oEvent Object representing the DOM event object  
2012         * passed back by the event utility (YAHOO.util.Event).
2013         */
2014         _onDblClick: function (p_oEvent) {
2015         
2016             var bReturnVal = true;
2017     
2018                         if (this.get("type") == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
2019
2020                                 bReturnVal = false;
2021                         
2022                         }
2023         
2024                 return bReturnVal;
2025         
2026         },        
2027         
2028         
2029         /**
2030         * @method _onAppendTo
2031         * @description "appendTo" event handler for the button.
2032         * @protected
2033         * @param {Event} p_oEvent Object representing the DOM event object  
2034         * passed back by the event utility (YAHOO.util.Event).
2035         */
2036         _onAppendTo: function (p_oEvent) {
2037         
2038             /*
2039                 It is necessary to call "_addListenersToForm" using 
2040                 "setTimeout" to make sure that the button's "form" property 
2041                 returns a node reference.  Sometimes, if you try to get the 
2042                 reference immediately after appending the field, it is null.
2043             */
2044         
2045             Lang.later(0, this, this._addListenersToForm);
2046         
2047         },
2048         
2049         
2050         /**
2051         * @method _onFormReset
2052         * @description "reset" event handler for the button's form.
2053         * @protected
2054         * @param {Event} p_oEvent Object representing the DOM event 
2055         * object passed back by the event utility (YAHOO.util.Event).
2056         */
2057         _onFormReset: function (p_oEvent) {
2058         
2059             var sType = this.get("type"),
2060                 oMenu = this._menu;
2061         
2062             if (sType == "checkbox" || sType == "radio") {
2063         
2064                 this.resetValue("checked");
2065         
2066             }
2067         
2068         
2069             if (Menu && oMenu && (oMenu instanceof Menu)) {
2070         
2071                 this.resetValue("selectedMenuItem");
2072         
2073             }
2074         
2075         },
2076
2077
2078         /**
2079         * @method _onFormSubmit
2080         * @description "submit" event handler for the button's form.
2081         * @protected
2082         * @param {Event} p_oEvent Object representing the DOM event 
2083         * object passed back by the event utility (YAHOO.util.Event).
2084         */        
2085         _onFormSubmit: function (p_oEvent) {
2086         
2087                 this.createHiddenFields();
2088         
2089         },
2090         
2091         
2092         /**
2093         * @method _onDocumentMouseDown
2094         * @description "mousedown" event handler for the document.
2095         * @protected
2096         * @param {Event} p_oEvent Object representing the DOM event object  
2097         * passed back by the event utility (YAHOO.util.Event).
2098         */
2099         _onDocumentMouseDown: function (p_oEvent) {
2100
2101             var oTarget = Event.getTarget(p_oEvent),
2102                 oButtonElement = this.get("element"),
2103                 oMenuElement = this._menu.element;
2104            
2105             function findTargetInSubmenus(aSubmenus) {
2106                 var i, iMax, oSubmenuElement;
2107                 if (!aSubmenus) {
2108                     return true;
2109                 }
2110                 for (i = 0, iMax = aSubmenus.length; i < iMax; i++) {
2111                     oSubmenuElement = aSubmenus[i].element;
2112                     if (oTarget == oSubmenuElement || Dom.isAncestor(oSubmenuElement, oTarget)) {
2113                         return true;
2114                     }
2115                     if (aSubmenus[i] && aSubmenus[i].getSubmenus) {
2116                         if (findTargetInSubmenus(aSubmenus[i].getSubmenus())) {
2117                             return true;
2118                         }
2119                     }
2120                 }
2121         
2122                 return false;
2123             }
2124
2125             if (oTarget != oButtonElement && 
2126                 !Dom.isAncestor(oButtonElement, oTarget) && 
2127                 oTarget != oMenuElement && 
2128                 !Dom.isAncestor(oMenuElement, oTarget)) {
2129                 
2130                 
2131                 if (this._menu  && this._menu.getSubmenus) {
2132                     if (!findTargetInSubmenus(this._menu.getSubmenus())) {
2133                         return;
2134                     }
2135                 }
2136                 
2137
2138                 this._hideMenu();
2139
2140                                 //      In IE when the user mouses down on a focusable element
2141                                 //      that element will be focused and become the "activeElement".
2142                                 //      (http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
2143                                 //      However, there is a bug in IE where if there is a  
2144                                 //      positioned element with a focused descendant that is 
2145                                 //      hidden in response to the mousedown event, the target of 
2146                                 //      the mousedown event will appear to have focus, but will 
2147                                 //      not be set as the activeElement.  This will result 
2148                                 //      in the element not firing key events, even though it
2149                                 //      appears to have focus.  The following call to "setActive"
2150                                 //      fixes this bug.
2151
2152                 if (UA.ie && (UA.ie < 9) && oTarget.focus) {
2153                                         oTarget.setActive();
2154                                 }
2155         
2156                 Event.removeListener(document, "mousedown", 
2157                     this._onDocumentMouseDown);    
2158             
2159             }
2160         
2161         },
2162         
2163         
2164         /**
2165         * @method _onOption
2166         * @description "option" event handler for the button.
2167         * @protected
2168         * @param {Event} p_oEvent Object representing the DOM event object  
2169         * passed back by the event utility (YAHOO.util.Event).
2170         */
2171         _onOption: function (p_oEvent) {
2172         
2173             if (this.hasClass(this.CLASS_NAME_PREFIX + "split-button-activeoption")) {
2174         
2175                 this._hideMenu();
2176         
2177                 this._bOptionPressed = false;
2178         
2179             }
2180             else {
2181         
2182                 this._showMenu(p_oEvent);    
2183         
2184                 this._bOptionPressed = true;
2185         
2186             }
2187         
2188         },
2189         
2190         
2191         /**
2192         * @method _onMenuShow
2193         * @description "show" event handler for the button's menu.
2194         * @private
2195         * @param {String} p_sType String representing the name of the event  
2196         * that was fired.
2197         */
2198         _onMenuShow: function (p_sType) {
2199         
2200             Event.on(document, "mousedown", this._onDocumentMouseDown, 
2201                 null, this);
2202         
2203             var sState = (this.get("type") == "split") ? "activeoption" : "active";
2204         
2205             this.addStateCSSClasses(sState);
2206         
2207         },
2208         
2209         
2210         /**
2211         * @method _onMenuHide
2212         * @description "hide" event handler for the button's menu.
2213         * @private
2214         * @param {String} p_sType String representing the name of the event  
2215         * that was fired.
2216         */
2217         _onMenuHide: function (p_sType) {
2218             
2219             var sState = (this.get("type") == "split") ? "activeoption" : "active";
2220         
2221             this.removeStateCSSClasses(sState);
2222         
2223         
2224             if (this.get("type") == "split") {
2225         
2226                 this._bOptionPressed = false;
2227             
2228             }
2229         
2230         },
2231         
2232         
2233         /**
2234         * @method _onMenuKeyDown
2235         * @description "keydown" event handler for the button's menu.
2236         * @private
2237         * @param {String} p_sType String representing the name of the event  
2238         * that was fired.
2239         * @param {Array} p_aArgs Array of arguments sent when the event 
2240         * was fired.
2241         */
2242         _onMenuKeyDown: function (p_sType, p_aArgs) {
2243         
2244             var oEvent = p_aArgs[0];
2245         
2246             if (Event.getCharCode(oEvent) == 27) {
2247         
2248                 this.focus();
2249         
2250                 if (this.get("type") == "split") {
2251                 
2252                     this._bOptionPressed = false;
2253                 
2254                 }
2255         
2256             }
2257         
2258         },
2259         
2260         
2261         /**
2262         * @method _onMenuRender
2263         * @description "render" event handler for the button's menu.
2264         * @private
2265         * @param {String} p_sType String representing the name of the  
2266         * event thatwas fired.
2267         */
2268         _onMenuRender: function (p_sType) {
2269         
2270             var oButtonElement = this.get("element"),
2271                 oButtonParent = oButtonElement.parentNode,
2272                                 oMenu = this._menu,
2273                 oMenuElement = oMenu.element,
2274                                 oSrcElement = oMenu.srcElement,
2275                                 oItem;
2276         
2277         
2278             if (oButtonParent != oMenuElement.parentNode) {
2279         
2280                 oButtonParent.appendChild(oMenuElement);
2281             
2282             }
2283
2284                         this._renderedMenu = true;
2285
2286                         //      If the user has designated an <option> of the Menu's source 
2287                         //      <select> element to be selected, sync the selectedIndex with 
2288                         //      the "selectedMenuItem" Attribute.
2289
2290                         if (oSrcElement && 
2291                                         oSrcElement.nodeName.toLowerCase() === "select" && 
2292                                         oSrcElement.value) {
2293                                 
2294                                 
2295                                 oItem = oMenu.getItem(oSrcElement.selectedIndex);
2296                                 
2297                                 //      Set the value of the "selectedMenuItem" attribute
2298                                 //      silently since this is the initial set--synchronizing 
2299                                 //      the value of the source <SELECT> element in the DOM with 
2300                                 //      its corresponding Menu instance.
2301
2302                                 this.set("selectedMenuItem", oItem, true);
2303                                 
2304                                 //      Call the "_onSelectedMenuItemChange" method since the 
2305                                 //      attribute was set silently.
2306
2307                                 this._onSelectedMenuItemChange({ newValue: oItem });
2308                                 
2309                         }
2310
2311         },
2312
2313         
2314         
2315         /**
2316         * @method _onMenuClick
2317         * @description "click" event handler for the button's menu.
2318         * @private
2319         * @param {String} p_sType String representing the name of the event  
2320         * that was fired.
2321         * @param {Array} p_aArgs Array of arguments sent when the event 
2322         * was fired.
2323         */
2324         _onMenuClick: function (p_sType, p_aArgs) {
2325
2326             var oItem = p_aArgs[1],
2327                 oSrcElement;
2328         
2329             if (oItem) {
2330         
2331                                 this.set("selectedMenuItem", oItem);
2332
2333                 oSrcElement = this.get("srcelement");
2334             
2335                 if (oSrcElement && oSrcElement.type == "submit") {
2336         
2337                     this.submitForm();
2338             
2339                 }
2340             
2341                 this._hideMenu();
2342             
2343             }
2344         
2345         },
2346
2347
2348         /**
2349         * @method _onSelectedMenuItemChange
2350         * @description "selectedMenuItemChange" event handler for the Button's
2351                 * "selectedMenuItem" attribute.
2352         * @param {Event} event Object representing the DOM event object  
2353         * passed back by the event utility (YAHOO.util.Event).
2354         */
2355                 _onSelectedMenuItemChange: function (event) {
2356                 
2357                         var oSelected = event.prevValue,
2358                                 oItem = event.newValue,
2359                                 sPrefix = this.CLASS_NAME_PREFIX;
2360
2361                         if (oSelected) {
2362                                 Dom.removeClass(oSelected.element, (sPrefix + "button-selectedmenuitem"));
2363                         }
2364                         
2365                         if (oItem) {
2366                                 Dom.addClass(oItem.element, (sPrefix + "button-selectedmenuitem"));
2367                         }
2368                         
2369                 },        
2370         
2371
2372         /**
2373         * @method _onLabelClick
2374         * @description "click" event handler for the Button's
2375                 * <code>&#60;label&#62;</code> element.
2376         * @param {Event} event Object representing the DOM event object  
2377         * passed back by the event utility (YAHOO.util.Event).
2378         */
2379                 _onLabelClick: function (event) {
2380
2381                         this.focus();
2382
2383                         var sType = this.get("type");
2384
2385                         if (sType == "radio" || sType == "checkbox") {
2386                                 this.set("checked", (!this.get("checked")));                                            
2387                         }
2388                         
2389                 },
2390
2391         
2392         // Public methods
2393         
2394         
2395         /**
2396         * @method createButtonElement
2397         * @description Creates the button's HTML elements.
2398         * @param {String} p_sType String indicating the type of element 
2399         * to create.
2400         * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2401         * level-one-html.html#ID-58190037">HTMLElement</a>}
2402         */
2403         createButtonElement: function (p_sType) {
2404         
2405             var sNodeName = this.NODE_NAME,
2406                 oElement = document.createElement(sNodeName);
2407         
2408             oElement.innerHTML =  "<" + sNodeName + " class=\"first-child\">" + 
2409                 (p_sType == "link" ? "<a></a>" : 
2410                 "<button type=\"button\"></button>") + "</" + sNodeName + ">";
2411         
2412             return oElement;
2413         
2414         },
2415
2416         
2417         /**
2418         * @method addStateCSSClasses
2419         * @description Appends state-specific CSS classes to the button's root 
2420         * DOM element.
2421         */
2422         addStateCSSClasses: function (p_sState) {
2423         
2424             var sType = this.get("type"),
2425                                 sPrefix = this.CLASS_NAME_PREFIX;
2426         
2427             if (Lang.isString(p_sState)) {
2428         
2429                 if (p_sState != "activeoption" && p_sState != "hoveroption") {
2430         
2431                     this.addClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2432         
2433                 }
2434         
2435                 this.addClass(sPrefix + sType + ("-button-" + p_sState));
2436             
2437             }
2438         
2439         },
2440         
2441         
2442         /**
2443         * @method removeStateCSSClasses
2444         * @description Removes state-specific CSS classes to the button's root 
2445         * DOM element.
2446         */
2447         removeStateCSSClasses: function (p_sState) {
2448         
2449             var sType = this.get("type"),
2450                                 sPrefix = this.CLASS_NAME_PREFIX;
2451         
2452             if (Lang.isString(p_sState)) {
2453         
2454                 this.removeClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2455                 this.removeClass(sPrefix + sType + ("-button-" + p_sState));
2456             
2457             }
2458         
2459         },
2460         
2461         
2462         /**
2463         * @method createHiddenFields
2464         * @description Creates the button's hidden form field and appends it 
2465         * to its parent form.
2466         * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2467         * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
2468         */
2469         createHiddenFields: function () {
2470         
2471             this.removeHiddenFields();
2472         
2473             var oForm = this.getForm(),
2474                 oButtonField,
2475                 sType,
2476                 bCheckable,
2477                 oMenu,
2478                 oMenuItem,
2479                 sButtonName,
2480                 oValue,
2481                 oMenuField,
2482                 oReturnVal,
2483                                 sMenuFieldName,
2484                                 oMenuSrcElement,
2485                                 bMenuSrcElementIsSelect = false;
2486         
2487         
2488             if (oForm && !this.get("disabled")) {
2489         
2490                 sType = this.get("type");
2491                 bCheckable = (sType == "checkbox" || sType == "radio");
2492         
2493         
2494                 if ((bCheckable && this.get("checked")) || (m_oSubmitTrigger == this)) {
2495                 
2496         
2497                     oButtonField = createInputElement((bCheckable ? sType : "hidden"),
2498                                     this.get("name"), this.get("value"), this.get("checked"));
2499             
2500             
2501                     if (oButtonField) {
2502             
2503                         if (bCheckable) {
2504             
2505                             oButtonField.style.display = "none";
2506             
2507                         }
2508             
2509                         oForm.appendChild(oButtonField);
2510             
2511                     }
2512         
2513                 }
2514                     
2515         
2516                 oMenu = this._menu;
2517             
2518             
2519                 if (Menu && oMenu && (oMenu instanceof Menu)) {
2520         
2521         
2522                     oMenuItem = this.get("selectedMenuItem");
2523                                         oMenuSrcElement = oMenu.srcElement;
2524                                         bMenuSrcElementIsSelect = (oMenuSrcElement && 
2525                                                                                                 oMenuSrcElement.nodeName.toUpperCase() == "SELECT");
2526
2527                     if (oMenuItem) {
2528
2529                                                 oValue = (oMenuItem.value === null || oMenuItem.value === "") ? 
2530                                                                         oMenuItem.cfg.getProperty("text") : oMenuItem.value;
2531
2532                                                 sButtonName = this.get("name");
2533
2534
2535                                                 if (bMenuSrcElementIsSelect) {
2536                                                 
2537                                                         sMenuFieldName = oMenuSrcElement.name;
2538                                                 
2539                                                 }
2540                                                 else if (sButtonName) {
2541
2542                                                         sMenuFieldName = (sButtonName + "_options");
2543                                                 
2544                                                 }
2545                                                 
2546
2547                                                 if (oValue && sMenuFieldName) {
2548                 
2549                                                         oMenuField = createInputElement("hidden", sMenuFieldName, oValue);
2550                                                         oForm.appendChild(oMenuField);
2551                 
2552                                                 }
2553                     
2554                     }
2555                     else if (bMenuSrcElementIsSelect) {
2556                                         
2557                                                 oMenuField = oForm.appendChild(oMenuSrcElement);
2558                     
2559                     }
2560         
2561                 }
2562             
2563             
2564                 if (oButtonField && oMenuField) {
2565         
2566                     this._hiddenFields = [oButtonField, oMenuField];
2567         
2568                 }
2569                 else if (!oButtonField && oMenuField) {
2570         
2571                     this._hiddenFields = oMenuField;
2572                 
2573                 }
2574                 else if (oButtonField && !oMenuField) {
2575         
2576                     this._hiddenFields = oButtonField;
2577                 
2578                 }
2579         
2580                         oReturnVal = this._hiddenFields;
2581         
2582             }
2583
2584                         return oReturnVal;
2585         
2586         },
2587         
2588         
2589         /**
2590         * @method removeHiddenFields
2591         * @description Removes the button's hidden form field(s) from its 
2592         * parent form.
2593         */
2594         removeHiddenFields: function () {
2595         
2596             var oField = this._hiddenFields,
2597                 nFields,
2598                 i;
2599         
2600             function removeChild(p_oElement) {
2601         
2602                 if (Dom.inDocument(p_oElement)) {
2603         
2604                     p_oElement.parentNode.removeChild(p_oElement);
2605
2606                 }
2607                 
2608             }
2609             
2610         
2611             if (oField) {
2612         
2613                 if (Lang.isArray(oField)) {
2614         
2615                     nFields = oField.length;
2616                     
2617                     if (nFields > 0) {
2618                     
2619                         i = nFields - 1;
2620                         
2621                         do {
2622         
2623                             removeChild(oField[i]);
2624         
2625                         }
2626                         while (i--);
2627                     
2628                     }
2629                 
2630                 }
2631                 else {
2632         
2633                     removeChild(oField);
2634         
2635                 }
2636         
2637                 this._hiddenFields = null;
2638             
2639             }
2640         
2641         },
2642         
2643         
2644         /**
2645         * @method submitForm
2646         * @description Submits the form to which the button belongs.  Returns  
2647         * true if the form was submitted successfully, false if the submission 
2648         * was cancelled.
2649         * @protected
2650         * @return {Boolean}
2651         */
2652         submitForm: function () {
2653         
2654             var oForm = this.getForm(),
2655         
2656                 oSrcElement = this.get("srcelement"),
2657         
2658                 /*
2659                     Boolean indicating if the event fired successfully 
2660                     (was not cancelled by any handlers)
2661                 */
2662         
2663                 bSubmitForm = false,
2664                 
2665                 oEvent;
2666         
2667         
2668             if (oForm) {
2669         
2670                 if (this.get("type") == "submit" || (oSrcElement && oSrcElement.type == "submit")) {
2671         
2672                     m_oSubmitTrigger = this;
2673                     
2674                 }
2675         
2676         
2677                 if (UA.ie && (UA.ie < 9)) {
2678         
2679                     bSubmitForm = oForm.fireEvent("onsubmit");
2680         
2681                 }
2682                 else {  // Gecko, Opera, and Safari
2683         
2684                     oEvent = document.createEvent("HTMLEvents");
2685                     oEvent.initEvent("submit", true, true);
2686         
2687                     bSubmitForm = oForm.dispatchEvent(oEvent);
2688         
2689                 }
2690         
2691         
2692                 /*
2693                     In IE and Safari, dispatching a "submit" event to a form 
2694                     WILL cause the form's "submit" event to fire, but WILL NOT 
2695                     submit the form.  Therefore, we need to call the "submit" 
2696                     method as well.
2697                 */
2698               
2699                 if ((UA.ie || UA.webkit) && bSubmitForm) {
2700         
2701                     oForm.submit();
2702                 
2703                 }
2704             
2705             }
2706         
2707             return bSubmitForm;
2708             
2709         },
2710         
2711         
2712         /**
2713         * @method init
2714         * @description The Button class's initialization method.
2715         * @param {String} p_oElement String specifying the id attribute of the 
2716         * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
2717         * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to 
2718         * be used to create the button.
2719         * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2720         * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://
2721         * www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
2722         * #ID-34812697">HTMLButtonElement</a>|<a href="http://www.w3.org/TR
2723         * /2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-33759296">
2724         * HTMLElement</a>} p_oElement Object reference for the 
2725         * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
2726         * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to be 
2727         * used to create the button.
2728         * @param {Object} p_oElement Object literal specifying a set of 
2729         * configuration attributes used to create the button.
2730         * @param {Object} p_oAttributes Optional. Object literal specifying a 
2731         * set of configuration attributes used to create the button.
2732         */
2733         init: function (p_oElement, p_oAttributes) {
2734         
2735             var sNodeName = p_oAttributes.type == "link" ? "a" : "button",
2736                 oSrcElement = p_oAttributes.srcelement,
2737                 oButton = p_oElement.getElementsByTagName(sNodeName)[0],
2738                 oInput;
2739
2740
2741             if (!oButton) {
2742
2743                 oInput = p_oElement.getElementsByTagName("input")[0];
2744
2745
2746                 if (oInput) {
2747
2748                     oButton = document.createElement("button");
2749                     oButton.setAttribute("type", "button");
2750
2751                     oInput.parentNode.replaceChild(oButton, oInput);
2752                 
2753                 }
2754
2755             }
2756
2757             this._button = oButton;
2758
2759
2760             YAHOO.widget.Button.superclass.init.call(this, p_oElement, p_oAttributes);
2761
2762
2763                         var sId = this.get("id"),
2764                                 sButtonId = sId + "-button";
2765
2766
2767                 oButton.id = sButtonId;
2768
2769
2770                         var aLabels,
2771                                 oLabel;
2772
2773
2774                 var hasLabel = function (element) {
2775                 
2776                                 return (element.htmlFor === sId);
2777
2778                 };
2779
2780
2781                         var setLabel = function () {
2782
2783                                 oLabel.setAttribute((UA.ie ? "htmlFor" : "for"), sButtonId);
2784                         
2785                         };
2786
2787
2788                         if (oSrcElement && this.get("type") != "link") {
2789
2790                                 aLabels = Dom.getElementsBy(hasLabel, "label");
2791
2792                                 if (Lang.isArray(aLabels) && aLabels.length > 0) {
2793                                 
2794                                         oLabel = aLabels[0];
2795                                 
2796                                 }
2797
2798                         }
2799         
2800
2801             m_oButtons[sId] = this;
2802
2803                 var sPrefix = this.CLASS_NAME_PREFIX;
2804
2805             this.addClass(sPrefix + this.CSS_CLASS_NAME);
2806             this.addClass(sPrefix + this.get("type") + "-button");
2807         
2808             Event.on(this._button, "focus", this._onFocus, null, this);
2809             this.on("mouseover", this._onMouseOver);
2810                         this.on("mousedown", this._onMouseDown);
2811                         this.on("mouseup", this._onMouseUp);
2812             this.on("click", this._onClick);
2813
2814                         //      Need to reset the value of the "onclick" Attribute so that any
2815                         //      handlers registered via the "onclick" Attribute are fired after 
2816                         //      Button's default "_onClick" listener.
2817
2818                         var fnOnClick = this.get("onclick");
2819
2820                         this.set("onclick", null);
2821                         this.set("onclick", fnOnClick);
2822
2823             this.on("dblclick", this._onDblClick);
2824
2825
2826                         var oParentNode;
2827
2828             if (oLabel) {
2829             
2830                                 if (this.get("replaceLabel")) {
2831
2832                                         this.set("label", oLabel.innerHTML);
2833                                         
2834                                         oParentNode = oLabel.parentNode;
2835                                         
2836                                         oParentNode.removeChild(oLabel);
2837                                         
2838                                 }
2839                                 else {
2840
2841                                         this.on("appendTo", setLabel); 
2842
2843                                         Event.on(oLabel, "click", this._onLabelClick, null, this);
2844
2845                                         this._label = oLabel;
2846                                         
2847                                 }
2848             
2849             }
2850             
2851             this.on("appendTo", this._onAppendTo);
2852        
2853         
2854
2855             var oContainer = this.get("container"),
2856                 oElement = this.get("element"),
2857                 bElInDoc = Dom.inDocument(oElement);
2858
2859
2860             if (oContainer) {
2861         
2862                 if (oSrcElement && oSrcElement != oElement) {
2863                 
2864                     oParentNode = oSrcElement.parentNode;
2865
2866                     if (oParentNode) {
2867                     
2868                         oParentNode.removeChild(oSrcElement);
2869                     
2870                     }
2871
2872                 }
2873         
2874                 if (Lang.isString(oContainer)) {
2875         
2876                     Event.onContentReady(oContainer, this.appendTo, oContainer, this);
2877         
2878                 }
2879                 else {
2880         
2881                                 this.on("init", function () {
2882                                 
2883                                         Lang.later(0, this, this.appendTo, oContainer);
2884                                 
2885                                 });
2886         
2887                 }
2888         
2889             }
2890             else if (!bElInDoc && oSrcElement && oSrcElement != oElement) {
2891
2892                 oParentNode = oSrcElement.parentNode;
2893         
2894                 if (oParentNode) {
2895         
2896                     this.fireEvent("beforeAppendTo", {
2897                         type: "beforeAppendTo",
2898                         target: oParentNode
2899                     });
2900             
2901                     oParentNode.replaceChild(oElement, oSrcElement);
2902             
2903                     this.fireEvent("appendTo", {
2904                         type: "appendTo",
2905                         target: oParentNode
2906                     });
2907                 
2908                 }
2909         
2910             }
2911             else if (this.get("type") != "link" && bElInDoc && oSrcElement && 
2912                 oSrcElement == oElement) {
2913         
2914                 this._addListenersToForm();
2915         
2916             }
2917         
2918         
2919
2920                         this.fireEvent("init", {
2921                                 type: "init",
2922                                 target: this
2923                         });        
2924         
2925         },
2926         
2927         
2928         /**
2929         * @method initAttributes
2930         * @description Initializes all of the configuration attributes used to  
2931         * create the button.
2932         * @param {Object} p_oAttributes Object literal specifying a set of 
2933         * configuration attributes used to create the button.
2934         */
2935         initAttributes: function (p_oAttributes) {
2936         
2937             var oAttributes = p_oAttributes || {};
2938         
2939             YAHOO.widget.Button.superclass.initAttributes.call(this, 
2940                 oAttributes);
2941         
2942         
2943             /**
2944             * @attribute type
2945             * @description String specifying the button's type.  Possible 
2946             * values are: "push," "link," "submit," "reset," "checkbox," 
2947             * "radio," "menu," and "split."
2948             * @default "push"
2949             * @type String
2950                         * @writeonce
2951             */
2952             this.setAttributeConfig("type", {
2953         
2954                 value: (oAttributes.type || "push"),
2955                 validator: Lang.isString,
2956                 writeOnce: true,
2957                 method: this._setType
2958
2959             });
2960         
2961         
2962             /**
2963             * @attribute label
2964             * @description {HTML} specifying the button's text label 
2965             * or innerHTML.
2966             * @default null
2967             * @type String
2968             */
2969             this.setAttributeConfig("label", {
2970         
2971                 value: oAttributes.label,
2972                 validator: Lang.isString,
2973                 method: this._setLabel
2974         
2975             });
2976         
2977         
2978             /**
2979             * @attribute value
2980             * @description Object specifying the value for the button.
2981             * @default null
2982             * @type Object
2983             */
2984             this.setAttributeConfig("value", {
2985         
2986                 value: oAttributes.value
2987         
2988             });
2989         
2990         
2991             /**
2992             * @attribute name
2993             * @description String specifying the name for the button.
2994             * @default null
2995             * @type String
2996             */
2997             this.setAttributeConfig("name", {
2998         
2999                 value: oAttributes.name,
3000                 validator: Lang.isString
3001         
3002             });
3003         
3004         
3005             /**
3006             * @attribute tabindex
3007             * @description Number specifying the tabindex for the button.
3008             * @default null
3009             * @type Number
3010             */
3011             this.setAttributeConfig("tabindex", {
3012         
3013                 value: oAttributes.tabindex,
3014                 validator: Lang.isNumber,
3015                 method: this._setTabIndex
3016         
3017             });
3018         
3019         
3020             /**
3021             * @attribute title
3022             * @description String specifying the title for the button.
3023             * @default null
3024             * @type String
3025             */
3026             this.configureAttribute("title", {
3027         
3028                 value: oAttributes.title,
3029                 validator: Lang.isString,
3030                 method: this._setTitle
3031         
3032             });
3033         
3034         
3035             /**
3036             * @attribute disabled
3037             * @description Boolean indicating if the button should be disabled.  
3038             * (Disabled buttons are dimmed and will not respond to user input 
3039             * or fire events.  Does not apply to button's of type "link.")
3040             * @default false
3041             * @type Boolean
3042             */
3043             this.setAttributeConfig("disabled", {
3044         
3045                 value: (oAttributes.disabled || false),
3046                 validator: Lang.isBoolean,
3047                 method: this._setDisabled
3048         
3049             });
3050         
3051         
3052             /**
3053             * @attribute href
3054             * @description String specifying the href for the button.  Applies
3055             * only to buttons of type "link."
3056             * @type String
3057             */
3058             this.setAttributeConfig("href", {
3059         
3060                 value: oAttributes.href,
3061                 validator: Lang.isString,
3062                 method: this._setHref
3063         
3064             });
3065         
3066         
3067             /**
3068             * @attribute target
3069             * @description String specifying the target for the button.  
3070             * Applies only to buttons of type "link."
3071             * @type String
3072             */
3073             this.setAttributeConfig("target", {
3074         
3075                 value: oAttributes.target,
3076                 validator: Lang.isString,
3077                 method: this._setTarget
3078         
3079             });
3080         
3081         
3082             /**
3083             * @attribute checked
3084             * @description Boolean indicating if the button is checked. 
3085             * Applies only to buttons of type "radio" and "checkbox."
3086             * @default false
3087             * @type Boolean
3088             */
3089             this.setAttributeConfig("checked", {
3090         
3091                 value: (oAttributes.checked || false),
3092                 validator: Lang.isBoolean,
3093                 method: this._setChecked
3094         
3095             });
3096         
3097         
3098             /**
3099             * @attribute container
3100             * @description HTML element reference or string specifying the id 
3101             * attribute of the HTML element that the button's markup should be 
3102             * rendered into.
3103             * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3104             * level-one-html.html#ID-58190037">HTMLElement</a>|String
3105             * @default null
3106                         * @writeonce
3107             */
3108             this.setAttributeConfig("container", {
3109         
3110                 value: oAttributes.container,
3111                 writeOnce: true
3112         
3113             });
3114         
3115         
3116             /**
3117             * @attribute srcelement
3118             * @description Object reference to the HTML element (either 
3119             * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code>) 
3120             * used to create the button.
3121             * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3122             * level-one-html.html#ID-58190037">HTMLElement</a>|String
3123             * @default null
3124                         * @writeonce
3125             */
3126             this.setAttributeConfig("srcelement", {
3127         
3128                 value: oAttributes.srcelement,
3129                 writeOnce: true
3130         
3131             });
3132         
3133         
3134             /**
3135             * @attribute menu
3136             * @description Object specifying the menu for the button.  
3137             * The value can be one of the following:
3138             * <ul>
3139             * <li>Object specifying a rendered <a href="YAHOO.widget.Menu.html">
3140             * YAHOO.widget.Menu</a> instance.</li>
3141             * <li>Object specifying a rendered <a href="YAHOO.widget.Overlay.html">
3142             * YAHOO.widget.Overlay</a> instance.</li>
3143             * <li>String specifying the id attribute of the <code>&#60;div&#62;
3144             * </code> element used to create the menu.  By default the menu 
3145             * will be created as an instance of 
3146             * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>.  
3147             * If the <a href="YAHOO.widget.Menu.html#CSS_CLASS_NAME">
3148             * default CSS class name for YAHOO.widget.Menu</a> is applied to 
3149             * the <code>&#60;div&#62;</code> element, it will be created as an
3150             * instance of <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu
3151             * </a>.</li><li>String specifying the id attribute of the 
3152             * <code>&#60;select&#62;</code> element used to create the menu.
3153             * </li><li>Object specifying the <code>&#60;div&#62;</code> element
3154             * used to create the menu.</li>
3155             * <li>Object specifying the <code>&#60;select&#62;</code> element
3156             * used to create the menu.</li>
3157             * <li>Array of object literals, each representing a set of 
3158             * <a href="YAHOO.widget.MenuItem.html">YAHOO.widget.MenuItem</a> 
3159             * configuration attributes.</li>
3160             * <li>Array of strings representing the text labels for each menu 
3161             * item in the menu.</li>
3162             * </ul>
3163             * @type <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>|<a 
3164             * href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|<a 
3165             * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3166             * one-html.html#ID-58190037">HTMLElement</a>|String|Array
3167             * @default null
3168                         * @writeonce
3169             */
3170             this.setAttributeConfig("menu", {
3171         
3172                 value: null,
3173                 method: this._setMenu,
3174                 writeOnce: true
3175             
3176             });
3177         
3178         
3179             /**
3180             * @attribute lazyloadmenu
3181             * @description Boolean indicating the value to set for the 
3182             * <a href="YAHOO.widget.Menu.html#lazyLoad">"lazyload"</a>
3183             * configuration property of the button's menu.  Setting 
3184             * "lazyloadmenu" to <code>true </code> will defer rendering of 
3185             * the button's menu until the first time it is made visible.  
3186             * If "lazyloadmenu" is set to <code>false</code>, the button's 
3187             * menu will be rendered immediately if the button is in the 
3188             * document, or in response to the button's "appendTo" event if 
3189             * the button is not yet in the document.  In either case, the 
3190             * menu is rendered into the button's parent HTML element.  
3191             * <em>This attribute does not apply if a 
3192             * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a> or 
3193             * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a> 
3194             * instance is passed as the value of the button's "menu" 
3195             * configuration attribute. <a href="YAHOO.widget.Menu.html">
3196             * YAHOO.widget.Menu</a> or <a href="YAHOO.widget.Overlay.html">
3197             * YAHOO.widget.Overlay</a> instances should be rendered before 
3198             * being set as the value for the "menu" configuration 
3199             * attribute.</em>
3200             * @default true
3201             * @type Boolean
3202                         * @writeonce
3203             */
3204             this.setAttributeConfig("lazyloadmenu", {
3205         
3206                 value: (oAttributes.lazyloadmenu === false ? false : true),
3207                 validator: Lang.isBoolean,
3208                 writeOnce: true
3209         
3210             });
3211
3212
3213             /**
3214             * @attribute menuclassname
3215             * @description String representing the CSS class name to be 
3216             * applied to the root element of the button's menu.
3217             * @type String
3218             * @default "yui-button-menu"
3219                         * @writeonce
3220             */
3221             this.setAttributeConfig("menuclassname", {
3222         
3223                 value: (oAttributes.menuclassname || (this.CLASS_NAME_PREFIX + "button-menu")),
3224                 validator: Lang.isString,
3225                 method: this._setMenuClassName,
3226                 writeOnce: true
3227         
3228             });        
3229
3230
3231                         /**
3232                         * @attribute menuminscrollheight
3233                         * @description Number defining the minimum threshold for the "menumaxheight" 
3234                         * configuration attribute.  When set this attribute is automatically applied 
3235                         * to all submenus.
3236                         * @default 90
3237                         * @type Number
3238                         */
3239             this.setAttributeConfig("menuminscrollheight", {
3240         
3241                 value: (oAttributes.menuminscrollheight || 90),
3242                 validator: Lang.isNumber
3243         
3244             });
3245
3246
3247             /**
3248             * @attribute menumaxheight
3249                         * @description Number defining the maximum height (in pixels) for a menu's 
3250                         * body element (<code>&#60;div class="bd"&#60;</code>).  Once a menu's body 
3251                         * exceeds this height, the contents of the body are scrolled to maintain 
3252                         * this value.  This value cannot be set lower than the value of the 
3253                         * "minscrollheight" configuration property.
3254             * @type Number
3255             * @default 0
3256             */
3257             this.setAttributeConfig("menumaxheight", {
3258         
3259                 value: (oAttributes.menumaxheight || 0),
3260                 validator: Lang.isNumber
3261         
3262             });
3263
3264
3265             /**
3266             * @attribute menualignment
3267                         * @description Array defining how the Button's Menu is aligned to the Button.  
3268             * The default value of ["tl", "bl"] aligns the Menu's top left corner to the Button's 
3269             * bottom left corner.
3270             * @type Array
3271             * @default ["tl", "bl"]
3272             */
3273             this.setAttributeConfig("menualignment", {
3274         
3275                 value: (oAttributes.menualignment || ["tl", "bl"]),
3276                 validator: Lang.isArray
3277         
3278             });
3279             
3280
3281             /**
3282             * @attribute selectedMenuItem
3283             * @description Object representing the item in the button's menu 
3284             * that is currently selected.
3285             * @type YAHOO.widget.MenuItem
3286             * @default null
3287             */
3288             this.setAttributeConfig("selectedMenuItem", {
3289         
3290                 value: null
3291         
3292             });
3293         
3294         
3295             /**
3296             * @attribute onclick
3297             * @description Object literal representing the code to be executed  
3298             * when the button is clicked.  Format:<br> <code> {<br> 
3299             * <strong>fn:</strong> Function,   &#47;&#47; The handler to call 
3300             * when the event fires.<br> <strong>obj:</strong> Object, 
3301             * &#47;&#47; An object to pass back to the handler.<br> 
3302             * <strong>scope:</strong> Object &#47;&#47;  The object to use 
3303             * for the scope of the handler.<br> } </code>
3304             * @type Object
3305             * @default null
3306             */
3307             this.setAttributeConfig("onclick", {
3308         
3309                 value: oAttributes.onclick,
3310                 method: this._setOnClick
3311             
3312             });
3313
3314
3315             /**
3316             * @attribute focusmenu
3317             * @description Boolean indicating whether or not the button's menu 
3318             * should be focused when it is made visible.
3319             * @type Boolean
3320             * @default true
3321             */
3322             this.setAttributeConfig("focusmenu", {
3323         
3324                 value: (oAttributes.focusmenu === false ? false : true),
3325                 validator: Lang.isBoolean
3326         
3327             });
3328
3329
3330             /**
3331             * @attribute replaceLabel
3332             * @description Boolean indicating whether or not the text of the 
3333                         * button's <code>&#60;label&#62;</code> element should be used as
3334                         * the source for the button's label configuration attribute and 
3335                         * removed from the DOM.
3336             * @type Boolean
3337             * @default false
3338             */
3339             this.setAttributeConfig("replaceLabel", {
3340         
3341                 value: false,
3342                 validator: Lang.isBoolean,
3343                 writeOnce: true
3344         
3345             });
3346
3347         },
3348         
3349         
3350         /**
3351         * @method focus
3352         * @description Causes the button to receive the focus and fires the 
3353         * button's "focus" event.
3354         */
3355         focus: function () {
3356         
3357             if (!this.get("disabled")) {
3358                 //Adding a try/catch in case the element is not
3359                 //  visible by the time it's focus is being called.
3360                 //  for example, on a dialog that closes on button click
3361                 try {
3362                     this._button.focus();
3363                 } catch (e) {}
3364             
3365             }
3366         
3367         },
3368         
3369         
3370         /**
3371         * @method blur
3372         * @description Causes the button to lose focus and fires the button's
3373         * "blur" event.
3374         */
3375         blur: function () {
3376         
3377             if (!this.get("disabled")) {
3378                 //Adding a try/catch in case the element is not
3379                 //  visible by the time it's focus is being called.
3380                 //  for example, on a dialog that closes on button click
3381                 try {
3382                     this._button.blur();
3383                 } catch (e) {}
3384         
3385             }
3386         
3387         },
3388         
3389         
3390         /**
3391         * @method hasFocus
3392         * @description Returns a boolean indicating whether or not the button 
3393         * has focus.
3394         * @return {Boolean}
3395         */
3396         hasFocus: function () {
3397         
3398             return (m_oFocusedButton == this);
3399         
3400         },
3401         
3402         
3403         /**
3404         * @method isActive
3405         * @description Returns a boolean indicating whether or not the button 
3406         * is active.
3407         * @return {Boolean}
3408         */
3409         isActive: function () {
3410         
3411             return this.hasClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME + "-active");
3412         
3413         },
3414         
3415         
3416         /**
3417         * @method getMenu
3418         * @description Returns a reference to the button's menu.
3419         * @return {<a href="YAHOO.widget.Overlay.html">
3420         * YAHOO.widget.Overlay</a>|<a 
3421         * href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
3422         */
3423         getMenu: function () {
3424         
3425             return this._menu;
3426         
3427         },
3428         
3429         
3430         /**
3431         * @method getForm
3432         * @description Returns a reference to the button's parent form.
3433         * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-
3434         * 20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>}
3435         */
3436         getForm: function () {
3437         
3438                 var oButton = this._button,
3439                         oForm;
3440         
3441             if (oButton) {
3442             
3443                 oForm = oButton.form;
3444             
3445             }
3446         
3447                 return oForm;
3448         
3449         },
3450         
3451         
3452         /** 
3453         * @method getHiddenFields
3454         * @description Returns an <code>&#60;input&#62;</code> element or 
3455         * array of form elements used to represent the button when its parent 
3456         * form is submitted.  
3457         * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3458         * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
3459         */
3460         getHiddenFields: function () {
3461         
3462             return this._hiddenFields;
3463         
3464         },
3465         
3466         
3467         /**
3468         * @method destroy
3469         * @description Removes the button's element from its parent element and 
3470         * removes all event handlers.
3471         */
3472         destroy: function () {
3473         
3474         
3475             var oElement = this.get("element"),
3476                 oMenu = this._menu,
3477                                 oLabel = this._label,
3478                 oParentNode,
3479                 aButtons;
3480         
3481             if (oMenu) {
3482         
3483
3484                 if (m_oOverlayManager && m_oOverlayManager.find(oMenu)) {
3485
3486                     m_oOverlayManager.remove(oMenu);
3487
3488                 }
3489         
3490                 oMenu.destroy();
3491         
3492             }
3493         
3494         
3495             Event.purgeElement(oElement);
3496             Event.purgeElement(this._button);
3497             Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
3498             Event.removeListener(document, "keyup", this._onDocumentKeyUp);
3499             Event.removeListener(document, "mousedown", this._onDocumentMouseDown);
3500
3501
3502                         if (oLabel) {
3503
3504                 Event.removeListener(oLabel, "click", this._onLabelClick);
3505                                 
3506                                 oParentNode = oLabel.parentNode;
3507                                 oParentNode.removeChild(oLabel);
3508                                 
3509                         }
3510         
3511         
3512             var oForm = this.getForm();
3513             
3514             if (oForm) {
3515         
3516                 Event.removeListener(oForm, "reset", this._onFormReset);
3517                 Event.removeListener(oForm, "submit", this._onFormSubmit);
3518         
3519             }
3520
3521
3522             this.unsubscribeAll();
3523
3524                         oParentNode = oElement.parentNode;
3525
3526             if (oParentNode) {
3527
3528                 oParentNode.removeChild(oElement);
3529             
3530             }
3531         
3532         
3533             delete m_oButtons[this.get("id")];
3534
3535                         var sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
3536
3537             aButtons = Dom.getElementsByClassName(sClass, 
3538                                 this.NODE_NAME, oForm); 
3539
3540             if (Lang.isArray(aButtons) && aButtons.length === 0) {
3541
3542                 Event.removeListener(oForm, "keypress", 
3543                         YAHOO.widget.Button.onFormKeyPress);
3544
3545             }
3546
3547         
3548         },
3549         
3550         
3551         fireEvent: function (p_sType , p_aArgs) {
3552         
3553                         var sType = arguments[0];
3554                 
3555                         //  Disabled buttons should not respond to DOM events
3556                 
3557                         if (this.DOM_EVENTS[sType] && this.get("disabled")) {
3558                 
3559                                 return false;
3560                 
3561                         }
3562                 
3563                         return YAHOO.widget.Button.superclass.fireEvent.apply(this, arguments);
3564         
3565         },
3566         
3567         
3568         /**
3569         * @method toString
3570         * @description Returns a string representing the button.
3571         * @return {String}
3572         */
3573         toString: function () {
3574         
3575             return ("Button " + this.get("id"));
3576         
3577         }
3578     
3579     });
3580     
3581     
3582     /**
3583     * @method YAHOO.widget.Button.onFormKeyPress
3584     * @description "keypress" event handler for the button's form.
3585     * @param {Event} p_oEvent Object representing the DOM event object passed 
3586     * back by the event utility (YAHOO.util.Event).
3587     */
3588     YAHOO.widget.Button.onFormKeyPress = function (p_oEvent) {
3589     
3590         var oTarget = Event.getTarget(p_oEvent),
3591             nCharCode = Event.getCharCode(p_oEvent),
3592             sNodeName = oTarget.nodeName && oTarget.nodeName.toUpperCase(),
3593             sType = oTarget.type,
3594     
3595             /*
3596                 Boolean indicating if the form contains any enabled or 
3597                 disabled YUI submit buttons
3598             */
3599     
3600             bFormContainsYUIButtons = false,
3601     
3602             oButton,
3603     
3604             oYUISubmitButton,   // The form's first, enabled YUI submit button
3605     
3606             /*
3607                  The form's first, enabled HTML submit button that precedes any 
3608                  YUI submit button
3609             */
3610     
3611             oPrecedingSubmitButton,
3612             
3613             oEvent; 
3614     
3615     
3616         function isSubmitButton(p_oElement) {
3617     
3618             var sId,
3619                 oSrcElement;
3620     
3621             switch (p_oElement.nodeName.toUpperCase()) {
3622     
3623             case "INPUT":
3624             case "BUTTON":
3625             
3626                 if (p_oElement.type == "submit" && !p_oElement.disabled) {
3627                     
3628                     if (!bFormContainsYUIButtons && !oPrecedingSubmitButton) {
3629
3630                         oPrecedingSubmitButton = p_oElement;
3631
3632                     }
3633                 
3634                 }
3635
3636                 break;
3637             
3638
3639             default:
3640             
3641                 sId = p_oElement.id;
3642     
3643                 if (sId) {
3644     
3645                     oButton = m_oButtons[sId];
3646         
3647                     if (oButton) {
3648
3649                         bFormContainsYUIButtons = true;
3650         
3651                         if (!oButton.get("disabled")) {
3652
3653                             oSrcElement = oButton.get("srcelement");
3654     
3655                             if (!oYUISubmitButton && (oButton.get("type") == "submit" || 
3656                                 (oSrcElement && oSrcElement.type == "submit"))) {
3657
3658                                 oYUISubmitButton = oButton;
3659                             
3660                             }
3661                         
3662                         }
3663                         
3664                     }
3665                 
3666                 }
3667
3668                 break;
3669     
3670             }
3671     
3672         }
3673     
3674     
3675         if (nCharCode == 13 && ((sNodeName == "INPUT" && (sType == "text" || 
3676             sType == "password" || sType == "checkbox" || sType == "radio" || 
3677             sType == "file")) || sNodeName == "SELECT")) {
3678     
3679             Dom.getElementsBy(isSubmitButton, "*", this);
3680     
3681     
3682             if (oPrecedingSubmitButton) {
3683     
3684                 /*
3685                      Need to set focus to the first enabled submit button
3686                      to make sure that IE includes its name and value 
3687                      in the form's data set.
3688                 */
3689     
3690                 oPrecedingSubmitButton.focus();
3691             
3692             }
3693             else if (!oPrecedingSubmitButton && oYUISubmitButton) {
3694     
3695                                 /*
3696                                         Need to call "preventDefault" to ensure that the form doesn't end up getting
3697                                         submitted twice.
3698                                 */
3699     
3700                         Event.preventDefault(p_oEvent);
3701
3702
3703                                 if (UA.ie) {
3704                                 
3705                                         oYUISubmitButton.get("element").fireEvent("onclick");
3706                                 
3707                                 }
3708                                 else {
3709
3710                                         oEvent = document.createEvent("HTMLEvents");
3711                                         oEvent.initEvent("click", true, true);
3712                         
3713
3714                                         if (UA.gecko < 1.9) {
3715                                         
3716                                                 oYUISubmitButton.fireEvent("click", oEvent);
3717                                         
3718                                         }
3719                                         else {
3720
3721                                                 oYUISubmitButton.get("element").dispatchEvent(oEvent);
3722                                         
3723                                         }
3724   
3725                 }
3726
3727             }
3728             
3729         }
3730     
3731     };
3732     
3733     
3734     /**
3735     * @method YAHOO.widget.Button.addHiddenFieldsToForm
3736     * @description Searches the specified form and adds hidden fields for  
3737     * instances of YAHOO.widget.Button that are of type "radio," "checkbox," 
3738     * "menu," and "split."
3739     * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3740     * one-html.html#ID-40002357">HTMLFormElement</a>} p_oForm Object reference 
3741     * for the form to search.
3742     */
3743     YAHOO.widget.Button.addHiddenFieldsToForm = function (p_oForm) {
3744     
3745         var proto = YAHOO.widget.Button.prototype,
3746                         aButtons = Dom.getElementsByClassName(
3747                                                         (proto.CLASS_NAME_PREFIX + proto.CSS_CLASS_NAME), 
3748                             "*", 
3749                             p_oForm),
3750     
3751             nButtons = aButtons.length,
3752             oButton,
3753             sId,
3754             i;
3755     
3756         if (nButtons > 0) {
3757     
3758     
3759             for (i = 0; i < nButtons; i++) {
3760     
3761                 sId = aButtons[i].id;
3762     
3763                 if (sId) {
3764     
3765                     oButton = m_oButtons[sId];
3766         
3767                     if (oButton) {
3768            
3769                         oButton.createHiddenFields();
3770                         
3771                     }
3772                 
3773                 }
3774             
3775             }
3776     
3777         }
3778     
3779     };
3780     
3781
3782     /**
3783     * @method YAHOO.widget.Button.getButton
3784     * @description Returns a button with the specified id.
3785     * @param {String} p_sId String specifying the id of the root node of the 
3786     * HTML element representing the button to be retrieved.
3787     * @return {YAHOO.widget.Button}
3788     */
3789     YAHOO.widget.Button.getButton = function (p_sId) {
3790
3791                 return m_oButtons[p_sId];
3792
3793     };
3794     
3795     
3796     // Events
3797     
3798     
3799     /**
3800     * @event focus
3801     * @description Fires when the menu item receives focus.  Passes back a  
3802     * single object representing the original DOM event object passed back by 
3803     * the event utility (YAHOO.util.Event) when the event was fired.  See 
3804     * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3805     * for more information on listening for this event.
3806     * @type YAHOO.util.CustomEvent
3807     */
3808     
3809     
3810     /**
3811     * @event blur
3812     * @description Fires when the menu item loses the input focus.  Passes back  
3813     * a single object representing the original DOM event object passed back by 
3814     * the event utility (YAHOO.util.Event) when the event was fired.  See 
3815     * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for  
3816     * more information on listening for this event.
3817     * @type YAHOO.util.CustomEvent
3818     */
3819     
3820     
3821     /**
3822     * @event option
3823     * @description Fires when the user invokes the button's option.  Passes 
3824     * back a single object representing the original DOM event (either 
3825     * "mousedown" or "keydown") that caused the "option" event to fire.  See 
3826     * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3827     * for more information on listening for this event.
3828     * @type YAHOO.util.CustomEvent
3829     */
3830
3831 })();
3832 (function () {
3833
3834     // Shorthard for utilities
3835     
3836     var Dom = YAHOO.util.Dom,
3837         Event = YAHOO.util.Event,
3838         Lang = YAHOO.lang,
3839         Button = YAHOO.widget.Button,  
3840     
3841         // Private collection of radio buttons
3842     
3843         m_oButtons = {};
3844
3845
3846
3847     /**
3848     * The ButtonGroup class creates a set of buttons that are mutually 
3849     * exclusive; checking one button in the set will uncheck all others in the 
3850     * button group.
3851     * @param {String} p_oElement String specifying the id attribute of the 
3852     * <code>&#60;div&#62;</code> element of the button group.
3853     * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3854     * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
3855     * specifying the <code>&#60;div&#62;</code> element of the button group.
3856     * @param {Object} p_oElement Object literal specifying a set of 
3857     * configuration attributes used to create the button group.
3858     * @param {Object} p_oAttributes Optional. Object literal specifying a set 
3859     * of configuration attributes used to create the button group.
3860     * @namespace YAHOO.widget
3861     * @class ButtonGroup
3862     * @constructor
3863     * @extends YAHOO.util.Element
3864     */
3865     YAHOO.widget.ButtonGroup = function (p_oElement, p_oAttributes) {
3866     
3867         var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor,
3868             sNodeName,
3869             oElement,
3870             sId;
3871     
3872         if (arguments.length == 1 && !Lang.isString(p_oElement) && 
3873             !p_oElement.nodeName) {
3874     
3875             if (!p_oElement.id) {
3876     
3877                 sId = Dom.generateId();
3878     
3879                 p_oElement.id = sId;
3880     
3881     
3882             }
3883     
3884     
3885     
3886             fnSuperClass.call(this, (this._createGroupElement()), p_oElement);
3887     
3888         }
3889         else if (Lang.isString(p_oElement)) {
3890     
3891             oElement = Dom.get(p_oElement);
3892     
3893             if (oElement) {
3894             
3895                 if (oElement.nodeName.toUpperCase() == this.NODE_NAME) {
3896     
3897             
3898                     fnSuperClass.call(this, oElement, p_oAttributes);
3899     
3900                 }
3901     
3902             }
3903         
3904         }
3905         else {
3906     
3907             sNodeName = p_oElement.nodeName.toUpperCase();
3908     
3909             if (sNodeName && sNodeName == this.NODE_NAME) {
3910         
3911                 if (!p_oElement.id) {
3912         
3913                     p_oElement.id = Dom.generateId();
3914         
3915         
3916                 }
3917         
3918         
3919                 fnSuperClass.call(this, p_oElement, p_oAttributes);
3920     
3921             }
3922     
3923         }
3924     
3925     };
3926     
3927     
3928     YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {
3929     
3930     
3931         // Protected properties
3932         
3933         
3934         /** 
3935         * @property _buttons
3936         * @description Array of buttons in the button group.
3937         * @default null
3938         * @protected
3939         * @type Array
3940         */
3941         _buttons: null,
3942         
3943         
3944         
3945         // Constants
3946         
3947         
3948         /**
3949         * @property NODE_NAME
3950         * @description The name of the tag to be used for the button 
3951         * group's element. 
3952         * @default "DIV"
3953         * @final
3954         * @type String
3955         */
3956         NODE_NAME: "DIV",
3957
3958
3959         /**
3960         * @property CLASS_NAME_PREFIX
3961         * @description Prefix used for all class names applied to a ButtonGroup.
3962         * @default "yui-"
3963         * @final
3964         * @type String
3965         */
3966         CLASS_NAME_PREFIX: "yui-",
3967         
3968         
3969         /**
3970         * @property CSS_CLASS_NAME
3971         * @description String representing the CSS class(es) to be applied  
3972         * to the button group's element.
3973         * @default "buttongroup"
3974         * @final
3975         * @type String
3976         */
3977         CSS_CLASS_NAME: "buttongroup",
3978     
3979     
3980     
3981         // Protected methods
3982         
3983         
3984         /**
3985         * @method _createGroupElement
3986         * @description Creates the button group's element.
3987         * @protected
3988         * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3989         * level-one-html.html#ID-22445964">HTMLDivElement</a>}
3990         */
3991         _createGroupElement: function () {
3992         
3993             var oElement = document.createElement(this.NODE_NAME);
3994         
3995             return oElement;
3996         
3997         },
3998         
3999         
4000         
4001         // Protected attribute setter methods
4002         
4003         
4004         /**
4005         * @method _setDisabled
4006         * @description Sets the value of the button groups's 
4007         * "disabled" attribute.
4008         * @protected
4009         * @param {Boolean} p_bDisabled Boolean indicating the value for
4010         * the button group's "disabled" attribute.
4011         */
4012         _setDisabled: function (p_bDisabled) {
4013         
4014             var nButtons = this.getCount(),
4015                 i;
4016         
4017             if (nButtons > 0) {
4018         
4019                 i = nButtons - 1;
4020                 
4021                 do {
4022         
4023                     this._buttons[i].set("disabled", p_bDisabled);
4024                 
4025                 }
4026                 while (i--);
4027         
4028             }
4029         
4030         },
4031         
4032         
4033         
4034         // Protected event handlers
4035         
4036         
4037         /**
4038         * @method _onKeyDown
4039         * @description "keydown" event handler for the button group.
4040         * @protected
4041         * @param {Event} p_oEvent Object representing the DOM event object  
4042         * passed back by the event utility (YAHOO.util.Event).
4043         */
4044         _onKeyDown: function (p_oEvent) {
4045         
4046             var oTarget = Event.getTarget(p_oEvent),
4047                 nCharCode = Event.getCharCode(p_oEvent),
4048                 sId = oTarget.parentNode.parentNode.id,
4049                 oButton = m_oButtons[sId],
4050                 nIndex = -1;
4051         
4052         
4053             if (nCharCode == 37 || nCharCode == 38) {
4054         
4055                 nIndex = (oButton.index === 0) ? 
4056                             (this._buttons.length - 1) : (oButton.index - 1);
4057             
4058             }
4059             else if (nCharCode == 39 || nCharCode == 40) {
4060         
4061                 nIndex = (oButton.index === (this._buttons.length - 1)) ? 
4062                             0 : (oButton.index + 1);
4063         
4064             }
4065         
4066         
4067             if (nIndex > -1) {
4068         
4069                 this.check(nIndex);
4070                 this.getButton(nIndex).focus();
4071             
4072             }        
4073         
4074         },
4075         
4076         
4077         /**
4078         * @method _onAppendTo
4079         * @description "appendTo" event handler for the button group.
4080         * @protected
4081         * @param {Event} p_oEvent Object representing the event that was fired.
4082         */
4083         _onAppendTo: function (p_oEvent) {
4084         
4085             var aButtons = this._buttons,
4086                 nButtons = aButtons.length,
4087                 i;
4088         
4089             for (i = 0; i < nButtons; i++) {
4090         
4091                 aButtons[i].appendTo(this.get("element"));
4092         
4093             }
4094         
4095         },
4096         
4097         
4098         /**
4099         * @method _onButtonCheckedChange
4100         * @description "checkedChange" event handler for each button in the 
4101         * button group.
4102         * @protected
4103         * @param {Event} p_oEvent Object representing the event that was fired.
4104         * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4105         * p_oButton Object representing the button that fired the event.
4106         */
4107         _onButtonCheckedChange: function (p_oEvent, p_oButton) {
4108         
4109             var bChecked = p_oEvent.newValue,
4110                 oCheckedButton = this.get("checkedButton");
4111         
4112             if (bChecked && oCheckedButton != p_oButton) {
4113         
4114                 if (oCheckedButton) {
4115         
4116                     oCheckedButton.set("checked", false, true);
4117         
4118                 }
4119         
4120                 this.set("checkedButton", p_oButton);
4121                 this.set("value", p_oButton.get("value"));
4122         
4123             }
4124             else if (oCheckedButton && !oCheckedButton.set("checked")) {
4125         
4126                 oCheckedButton.set("checked", true, true);
4127         
4128             }
4129            
4130         },
4131         
4132         
4133         
4134         // Public methods
4135         
4136         
4137         /**
4138         * @method init
4139         * @description The ButtonGroup class's initialization method.
4140         * @param {String} p_oElement String specifying the id attribute of the 
4141         * <code>&#60;div&#62;</code> element of the button group.
4142         * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4143         * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
4144         * specifying the <code>&#60;div&#62;</code> element of the button group.
4145         * @param {Object} p_oElement Object literal specifying a set of  
4146         * configuration attributes used to create the button group.
4147         * @param {Object} p_oAttributes Optional. Object literal specifying a
4148         * set of configuration attributes used to create the button group.
4149         */
4150         init: function (p_oElement, p_oAttributes) {
4151         
4152             this._buttons = [];
4153         
4154             YAHOO.widget.ButtonGroup.superclass.init.call(this, p_oElement, 
4155                     p_oAttributes);
4156         
4157             this.addClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
4158
4159         
4160             var sClass = (YAHOO.widget.Button.prototype.CLASS_NAME_PREFIX + "radio-button"),
4161                                 aButtons = this.getElementsByClassName(sClass);
4162
4163         
4164         
4165             if (aButtons.length > 0) {
4166         
4167         
4168                 this.addButtons(aButtons);
4169         
4170             }
4171         
4172         
4173         
4174             function isRadioButton(p_oElement) {
4175         
4176                 return (p_oElement.type == "radio");
4177         
4178             }
4179         
4180             aButtons = 
4181                 Dom.getElementsBy(isRadioButton, "input", this.get("element"));
4182         
4183         
4184             if (aButtons.length > 0) {
4185         
4186         
4187                 this.addButtons(aButtons);
4188         
4189             }
4190         
4191             this.on("keydown", this._onKeyDown);
4192             this.on("appendTo", this._onAppendTo);
4193         
4194
4195             var oContainer = this.get("container");
4196
4197             if (oContainer) {
4198         
4199                 if (Lang.isString(oContainer)) {
4200         
4201                     Event.onContentReady(oContainer, function () {
4202         
4203                         this.appendTo(oContainer);            
4204                     
4205                     }, null, this);
4206         
4207                 }
4208                 else {
4209         
4210                     this.appendTo(oContainer);
4211         
4212                 }
4213         
4214             }
4215         
4216         
4217         
4218         },
4219         
4220         
4221         /**
4222         * @method initAttributes
4223         * @description Initializes all of the configuration attributes used to  
4224         * create the button group.
4225         * @param {Object} p_oAttributes Object literal specifying a set of 
4226         * configuration attributes used to create the button group.
4227         */
4228         initAttributes: function (p_oAttributes) {
4229         
4230             var oAttributes = p_oAttributes || {};
4231         
4232             YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
4233                 this, oAttributes);
4234         
4235         
4236             /**
4237             * @attribute name
4238             * @description String specifying the name for the button group.  
4239             * This name will be applied to each button in the button group.
4240             * @default null
4241             * @type String
4242             */
4243             this.setAttributeConfig("name", {
4244         
4245                 value: oAttributes.name,
4246                 validator: Lang.isString
4247         
4248             });
4249         
4250         
4251             /**
4252             * @attribute disabled
4253             * @description Boolean indicating if the button group should be 
4254             * disabled.  Disabling the button group will disable each button 
4255             * in the button group.  Disabled buttons are dimmed and will not 
4256             * respond to user input or fire events.
4257             * @default false
4258             * @type Boolean
4259             */
4260             this.setAttributeConfig("disabled", {
4261         
4262                 value: (oAttributes.disabled || false),
4263                 validator: Lang.isBoolean,
4264                 method: this._setDisabled
4265         
4266             });
4267         
4268         
4269             /**
4270             * @attribute value
4271             * @description Object specifying the value for the button group.
4272             * @default null
4273             * @type Object
4274             */
4275             this.setAttributeConfig("value", {
4276         
4277                 value: oAttributes.value
4278         
4279             });
4280         
4281         
4282             /**
4283             * @attribute container
4284             * @description HTML element reference or string specifying the id 
4285             * attribute of the HTML element that the button group's markup
4286             * should be rendered into.
4287             * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4288             * level-one-html.html#ID-58190037">HTMLElement</a>|String
4289             * @default null
4290                         * @writeonce
4291             */
4292             this.setAttributeConfig("container", {
4293         
4294                 value: oAttributes.container,
4295                 writeOnce: true
4296         
4297             });
4298         
4299         
4300             /**
4301             * @attribute checkedButton
4302             * @description Reference for the button in the button group that 
4303             * is checked.
4304             * @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4305             * @default null
4306             */
4307             this.setAttributeConfig("checkedButton", {
4308         
4309                 value: null
4310         
4311             });
4312         
4313         },
4314         
4315         
4316         /**
4317         * @method addButton
4318         * @description Adds the button to the button group.
4319         * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4320         * p_oButton Object reference for the <a href="YAHOO.widget.Button.html">
4321         * YAHOO.widget.Button</a> instance to be added to the button group.
4322         * @param {String} p_oButton String specifying the id attribute of the 
4323         * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4324         * to be used to create the button to be added to the button group.
4325         * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4326         * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
4327         * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
4328         * ID-33759296">HTMLElement</a>} p_oButton Object reference for the 
4329         * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4330         * to be used to create the button to be added to the button group.
4331         * @param {Object} p_oButton Object literal specifying a set of 
4332         * <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a> 
4333         * configuration attributes used to configure the button to be added to 
4334         * the button group.
4335         * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} 
4336         */
4337         addButton: function (p_oButton) {
4338         
4339             var oButton,
4340                 oButtonElement,
4341                 oGroupElement,
4342                 nIndex,
4343                 sButtonName,
4344                 sGroupName;
4345         
4346         
4347             if (p_oButton instanceof Button && 
4348                 p_oButton.get("type") == "radio") {
4349         
4350                 oButton = p_oButton;
4351         
4352             }
4353             else if (!Lang.isString(p_oButton) && !p_oButton.nodeName) {
4354         
4355                 p_oButton.type = "radio";
4356         
4357                 oButton = new Button(p_oButton);
4358
4359             }
4360             else {
4361         
4362                 oButton = new Button(p_oButton, { type: "radio" });
4363         
4364             }
4365         
4366         
4367             if (oButton) {
4368         
4369                 nIndex = this._buttons.length;
4370                 sButtonName = oButton.get("name");
4371                 sGroupName = this.get("name");
4372         
4373                 oButton.index = nIndex;
4374         
4375                 this._buttons[nIndex] = oButton;
4376                 m_oButtons[oButton.get("id")] = oButton;
4377         
4378         
4379                 if (sButtonName != sGroupName) {
4380         
4381                     oButton.set("name", sGroupName);
4382                 
4383                 }
4384         
4385         
4386                 if (this.get("disabled")) {
4387         
4388                     oButton.set("disabled", true);
4389         
4390                 }
4391         
4392         
4393                 if (oButton.get("checked")) {
4394         
4395                     this.set("checkedButton", oButton);
4396         
4397                 }
4398
4399                 
4400                 oButtonElement = oButton.get("element");
4401                 oGroupElement = this.get("element");
4402                 
4403                 if (oButtonElement.parentNode != oGroupElement) {
4404                 
4405                     oGroupElement.appendChild(oButtonElement);
4406                 
4407                 }
4408         
4409                 
4410                 oButton.on("checkedChange", 
4411                     this._onButtonCheckedChange, oButton, this);
4412         
4413         
4414             }
4415
4416                         return oButton;
4417         
4418         },
4419         
4420         
4421         /**
4422         * @method addButtons
4423         * @description Adds the array of buttons to the button group.
4424         * @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
4425         * YAHOO.widget.Button</a> instances to be added 
4426         * to the button group.
4427         * @param {Array} p_aButtons Array of strings specifying the id 
4428         * attribute of the <code>&#60;input&#62;</code> or <code>&#60;span&#62;
4429         * </code> elements to be used to create the buttons to be added to the 
4430         * button group.
4431         * @param {Array} p_aButtons Array of object references for the 
4432         * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> elements 
4433         * to be used to create the buttons to be added to the button group.
4434         * @param {Array} p_aButtons Array of object literals, each containing
4435         * a set of <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>  
4436         * configuration attributes used to configure each button to be added 
4437         * to the button group.
4438         * @return {Array}
4439         */
4440         addButtons: function (p_aButtons) {
4441     
4442             var nButtons,
4443                 oButton,
4444                 aButtons,
4445                 i;
4446         
4447             if (Lang.isArray(p_aButtons)) {
4448             
4449                 nButtons = p_aButtons.length;
4450                 aButtons = [];
4451         
4452                 if (nButtons > 0) {
4453         
4454                     for (i = 0; i < nButtons; i++) {
4455         
4456                         oButton = this.addButton(p_aButtons[i]);
4457                         
4458                         if (oButton) {
4459         
4460                             aButtons[aButtons.length] = oButton;
4461         
4462                         }
4463                     
4464                     }
4465                 
4466                 }
4467         
4468             }
4469
4470                         return aButtons;
4471         
4472         },
4473         
4474         
4475         /**
4476         * @method removeButton
4477         * @description Removes the button at the specified index from the 
4478         * button group.
4479         * @param {Number} p_nIndex Number specifying the index of the button 
4480         * to be removed from the button group.
4481         */
4482         removeButton: function (p_nIndex) {
4483         
4484             var oButton = this.getButton(p_nIndex),
4485                 nButtons,
4486                 i;
4487             
4488             if (oButton) {
4489         
4490         
4491                 this._buttons.splice(p_nIndex, 1);
4492                 delete m_oButtons[oButton.get("id")];
4493         
4494                 oButton.removeListener("checkedChange", 
4495                     this._onButtonCheckedChange);
4496
4497                 oButton.destroy();
4498         
4499         
4500                 nButtons = this._buttons.length;
4501                 
4502                 if (nButtons > 0) {
4503         
4504                     i = this._buttons.length - 1;
4505                     
4506                     do {
4507         
4508                         this._buttons[i].index = i;
4509         
4510                     }
4511                     while (i--);
4512                 
4513                 }
4514         
4515         
4516             }
4517         
4518         },
4519         
4520         
4521         /**
4522         * @method getButton
4523         * @description Returns the button at the specified index.
4524         * @param {Number} p_nIndex The index of the button to retrieve from the 
4525         * button group.
4526         * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4527         */
4528         getButton: function (p_nIndex) {
4529         
4530             return this._buttons[p_nIndex];
4531         
4532         },
4533         
4534         
4535         /**
4536         * @method getButtons
4537         * @description Returns an array of the buttons in the button group.
4538         * @return {Array}
4539         */
4540         getButtons: function () {
4541         
4542             return this._buttons;
4543         
4544         },
4545         
4546         
4547         /**
4548         * @method getCount
4549         * @description Returns the number of buttons in the button group.
4550         * @return {Number}
4551         */
4552         getCount: function () {
4553         
4554             return this._buttons.length;
4555         
4556         },
4557         
4558         
4559         /**
4560         * @method focus
4561         * @description Sets focus to the button at the specified index.
4562         * @param {Number} p_nIndex Number indicating the index of the button 
4563         * to focus. 
4564         */
4565         focus: function (p_nIndex) {
4566         
4567             var oButton,
4568                 nButtons,
4569                 i;
4570         
4571             if (Lang.isNumber(p_nIndex)) {
4572         
4573                 oButton = this._buttons[p_nIndex];
4574                 
4575                 if (oButton) {
4576         
4577                     oButton.focus();
4578         
4579                 }
4580             
4581             }
4582             else {
4583         
4584                 nButtons = this.getCount();
4585         
4586                 for (i = 0; i < nButtons; i++) {
4587         
4588                     oButton = this._buttons[i];
4589         
4590                     if (!oButton.get("disabled")) {
4591         
4592                         oButton.focus();
4593                         break;
4594         
4595                     }
4596         
4597                 }
4598         
4599             }
4600         
4601         },
4602         
4603         
4604         /**
4605         * @method check
4606         * @description Checks the button at the specified index.
4607         * @param {Number} p_nIndex Number indicating the index of the button 
4608         * to check. 
4609         */
4610         check: function (p_nIndex) {
4611         
4612             var oButton = this.getButton(p_nIndex);
4613             
4614             if (oButton) {
4615         
4616                 oButton.set("checked", true);
4617             
4618             }
4619         
4620         },
4621         
4622         
4623         /**
4624         * @method destroy
4625         * @description Removes the button group's element from its parent 
4626         * element and removes all event handlers.
4627         */
4628         destroy: function () {
4629         
4630         
4631             var nButtons = this._buttons.length,
4632                 oElement = this.get("element"),
4633                 oParentNode = oElement.parentNode,
4634                 i;
4635             
4636             if (nButtons > 0) {
4637         
4638                 i = this._buttons.length - 1;
4639         
4640                 do {
4641         
4642                     this._buttons[i].destroy();
4643         
4644                 }
4645                 while (i--);
4646             
4647             }
4648         
4649         
4650             Event.purgeElement(oElement);
4651             
4652         
4653             oParentNode.removeChild(oElement);
4654         
4655         },
4656         
4657         
4658         /**
4659         * @method toString
4660         * @description Returns a string representing the button group.
4661         * @return {String}
4662         */
4663         toString: function () {
4664         
4665             return ("ButtonGroup " + this.get("id"));
4666         
4667         }
4668     
4669     });
4670
4671 })();
4672 YAHOO.register("button", YAHOO.widget.Button, {version: "2.9.0", build: "2800"});