 /*
 /// jQuery ButtonGroup plugin
 /// jQuery is required !!!
 ///
 /// Copyright (c) 2010 Tom Gröger, TomSoft
 /// http://www.tomsoft.de/
 ///
 /// Version 1.62 - 11.04.2010
 /// Licensed under MIT License
 /// http://en.wikipedia.org/wiki/MIT_License
 ///
  */


////////////////////// Check- und RadioButtons & Groups //////////////////////////



$.fn.Checkbox = function(lbl) {
    /// <summary>
    /// JQuery plugin that wraps a Check- or Radiobutton Input and its associated 
    /// text label. The jQuery wrapper is extended with a disable and enable method that
    /// will not only enable/disable the button but also the label.
    /// If the wrapped control is a checkbutton then the native jQuery val()
    /// method is overwritten to set/get true/false values both reflecting and setting the checked state
    /// </summary>
    if (this.length == 0) {
        throw new Error("bad selector for Checkbox " + this.selector, "window.document");
        return this;
    };

    this.mode = this.get(0).type;
    this.button = this.get(0);
    this.label = $(lbl || "label[for='" + this.button.id + "']")

    // overwrite base.val() to set/get boolean values ( for checkbuttons only  )
    if (this.mode == "checkbox") {
        this.val = function(value) {
            // setter:
            if (arguments.length) {
                this.button.checked = (value);
            };
            // getter
            return this.button.checked;
        };

    };

    this.uncheck = function() {
        /// <summary>
        /// clears all check- and radiobuttons in the Group
        /// </summary>    
        this.button.checked = false;
        return this;
    };

    this.checked = function(bChecked) {
        /// <summary>
        /// gets or sets the checkded state of the checkbox
        /// </summary>    
        ///	<returns type="boolean">checked state</returns>
        if (arguments.length) {
            bChecked = (typeof (bChecked) == 'boolean') ? bChecked : true;
            this.button.checked = bChecked; // setter
            return this;
        };
        return this.button.checked;  // getter
    };

    this.enable = function(bEnable) {
        /// <summary>
        /// enable/disable checkbox and associated Label
        /// </summary>    
        bEnable = (typeof bEnable == 'boolean') ? bEnable : true;
        this.button.disabled = !bEnable;
        this.label.css("color", bEnable ? "" : "#aab")

        // uncheck disabled Radiobuttons
        if (!bEnable && this.mode == "radio")
            this.button.checked = false;

        return this;
    };

    this.disable = function() {
        /// <summary>
        /// diables  checkbox and associated Label
        /// </summary>    
        return this.enable(false);
    };

    return this;
};

