Close Dropdown when another Dropdown is opened - javascript

I have a vertical sidebar nav menu with multiple buttons, each of which contains a dropdown of links. Clicking a button reveals a dropdown of anchor links in the nav menu (e.g. TF000120), and a div (e.g.'the forest') to the right of the nav menu in the main content area. Currently, if I click a button, its div and dropdown are both revealed fine. However if I click another button before closing the first, both sets of divs and dropdowns open. How would I make it so when another button is clicked, the currently open div and dropdown links are hidden again, before revealing the new div and dropdown links?
I used this tutorial on W3.
HTML (Nav Menu)
<nav class="sidenav">
<a href="#theforest" class="dropdown-btn" onclick="toggle_visibility('theforest');">The Forest
</a>
<div class="dropdown-container">
<a class="entry-num" href="#TF000120">[TF000120]</a>
<a class="entry-num" href="#TF000220">[TF000220]</a>
<a class="entry-num" href="#TF000320">[TF000320]</a>
</div>
The Ocean
<div class="dropdown-container" >
<a class="entry-num" href="#TO000120">[TO000120]</a>
<a class="entry-num" href="#TO000220">[TO000220]</a>
<a class="entry-num" href="#TO000320">[TO000320]</a>
</div>
The Sky
<div class="dropdown-container" >
<a class="entry-num" href="#TS000120">[TS000120]</a>
<a class="entry-num" href="#TS000220">[TS000220]</a>
<a class="entry-num" href="#TS000320">[TS000320]</a>
</div>
</nav>
JS
<script>
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
</script>
<!--Toggle Function-->
<script type="text/javascript">
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
</script>
Thanks!

reset the style of all dropdowns on click, before you show the new one:
dropdown[i].addEventListener("click", function() {
//hide all divs that may be visible
var lst = document.getElementsByClassName("dropdown-containder");
for (var j = 0; j < lst.length; j++) { lst[j].style.display = "none";}
//show the dive that the user selected
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}

Related

window.addEventListener function is not working at all times

Through this code i have to hide the dropdown-container when a user clicked outside of the button. And the code works fine initially. But later, it is not responding to the onclick event on button also. sometimes it closes the dropdown if i cliked a button. I have tried with many stackoverflow questions but i didnot get answer. Here is my code. Hope someone could solve this issue.
<div class="button-grp">
<button class="icon-button" type="button" onclick="menu(event, '1')"><img
src="../../Images/icons/local_library-white-24dp.svg" class="icon"><br>Learning
</button>
<button class="icon-button" type="button" onclick="menu(event, '2')"><img
src="../../Images/icons/gamepad-white-24dp.svg" class="icon"><br>Tools
</button>
</div>
<div class="sidebar-open">
<div class="main-options" id="0">
<button class="options-button" type="button">Academics</button>
<div class="dropdown-container">
Course Details
Assignments
</div>
<button class="options-button" type="button">Schedule</button>
<div class="dropdown-container">
Exams
Classes
</div>
</div>
</div>
<div id="mainmenu">
Lorem ipsum dolor sit,
</div>
And my Javascript code is as follows..
//function to toggle between clicked buttons and close when double clicked on it.
function menu(evt, id) {
document.querySelectorAll(".main-options").forEach(function(div) {
if (div.id === id) {
// Toggle specified DIV
if(div.style.display === "block"){
div.style.display = "none";
document.getElementById("mainmenu").style.marginLeft = "80px";
document.body.style.backgroundColor = "#fff";
}else{
div.style.display = "block";
document.getElementById("mainmenu").style.marginLeft = "230px";
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
} else {
// Hide other DIVs
div.style.display = "none";
}
});
}
//function to hide the dropdown when clicked outside the button.
window.addEventListener('click', function(event){
if (!event.target.matches('.icon-button') ){
var dropdowns = document.getElementsByClassName("main-options");
var i;
for (i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].style.display === "block") {
dropdowns[i].style.display ="none";
document.getElementById("mainmenu").style.marginLeft = "80px";
document.body.style.backgroundColor = "#fff";
}
}
}
});
Why don't you try this:
document.addEventListener("DOMContentLoaded", () => {
document.querySelector(".icon-button").forEach((button) => {
button.addEventListener('click', ()=>{
...
});
});
});

Javascript Hide div on page load toggle between buttons

