Yahoo! UI Library

Button  2.2.0

Yahoo! UI Library > button > buttongroup.js (source view)

(function() {

// Shorthard for utilities

var Dom = YAHOO.util.Dom,
    Event = YAHOO.util.Event,
    Lang = YAHOO.lang,
    Button = YAHOO.widget.Button;    

    // Private collection of radio buttons

    m_oButtons = {};



/**
* The ButtonGroup class creates a set of buttons that are mutually exclusive; 
* checking one button in the set will uncheck all others in the button group.
* @param {String} p_oElement String specifying the id attribute of the 
* <code>&#60;div&#62;</code> element of the button group.
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
* specifying the <code>&#60;div&#62;</code> element of the button group.
* @param {Object} p_oElement Object literal specifying a set of 
* configuration attributes used to create the button group.
* @param {Object} p_oAttributes Optional. Object literal specifying a set of 
* configuration attributes used to create the button group.
* @namespace YAHOO.widget
* @class ButtonGroup
* @constructor
* @extends YAHOO.util.Element
*/
YAHOO.widget.ButtonGroup = function(p_oElement, p_oAttributes) {

    var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor;

    if(
        arguments.length == 1 && 
        !Lang.isString(p_oElement) && 
        !p_oElement.nodeName
    ) {

        if(!p_oElement.id) {

            var sId = Dom.generateId();

            p_oElement.id = sId;

            YAHOO.log(
                "No value specified for the button group's \"id\" attribute. " +
                "Setting button group id to \"" + sId + "\".",
                "warn"
            );

        }

        this.logger = new YAHOO.widget.LogWriter("ButtonGroup " + sId);

        this.logger.log(
                "No source HTML element.  "  +
                "Building the button group using the set of " + 
                "configuration attributes."
            );

        fnSuperClass.call(this, (this._createGroupElement()), p_oElement);

    }
    else if(Lang.isString(p_oElement)) {

        var me = this;

        Event.onContentReady(p_oElement, function() {
        
            if(this.nodeName.toUpperCase() == me.TAG_NAME) {

                me.logger = 
                    new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement);
        
                fnSuperClass.call(me, this, p_oAttributes);

            }

        });
    
    }
    else {

        var sNodeName = p_oElement.nodeName;

        if(sNodeName && sNodeName == this.TAG_NAME) {
    
            if(!p_oElement.id) {
    
                p_oElement.id = Dom.generateId();
    
                YAHOO.log(
                    "No value specified for the button group's \"id\" " +
                    "attribute. Setting button group id " +
                    "to \"" + p_oElement.id + "\".",
                    "warn"
                );
    
            }
    
            this.logger = 
                    new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement.id);
    
            fnSuperClass.call(this, p_oElement, p_oAttributes);

        }

    }

};


YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {


// Protected properties


/** 
* @property _buttons
* @description Array of buttons in the button group.
* @default null
* @protected
* @type Array
*/
_buttons: null,


/** 
* @property _oninitAttributeValue
* @description Object reference to the button group's current value for the 
* "oninit" configuration attribute.
* @default null
* @protected
* @type Object
*/
_oninitAttributeValue: null,



// Constants


/**
* @property TAG_NAME
* @description The name of the tag to be used for the button group's element. 
* @default "DIV"
* @final
* @type String
*/
TAG_NAME: "DIV",


/**
* @property CSS_CLASS_NAME
* @description String representing the CSS class(es) to be applied to the 
* button group's element.
* @default "yuibuttongroup"
* @final
* @type String
*/
CSS_CLASS_NAME: "yuibuttongroup",



// Protected methods


/**
* @method _createGroupElement
* @description Creates the button group's element.
* @protected
* @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
* level-one-html.html#ID-22445964">HTMLDivElement</a>}
*/
_createGroupElement: function() {

    var oElement = document.createElement(this.TAG_NAME);

    oElement.className = this.CSS_CLASS_NAME;

    return oElement;

},



// Protected attribute setter methods


/**
* @method _setDisabled
* @description Sets the value of the button groups's "disabled" attribute.
* @protected
* @param {Boolean} p_bDisabled Boolean indicating the value for the button
* group's "disabled" attribute.
*/
_setDisabled: function(p_bDisabled) {

    var nButtons = this.getCount();

    if(nButtons > 0) {

        var i = nButtons - 1;
        
        do {

            this._buttons[i].set("disabled", p_bDisabled);
        
        }
        while(i--);

    }

},


/**
* @method _setOnInit
* @description Sets the value of the button group's "init" attribute.
* @protected
* @param {Object} p_oObject Object indicating the value for the button's 
* "oninit" attribute.
*/
_setOnInit: function(p_oObject) {

    /*
        Remove any existing listeners if a "init" event handler has already 
        been specified.
    */

    if(
        this._oninitAttributeValue && 
        (this._oninitAttributeValue != p_oObject)
    ) {

        this.removeListener("init", this._oninitAttributeValue.fn);

        this._oninitAttributeValue = null;

    }


    if(
        !this._oninitAttributeValue && 
        Lang.isObject(p_oObject) && 
        Lang.isFunction(p_oObject.fn)
    ) {

        this.on("init", p_oObject.fn, p_oObject.obj, p_oObject.scope);

        this._oninitAttributeValue = p_oObject;

    }

},


// Protected event handlers


/**
* @method _onKeyDown
* @description "keydown" event handler for the button group.
* @protected
* @param {Event} p_oEvent Object representing the DOM event object passed 
* back by the event utility (YAHOO.util.Event).
*/
_onKeyDown: function(p_oEvent) {

    var oTarget = Event.getTarget(p_oEvent),
        nCharCode = Event.getCharCode(p_oEvent),
        sId = oTarget.parentNode.parentNode.id,
        oButton = m_oButtons[sId],
        nIndex = -1;


    if(nCharCode == 37 || nCharCode == 38) {

        nIndex = (oButton.index === 0) ? 
                    (this._buttons.length -1) : (oButton.index - 1);
    
    }
    else if(nCharCode == 39 || nCharCode == 40) {

        nIndex = (oButton.index === (this._buttons.length - 1)) ? 
                    0 : (oButton.index + 1);

    }


    if(nIndex > -1) {

        this.check(nIndex);
        this.getButton(nIndex).focus();
    
    }        

},


/**
* @method _onAppendTo
* @description "appendTo" event handler for the button group.
* @protected
* @param {Event} p_oEvent Object representing the event that was fired.
*/
_onAppendTo: function(p_oEvent) {

    var aButtons = this._buttons,
        nButtons = aButtons.length;

    for(var i=0; i<nButtons; i++) {

        aButtons[i].appendTo(this.get("element"));

    }

},


/**
* @method _onButtonCheckedChange
* @description "checkedChange" event handler for each button in the 
* button group.
* @protected
* @param {Event} p_oEvent Object representing the event that was fired.
* @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} p_oButton 
* Object representing the button that 
* fired the event.
*/
_onButtonCheckedChange: function(p_oEvent, p_oButton) {

    var bChecked = p_oEvent.newValue,
        oCheckedButton = this.get("checkedButton");

    if(bChecked && oCheckedButton != p_oButton) {

        if(oCheckedButton) {

            oCheckedButton.set("checked", false, true);

        }

        this.set("checkedButton", p_oButton);
        this.set("value", p_oButton.get("value"));

    }
    else if(oCheckedButton && !oCheckedButton.set("checked")) {

        oCheckedButton.set("checked", true, true);

    }
   
},



// Public methods


/**
* @method init
* @description The ButtonGroup class's initialization method.
* @param {String} p_oElement String specifying the id attribute of the 
* <code>&#60;div&#62;</code> element of the button group.
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
* specifying the <code>&#60;div&#62;</code> element of the button group.
* @param {Object} p_oElement Object literal specifying a set of configuration 
* attributes used to create the button group.
* @param {Object} p_oAttributes Optional. Object literal specifying a set of 
* configuration attributes used to create the button group.
*/
init: function(p_oElement, p_oAttributes) {

    this._buttons = [];

    YAHOO.widget.ButtonGroup.superclass.init.call(
            this, p_oElement, 
            p_oAttributes
        );


    this.logger.log(
        "Searching for child nodes with the class name " +
        "\"yuibutton\" to add to the button group."
    );

    var aButtons = this.getElementsByClassName("yuibutton");


    if(aButtons.length > 0) {

        this.logger.log(
            "Found " + aButtons.length + " child nodes with the class " + 
            "name \"yuibutton.\"  Attempting to add to button group."
        );

        this.addButtons(aButtons);

    }


    this.logger.log(
        "Searching for child nodes with the type of \"radio\" to add to the " +
        " button group."
    );

    function isRadioButton(p_oElement) {

        return (p_oElement.type == "radio");

    }

    aButtons = Dom.getElementsBy(isRadioButton, "input", this.get("element"));


    if(aButtons.length > 0) {

        this.logger.log(
            "Found " + aButtons.length + " child nodes with the type of " +
            "\"radio.\"  Attempting to add to button group."
        );

        this.addButtons(aButtons);

    }

    this.on("keydown", this._onKeyDown);
    this.on("appendTo", this._onAppendTo);

    var oContainer = this.get("container");

    if(oContainer) {

        if(Lang.isString(oContainer)) {

            var me = this;

            Event.onContentReady(oContainer, function() {

                me.appendTo(this);            
            
            });

        }
        else {

            this.appendTo(oContainer);

        }

    }


    this.fireEvent("init");

    this.logger.log("Initialization completed.");

},


/**
* @method initAttributes
* @description Initializes all of the configuration attributes used to create  
* the button group.
* @param {Object} p_oAttributes Object literal specifying a set of 
* configuration attributes used to create the button group.
*/
initAttributes: function(p_oAttributes) {

    var oAttributes = p_oAttributes || {};

    YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
        this, 
        oAttributes
    );


    /**
    * @config name
    * @description String specifying the name for the button group.  This
    * name will be applied to each button in the button group.
    * @default null
    * @type String
    */
    this.setAttributeConfig("name", {

        value: oAttributes.name,
        validator: Lang.isString

    });


    /**
    * @config disabled
    * @description Boolean indicating if the button group should be disabled.  
    * Disabling the button group will disable each button in the button group.  
    * Disabled buttons are dimmed and will not respond to user input 
    * or fire events.
    * @default false
    * @type Boolean
    */
    this.setAttributeConfig("disabled", {

        value: (oAttributes.disabled || false),
        validator: Lang.isBoolean,
        method: this._setDisabled

    });


    /**
    * @config value
    * @description Object specifying the value for the button group.
    * @default null
    * @type Object
    */
    this.setAttributeConfig("value", {

        value: oAttributes.value

    });


	/**
	* @config container
	* @description HTML element reference or string specifying the id 
	* attribute of the HTML element that the button group's markup should be 
	* rendered into.
	* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
	* level-one-html.html#ID-58190037">HTMLElement</a>|String
	* @default null
	*/
    this.setAttributeConfig("container", {

        value: oAttributes.container

    });


	/**
	* @config checkedButton
    * @description Reference for the button in the button group that 
    * is checked.
	* @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
	* @default null
	*/
    this.setAttributeConfig("checkedButton", {

        value: null

    });


	/**
	* @config oninit
    * @description Object literal representing the code to be executed when 
    * the button group is initialized.  Format:<br> <code> {<br> 
    * <strong>fn:</strong> Function,   &#47;&#47; The handler to call when the 
    * event fires.<br> <strong>obj:</strong> Object, &#47;&#47; An object to 
    * pass back to the handler.<br> <strong>scope:</strong> Object &#47;&#47; 
    * The object to use for the scope of the handler.<br> } </code>
    * @type Object
	* @default null
	*/
    this.setAttributeConfig("oninit", {

        value: oAttributes.oninit,
        method: this._setOnInit
    
    });

},


