Jump to content

Repsonsive Navigation Menu with Multiple Dropdowns


gpjuno13

Recommended Posts

Good day everyone!

 

I will admit right off the hop that I know very little about javascript programming but I hope that with your help, I can learn something today. I've looked on w3 and elsewhere to find my answer but I have not been successful. I think what I'm trying to do is simple...

 

Using w3.css, I am trying to create a navigation menu that will include more than one dropdown menu. I have the menu working to a point. Right now if I click on the three links with sub menus, the sub menus will display. However, they do not 'hide' unless I click on the top-menu link. That is, if I click on 'Training', the sub menu appears but will only disappear if I click on 'Training' again. Of course I want the sub-menu to disappear if I click anywhere outside the sub-menu or have another sub-menu appear if I click on its top-menu link.

 

I've attached my html file for you to have a look.

 

Any help and guidance would be greatly appreciated.

 

Thanks so much! Have a great day!

<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">

<body>

<div class="w3-container">

  <ul class="w3-navbar w3-light-grey">
    <li><a href="#">Home</a></li>

    <li class="w3-dropdown-click">
      <a onclick="myFunction()" href="#">Manuals <i class="fa fa-caret-down"></i></a>
      <div id="sub-menu" class="w3-dropdown-content w3-white w3-card-4">
        <a href="#">Power Unit/Truck/Bus Safety Inspections and Standards</a>
        <a href="#">School Bus Safety Inspections and Standards</a>
        <a href="#">Trailer/Semi-Trailer Safety Inspections and Standards</a>
		<a href="#">Motorcycle Safety Inspections and Standards</a>
      </div>    
    </li>
	
	<li class="w3-dropdown-click">
      <a onclick="myFunction2()" href="#">Forms <i class="fa fa-caret-down"></i></a>
      <div id="sub-menu2" class="w3-dropdown-content w3-white w3-card-4">
        <a href="#">Supply Form</a>
        <a href="#">Backup Forms</a>
		<a href="#">Station Application</a>
      </div> 
	</li>
	
	<li class="w3-dropdown-click">
      <a onclick="myFunction3()" href="#">Training <i class="fa fa-caret-down"></i></a>
      <div id="sub-menu3" class="w3-dropdown-content w3-white w3-card-4">
        <a href="#">Option 1</a>
        <a href="#">Option 2</a>
		<a href="#">Option 3</a>
      </div> 
	</li>
	
	<li><a href="#">Who to Call</a></li>
  </ul>
</div>

<script>
function myFunction() {
    var x = document.getElementById("sub-menu");

    if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
	}else { 
        x.className = x.className.replace(" w3-show", "");
    }
}

function myFunction2() {
    var x = document.getElementById("sub-menu2");

    if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
	}else { 
        x.className = x.className.replace(" w3-show", "");
    }
}

function myFunction3() {
    var x = document.getElementById("sub-menu3");

    if (x.className.indexOf("w3-show") == -1) {
        x.className += " w3-show";
	}else { 
        x.className = x.className.replace(" w3-show", "");
    }
}



</script>
</body>

</html>

test.html

Edited by gpjuno13
Link to comment
Share on other sites

The solution to make something close when clicking anywhere on the page is to add an event listener to the body. We can take advantage of the event target to make sure that the menu only closes if you click on something that is not the menu.

document.body.addEventListener("click", closeMenu, false);

var menu = document.getElementbyId("my-menu");
function closeMenu(e) {
  var element = e.target; // This is the element that was clicked on

  // Make sure that none of the ancestors is the menu
  var foundMenu = false;
  while(element && !foundMenu) {
    if(element == menu) {
      // The menu was clicked on
      foundMenu = true;
    }
    element = element.parentNode;
  }

  // Close the menu if we didn't click on it
  if(!foundMenu) {
    // Hide menu
    //
    //
  }
}
Link to comment
Share on other sites

