1

I would like to write jQuery statements like:

$(".someparentcontainer input[type=checkbox]:is(.foo, .bar, .xyz)")

As a shorthand for:

$(".someparentcontainer input[type=checkbox].foo, .someparentcontainer input[type=checkbox].bar, .someparentcontainer input[type=checkbox].xyz)")

Since jQuery doesn't support (to my knowledge) an :is() selector I came up with the following workaround:

$(".someparentcontainer input[type=checkbox]:not(:not(.foo, .bar, .xyz))")

I do realize that it has its drawbacks in terms of performance if .someparentcontainer has a ton of child elements, but it works pretty well for small dom-trees.

Are there any pitfalls I might be missing here? Any scenarios where this technique might fail?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
XDS
  • 3,786
  • 2
  • 36
  • 56

2 Answers2

2

You can use jquery's find function:

$("#someparentcontainer").find("#foo, #bar, #xyz").css('color', 'red')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="someparentcontainer">
  <div id="foo">foo</div>
  <div id="bar">bar</div>
  <div id="abc">abc</div>
</div>
<div id="xyz">xyz</div>

Which makes much more sense.

Dekel
  • 60,707
  • 10
  • 101
  • 129
  • +1 for the tip on find. Breaking the selector in two pieces would however pose some issues when/if utility functions are involved, if said functions expect a unified selector. Things are bound to get harder if said utility functions are part of third party libraries. The .find() approach has its advantages but at a price similar to that of using :not(:not()). Feel free to tip me off in case I'm missing something. – XDS Oct 04 '16 at 19:38
1

Are there any pitfalls I might be missing here? Any scenarios where this technique might fail?

As you've tagged your question , the standard does not allow :not() to be nested within another :not(). Every known implementation of :not() in the standard correctly treats what you have as invalid. If jQuery allows this (I can't say I'm surprised if it does), then this is non-standard and you need to be very careful not to rely on it outside of jQuery (for example, it won't work in querySelectorAll(), or in CSS).

The recommended way to do this is to use .filter() instead:

// If you know that the element with any of these ids is always a checkbox,
// substitute ".someparentcontainer *" for the second selector string
$(".someparentcontainer input[type=checkbox]").filter(".foo, .bar, .xyz")

But this means you have to write two separate selector strings. Then again, there's no way to do this with a single standards-compliant complex selector until Selectors 4's :matches() is implemented anyway (see Does jQuery have something like the :any or :matches pseudo-class?).

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • I guess your answer sums up the one landmine that people should keep an eye out for. So I will accept it as the answer. Thanks for the insight! – XDS Oct 05 '16 at 07:49