3

Simple functionality, I want to toggle checking/unchecking checkboxes based on changing a top level checkbox.

The problem is that Toggle/Click event handlers have inherent issues. If you try to bind these handlers to an input checkbox, the default checking behavior of the box fails.

So, I tried to use the Change handler in one of two different ways.

     $('input.all_neighborhoods').change(function(){
    if($(this).not(':checked')){
        $(this).closest('li').siblings('li').find('input[name=neighborhood_id]').attr('checked','checked');
    }
    else{
        $(this).closest('li').siblings('li').find('input[name=neighborhood_id]').removeAttr('checked');
    }

    });

Here, the first change works as you'd expect. All sibling checkboxes are selected and checked. However, when I click again to uncheck, nothing happens. The event handler doesn't work.

I then tried this:

   $('input.all_neighborhoods').change(function(){
    $(this).attr( 'checked', $(this).is( ':checked' ) ? $(this).closest('li').siblings('li').find('input[name=neighborhood_id]').attr('checked','checked'): $(this).removeAttr('checked').closest('li').siblings('li').find('input[name=neighborhood_id]').removeAttr('checked') );
}); 

Here, the sibling checkboxes effectively toggle. However, the main on/off switch checkbox stays checked.

Is the issue here related to the fact that they are all siblings and the main checkbox is not the parent?

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
Ben
  • 15,010
  • 11
  • 58
  • 90
  • Hey Brendan, perhaps you could provide some of the HTML markup as well - I'm having a hard time visualizing what is going on without seeing the structure. If you have a live link as well, that would make it really easy to solve. – SikoSoft Apr 24 '11 at 16:50

1 Answers1

5

(Warning, shameless self-promotion ahead). I've written a jQuery plugin that handles all of this messiness for you. No need to reinvent the wheel.

Check it out: http://mjball.github.com/jQuery-CheckAll/


If you want to stick with your current method, here's how to fix it:

$('input.all_neighborhoods').change(function() {
    $(this).closest('li')
        .siblings('li')
        .find('input[name=neighborhood_id]').attr('checked', this.checked);
}

Just pass a boolean to .attr(). Also, as per When to use Vanilla JavaScript vs. jQuery? don't use

$(this).is(':checked')

Instead use

this.checked

It's fewer characters to write, doesn't require any jQuery, and is way more efficient.

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • I got sick of writing the master/slave logic after the 3rd time or so, and it was really not much work to turn it into a plugin. – Matt Ball Apr 24 '11 at 16:53
  • Ahhh, I wish I could just do this without a plugin. I will try this out though, thanks Matt – Ben Apr 24 '11 at 16:56
  • @Bredan: you _can_ do it without a plugin. The plugin just makes it nicely encapsulated and reusable. The actual code is < 100 lines - that includes lots of whitespace and [Allman-style indentation](http://en.wikipedia.org/wiki/Indent_style#Allman_style) - so you should be able to go through the code and understand what it does. – Matt Ball Apr 24 '11 at 17:01
  • Brilliant. Also, thanks for the link, I'm a noob and am trying to figure out efficiency as I go – Ben Apr 24 '11 at 17:02