5

The Goal

I want to select <td> elements that contain only a checkbox. I want to do this with a single selector (not using chaining or logic outside the selector) so that I can use the selector with jQuery functions like live or delegate.

The bigger pictures is that I want to listen for a click event on these <td>s and pass the click event on to the checkbox, thus creating a larger clicking area. This is important, because the <tr> also has a different click event that I don't want to activate when users click and miss the checkbox.

The specifics

I created a jsfiddle with an example scenario: http://jsfiddle.net/ytA3X/

This is what I started with that is not working. In other words, select any td element that has a checkbox but does not have anything that is not a checkbox.

$('td:has(:checkbox):not(:has(:not(:checkbox)))')
=> []

:not(:has(...)) works in my jsfiddle example.

:has(:not(...)) works in my jsfiddle example.

:not(:has(:not(...))) always seems to select nothing.

Is there a different way that I can select td elements with only a checkbox, or am I doing something wrong?

Edward Anderson
  • 13,591
  • 4
  • 52
  • 48
  • So what is your question, you want to select `td` that has only one checkbox element and no other element? – Selvakumar Arumugam May 29 '12 at 18:04
  • Any specific reason you aren't using to increase the clicking area? Also why are you using a table? Is the data you're presenting tabular? – Madara's Ghost May 29 '12 at 18:08
  • Yes, it's a data table. That's really irrelevant to the question though - you don't need to be the the table police. Even if I were using other elements, I would still have the same problem. What were you saying about increasing the clicking area though? Looks like you left out a word that might have made that comment useful ;-) – Edward Anderson May 30 '12 at 00:59

4 Answers4

8

How about using :only-child:

$('td:has(:checkbox:only-child)')...

JSFiddle

Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
2

Don't do it with one selector, it will make your code hard to read and extremely hard to maintain and debug.

$('td:has(input[type="checkbox"])').filter(function(){
    return $(this).children().length === 1
});

Live DEMO

gdoron
  • 147,333
  • 58
  • 291
  • 367
  • But then I can't use delegate or live to watch for the click event with a dynamic form. – Edward Anderson May 29 '12 at 18:03
  • 3
    @nilbus: What do you mean? You can still chain `.live` after the call to `.filter`. – mellamokb May 29 '12 at 18:05
  • @nilbus add a class to all matching elements that in the delegation. – Madara's Ghost May 29 '12 at 18:10
  • Do you really need to do a `===` check for length property? – Selvakumar Arumugam May 29 '12 at 18:11
  • @Vega. You don't **need** to, but `===` is faster than `==`, and always using only this comparison operator can saves you from trouble. – gdoron May 29 '12 at 18:13
  • @gdoron Is it true that `===` is faster than `==`? >> http://jsperf.com/equals-operator <<. I agree that using `===` is better but not in this specific case.. – Selvakumar Arumugam May 29 '12 at 18:19
  • @gdoron I understand completely and I agree that using `===` is better.. but What I was trying to say is `===` is not faster if the types are the same and it is not THE BEST in this specific case as you had mentioned.. Well to be honest, it is not even a matter of concern to have it discussed so much >.< .. Just trying to explain what I meant. – Selvakumar Arumugam May 29 '12 at 18:30
  • @Vega. You're right, in this case, it just a good habit... :) End. – gdoron May 29 '12 at 18:32
  • From the jQuery docs: "Chaining methods is not supported. For example, $("a").find(".offsite, .external").live( ... ); is not valid and does not work as expected." Unless filter is special, I'm pretty sure that doesn't work. – Edward Anderson May 29 '12 at 19:30
  • @nilbus. What jQuery version are you using? why do you still using the deprecated `live` function? – gdoron May 29 '12 at 20:38
  • @ the app is using 1.4.4 where .on isn't available yet. I hesitate to upgrade until I have time to test thoroughly. – Edward Anderson May 30 '12 at 00:49
2

You can use the only-child selector:

$('td:has(:checkbox:only-child)')

Here it is in use with your markup.

FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
1

You can simply use .not instead and split it into two separate selectors:

http://jsfiddle.net/ytA3X/1/

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405