views:

198

answers:

4

I have a table of data and have one checkbox per row for the user to select the item.

I'm using the following jQuery code to allow the user to select the item by clicking anywhere in the row:

$("tbody tr").click(function() {
    var checkbox = $(this).find(':checkbox');
    checkbox.attr('checked', !checkbox.attr('checked'));
});

The problem is if I click directly on the checkbox, nothing happens. ie. if the checkbox is not checked, it remains unchecked. If I click anywhere else in the row, the checkbox changes status.

I'm thinking that the jQuery code is causing the action to be performed twice. If I click on the checkbox, the checkbox will change but then the jQuery code for clicking on the row will be performed and the checkbox will be changed back. Not sure if that is actually happening but that is my guess.

How can I get a checkbox to be toggled when a user clicks on a row and the same thing if they click directly on the checkbox?

A: 

You're catching a click event on the row. If the checkbox is within the TR then the event is getting triggered and you're inverting the "checked" attribute. One solution would be to place the event on each TD within the TR, except for the TD containing the checkbox.

Matt S
+3  A: 

Tt is because the checkbox is in the tbody tr. If you were to step through the code you would notice that it was checked but then unchecked by your click function. change your click function to exclude the td that holds the checkbox.

$("tbody tr td").click(function() { 
    if ($("input:checkbox", $(this)).length) {
       //td contains check box  do nothing
    } else {
      var checkbox = $(this).find(':checkbox'); 
      checkbox.attr('checked', !checkbox.attr('checked')); 
    }
}); 
John Hartsock
If the td contains anything else than the checkbox, eg a label, when you click the label, nothing will happen. Example: http://jsfiddle.net/crX7L/ . I posted another suggestion that looks at the event instead and decides what to do based on that
Simen Echholt
your absoutely right.
John Hartsock
A: 

If the problem is that the event is actually getting triggered twice (and that seems like a fair supposition), then you should try using the event.preventDefault() and event.stopPropagation() event methods. They should stop the event from reaching the checkbox itself.

yarmiganosca
Good Idea, but IMHO preventing the browser from implementing its default behavior should be the last resort. Preventing events from propogating can cause other issue when refactoring code or in future implementations.
John Hartsock
+2  A: 

Check what item is being clicked by checking the event information. Then if it's a checkbox, don't run the code. Otherwise, toggle the checked attribute

$("tbody tr").click(function(e) {
        e = e || event;
        var isCheckbox = $(e.target).is(":checkbox");
        if (!isCheckbox) {
            var checkbox = $(this).find(':checkbox');
            checkbox.attr('checked', !checkbox.attr('checked'));
        }
});
Simen Echholt
good solution and probably better than mine but you should add this line at the begining of the function. ( e = e || event; ) this will handle the event properly in browsers.
John Hartsock
Good point, edited my code
Simen Echholt