Thank you very much for your quick response, Foxy Mod. added your script snippet to my existing script code and added a div with an id of "menu" around my menu code but I could not get it to work.

 

I've updated my original post so that my original html (with old javascript) is visible without the need to download the html file. I hope this helps.

Link to comment
Share on other sites

The event needs to be passed on to relevant functions

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Document Title</title>
        <link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
        <style>
           /* body, html {height:100%;}*/
        </style>
    </head>
    <body>

        <div class="w3-container">

            <ul id="DS_Nav" class="w3-navbar w3-light-grey ">
                <li><a href="#">Home</a></li>

                <li class="w3-dropdown-click">
                    <a  href="#">Manuals <i class="fa fa-caret-down"></i></a>
                    <div  class="w3-dropdown-content w3-white w3-card-4">
                        <a href="#">Power Unit/Truck/Bus Safety Inspections and Standards</a>
                        <a href="#">School Bus Safety Inspections and Standards</a>
                        <a href="#">Trailer/Semi-Trailer Safety Inspections and Standards</a>
                        <a href="#">Motorcycle Safety Inspections and Standards</a>
                    </div>
                </li>

                <li class="w3-dropdown-click">
                    <a  href="#">Forms <i class="fa fa-caret-down"></i></a>
                    <div  class="w3-dropdown-content w3-white w3-card-4">
                        <a href="#">Supply Form</a>
                        <a href="#">Backup Forms</a>
                        <a href="#">Station Application</a>
                    </div>
                </li>

                <li class="w3-dropdown-click">
                    <a href="#">Training <i class="fa fa-caret-down"></i></a>
                    <div  class="w3-dropdown-content w3-white w3-card-4">
                        <a href="#">Option 1</a>
                        <a href="#">Option 2</a>
                        <a href="#">Option 3</a>
                    </div>
                </li>

                <li><a href="#">Who to Call</a></li>
            </ul>
        </div>

        <script>
            window.addEventListener("click", function(event) {
                closeMenu(event);
            }, false);

            var menu = document.getElementById('DS_Nav');
            function closeMenu(e) {

                var element = e.target; // This is the element that was clicked on

                // Make sure that none of the ancestors is the menu
                var foundMenu = false;
                while (element && !foundMenu) {
                    if (element === menu) {
                        // The menu was clicked on
                        foundMenu = true;

                    }
                    element = element.parentNode;
                }

                // Close the menu if we didn't click on it
                if (!foundMenu) {
                    // Hide menu
                    ClearActiveMenu();
                }
            }
            window.onload = function() {
                var parentNav = document.getElementById('DS_Nav');
                var navListItem = parentNav.getElementsByTagName('LI');

                for (var i = 0; i < navListItem.length; i++)
                {
                    if (navListItem[i].className.indexOf("w3-dropdown-click") === -1) {
                        navListItem[i].getElementsByTagName('A')[0].addEventListener("click", function() {

                            ClearActiveMenu();
                        }, false);
                    }
                    else
                    {
                        navListItem[i].getElementsByTagName('A')[0].addEventListener("click", function() {
                            ShowActiveMenu(this);
                        }, false);
                    }
                }
            };

            function ClearActiveMenu()
            {
                var z = document.getElementsByClassName('w3-dropdown-content');
                for (var i = 0; i < z.length; i++)
                {
                    z[i].className = z[i].className.replace(" w3-show", "");
                }
            }



            function ShowActiveMenu(elem) {
                ClearActiveMenu();
                var z = elem.parentNode.getElementsByTagName('div')[0];
                z.className = z.className += " w3-show";

            }





        </script>
    </body>

</html>

Also because body height might be less than browser viewport height, it would be better to use window instead.

Edited by dsonesuk
  • Like 1
Link to comment
Share on other sites

  • 9 months later...

I need the same thing but for the NEW w3.css (version 4)

The nav bar code is much different and so the javascript would need a small updating.

I know this would  help a great number of people since it is one of the small drawbacks to using w3.css in the "real world"

Edited by Webby
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...