3

For example, if I have a snippet of a document:

<div> <!-- I have a reference to this: "outerDiv". -->
  <p> <!-- This is the <p> I want to select. -->
    <div>
      <p> <!-- I don't want to select this <p>. --> </p>
    </div>
  </p>
</div>

(This is a hypothetical document. HTML parsers would not actually construct a DOM that looks like this.)

and a reference to the outermost <div> element, I'd like to somehow use outerDiv.querySelectorAll('p') to select only the <p> elements that are direct children of the outer <div>.

I can't use outerDiv.childNodes and search for the <p> elements because I actually have a selector that is much longer than "p" (e.g., it might look like "p > a > b"). I also don't have control over the HTML and can't use jQuery or other JavaScript libraries.

It's also not sufficient to prepend "div > " to the selector and apply it from outerDiv.parentNode since the inner <p> also matches "div > p".

Is there a clean way to do this without having to parse the CSS selector myself, too much?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
ide
  • 19,942
  • 5
  • 64
  • 106
  • The only solution I know of requires looking directly at a subset of the `childNodes`. However, you say "I actually have a selector that is much longer than `p`." Can you post a more realistic selector that better reflects your situation? – Chris Calo Oct 23 '11 at 23:53

2 Answers2

3

Supposing that you have a reference to the outer div you can use the below expression:

outerDiv.querySelectorAll(":scope > p");

This expression will select all p elements that are direct children of outerDiv element because as referred on developer.mozilla.org

When used from a DOM API such as querySelector(), querySelectorAll(), matches(), or Element.closest(), :scope matches the element you called the method on.


(in the following code snippet I dont use the example with paragraph because is wrong to put a div or p element inside a p element. Check these links about this: Stack Overflow & Mozilla Developer)

//reference to outer div
let outerDiv = document.getElementById("outerDiv");

let selected = outerDiv.querySelectorAll(":scope > div");

console.log(selected);//it returns only the direct child div
<div id="outerDiv"> <!-- I have a reference to this: "outerDiv". -->
  <div class="I want this"> <!-- This is the <div> I want to select. -->
     <div class="I dont want this"> <!-- I don't want to select this <div>. --></div>
  </div>
</div>
Nick Pantelidis
  • 455
  • 4
  • 12
2

Can you use body > div > p or whatever lies outside of the outermost div?

Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • No, my elements may be arbitrarily deep and this gets hairy when there are multiple siblings with the same tag name higher up (starts requiring `:nth-child` in the selector). – ide Apr 08 '11 at 01:44
  • can you set rules for `div > p` and then re-set the nested `div > p > div > p` to what it was before..? – Billy Moon Apr 08 '11 at 01:50
  • 1
    I'm not sure if this is what you meant, but your comment gave me an idea. I can temporarily attach a class to the outer `
    ` (`outerDiv.className = "unique-name-123"`) and then apply `".unique-name-123 > p"`.
    – ide Apr 08 '11 at 01:55
  • @ide: That would still select both `p` tags, wouldn't it? See my answer. – BoltClock Apr 08 '11 at 02:05