WordPress now features the ability to toggle both parent menu items when clicked, providing a more streamlined user experience

I am currently facing an issue with a menu structure, where parent menu items have submenus that need to toggle on click.

However, I am encountering a problem where, upon placing the code inside a forEach loop, both submenus toggle instead of only toggling the submenu of the clicked parent item.

Is there a way to instruct JavaScript to toggle only the submenu related to the clicked element?

Implementing PHP in WordPress:

<?php
function main_navigation() {
    $menu_name      = 'main_menu';
    $locations      = get_nav_menu_locations();
    $menu           = wp_get_nav_menu_object( $locations[ $menu_name ] );
    $menu_items     = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'ASC' ) );
    $count          = 0;
    $sub_menu       = false;
?>

<ul class="header__list">
    <?php
    foreach( $menu_items as $item ):

        $link           = $item->url;
        $title          = $item->title;
        $class          = $item->classes[0];

        // Check if item has no parent (menu_item_parent equals 0)
        if ( !$item->menu_item_parent ):

        // Save this id for comparison with sub-menu items
        $parent_id = $item->ID;
    ?>

    <li class="header__item">
        <a href="<?php echo $link; ?>" class="header__link <?php echo $class ?>"><?php echo $title; ?></a>

        <?php endif; ?>

        <?php if ( $parent_id == $item->menu_item_parent ): ?>

            <?php if ( !$sub_menu ): $sub_menu = true; ?>
            <ul class="header__sub-list" aria-role="header-sublist">
            <?php endif; ?>

                <li class="header__sub-item">
                    <a href="<?php echo $link; ?>" class="header__sub-link"><?php echo $title; ?></a>
                </li>

            <?php if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id && $sub_menu ): ?>
            </ul>
            <?php $sub_menu = false; endif; ?>

        <?php endif; ?>
    </li>

<?php
$count++;
endforeach;
?>

</ul>
<?php
}

Implementing JavaScript functionality:

const headerSubLists = document.querySelectorAll('.header__link-sub');

headerSubLists.forEach((headerSubList) => {
    const headerSubMenu = document.querySelectorAll(
        '[aria-role="header-sublist"]'
    );

    const openSubMenu = (e) => {
        e.preventDefault();

        headerSubMenu.forEach((menu) => {
            menu.classList.toggle('is-open');
        });
    };

    headerSubList.addEventListener('click', openSubMenu);
});

Answer №1

To start, update your JavaScript code as follows:

const headerSubLists = document.querySelectorAll('.header__link-sub');

headerSubLists.forEach((headerSubList) => {
    const parentItem = headerSubList.closest('.header__item');
    const subMenuId = parentItem.dataset.subMenu;
    const subMenu = document.getElementById(subMenuId);

    const openSubMenu = (e) => {
        e.preventDefault();
        subMenu.classList.toggle('is-open');
    };

    headerSubList.addEventListener('click', openSubMenu);
});

Next, in your PHP file, make sure to include the data attribute when generating the sub-menu:

<?php if ( !$sub_menu ): $sub_menu = true; ?>
    <ul class="header__sub-list" aria-role="header-sublist" id="sub-menu-<?php echo $parent_id ?>" data-sub-menu="sub-menu-<?php echo $parent_id ?>">
<?php endif; ?>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for setting a value in $scope within an ng-repeat loop in AngularJS

I'm currently facing an issue with ng-repeat in angularJS, specifically on how to assign a value in $scope inside ng-repeat. Here is my scenario: I have a JSON file that contains all the data structured like this: [ {BookID:1,Chapter:1,ContentID:1, ...

Incorporating JavaScript into a pre-existing HTML and CSS user interface

After successfully coding a chat app UI for my project site using CSS and HTML, I am now facing the challenge of adding functionality to my existing code. The issue is setting up the client server and integrating chatting functions into my current UI. Mo ...

"Emphasize menu items with an underline as you navigate through the

I am using Gatsby with React and have a navigation menu with links. I would like to make it so that when a link is clicked, a border bottom appears to indicate the current page, rather than only on hover. <ul className="men" id="menu"> ...

Resizing an image with six corners using the canvas technique

Currently, I am facing two issues: The topcenter, bottomcenter, left and right anchors are not clickable. I'm struggling with the logic to adjust the image size proportionally as described below: The corner anchors should resize both height and wi ...

