Reputation: 79
I am working on navigation with a clickable dropdown menu. The dropdown uses an input tag. Where I'm getting stuck is that I need the dropdown to close if the visitor clicks somewhere else on the page. I'm trying to use a target property, matches() method, and an onclick event.
What I notice in the console is that when I open the dropdown, both conditional statements appear and the dropdown doesn't open. It's as though the dropdown opens and closes at the same time.
What am I doing wrong and how do I get this to function correctly so that a user can simply open the dropdown menu and have it close when they click somewhere else on the webpage?
Thanks in advance! Below is the code. Here is the codepen: https://codepen.io/bfoley650/pen/NWxeXRB?editors=1111
HTML
<div class="dropdown">
<input id="checkId" type="checkbox" name="menu" />
<label for="checkId">
<span class="heyhey">⋮</span>
</label>
<div class="dropdown-content">
<ul class="heyheyhey">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
</ul>
</div>
</div>
CSS
span {
color: black;
font-size: 24px;
margin: 0 15px;
}
li {
list-style-type: none;
}
.dropdown {
float: left;
overflow: hidden;
font-size: 17px;
border: none;
outline: none;
color: white;
background-color: inherit;
font-family: inherit;
margin: 10px 0;
}
.dropdown-content {
display: none;
position: absolute;
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 20px 12px 0;
text-decoration: none;
display: block;
text-align: left;
}
input {
display: none;
}
label {
position: relative;
cursor: pointer;
}
input:checked~.dropdown-content {
display: block;
}
JS
let el = document.querySelector(".dropdown-content");
window.onclick = function(e) {
if (e.target.matches(".heyhey")) {
console.log("You clicked the dropdown menu");
} else {
console.log("You clicked somewhere else");
el.style.display = "none";
}
}
Upvotes: 0
Views: 1367
Reputation: 31
I think you should move the span above the label:
<span class="heyhey">⋮</span>
<label for="checkId">
<input id="checkId" type="checkbox" name="menu" />
</label>
and add the following code to your conditional:
console.log("You clicked the dropdown menu");
el.style.display = "block";
Upvotes: 0
Reputation: 2812
window.onclick = function(e) {
if (e.target.matches(".heyhey")) {
console.log("You clicked the dropdown menu");
el.style.display = "block"; // Shows the element
e.preventDefault(); // Prevents propagation
} else {
console.log("You clicked somewhere else");
el.style.display = "none";
}
}
event.preventDefault
stops propagation, JS by default calls onclick
for parent elements, this stops the double counting of your onclick
handler.
This changes the display
style from none, thus showing the element. This could be changed to any other display style except none
.
Upvotes: 1