简体   繁体   中英

How to Close One Javascript Drop Down Menu When Opening Another

I'm not to familiar with JavaScript and I was hoping to get a little help with a problem I can't seem to fix. I currently have 2 Drop Down Menus on my website. One is a drop down menu for the navigation which is activated when clicking a hamburger menu icon. The second drop down is being used to show categories on my website. Currently when I click one drop down, I have to click it again in order to close it. If I click the second drop down without closing the first both will remain visible. What I would like to happen is two things. First I would like it so that if a user clicks anywhere outside of the div for the drop down menu it automatically closes. The second thing I would like to see happen is only have one drop down menu visible at a time. So if I click one and another drop down is open I want it to be closed. Hopefully I explained this well. Now onto the code I'm using.

The following is within my head.

<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function DropDownMenuNavigation() {
document.getElementById("b2DropDownMenuNav").classList.toggle("show");
}
function DropDownMenuCategory() {
document.getElementById("b2DropDownMenuCat").classList.toggle("show");  
}
</script>

Then I use this as the button to activate the navigation drop down menu. This is included within my body.

<div class="dropbtn" style="float: left;">
<button onclick="DropDownMenuNavigation()" class="dropbtn">&#9776; MENU</button>
</div>

and this what I use to include my category drop down menu.

<div class="dropbtn" style="float: left;">
<button onclick="DropDownMenuCategory()" class="dropbtn">CATEGORIES</button>
</div>

Now lastly is the css I use just on the off chance that helps any.

/* Dropdown Button */
.dropbtn {
background-color: #0066a2;
color: white;
padding: 1px;
font-size: 15px;
font-weight: bold;
border: none;
cursor: pointer;
}
.dropbtn a {
color: #FFFFFF;
text-decoration: none;
font-size: 15px;
font-weight: bold;
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
float: left;
position: relative;
display: inline-block;
}

/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #0066a2;
min-width: 260px;
max-width: 960px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}

/* Links inside the dropdown  */
.dropdown-content a {
color: #000000;
text-decoration: none;
}

/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;} 

So what would be the best method to go about doing what I'm asking? Could someone maybe lend me a hand and point me in the right direction. Thanks a lot and I appreciate any help you could lend me.

The onclick attribute shouldn't include the () . It should look like this:

<button onclick="DropDownMenuNavigation" class="dropbtn">&#9776; MENU</button>

Or—even better—don't put the event listener inline, put it in the script.

Also, remove the “show” class from the other dropdown when the button is pressed.

