Home > Software design >  How to Query Select all children of a class, but no grandsons of that class
How to Query Select all children of a class, but no grandsons of that class

Time:05-24

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.

  • Related