1

I've trying to create dropdown menu on click and close menu when clicked outside.

My currently problem is when i clicked on menu it only toggle or drop down only 1 menu, it doesn't toggle or dropdown on the other menu,

I've searching for the solution i found this one https://stackoverflow.com/a/3028037/14862921

function hideOnClickOutside(element) {
const outsideClickListener = event => {
    if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
      element.style.display = 'none'
      removeClickListener()
    }
}

const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener)
}

document.addEventListener('click', outsideClickListener)
}

const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )

at the Edit – 2018-03-11 this is pure Javascrilpt, I want to apply this code to my project, honestly i'm new to Javascript i have no idea how to raplace the code to my project.

Any help or advices i will appreciate it. Thank you very much.

This is my project. https://jsfiddle.net/Yurael/7aju8x1k/14/

function dropDownMenu() {
    var btnNav = document.querySelector('.nav-menu');
    var dropSub = document.querySelector('.nav-dropdown');

    btnNav.addEventListener('click', function () {
        dropSub.classList.toggle('show');
    })

}
dropDownMenu();
/*Block*/
.nav li {
    display: inline-block;
    list-style: none;
    color: black;
    width: 100px;
    height: auto;
    border: 1px solid red;
    font-size: 20px;
    text-align: center;
}


/*Element*/
.nav-dropdown {
    display: none;
    position: absolute;
}

.nav-dropdown li {
    position: relative;
    display: flex;
    left: -40%;
}

.show {
    display: block;
}
    <ul class="nav">
        <li>Home</li>
        <li class="nav-menu">Menu1
            <ul class="nav-dropdown">
                <li>Example1</li>
                <li>Example2</li>
                <li>Example3</li>
            </ul>
        </li>

        <li class="nav-menu">Menu2
            <ul class="nav-dropdown">
                <li>Example1</li>
                <li>Example2</li>
                <li>Example3</li>
            </ul>
        </li>
    </ul>
connexo
  • 53,704
  • 14
  • 91
  • 128
Yurael
  • 23
  • 6

1 Answers1

3

querySelector returns only the first match. You want to select all of the menu buttons, so use querySelectorAll and iterate over the resulting NodeList:

document.addEventListener(
  'DOMContentLoaded', // make sure DOM is fully parsed before accessing elements!
  function() {
    const buttons = document.querySelectorAll('.nav-menu');

    for (const button of buttons) {
      button.addEventListener('click', function(event) {
        if (event.target.matches('li.nav-menu')) { // make sure it's not a click from the dropdown that has bubbled up
          button.querySelector('.nav-dropdown').classList.toggle('show');
        }
      })
    }
    // on outside click, close all dropdowns
    document.addEventListener('click', function(event) {
      const clickedElement = event.target;
      const dropdowns = document.querySelectorAll('.nav-dropdown');
      if (clickedElement.closest('.nav-menu') === null) {
        for (const dropdown of dropdowns) {
          dropdown.classList.remove('show');
        }
      }
    })
  }
);
/*Block*/

.nav li {
  display: inline-block;
  list-style: none;
  color: black;
  width: 100px;
  height: auto;
  border: 1px solid red;
  font-size: 20px;
  text-align: center;
}


/*Element*/

.nav-dropdown {
  display: none;
  position: absolute;
}

.nav-dropdown li {
  position: relative;
  display: flex;
  left: -40%;
}

.show {
  display: block;
}
<ul class="nav">
  <li>Home</li>
  <li class="nav-menu">Menu1
    <ul class="nav-dropdown">
      <li>Example1</li>
      <li>Example2</li>
      <li>Example3</li>
    </ul>
  </li>

  <li class="nav-menu">Menu2
    <ul class="nav-dropdown">
      <li>Example1</li>
      <li>Example2</li>
      <li>Example3</li>
    </ul>
  </li>
</ul>
connexo
  • 53,704
  • 14
  • 91
  • 128