See here:

 document.getElementById('menudropbtn').addEventListener('click', function () { document.getElementById('b2DropDownMenuNav').classList.toggle('show') document.getElementById('b2DropDownMenuCat').classList.remove('show') }) document.getElementById('categoriesdropbtn').addEventListener('click', function () { document.getElementById('b2DropDownMenuCat').classList.toggle('show') document.getElementById('b2DropDownMenuNav').classList.remove('show') })
 /* Dropdown Button */ .dropbtn { background-color: #0066a2; color: white; padding: 1px; font-size: 15px; font-weight: bold; border: none; cursor: pointer; } .dropbtn a { color: #FFFFFF; text-decoration: none; font-size: 15px; font-weight: bold; } /* The container <div> - needed to position the dropdown content */ .dropdown { float: left; position: relative; display: inline-block; } /* Dropdown Content (Hidden by Default) */ .dropdown-content { display: none; position: absolute; background-color: #0066a2; min-width: 260px; max-width: 960px; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a { color: #000000; text-decoration: none; } /* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ .show { display: block; }
 <div class="dropbtn" style="float: left;"> <button class="dropbtn" id="menudropbtn">&#9776; MENU</button> <div class="dropdown"> <div class="dropdown-content" id="b2DropDownMenuNav"> <a>Something</a> </div> </div> </div> <div class="dropbtn" style="float: left;"> <button class="dropbtn" id="categoriesdropbtn">CATEGORIES</button> <div class="dropdown"> <div class="dropdown-content" id="b2DropDownMenuCat"> <a>Something else</a> </div> </div> </div>

To do this, you can add custom JS functions that will open dropdowns based on element ID, and when one dropdown is opened, all others will be closed. You can create a function that closes all the dropdowns. Then, in your "open" function, call the "close_all" function first.

Here's a working snippet.

 // Functions for Interactive File Menu Bar // - Click Butoon to Open Dropdown // - Clicking one dropdown closes all other // - Clicking outside the file menu bar will close all the dropdown. function open_dropdown(element_id) { console.log('Opening Dropdown:', element_id) close_all_dropdowns() document.getElementById(element_id).style.display = 'block'; } // Close the dropdown if the user clicks outside of it function close_dropdown(element) { console.log('I am closing dropdown:', element) element.style.display = 'none' } // Close all dropdowns. function close_all_dropdowns() { var dropdowns = document.getElementsByClassName('dropdown-content') for (var i = 0; i < dropdowns.length; i++) { close_dropdown(dropdowns[i]); } } // Close all dropdowns when clicking outside. window.onclick = function (e) { if (!e.target.matches('.dropbtn')) { close_all_dropdowns() } }
 /* Styles for the File Menu Bar. */ .dropdown { position: relative; display: inline-block; } .dropdown-content { display: none; position: absolute; background-color: #f1f1f1; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); z-index: 1; } .dropdown-content a { float: none; color: black; padding: 12px 16px; text-decoration: none; display: block; text-align: left; }
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://unpkg.com/98.css"> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> <title>RetroNet</title> </head> <body> <div class="window" style="width: 100%"> <div class="title-bar"> <div class="title-bar-text">Welcome to RetroNet!</div> <div class="title-bar-controls"> <button aria-label="Minimize"></button> <button aria-label="Maximize"></button> <button aria-label="Close"></button> </div> </div> <!-- Main menu --> <div class="window-body"> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_file')">File</button> <div class="dropdown-content" id="dd_file"> <a href="#">Open</a> <a href="#">Close</a> <a href="#">Settings</a> </div> </div> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_edit')">Edit</button> <div class="dropdown-content" id="dd_edit"> <a href="#">Cut</a> <a href="#">Copy</a> <a href="#">Paste</a> </div> </div> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_view')">View</button> <div class="dropdown-content" id="dd_view"> <a href="#">Toggle CSS</a> <a href="#">Toggle Javascript</a> </div> </div> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_tools')">Tools</button> <div class="dropdown-content" id="dd_tools"> <a href="#">Not Decided</a> </div> </div> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_favorite')">Favourties</button> <div class="dropdown-content" id="dd_favorite"> <a href="#">Add New Favorite</a> <a href="#">Add this Page to Favorites</a> <a href="#">Show Favorites</a> </div> </div> <div class="dropdown"> <button class="dropbtn" onclick="open_dropdown('dd_help')">Help</button> <div class="dropdown-content" id="dd_help"> <a href="https://github.com/ayushxx7/summer-code-jam-2020/blob/master/adventurous-anteaters/README.md">README</a> </div> </div> </div> </div> </body> </html>

Maybe the following code can help. You can use custom event to have module items (like menu, popup or such) communicate to each other.

If a menu button is clicked then you can dispatch a custom event. Any other item on the page may do something according to what this event is (like pausing a game when a main menu is opened).

 // find menu-content in item (=menu-button) and return // "none" if menu-content.style.display is "block" // "block" if menu-content.style.display is not "block" const toggle = (item) => { const content = item.querySelector("[x-role=\\"menu-content\\"]"); return content.style.display === "block" ? "none" : "block" } ; // set menu-content found in item (=menu-button) to // none or block const changeDisplay = (item,display) => item.querySelector("[x-role=\\"menu-content\\"]") .style.display = display; // when menu-button is clicked const menuButtonClicked = e => { //get the toggled content style // if current style is block then // toggled is none and vice versa const style = toggle(e.target); //hide all menus, in the for each we // added an event listener for "menu-click" event // the listener will hide the menu var evt = new Event("menu-click",{}); document.body.dispatchEvent(evt); //set style of the current changeDisplay(e.target,style); } ; //for each menu-botton role // I am not using css selectors on class, class is for style, // user defined properties can be used for behavior. // If you mix this up then you can break style, behavior // or both when changing behavior or style document.querySelectorAll("[x-role=\\"menu-button\\"]") .forEach( x => { //when clicked let menuButtonClicked handle it x.addEventListener( "click" ,menuButtonClicked ); //listen to custom event called "menu-click" // set display to none when this happens // if you were to dynamically add and remove // menu items then you should remove the event // listeners when you remove the menu document.body.addEventListener( "menu-click" ,e => changeDisplay(x,"none") ); } ) ;
 .menu-button { cursor: pointer; } .menu-content { display:none; }
 <div class="menu-button" x-role="menu-button"> menu1 <div class="menu-content" x-role="menu-content"> <ul> <li>one</li> <li>two</li> </ul> </div> </div> <div class="menu-button" x-role="menu-button"> menu2 <div class="menu-content" x-role="menu-content"> <ul> <li>three</li> <li>four</li> </ul> </div> </div> <div class="menu-button" x-role="menu-button"> menu3 <div class="menu-content" x-role="menu-content"> <ul> <li>five</li> <li>six</li> </ul> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM