I have the css class 'control', and I want to get all the 'control' children elements from my container, but I dont want to get grandsons 'control'.
<div id='mydiv'>
<div id='div1' class='control'>
<div id='div2' class='control'></div>
<div id='div3' class='control'></div>
</div>
<div class='other'>
<div id='div4' class='control'></div>
<div id='div5' class='control'>
<div id='div6' class='control'></div>
<div id='div7' class='control'></div>
</div>
</div>
</div>
The call below will get me all the controls inside 'mydiv'.
document.querySelectorAll('#mydiv .control');
I want a query that brings me only #div1, #div4 and #div5; Is that possible?
CodePudding user response:
With only querySelector*
it will not work at the moment.
In the future, browsers will support the :has()
pseudo-selector.
Then you can select only elements which has or not has elements inside them like this:
#mydiv .control:not(:has(.control))
See the current browser support for this: https://caniuse.com/css-has
For now you need following sulution:
const elements = [...document.querySelectorAll('#mydiv .control')].filter(element => {
return element.parentNode.closest('.control') == null
});
console.log(elements);
<div id='mydiv'>
<div id='div1' class='control'>
<div id='div2' class='control'></div>
<div id='div3' class='control'></div>
</div>
<div class='other'>
<div id='div4' class='control'></div>
<div id='div5' class='control'>
<div id='div6' class='control'></div>
<div id='div7' class='control'></div>
</div>
</div>
</div>
Explanation:
Get at first all .control
elements into an array (querySelectorAll
returns a NodeList
and NodeList
does'nt have methods like filter
. So we extract it with the spread syntax [...variable]
Then filter all elements which has no parent elements named .control
.
.closest()
can return itself, so we need to make sure we call parentNode
at first.