/**
* @method addButton
* @description Adds the button to the button group.
* @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} p_oButton 
* Object reference for the <a href="YAHOO.widget.Button.html">
* YAHOO.widget.Button</a> instance to be added to the button group.
* @param {String} p_oButton String specifying the id attribute of the 
* <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element to be 
* used to create the button to be added to the button group.
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
* one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
* http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
* ID-33759296">HTMLElement</a>} p_oButton Object reference for the 
* <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element to be 
* used to create the button to be added to the button group.
* @param {Object} p_oButton Object literal specifying a set of 
* <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a> configuration 
* attributes used to configure the button to be added to the button group.
* @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} 
*/
addButton: function(p_oButton) {

    var oButton;


    if(p_oButton instanceof Button && p_oButton.get("type") == "radio") {

        oButton = p_oButton;

    }
    else if(!Lang.isString(p_oButton) && !p_oButton.nodeName) {

        p_oButton.type = "radio";

        oButton = new Button(p_oButton);
    
    }
    else {

        oButton = new Button(p_oButton, { type: "radio" });

    }


    if(oButton) {

        var nIndex = this._buttons.length,
            sButtonName = oButton.get("name"),
            sGroupName = this.get("name");

        oButton.index = nIndex;

        this._buttons[nIndex] = oButton;
        m_oButtons[oButton.get("id")] = oButton;


        if(sButtonName != sGroupName) {

            oButton.set("name", sGroupName);
        
        }


        if(this.get("disabled")) {

            oButton.set("disabled", true);

        }


        if(oButton.get("checked")) {

            this.set("checkedButton", oButton);

        }

        
        oButton.on("checkedChange", this._onButtonCheckedChange, oButton, this);

        this.logger.log("Button " + oButton.get("id") + " added.");

        return oButton;

    }

},