I know this has been asked, but I cannot figure out how to fix my issue. I have 2 buttons a drink menu and a food menu. I'm able to correctly show the different menus show when their button is clicked. However when the page loads the drink menu appears below the food menu. Once I click food menu buttons the drink menu disappears,and the buttons function as you would expect ie. one menu is shown while the other one is not. I'm not sure what the best method is to hide the drink menu. Any help would be much appreciated.
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu">
<h1>Drink Menu</h1>
</div>
var divs = [ "foodMenu", "drinkMenu" ];
function toggle(layer) {
var d
for(var i = 0; i < divs.length; i += 1) {
d = document.getElementById(divs[i]);
d.style.display = 'none';
}
}
I rewrote your script some. I used a class of menu to reference the divs and to set them default to be hidden.
Its also setup to hide any div not selected but only show the selected div.
var divs = [ "foodMenu", "drinkMenu" ];
function toggle(layer) {
var _menus = document.getElementsByClassName("menu");
for(var i = 0; i < _menus.length; i++) {
_menu = _menus[i];
_menu.style.display = 'none';
}
var _menu = document.getElementById(layer);
_menu.style.display = 'block';
}
.menu{
display:none;
}
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div class="menu" id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div class="menu" id="drinkMenu">
<h1>Drink Menu</h1>
</div>
You can toggle by default the food menu, so every time you click a button, you color its text with red, so you know it is selected: its corresponding menu block will show.
Your HTML code:
<button onclick="javascript:toggle('foodMenu')" class="btnMenu" id="foodMenu-btn">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu" id="drinkMenu-btn">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu">
<h1>Drink Menu</h1>
</div>
Your JavaScript code:
// available menu divs
let divs = ["foodMenu", "drinkMenu"];
function toggle(layer) {
// reset all buttons and divs
for (let i = 0; i < divs.length; i += 1) {
let d = document.getElementById(divs[i]);
d.style.display = 'none';
// reset all buttons text colors
let b = document.getElementById(divs[i] + '-btn');
b.style.color = 'black';
}
// set current menu visible
let menu = document.getElementById(layer);
menu.style.display = 'block';
// set current menu button colored "red"
let btn = document.getElementById(layer + '-btn');
btn.style.color = 'red';
}
// select food menu by default
toggle('foodMenu')
I added style="display:none" to the second div in your first block of code. So when the page loads it will display the food Menu.
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu" style="display:none">
<h1>Drink Menu</h1>
</div>
For the javascript part use the following code. It will toggle between displaying the food and drink menu.
function toggle(layer) {
const hidingDiv = (layer == 'foodMenu') ? 'drinkMenu' : 'foodMenu';
document.getElementById(layer).style.display = 'block';
document.getElementById(hidingDiv).style.display = 'none';
}

HTML/Javascript/CSS Collapsible Menu not staying closed when refreshed

as it states in the title, my collapsible menu is not staying closed when the page is refreshed. Every time the page is loaded, the collapsible menu is fully expanded out, even if before the refresh it was completely closed. This is a bit of a problem, because there is a lot of stuff in this collapsible.
Here is basic code for it:
CSS:
//some code here for the design, background color and stuff that shouldn't matter,
// .active is what I think I need
.active, .collapsible:hover{
background-color: #02538D;
}
HTML:
<button class="collapsible">Tutorials</button>
<div>
<div class="content">
<p>
<?php
//some php here for output of collapsible
?>
</p>
</div>
<div class="content">
<p>
<?php>
//some php here for output of collapsible
?>
</p>
</div>
</div>
JavaScript:
<script>
var coll = document.getElementsByClassName("collapsible");
var i;
for(i = 0; i< coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if(content.style.display === "block") {
content.style.display = "none";
}
else {
content.style.display = "block";
}
});
}
</script>
I'm a beginner when it comes to JavaScript so I'm pretty sure that's where the error is but any help at all would be greatly appreciated. Thank you so much!
In the code you've provided, the state of the menu is never saved - so when the page is refreshed everything is simply 'reset' to the default.
One solution is of course to use 'display:none;' as the default in your css. That would make the menu hidden on page-refresh but the problem would persist if you need it to also stay visible between refreshes if the users have opened it.
In that case you could set a cookie with javascript at the time you toggle the styles:
HTML
<button class="collapsible">Collapsible 1</button>
<div>
<div class="menu-item">
<p>Content 1</p>
</div>
<div class="menu-item">
<p>Content 2</p>
</div>
</div>
JAVASCRIPT
var coll = document.getElementsByClassName("collapsible");
for(i = 0; i< coll.length; i++) {
var cookies = decodeURIComponent(document.cookie).split(";");
for(i=0;i<cookies.length;i++) {
if(cookies[i] == "menu-state=hide") {
var content = coll[i].nextElementSibling;
content.style.display = "none";
}
}
coll[i].addEventListener("click", function() {
var content = this.nextElementSibling;
if(content.style.display === "block") {
content.style.display = "none";
document.cookie = "menu-state=hide";
}
else {
content.style.display = "block";
document.cookie = "menu-state=display";
}
});
}
https://jsfiddle.net/hxcy1vLr/41/
The above code will check if there is a cookie with the name and value "menu-state=hide". If there is, the menu will be hidden initially. This cookie is set and changed when you click the toggle.
About cookies in javascript:
https://www.w3schools.com/js/js_cookies.asp
Hope this helps!

