darkhorse
darkhorse

Reputation: 8722

Closing dropdown menus when a user clicks outside using Javascript

I am trying to create dropdown menus which open on click. This is done by adding the .active class to the .dropdown-trigger.on-click class elements which basically displays the menu. So far, everything works, but I don't really understand how I can close an opened dropdown menu when the user clicks anywhere outside of the opened menu. So far, my code looks like this:

document.querySelectorAll(".dropdown-trigger.on-click").forEach(function(elem) {
    elem.addEventListener("click", function() {
        this.classList.toggle("active");
    })
})
.dropdown {
    display: inline-block;
    position: relative;
}
.dropdown .dropdown-menu {
    display: none;
    position: absolute;
    -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    width: auto;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: var(--border-radius);
    background-color: #ffffff;
    z-index: 1;
}
.dropdown .dropdown-menu ul {
    padding: 0;
    margin: 0;
}
.dropdown .dropdown-menu ul > li {
    list-style: none;
    margin: 0;
}
.dropdown .dropdown-menu ul > li.dropdown-menu-content {
    padding: 0.6rem 1.2rem;
    white-space: nowrap;
}
.dropdown .dropdown-menu ul > li.dropdown-menu-divider {
    height: 1px;
    background-color: rgba(0, 0, 0, 0.05);
}
.dropdown .dropdown-menu ul > li > a {
    display: block;
    text-decoration: none;
    padding: 0.6rem 1.2rem;
    color: rgba(0, 0, 0, 0.8);
    cursor: pointer;
    white-space: nowrap;
    min-width: 12rem;
}
.dropdown .dropdown-menu ul > li > a:hover {
    background-color: rgba(0, 0, 0, 0.025);
}
.dropdown .dropdown-trigger.on-click.active + .dropdown-menu {
    display: block;
}
<div class="dropdown">
    <button class="dropdown-trigger on-click">Pick your weapon <i class="fa fa-angle-down"></i></button>
    <div class="dropdown-menu">
        <ul>
            <li class="dropdown-menu-content">
                Weapons
            </li>
            <li class="dropdown-menu-divider"></li>
            <li><a href="#">Sword</a></li>
            <li><a href="#">Lance</a></li>
            <li><a href="#">Axe</a></li>
            <li><a href="#">Bow</a></li>
        </ul>
    </div>
</div>

<div class="dropdown">
    <button class="dropdown-trigger on-click">Pick your class <i class="fa fa-angle-down"></i></button>
    <div class="dropdown-menu">
        <ul>
            <li class="dropdown-menu-content">
                Classes
            </li>
            <li class="dropdown-menu-divider"></li>
            <li><a href="#">Fighter</a></li>
            <li><a href="#">Archer</a></li>
            <li><a href="#">Thief</a></li>
            <li><a href="#">Ninja</a></li>
        </ul>
    </div>
</div>

Note: When a user clicks on an opened menu, the menu should not close. It should only close when a user clicks outside of the opened menu.

How can I do this using plain Javascript? Thanks for any help.

Upvotes: 0

Views: 254

Answers (1)

Christopher Anderson
Christopher Anderson

Reputation: 101

This will add a click to your document that checks if the button is being clicked. If not, it will check if there is an active dropdown and make it inactive.

document.addEventListener('click', function (event) {

    // Return if clicking on trigger
    if (event.target.matches('.dropdown-trigger')) {
      return;
    }

    document.querySelectorAll(".dropdown-trigger.active").forEach(function(elem) {
       elem.classList.remove('active');
    })

}, false);

Upvotes: 2

Related Questions