carte
carte

Reputation: 1083

Translate jQuery selector to javascript querySelector

I am trying to replicate this jQuery selector using querySelector:

$("*:not(#player > div)")

I know I can select all the elements using querySelector('*'), but how do I exclude the elements matching #player > div

Upvotes: 4

Views: 725

Answers (2)

BoltClock
BoltClock

Reputation: 724342

Most jQuery selectors can be ported to querySelector() or CSS, but not all of them, as jQuery extends certain existing ones, along with introducing entirely non-standard selectors altogether.

In your particular case, unlike in jQuery, :not() only accepts a simple selector in CSS. #player > div is a complex selector, consisting of two simple selectors and a combinator. See this question for details:

Why is my jQuery :not() selector not working in CSS?

There is no standardized equivalent for your jQuery selector. You will have to exclude #player > div elements separately, by doing document.querySelectorAll('#player > div'), and removing elements matching that set from your original set of elements.

... well, actually, while there isn't a way to express :not(#player > div) in a single complex selector, because of the > combinator it is still possible to enumerate all the possibilities using no fewer than four complex selectors:

:root, :not(#player) > div, #player > :not(div), :not(#player) > :not(div)

Here's a proof-of-concept:

// The following JS + CSS should give all matching elements a 1px solid red border
$(':not(#player > div)').css('border-color', 'red');
* { margin: 10px; }
html::before { content: 'html - Match'; }
body::before { content: 'body - Match'; }

:root, :not(#player) > div, #player > :not(div), :not(#player) > :not(div) {
  border-style: solid;
  border-width: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>body > p - Match</p>
<div>body > div - Match</div>
<div>
  body > div:not(#player) - Match
  <p>:not(#player) > p - Match</p>
  <div>:not(#player) > div - Match</div>
</div>
<div id=player>
  body > div#player - Match
  <p>#player > p - Match</p>
  <div>
    #player > div - Non-match
    <div>#player > div:not(#player) > div - Match</div>
  </div>
</div>

But you're still much better off either selecting those elements and removing them from your original set as described above, or just grabbing a matches() polyfill and excluding elements that way.

Upvotes: 3

Imesh Chandrasiri
Imesh Chandrasiri

Reputation: 5679

Use this to remove the unwanted elements.

var el = Array.prototype.slice.call(document.querySelectorAll('*'),0)
el.splice(el.indexOf(document.querySelectorAll('html')),1)

Upvotes: 0

Related Questions