/**
* @method addButtons
* @description Adds the array of buttons to the button group.
* @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
* YAHOO.widget.Button</a> instances to be added 
* to the button group.
* @param {Array} p_aButtons Array of strings specifying the id attribute of 
* the <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> elements to 
* be used to create the buttons to be added to the button group.
* @param {Array} p_aButtons Array of object references for the 
* <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> elements to be 
* used to create the buttons to be added to the button group.
* @param {Array} p_aButtons Array of object literals, each containing a set of 
* <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a> configuration 
* attributes used to configure each button to be added to the button group.
* @return {Array}
*/
addButtons: function(p_aButtons) {

    if(Lang.isArray(p_aButtons)) {
    
        var nButtons = p_aButtons.length,
            oButton,
            aButtons = [];

        if(nButtons > 0) {

            for(var i=0; i<nButtons; i++) {

                oButton = this.addButton(p_aButtons[i]);
                
                if(oButton) {

                    aButtons[aButtons.length] = oButton;

                }
            
            }

            if(aButtons.length > 0) {

                this.logger.log(aButtons.length + " buttons added.");

                return aButtons;

            }
        
        }

    }

},


/**
* @method removeButton
* @description Removes the button at the specified index from the button group.
* @param {Number} p_nIndex Number specifying the index of the button to be 
* removed from the button group.
*/
removeButton: function(p_nIndex) {

    var oButton = this.getButton(p_nIndex);
    
    if(oButton) {

        this.logger.log("Removing button " + oButton.get("id") + ".");

        this._buttons.splice(p_nIndex, 1);
        delete m_oButtons[oButton.get("id")];

        oButton.removeListener("checkedChange", this._onButtonCheckedChange);
        oButton.destroy();


        var nButtons = this._buttons.length;
        
        if(nButtons > 0) {

            var i = this._buttons.length - 1;
            
            do {

                this._buttons[i].index = i;

            }
            while(i--);
        
        }

        this.logger.log("Button " + oButton.get("id") + " removed.");

    }

},


/**
* @method getButton
* @description Returns the button at the specified index.
* @param {Number} p_nIndex The index of the button to retrieve from the 
* button group.
* @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
*/
getButton: function(p_nIndex) {

    if(Lang.isNumber(p_nIndex)) {

        return this._buttons[p_nIndex];

    }

},


/**
* @method getButtons
* @description Returns an array of the buttons in the button group.
* @return {Array}
*/
getButtons: function() {

    return this._buttons;

},


/**
* @method getCount
* @description Returns the number of buttons in the button group.
* @return {Number}
*/
getCount: function() {

    return this._buttons.length;

},


/**
* @method focus
* @description Sets focus to the button at the specified index.
* @param {Number} p_nIndex Number indicating the index of the button to focus. 
*/
focus: function(p_nIndex) {

    var oButton;

    if(Lang.isNumber(p_nIndex)) {

        oButton = this._buttons[p_nIndex];
        
        if(oButton) {

            oButton.focus();

        }
    
    }
    else {

        var nButtons = this.getCount();

        for(var i=0; i<nButtons; i++) {

            oButton = this._buttons[i];

            if(!oButton.get("disabled")) {

                oButton.focus();
                break;

            }

        }

    }

},


/**
* @method check
* @description Checks the button at the specified index.
* @param {Number} p_nIndex Number indicating the index of the button to check. 
*/
check: function(p_nIndex) {

    var oButton = this.getButton(p_nIndex);
    
    if(oButton) {

        oButton.set("checked", true);
    
    }

},


/**
* @method destroy
* @description Removes the button group's element from its parent element and 
* removes all event handlers.
*/
destroy: function() {

    this.logger.log("Destroying...");

    var nButtons = this._buttons.length,
        oElement = this.get("element"),
        oParentNode = oElement.parentNode;
    
    if(nButtons > 0) {

        var i = this._buttons.length - 1;
        
        do {

            this._buttons[i].destroy();

        }
        while(i--);
    
    }

    this.logger.log("Removing DOM event handlers.");

    Event.purgeElement(oElement);
    
    this.logger.log("Removing from document.");

    oParentNode.removeChild(oElement);

},


/**
* @method toString
* @description Returns a string representing the button group.
* @return {String}
*/
toString: function() {

    return ("ButtonGroup " + this.get("id"));

}

});



// Events


/**
* @event init
* @description Fires when the button group is initialized.  Subscribe to this 
* event by specifying a value for the "oninit" configuration attribute.  
* Format:<br> <code> {<br> <strong>fn:</strong> Function,   &#47;&#47; The 
* handler to call when the event fires.<br> <strong>obj:</strong> Object, 
* &#47;&#47; An object to pass back to the handler.<br> <strong>scope:</strong>
* Object &#47;&#47; The object to use for the scope of the handler.<br> 
* } </code>
* @type YAHOO.util.CustomEvent
*/

})();

Copyright © 2007 Yahoo! Inc. All rights reserved.