Encountering an issue with compiling Angular due to a Type Inference error

interface Course { name: string; lessonCount: number; } interface Named { name: string; } let named: Named = { name: 'Placeholder Name' }; let course: Course = { name: 'Developing Apps with Angular', lessonCount: 15 }; named = ...

Launching an external JavaScript from within a separate JavaScript file

I'm in the process of developing a virtual 'directory' for various locations in my city to assist fellow students. Here's the concept: On a map, I've pinned all the locations Clicking on these pins triggers a JavaScript funct ...

What are the ideal scenarios for implementing React.Fragments?

Today I discovered React Fragments and their benefits. I learned that fragments are more efficient by reducing the number of tree nodes and improving cleanliness in the inspector. However, is there still a need to use div tags as containers in React compo ...

Having trouble with updating label text in MUIDataTable in ReactJS?

Looking to implement multi-language support in MUI Datatables. I have been able to modify the translations, but when attempting to change languages by providing a different object with new translations (verified using console log), the label texts do not u ...

What is the procedure to incorporate login credentials into the source of an iframe?

Is there a way to pass user auto login in the src URL? <iframe src="https://secure.aws.XXX.com/app/share/28228b0ccf0a987" width="1060px" height="1100px"></iframe> I attempted to achieve this, but it still shows the login screen <ifr ...

When using Jquery, hovering over an element will cause the full title to be

I have created a toggle div that displays an ellipsis (...) when the long title is longer than 30 characters. Now, I want the full text of the long title to appear when hovering over the div. Check out this JS Fiddle for reference. JS $('#popu ...

Troubleshooting undefined value issue with pagination in AJAX GET request with Laravel

I am currently working on a GET request using AJAX. In my Laravel Controller, I attempted to use "->paginate(5);" and encountered undefined values. However, when I use "->get();", it works flawlessly. Nevertheless, I prefer to use paginate to impleme ...

Changing the rotation of an object in THREE.js to match Canvas rotation

Hello amazing minds of stackoverflow. I am in the process of converting three js mesh positions to html5 canvas positions. While I have successfully converted vector3 position to canvas position, I am facing difficulties with converting mesh rotation to ca ...

What causes Chrome to crash when dealing with lengthy tail files?

My objective is to display a log file in real-time using a websocket connection. However, I am facing performance issues with Chrome when the paragraph ('p') element in the HTML becomes large (about 450 lines). This is the current implementation ...

Demonstrate a array of values at varying angles within a circle using the functionalities of HTML5 canvas

Looking to utilize HTML5 Canvas and Javascript for a project where I need to showcase various values (depicted by dots possibly) at different angles within a circle. For example, data could include: val 34% @ 0°, val 54% @ 12°, val 23% @ 70°, a ...

Ways to delete scheduled tasks in BreeJS

I am currently working on an express server that initiates a recurring job upon client request for a specific duration. The challenge I am encountering is figuring out how to stop and remove that particular job once it has been completed. The following is ...

The ES6 alternative to require() when not using exports

When I utilize require(./filename), I am able to include and run the code within filename without any explicit export being defined inside filename. In ES6, what is the equivalent of this using import ? Appreciate it ...

Deliver transcluded data to the descendant element of a hierarchical roster

I understand that there have been similar questions asked before, but my situation is slightly different. I am currently constructing a nested list and I want to include custom HTML content in each grandchild element alongside some common HTML. The problem ...

Removing buttons from a table row dynamically

Below is how I am adding the Button to Element: (this.sample as any).element.addEventListener("mouseover", function (e) { if ((e.target as HTMLElement).classList.contains("e-rowcell")) { let ele: Element = e.target as Element; let ro ...

"Step-by-Step Guide: Activating Tab Functionality in J

I'm facing an issue here - I've been attempting to log the event's key code and I keep getting key number (9). I believe my script isn't disabling event.keyCode properly, hence the key function remains active. What changes should I make ...

What could be causing my JQuery code to fail after loading data via ajax?

My tree view is set up using the following jQuery code: $(".treeView").on("click", ".CollOpen, .CollClosed", function () { $(this).toggleClass("CollOpen CollClosed").nextAll('ul').first().toggle(); }); Initially, this code works perfectly. ...