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