Somebody on the jQuery Google Group asked the other day about toggling a checkbox within a table row when the user clicked anywhere within the row. This can be a nice feature to have, and it's also very straightforward to implement.
The one tricky part is that we don't want to trigger the click if the user clicks on the checkbox itself, because then it would effectively be clicked twice, once by the user and once programmatically. To avoid this, we can use the event argument inside the click handler. Let's take a look at how the code might be written:
Line 3 makes sure that the
type attribute of the
target element is not "checkbox." If it isn't, then line 4 finds all checkboxes within the clicked table row (
this) and clicks them.
Give it a shot:
Adding a "Selected" Class
While we're at it, we can add a "selected" class to rows when they are clicked. This way, the user will have one more visual indicator that the checkbox has been checked. We'll use the
.toggleClass() method so that it adds the class if it isn't there, and removes it if it is:
Notice that the
.toggleClass() line is outside of the
if statement. We want the class to toggle whether the actual target of the click is on the checkbox or not.
If you look carefully at this table, you'll notice that the second row has a little problem. Since its checkbox is initially checked, the first click on that row adds the "selected" class while it also unchecks the checkbox.
Initializing the "Selected" Class
We can fix this problem by making sure that all rows that have a checked checkbox are given the "selected" class when the page loads:
Line 3 filters the matched set of table rows to include only those that have checked checkboxes. After the "selected" class is added to those rows, line 5 reverts the matched set to all rows (within #rowclick3). Then we carry on with binding the click handler to the rows. This example should work as expected:
These rows are also enhanced by a little CSS rule:
As of jQuery 1.3, the
.toggleClass() part of this code doesn't appear to work. In fact, it is being fired twice on each click. The problem has arisen because event bubbling is now supported for the
.trigger() method. As the documentation states, "All triggered events now bubble up the DOM tree. For example if you trigger an event on a [checkbox] then it will trigger on that element first, then on the parent element, and its parent, and so on up to the document."
So, how can we get the script working again the way it was intended? I have two solutions, and I welcome others.
Bind to the Checkbox
The first solution involves binding a click handler directly to the checkboxes for the
.toggleClass(). In this way, we take advantage of the triggered event bubbling.
- $('#rowclick4 tr')
This fixes the problem, but I'm not crazy about it. It doubles the number of elements that have events bound to them, and I've been trying lately to reduce bound elements.
The second solution forgoes the click trigger in favor of simply changing the value of the checkbox's
I used an anonymous function for the
.attr() method's second argument because it seemed the most efficient way to toggle the value.
Both solutions work, but I prefer the second. Again, if you have a better idea, please let me know (by posting it in the comments).
With the updates, this hardly qualifies as a quick tip anymore. Oh well—back to our regularly scheduled blog post.…
This sort of thing can be done with other elements as well: clicking on a containing element to trigger the click of an element inside it. If we try to achieve this effect with links, though, we'll have to do it a little differently. Here is a quick example:
Keep in mind that this will send the user to the
href of the first link inside the div.