How to target all elements with a specific class in JavaScript

Issue

I’m currently working with WordPress and Bootstrap 5.

Due to WordPress limitations with the wp_nav_men function. I can’t see the markup at all. This means I can’t manually added classes here and there. I need to do this in order to get the Bootstrap sub menu navs to work. This means I need to use JavaScript to inject specific things to certain elements to

For me to achieve this, it would seem I need to get additional child nodes with the same class names to inherit the same JavaScript settings. Here’s what I am trying to do. Below I have listed what I see in the markup, the steps I would like to see happen, and what the JavaScript looks like currently.

MARKUP:

<ul id="mainNav" class="menu">
    <li id="menu-item-84" class="menu-item-has-children  highlight"><a href="" id="dropdownMenuLink" role="button" data-bs-toggle="dropdown" class="nav-link dropdown-toggle show" aria-expanded="true"></a>
        
        <ul class="sub-menu dropdown-menu show" style="position: absolute; inset: 0px auto auto 0px; margin: 0px; transform: translate3d(906px, 61px, 0px);" data-popper-placement="bottom-start">
            <li id="menu-item-269" class="menu-item-has-children"><a href=""></a>
                <ul class="sub-menu">
                    <li id="menu-item-271" class=""><a href=""></a></li>
                    <li id="menu-item-272" class=""><a href=""></a></li>
                    <li id="menu-item-270" class=""><a href=""></a></li>
                </ul>
            </li>
        </ul>
        
    </li>
    <li id="menu-item-101" class=""><a href="">Product</a></li>
    <li id="menu-item-103" class="menu-item-has-children"><a href="">About Us</a>
        <ul class="sub-menu">
            <li id="menu-item-228" class=""><a href="">About Us</a></li>
            <li id="menu-item-105" class=""><a href="">News and Events</a></li>
            <li id="menu-item-106" class=""><a href="">Join Our Team</a></li>
        </ul>
    </li>
    <li id="menu-item-99" class=""><a href="">Contact</a></li>
</ul>

STEP 1:
If any li with a class of .menu-item-has-children, add the following id, role, data-bs-toggle and class to the element.

STEP 2:
Any li with a with a class of .menu-item-has-children also with a ul will have a sub nav menu. Because of this, the sub nav menu must inherit the following class of dropdown-menu.

    // Toggle child menu item in main nav

    // assign expanse li to variable
    let liExpanse = document.querySelector('.menu-item-has-children');

    // check if nested ul is contained in parent li of main nav
    let liExpanseChild = document.querySelector('.sub-menu');

    // add id, role, data attributes to div
    function addAtt() {
        liExpanse.firstChild.setAttribute('id','dropdownMenuLink');
        liExpanse.firstChild.setAttribute('role','button');
        liExpanse.firstChild.setAttribute('data-bs-toggle','dropdown');
    }
    addAtt();

    // add classnames to divs
    function addClassName() {
        liExpanse.firstChild.classList.add('nav-link', 'dropdown-toggle');
        liExpanseChild.classList.add('dropdown-menu');
    }
    addClassName();

THOUGHTS:
I do notice that when using firstChild methods, it only looks for the first child. There is also a lastChild option, but what I am looking for is to find all nodes with a class of .menu-item-has-children, then do the following.

With some research and based on comments, I actually don’t want the querySelectorAll to pick up on all that is related to that class or ID. Just the one level.

Solution

Top-level elements will have .menu as their parent. You could also use #mainNav in its place. In css > means thing on the left is a direct parent of thing on the right.

Top-level anchor selector

document.querySelectorAll(".menu > .menu-item-has-children > a")

Top-level submenu selector

document.querySelectorAll(".menu > .menu-item-has-children > .sub-menu")

Using the id of the parent instead of the class, if its more convenient

document.querySelectorAll("#mainNav > .menu-item-has-children > .sub-menu")

Answered By – James

Answer Checked By – Pedro (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.