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