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