Vanilla Javascript Tabs Won't Close On Click

I've attempted to code vanilla Javascript that opens and closes buttons (tabs) and shows content.
They show the content correctly, but don't hide the content once clicked.
I've 'reverse engineered' the code that the opens the tab, but this code hides the content and the button when clicked.
Clearly my code is wrong, but i feel that i'm so close to achieving what i set out to achieve. So i'm looking to edit the existing code, not try not change anything drastically.
Cheers
function openTab(click, openTab) {
var i;
var content;
var link;
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
links = document.getElementsByClassName("link");
for (i = 0; i < links.length; i++) {
links[i].className = links[i].className.replace("active", "");
}
document.getElementById(openTab).style.display = "block";
for (i = 0; i < links.length; i++) {
click.currentTarget.className += "active";
}
document.getElementById(openTab).style.display = "active";
click.currentTarget.style.display = "none";
}
<div class="tabs">
<button class="link" onclick="openTab(event, 'About')">About</button>
<button class="link" onclick="openTab(event, 'Hire')">Why You Should Hire Me</button>
<button class="link" onclick="openTab(event, 'Contact')">Contact</button>
</div>
<div id="About" class="content">
</div>
<div id="Hire" class="content">
</div>
<div id="Contact" class="content">
</div>
The code you posted had some confusing behaviour (such as the buttons disappearing completely). I removed the line that made buttons disappear, as well two different loops that seemed to conflict with each other regarding the class name of the links.
I edited the code down to something simple that displays the content according to the button clicked, but I suspect I've misunderstood something and you're after something else. Maybe you can clarify what's missing?
function openTab(click, openTab) {
var i;
var content;
var wasOpen = document.getElementById(openTab).style.display === "block";
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
if (wasOpen) return;
document.getElementById(openTab).style.display = "block";
}
<div class="tabs">
<button class="link" onclick="openTab(event, 'About')">About</button>
<button class="link" onclick="openTab(event, 'Hire')">Why You Should Hire Me</button>
<button class="link" onclick="openTab(event, 'Contact')">Contact</button>
</div>
<div id="About" class="content" style="display:none">
ABOUT CONTENT
</div>
<div id="Hire" class="content" style="display:none">
HIRE CONTENT
</div>
<div id="Contact" class="content" style="display:none">
CONTACT CONTENT
</div>
Explainer:
The changes I made to the html was 1- to add some text in each tab and 2- set all tabs to display:none
Within the javascript:
On click, we have a value for "openTab", representing one of the tabs. The line:
var wasOpen = document.getElementById(openTab).style.display === "block";
Sets a Boolean variable which is true if "openTab"'s display property is set to block.
Then we set all tabs to display:none with the following:
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
And now, depending on whether or not the tab was already open, we either leave the function already, or set the tab to "block"
if (wasOpen) return;
document.getElementById(openTab).style.display = "block";
Tadaaaa!

Accordian div Pops up on page load

I'm trying to use accordian to create my page.
It works fine when I click the button but the only problem is that the div comes open on page load and I want it to be closed. It should only open when the button is clicked.
Click here
<div class="panel" id="AccordionDiv">
<div class="store">
<div class="store-row">
<div class="cells store-logo text-center">
<img src="#strStaticWebsiteUrl#(objOfferPrice.StoreImage)" alt="" />
</div>
#if (objOfferPrice.Price < objOfferPrice.UrlPrice)
{
<div class="cells text-center">
<div class="product-price offer-price">Rs. #String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0,0}", objOfferPrice.Price)<sup>*</sup></div>
<p class="real-price">Price: #objOfferPrice.UrlPrice</p>
</div>
}
</div>
</div>
This is html code and below is the Script code.
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
</script>
Simply add style="display:none" to your pannel div
Change
<div class="panel" id="AccordionDiv">
To
<div class="panel" id="AccordionDiv" style="display:none">
Wokring demo
With the code you have, set an inline style="display:none" so the accordion will be closed by default. The recommended way would be to have classes as open/close and toggle between them rather than having styles inlined.
Hide it initially and show it when button click fires
<div class="panel" id="AccordionDiv" style="display:none";>
<script>
window.onload = function(){
var acc = document.getElementByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
document.getElementById("AccordionDiv").style.display="block";
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}}
</script>

Categories

Resources