Hi Im trying to build my own navigation with just pure HTML, CSS, Js. I pretty much got it working but my Js is not good and think it could be cleaner. The functionality I want is…
when you click a dropdown if there is another dropdown open it will close it. If you click outside the dropdown it will close it. I have achieved this but I think it could be cleaner. Also for the mobile nav I would like it to close when you click outside of the navigation which I have not achieved. Here is the github repository https://github.com/danbakerri/bulma-test and the actual site https://danbakerri.github.io/bulma-test/ to see it in action the script is at the bottom of the index page(using the Bulma framework for now)
this is the HTML for the dropdowns
<div class="navbar-item has-dropdown" data-dropdown>
<a
class="navbar-link navbar-dropdown-link"
aria-label="menu"
aria-expanded="false"
>
More
</a>
<div class="navbar-dropdown">
<a class="navbar-item"> About </a>
<a class="navbar-item is-selected"> Jobs </a>
<a class="navbar-item"> Contact </a>
<hr class="navbar-divider" />
<a class="navbar-item"> Report an issue </a>
</div>
</div>
and this is the js (it works the way I want it to but I think it could be cleaner any Ideas?)
window.addEventListener("load", function () {
// wait until the page loads before working with HTML elements
document.addEventListener("click", function (event) {
//click listener on the document
document.querySelectorAll(".navbar-dropdown").forEach(function (el) {
if (el !== event.target) el.classList.remove("is-active");
// close any showing dropdown that isn't the one just clicked
});
document
.querySelectorAll(".navbar-dropdown-link")
.forEach(function (el) {
if (el !== event.target) el.classList.remove("is-active");
// close any showing dropdown that isn't the one just clicked
});
if (event.target.matches(".navbar-dropdown-link")) {
event.target
.closest(".has-dropdown")
.querySelector(".navbar-dropdown")
.classList.toggle("is-active");
}
if (
event.target.matches(".navbar-dropdown-link") &&
event.target.matches(".is-active")
) {
event.target
.closest(".has-dropdown")
.querySelector(".navbar-dropdown")
.classList.remove("is-active");
}
if (event.target.matches(".navbar-dropdown-link")) {
event.target
.closest(".has-dropdown")
.querySelector(".navbar-dropdown-link")
.classList.toggle("is-active");
}
// if this is a dropdown button being clicked, toggle the show class
});
});
and to open and close the nav in mobile I have the button
<a
role="button"
class="navbar-burger"
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarBasicExample" class="navbar-menu">
<!--body of nav-->
</div>
and Js. I would like to edit this script so it closes when you click anywhere out side of the nav <div id="navbarBasicExample" class="navbar-menu">
any ideas? here is the script I have (taken from the bulma site
document.addEventListener("DOMContentLoaded", () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(
document.querySelectorAll(".navbar-burger"),
0
);
// Add a click event on each of them
$navbarBurgers.forEach((el) => {
el.addEventListener("click", () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle("is-active");
$target.classList.toggle("is-active");
});
});
});
Any suggestions on how I could simplify my script and get the functionality of the nav closing when I click out of it would be greatly appreciated thanks!