Two options (both involve removing the tr:not stuff from your existing code, which as you say doesn't work — tr elements can't be checkboxes, and :not checks the element, not its contents):
Add an event handler to the checkbox that calls e.stopPropagation. Then the click event won't reach the row. You can do that either directly or via delegation. Here's a live example going direct. If you go indirect, be sure to test clicking labels that activate the checkbox (if you're going to have them) on all of the browsers you intend to support.
or
Add this to your handler:
if ($(event.target).is('input[type=checkbox]')) {
return;
}
E.g.:
$('table').on('click', 'td', function(event) {
if ($(event.target).is('input[type=checkbox]')) {
return;
}
// Logic here
});
That works by testing the source of the event to see if it's a checkbox, and bailing early.
In both cases, if you use a label to activate the checkbox, you may need to do the same thing for the label.
I got curious about what #2 would look like handling labels, and it turns out it's enough code to move into a function, but not hard &mdash probably how I'd go: Live example | source
jQuery(function($) {
// The table cell click handler
$("table").on("click", "td", function(e) {
// Is the source a checkbox or the label for
// one?
if (isCheckbox($(e.target))) {
return;
}
// Normal handling
$(this).toggleClass("foo");
});
// Function to test whether the source is a
// checkbox, or the label of a checkbox
function isCheckbox($elm) {
var chkid;
if ($elm.is("input[type=checkbox]")) {
return true;
}
if ($elm.is("label")) {
chkid = $elm.attr("for");
if (chkid) {
return $("#" + chkid).is("input[type=checkbox]");
}
return !!$elm.find("input[type=checkbox]")[0];
}
return false;
}
});