Guide on setting up a multi-level dropdown submenu with hover effect on the navbar using Bootstrap v4

I am in need of modifying the code below to allow for mousehover functionality with multiple levels in a Bootstrap 4 and JQuery menu. The current setup only works with single-level menus, as opening one level triggers the next (dropdown-submenu).

Here is my HTML code...

<nav class="navbar navbar-expand-lg navbar-default fixed-top">
    <div class="container">
        <a class="navbar-brand" href="/">
            <img src="/img/logo.png" alt="Brand">
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
            <i class="fas fa-bars text-primary"></i>
        </button>
        <div class="collapse navbar-collapse" id="navbarResponsive">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="/">Home</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" role="button" id="item1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Item 1 <small><i class="fas fa-angle-down ml-1"></i></small>
                    </a>
                    <ul class="dropdown-menu p-0" aria-labelledby="item1">
                        <li><a class="dropdown-item " href="">Item Level 1</a></li>
                        <li><a class="dropdown-item " href="">Item Level 1</a></li>
                        <li><a class="dropdown-item " href="">Item Level 1</a></li>
                    </ul>
                </li>

                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" role="button" id="item2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Item 2 <small><i class="fas fa-angle-down ml-1"></i></small>
                    <div class="ripple-container"></div></a>
                    <ul class="dropdown-menu p-0" aria-labelledby="item2">
                        <li><a class="dropdown-item " href="">Item Level 1</a></li>
                        <li class="dropdown-submenu">
                            <a class="nav-link dropdown-toggle dropdown-item" href="#" role="button" id="itemlevel1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                Item Level 1 <small><i class="fas fa-angle-right"></i></small>
                            </a>
                            <ul class="dropdown-menu p-0" aria-labelledby="itemlevel1">
                                <li><a class="dropdown-item " href="">Item Level 2</a></li>
                            </ul>
                        </li>
                    </ul>
                </li>

                <li class="nav-item ">
                    <a class="nav-link" href="">Item 3
                    </a>
                </li>
            </ul>
        </div>
    </div>
</nav>

And this is my JS code...

//Dropdown hover
    const $dropdown = $(".dropdown");
    const $dropdownToggle = $(".dropdown-toggle");
    const $dropdownMenu = $(".dropdown-menu");
    const $dropdownSubMenu = $(".dropdown-submenu");
    const showClass = "show";
    $(window).on("load resize", function() {
        if (this.matchMedia("(min-width: 768px)").matches) {
            $dropdown.hover(
                function() {
                    const $this = $(this);
                    $this.addClass(showClass);
                    $this.find($dropdownToggle).attr("aria-expanded", "true");
                    $this.find($dropdownMenu).addClass(showClass);
                    $this.find($dropdownSubMenu).addClass(showClass);
                },
                function() {
                    const $this = $(this);
                    $this.removeClass(showClass);
                    $this.find($dropdownToggle).attr("aria-expanded", "false");
                    $this.find($dropdownMenu).removeClass(showClass);
                    $this.find($dropdownSubMenu).removeClass(showClass);
                }
            );
        } else {
            $dropdown.off("mouseenter mouseleave");
        }
    });

Answer №1

Here is the code for creating a dropdown hover effect:

//Dropdown hover
const $dropdown = $(".navbar-nav > .dropdown");
const $dropdownToggle = $(".navbar-nav > .dropdown > .dropdown-toggle");
const $dropdownMenu = $(".navbar-nav > .dropdown > .dropdown-menu");

const $dropdown2 = $(".dropdown-submenu");
const $dropdownToggle2 = $(".dropdown-submenu > .dropdown-toggle");
const $dropdownMenu2 = $(".dropdown-submenu > .dropdown-menu");

const showClass = "show";
$(window).on("load resize", function() {
    if (this.matchMedia("(min-width: 768px)").matches) {
        $dropdown.hover(
            function() {
                const $this = $(this);
                $this.addClass(showClass);
                $this.find($dropdownToggle).attr("aria-expanded", "true");
                $this.find($dropdownMenu).addClass(showClass);
            },
            function() {
                const $this = $(this);
                $this.removeClass(showClass);
                $this.find($dropdownToggle).attr("aria-expanded", "false");
                $this.find($dropdownMenu).removeClass(showClass);
            }
        );
        $dropdown2.hover(
            function() {
                const $this = $(this);
                $this.addClass(showClass);
                $this.find($dropdownToggle2).attr("aria-expanded", "true");
                $this.find($dropdownMenu2).addClass(showClass);
            },
            function() {
                const $this = $(this);
                $this.removeClass(showClass);
                $this.find($dropdownToggle2).attr("aria-expanded", "false");
                $this.find($dropdownMenu2).removeClass(showClass);
            }
        );
    } else {
        $dropdown.off("mouseenter mouseleave");
        $dropdown2.off("mouseenter mouseleave");

        $(function () {
            // Multi Level dropdowns on Click for Mobile
            $("ul.dropdown-menu [data-toggle='dropdown']").on("click", function (event) {
                event.preventDefault();
                event.stopPropagation();

                $(this).siblings().toggleClass("show");


                if (!$(this).next().hasClass('show')) {
                    $(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
                }
                $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) {
                    $('.dropdown-submenu .show').removeClass("show");
                });

            });
        })
    }
});

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

Angular.js routing malfunctioning

