A jQuery-Room for RadioGroups

Wednesday, 30 December 2009 16:14 by Tom Gröger

Please note: This Code has been revised and replaced by the ButtonGroup plugin!

So one day I had enough of reading about the oh-so great jQuery Library and decided to give it a try. After all what could be so exciting about a JavaScript library ? Just a couple of methods to select a Dom element? Man, was I wrong - learning jQuery completely changed my way of programming.

More than a year later now I have moved most of my UI code into my JavaScript Framework, using jQuery as my Control-container and Ajax engine ( and for all the other neat stuff that it does ). One thing I always stumbled upon was the use of Radio buttons; like Check buttons they can be checked or not, but unlike them they can be combined to a Radio group that returns a value. My first shot was to wrap the Radio group into a jQuery object and then work on it:

<div id="container">
<input type="radio" id="rad1" name="radKult" value="1" />
<label for="rad1">free drinks</label>
<input type="radio" id="rad2" name="radKult" value="2" />
<label for="rad1">paid drinks</label>
</div>
// Create RadioGroup wrapper and set/get value
jGroup = $("#container input:radio");
var sel = jGroup.filter(':checked').val()
jGroup.attr("checked", "checked");


Ok, that worked somehow, but honestly it was a pain in the rear and most of the time I found myself working with the Dom elements again. The other problem I had with this approach was that while I could easily enable or disable the Radio buttons, but not the attached Labels.

So, finally I came across this problem once too many and sat down to write a jQuery plug-in:


The RadioGroup Control:


The Control should be an extended jQuery object with some methods added and others overwritten. The jQuery part would only wrap the radio buttons,  and the inner class keeps its own a list of radio button objects and associated labels.

  • The val() method is overwritten to easily return and set the Radio group's value
  • The enable() and disable() methods should enable and disable either the complete group (including labels) or only selected buttons
  • The modified get() method will return an extended Radio button object that also understands checked/enable/disable messages


The Code itself is simple and straightforward, inside my controls I do prefer to use the DOM methods ( for performance reasons ) whenever possible:


   ////////////////////// RadioGroup //////////////////////////
    

$.fn.RadioGroup = function() {
/// <summary>
/// JQuery plugin that creates a TomSoft.Form.RadioGroup object and
/// attaches this to the Wrapper of the RadioGroup-Container.
/// <returns type="jQuery" />

if (this.length != 1) {
throw new Error("bad selector for RadioGroup " + this.selector,
"window.document");
return this;
}

var items = [];
_init(this);

//
// JQuery object extensions
//
this.val = function(value) {
/// <summary>
/// Returns the value of the checked radio button within the Group
/// or checks the radiobutton with the given value. if the value
/// does not exist then the radiogroup remains unchecked
/// </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
var j = this.selected();
return ((j) ? j.val() : -1);
};

this.enable = function(bEnable) {
/// <summary>
/// enable/disable RadioGroup and associated Labels
/// </summary>
bEnable = (typeof (bEnable) == 'boolean') ? bEnable : true;
for (var i = 0; i < items.length; ++i) {
items[i].enable(bEnable);
}
return this;
};

this.disable = function() {
/// <summary>
/// if called without arguments the method disables all RadioButton
/// and associated Labels. If numeric arguments are passed then
/// all RadioButtons of the group are enabled except those with
/// matching the index position.
/// </summary>
/// <example>
/// $Controls.radioGroupHerkunft.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>
/// Returns the checked radiobutton 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 modified RadioButton Object by position or ID(s):
///
/// radio.get( 0 ) returns first jRadioLabel
/// radio.get( 0,2,3 ) returns Array of buttons in Pos 0,2 and 3
/// usage: $.each( radio.get(0,..),
/// function(){this.disable()})
/// radio.get("checked") return selected jRadioLabel
/// radio.get("all") return list array of all Radio Buttons
/// </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].radio.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;


//
// Initialize the object
//
function _init(jObj) {

var jLabel = $("label", jObj);
var jRadio = $(":radio", jObj);
for (var i = 0; i < jRadio.size(); ++i) {
items.push(_jRadioLabel(jRadio.get(i), jLabel.get(i)));
};
};

//
// Creates a modified jQuery Object-Wrapper for the given Radio/Label pair
// The jQuery radio Object has some added methods and properties:
// .radio: returns the dom-RadioButton Object
// .label returns the jQuery-Label Object
// .checked: gets/sets the checked state of the RadioButton
//
function _jRadioLabel(radio, label) {

var jRadio = $(radio);

jRadio.radio = radio;
jRadio.label = $(label);

if (jRadio.label.size() == 1)
label.htmlFor = radio.id;

jRadio.checked = function(bChecked) {
/// <summary>
/// gets or sets the checkded state of the RadioButton
/// </summary>
/// <returns type="boolean">checked state</returns>
if (arguments.length) {
bChecked = (typeof (bChecked) == 'boolean') ? bChecked : true;
radio.checked = bChecked; // setter
return jRadio;
};
return radio.checked; // getter
};

jRadio.enable = function(bEnable) {
/// <summary>
/// enable/disable RadioButton and associated Label
/// </summary>
bEnable = (typeof (bEnable) == 'boolean') ? bEnable : true;
radio.disabled = !bEnable;
jRadio.label.css("color", bEnable ? "" : "#ccc")
if (!bEnable) radio.checked = false;
return jRadio;
};

jRadio.disable = function() {
/// <summary>
/// diables RadioButton and associated Label
/// </summary>
return jRadio.enable(false);
};

return jRadio;
};
};


Using the RadioGroup Control:



The usage should be intuitive and easy, yet give you access to every single element of the Radio Group:
jGroup=$("#container").RadioGroup();  // Create extended RadioGroup Object
jGroup.disable(0);                    // disable the first button
jGroup.disable(0,3,4);                // disable a list of radio buttons
jGroup.val("1"); // Set a value and so select a button db.IDRadio = jGroup.val().toInt(); // read the radio group into a field ..
jGroup.get(0); // returns first button as jQuery object jGroup.get(1,2); // returns Array of two jQuery radio buttons jGroup.get("checked"); // return selected jQuery radio button
var domRadio = jGroup.get(0).radio; // access the radio Dom object var domLabel = jGroup.get(0).label; // access the label Dom object

 

Resources:




  ,
  ASP.NET | JavaScript | jQuery
  E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed