Archive

Archive for March, 2011

jQuery checkbox/radiobutton dependence plugin

March 29th, 2011

I have made a small jQuery plugin that enables you to have checkboxes and radiobuttons that depends on each other in a nested way.

The usage is very simple, just take a collection of radios or checkboxes and define an element they depend on. If you check an element that depends on something, the parent will be checked as well.

In the same way, if you uncheck a parent element that have children, then the children will be unchecked as well.

The plugin is designed to also work with jQuery UI buttons

$('#fruitlist>li>input').dependsOn('#fruits');
$('#citruslist input').dependsOn('#citrus');
<ul>
	<li><input type="radio" name="products" value="books">books</li>
	<li><input type="radio" name="products" id="fruits" value="fruits">fruits
		<ul id="fruitlist">
			<li><input type="checkbox">apples</li>
			<li><input type="checkbox" id="citrus">citrus fruits
				<ul id="citruslist">
					<li><input type="radio" name="citrus">lemons</li>
					<li><input type="radio" name="citrus">oranges</li>
				</ul>
			</li>
		</ul>
	</li>
	<li><input type="radio" name="products" value="pens">pens</li>
</ul>

Demo:


  • books
  • fruits

    • apples
    • citrus fruits

      • lemons
      • oranges
  • pens

Here is the code:

/* jQuery checkbox/radiobutton dependance plugin
* By Martin Hansen http://martinhansen.no
* MIT Licensed.
*/
(function($) {
  $.fn.dependsOn = function(parent) {
    // build main options before element iteration
    if(parent === undefined){ console.log('Parent is required'); return;   }        

    var opts = {parent: parent, value: null};

     //If parent is a radiobutton part of a group, make the group the parent
    if($(opts.parent).attr('type') == 'radio'){
      opts.origparent  = $(opts.parent);
      opts.parent = 'input[name=' +$(opts.parent).attr('name') +']';
    }  

    return this.each(function() {
    var caller = $(this);
    $.data(this, 'dependsOnOptions', opts);//Store the dependency options

    caller.bind('click iterate', function(event){
      var parent = (opts.origparent) ? opts.origparent : $(opts.parent);
      parent.attr('checked', true).trigger('iterate', ['Iterate', 'Event']);
      if (jQuery.ui)parent.button('refresh'); //If jquery ui is loaded try to refesh button
    });              

    $(opts.parent).each(function(i){
      var pp = $(this);
      //Do first time checks
      var checked = pp.attr('checked');
      if(checked){
        $.fn.dependsOn.check(pp, caller, opts);
      }
      //bind for change
      pp.change(function(event){
        $.fn.dependsOn.check($(this), caller, opts);
      });
    });

   });
  };     

   $.fn.dependsOn.check = function(parent, child, opts){
    if (!parent.is(':checked') || !$(opts.origparent).is(':checked')) {
      child.attr('checked', false).change(); //uncheck the checked child, and trigger the change event so that any potential grandchildren also gets updated
      if (jQuery.ui)parent.button('refresh'); //If jquery ui is loaded try to refesh button
    }
   };
})(jQuery);

On github: https://github.com/mokkabonna/jQuery-dependency

Edit:updated the code to use .is(‘:checked’) instead of .attr(‘checked’), as jQuery 1.6.3 returns ‘checked’ instead of true. Thanks to “all” in the comments for making me aware of if.

Martin Javascript