I am currently working on an angular.js controller called loginErrorCtrl, which is responsible for redirecting to a specific view (/menu) when the data entered into an input matches a predefined string in the application (Data.serverToken). function login ...

Preventing responsive elements from loading with HTML scripts

Currently, I am utilizing the Gumby framework which can be found here. Everything appears to be running smoothly. My goal is to incorporate a mobile navigation list where the links are grouped under a single button, as outlined here. Initially, this funct ...

Retrieve an HTML document from a specified URL using JavaScript AJAX methods

var $ = require('jquery'); $.ajax({ type:"GET", dataType: 'html', url: 'http://www.google.com/', success: function(res){ console.log(res); } }); The error displaying in the console is: XMLHttpRequest cannot lo ...

Using Three.js for 3D modeling in web development, the JSONLoader coupled

While dealing with heavy models, I am experimenting with displaying the loading percentage dynamically when loading JSON data. I conducted a basic test using the loadAjaxJSON method... The loading process shows the percentage completion, but it never reac ...

Unable to adjust the padding of the material UI Select component

I'm having trouble adjusting the padding of the Select component in order to align it with the size of my other text fields. Despite knowing that I need to make changes to nested components, I have yet to discover a viable solution. <div className ...

Queue with prioritization

We are currently exploring the use of queues to streamline our Discord-related tasks that rely on the Discord API. Suggestions and guidance on how this can be successfully implemented would be greatly appreciated. Key expectations for this implementation ...

Guide to altering number font colors according to their values through JavaScript and React

In my JavaScript project, I'm looking to dynamically apply colors to a variable named count based on its value. My goal is as follows: The count variable's value can vary, ranging from below 0 to greater than 0. Specifically, here's what I ...

Combining Laravel and VueJs for a Multi-Page Application (MPA)

I have recently developed a website using a combination of Laravel and VueJs. However, I am facing some confusion regarding the most suitable routing architecture to implement. Currently, my application has the following setup: The routing system is man ...

Creating flexible DIV columns that adjust to display changes using Bootstrap 3's CSS

I am currently facing a challenge with a simple layout problem: My objective is to create a toggle side menu. When the side menu is visible, the main layout should be 80% width, and when it is not visible, the main layout should be 100% width, as shown be ...

Can you identify the selected item on the menu?

My goal is to highlight the menu item for the current page by adding a "current" class. I've tried several code snippets from this website, but most of them didn't work as expected. The code I'm currently using almost works, but it has a sma ...

Jquery code fails to execute unless a breakpoint is set

I'm encountering a strange issue with the jquery star rating plugin. It seems that only when there's a breakpoint in my JS code will the radio buttons transform into stars; otherwise, they remain unchanged. Let me break down the code step by step ...

What is the recommended method for incorporating a frontend npm package that includes both CSS and JavaScript?

Recently, I've started using NPM and Gulp in my workflow. Up until this point, I've only dealt with NPM packages that consisted of either only JavaScript or CSS/SASS. Typically, I would either copy the package to a vendor directory to work with i ...

Before computing the width, Next.js Swiper slide occupies the entire width

Check out the code snippet below: 'use client'; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/css'; import 'swiper/css/pagination'; export default function Component() { const cards = [{ id: 0 ...

What is the best way to postpone one of the 3 ajax requests?

Can anyone assist me with handling AJAX forms? I am trying to ensure that the smallest one is executed after the others, but I also want to introduce a delay in the process. I attempted to utilize setTimeout(), however, it does not seem to be functioning ...

Watching an array of objects in AngularJS with assigned indices

I'm seeking guidance on how to utilize Angular watch with an array of objects. Here is an example array $scope.chartSeries containing objects like this: [{"location": {values}, "id":"serie-1", "meter":{values}, "name": "seriename", "data":[{1,2,4,5, ...

How about "Incorporate Google Auth into your Vue.js project with modular

I'm on the search for a project that showcases using Vue.js and the Google client library to authenticate with JavaScript, but without the need for transpilers, bundlers, or Node/npm. Does anyone know of such an example out there? I simply want to cre ...

Ensuring Accessibility in Vue using Jest-Axe: It is important for buttons to have clear and distinguishable text. Is there a way to include a button name or aria-label when the content is passed through a slot

I have been focusing on enhancing the accessibility of my project by incorporating ESLint rules from vuejs-accessibility and integrating Jest-Axe. During the accessibility tests for my button components, Jest-Axe highlighted that Buttons must have discern ...

Tips for handling the response after a view has been submitted on Slack using Bolt.js

Hey there! I added a simple shortcut to retrieve data from an input, but I'm facing an issue after submitting the view. The response payload is not received and the view doesn't update to give feedback to the user. Check out my code below: const ...

Custom Log4j rollover script to automatically delete logs once the filesystem usage exceeds a specific threshold

Utilizing log4j for logging in my application has been beneficial. I am now exploring the option to automatically delete compressed files when the filesystem reaches 80 percent usage. While log4j lacks a built-in appender for this task, it does offer the S ...

Tips for testing Sequelize with Jasmine

In my database/index.ts file, I set up a Sequelize database using the code below: import { Sequelize } from 'sequelize'; const { DATABASE_DIALECT, DATABASE_HOST, DATABASE_PORT, DATABASE_USER_NAME, DATABASE_USER_PASSWORD, DATABASE_NAM ...