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