$.fn.ButtonGroup = function(options) {
    /// <summary>
    /// This Control extends a jQuery object ( usually a table or fieldset ) that wraps &#xA;
    /// a couple of radio- or checkbox buttons together with associated labels.
    /// The ButtonGroup then allows you to easily set/get a Radio group's value,
    /// dis- or enable the complete Group (including labels) or only selected buttons,
    /// The modified get() method will return an extended button object that also
    /// 'understands' checked/enable/disable messages.
    /// By default the control takes and returns int-values, if no button is selected
    /// then the ButtonGroup.val() returns Zero only if Zero is not a valid value for 
    /// one of the Buttons, otherwise it returns -1
    /// </summary>
    /// <param name="e" type="number"></param>
    /// <returns type="jQuery" />

    if (this.length != 1) {
        throw new Error("bad selector for ButtonGroup " + this.selector, "window.document");
        return this;
    };

    // Extend our default options with the argument-options
    var opts = $.extend({
        nullValue: 0,   // defines the returnValue if no button is selected, default is Zero   
        valtype: "int"  // defines the primitive type of our returnValue, possible values are string, boolean, (default) int
    }, options);

    var items = [];
    var mode = _init(this);

    if (!mode) {
        throw new Error("No Buttons found in ButtonGroup " + this.selector, "window.document");
        return this;
    };

    if (mode === "check") {
        // CheckboxGroup
        // todo: set/get checkbuttons from bitarray
    }
    else {
        // RadioGroup
        this.val = function(value) {
            /// <summary>
            /// extend jQuery.val() to return or set the radioGroup-Value
            /// </summary>
            if (arguments.length) {
                value = value.toString();   // setter
                for (var i = 0; i < items.length; ++i) {
                    var j = items[i];
                    j.checked(false);
                    if (value == j.val()) {
                        j.checked(true);
                        break;
                    };
                };
                return this;
            };

            // getter, see if one of the buttons is selected and
            // return it's value as an integer, or a nullValue
            var j = this.selected();
            var retVal = j ? j.val() : opts.nullValue;

            switch (opts.valtype.toLowerCase()) {
                case "string":
                    return retVal.toString();
                case "boolean":
                    return (retVal > 0);
                default:
                    break;
            };
            return (isNaN(parseInt(retVal)) ? opts.nullValue : parseInt(retVal));
        };
    };


    this.enable = function(bEnable) {
        /// <summary>
        /// enables/disables the Checkbuttons in the Group and their associated Labels
        /// </summary>    
        bEnable = (typeof (bEnable) == 'boolean') ? bEnable : true;
        for (var i = 0; i < items.length; ++i) {
            items[i].enable(bEnable);
        }
        return this;
    };

    this.uncheck = function() {
        /// <summary>
        /// clears all check- and radiobuttons in the Group
        /// </summary>    
        for (var i = 0; i < items.length; ++i) {
            items[i].checked(false);
        }
        return this;
    };

    this.disable = function() {
        /// <summary>
        /// if called without arguments this method disables all checkboxes and associated Label
        /// of the Group. If numeric arguments are passed then all checkboxes of the group 
        /// are enabled except those which match the index position.
        /// </summary>
        /// <example>
        ///     $Controls.cbGroup.disable(1,4,5); 
        /// </example>    
        if (arguments.length) {
            for (var i = 0; i < items.length; ++i) {
                // check if pos i is in the argument list to be disabled
                var bEnable = ($.inArray(i, arguments) == -1);
                items[i].enable(bEnable);
            };
            return this;
        };
        return this.enable(false);
    };

    this.selected = function() {
        /// <summary>
        /// Radiogroup: returns the selected radiobutton within the group
        /// CheckGroup: returns the irst, checked checkbutton within the group
        /// </summary>
        for (var i = 0; i < items.length; ++i) {
            if (items[i].checked()) {
                return items[i];
            };
        };
        return null;
    };


    this.get = function(index) {
        /// <summary>
        ///
        /// Returns an extended button Object by position or ID(s):
        /// button.get( 0 )         returns first jLabelButton
        /// button.get( 0,2,3 )     returns an Array of jLabelButton in Position 0,2 and 3
        ///                         usage: $.each( button.get(0,..), function(){this.disable()})
        /// button.get("checked")   return selected jLabelButton
        /// button.get("all")       return list array of all jLabelButton
        ///
        /// </summary>

        var list = [];

        for (var cx = 0; cx < arguments.length; ++cx) {
            var arg = arguments[cx];

            if (typeof (arg) == 'string') {
                if (arg == "checked") return this.selected();
                if (arg == "all") return items;

                for (var i = 0; i < items.length; ++i) {
                    if (items[i].button.id == arg)
                        list.push(items[i]);
                };
            }
            else if (arg >= 0 && arg < items.length) {
                list.push(items[arg]);
            };
        };
        if (list.length)
            return (list.length == 1) ? list[0] : list;

        return;
    };
    return this;

    function _init(jObj) {
        /// <summary>
        /// Wraps all input[checkbox] or input[radio] controls and their associated labels
        /// inside an extended jQuery "LabelButton" object and saves that to our Group-Array
        /// return "check" or "radio", depending on the controls that are grouped                
        /// <summary>
        var mode = "radio";
        var len = 0;

        var jBtn = $("input:radio", jObj);
        if ((len = jBtn.size()) == 0) {
            mode = "check";
            jBtn = $("input:checkbox", jObj);
            if ((len = jBtn.size()) == 0) {
                return null;
            };
        };

        // search Labels, by default we are looking for the "label for" tag with our buttons id.
        // if that fails then we assume a 1:1 relation between radiobuttons and labels, 
        // iE label[2] belongs to radio[2] 
        var jLabel = $("label", jObj);
        for (var i = 0; i < len; ++i) {
             var lbl = $("label[for='" + jBtn.get(i).id + "']");
             if (lbl.size() == 0)
                 lbl = jLabel.get(i);
             items.push($(jBtn.get(i)).Checkbox(lbl));
        };
        return mode;

    };


};

