点击一个下拉菜单并关闭所有其他下拉菜单(香草javascript)

时间:2017-08-29 06:55:52

标签: javascript drop-down-menu

您好我是vanilla JavaScript的新手,并试图对它有一个很好的理解。我创建了一个多下拉菜单导航,当单击下拉按钮时,单击事件触发菜单,将具有display属性block的.show CSS类添加到下拉菜单中。我遇到的问题是,当我打开一个菜单并单击另一个下拉菜单按钮时,我希望关闭当前/所有其他菜单。我不确定如何实现这一目标。非常感谢任何帮助,谢谢。

这是JS:

(function() {

  var dropBtns = document.querySelectorAll('.dropdown');

  dropBtns.forEach(function(btn) {

    btn.addEventListener('click', function(e) {
      var dropContent = btn.querySelector('.dropMenu');
      e.preventDefault();

      if (!dropContent.classList.contains('show')) {
        dropContent.classList.add('show');
      } else {
        dropContent.classList.remove('show');
      }
      e.stopPropagation();
    });


  });

  //   close menus when clicking outside of them
  window.addEventListener('click', function(event) {
    if (event.target != dropBtns) {
      openMenus = document.querySelectorAll('.dropMenu');
      openMenus.forEach(function(menus) {
        menus.classList.remove('show');
      });
    }
  });

})();

这是CSS:

.room-sort {
  background: #434A54;
  margin: 0;
  padding: 0;
  text-align: center;
}

.room-sort-menu ul {
  margin: 0;
  padding: 0;
}

span.sort {
  margin-right: 30px;
  color: #fff;
  font-weight: 500;
}

.sort-mobile {
  display: none;
}

.room-sort-menu>li {
  display: inline-block;
  color: #fff;
}

.room-sort-menu>li>a {
  display: inline-block;
  padding: 16px 30px;
  margin: 0;
  font-size: 0.8em;
  color: #fff;
  text-decoration: none;
}

.room-sort-menu>li>a:hover,
.room-sort-menu>li>a:focus {
  background: #2e333a;
}

.dropdown {
  position: relative;
}

.dropMenu {
  position: absolute;
  display: none;
  top: 46px;
  left: 0px;
  border: 1px solid color;
  width: 109px;
  background: #CB242D;
  font-size: 0.8em;
  z-index: 1;
}

.show {
  display: block;
}

.room-sort-menu li:last-of-type ul.dropMenu {
  width: 166px;
}

.dropMenu li a {
  display: block;
  padding: 16px 20px;
  color: #fff;
  text-decoration: none;
}

.dropMenu li a:hover {
  background: #a0080d;
}

这是HTML:

<div class="room-sort">

  <ul class="room-sort-menu">

    <span class="sort">Sort by :</span>
    <li class="dropdown"><a class="dropBtn" href="#">Price <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Price (hi to low)</a></li>
        <li><a href="#">Price (low to hi)</a></li>
      </ul>
    </li>
    <li class="dropdown"><a class="dropBtn" href="#">Stars <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Stars (hi to low)</a></li>
        <li><a href="#">Stars (low to hi)</a></li>
      </ul>
    </li>

    <li class="dropdown"><a class="dropBtn" href="#">Review score <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Score (hi to low)</a></li>
        <li><a href="#">Score (low to hi)</a></li>
      </ul>
    </li>
  </ul>
</div>

1 个答案:

答案 0 :(得分:4)

你几乎就在那里,只是将代码移动了一下,它按预期工作。

(function() {

  var dropBtns = document.querySelectorAll('.dropdown');

  function closeOpenItems() {
      openMenus = document.querySelectorAll('.dropMenu');
      openMenus.forEach(function(menus) {
        menus.classList.remove('show');
      });  
  }

  dropBtns.forEach(function(btn) {

    btn.addEventListener('click', function(e) {
      var 
        dropContent = btn.querySelector('.dropMenu'),
        shouldOpen = !dropContent.classList.contains('show');
      e.preventDefault();

      // First close all open items.
      closeOpenItems();
      // Check if the clicked item should be opened. It is already closed at this point so no further action is required if it should be closed.
      if (shouldOpen) {
        // Open the clicked item.
        dropContent.classList.add('show');      
      }
      e.stopPropagation();
    });


  });

  //   close menus when clicking outside of them
  window.addEventListener('click', function(event) {
    if (event.target != dropBtns) {
      // Moved the code here to its own function.
      closeOpenItems();
    }
  });

})();
.room-sort {
  background: #434A54;
  margin: 0;
  padding: 0;
  text-align: center;
}

.room-sort-menu ul {
  margin: 0;
  padding: 0;
}

span.sort {
  margin-right: 30px;
  color: #fff;
  font-weight: 500;
}

.sort-mobile {
  display: none;
}

.room-sort-menu>li {
  display: inline-block;
  color: #fff;
}

.room-sort-menu>li>a {
  display: inline-block;
  padding: 16px 30px;
  margin: 0;
  font-size: 0.8em;
  color: #fff;
  text-decoration: none;
}

.room-sort-menu>li>a:hover,
.room-sort-menu>li>a:focus {
  background: #2e333a;
}

.dropdown {
  position: relative;
}

.dropMenu {
  position: absolute;
  display: none;
  top: 46px;
  left: 0px;
  border: 1px solid color;
  width: 109px;
  background: #CB242D;
  font-size: 0.8em;
  z-index: 1;
}

.show {
  display: block;
}

.room-sort-menu li:last-of-type ul.dropMenu {
  width: 166px;
}

.dropMenu li a {
  display: block;
  padding: 16px 20px;
  color: #fff;
  text-decoration: none;
}

.dropMenu li a:hover {
  background: #a0080d;
}
<div class="room-sort">

  <ul class="room-sort-menu">

    <span class="sort">Sort by :</span>
    <li class="dropdown"><a class="dropBtn" href="#">Price <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Price (hi to low)</a></li>
        <li><a href="#">Price (low to hi)</a></li>
      </ul>
    </li>
    <li class="dropdown"><a class="dropBtn" href="#">Stars <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Stars (hi to low)</a></li>
        <li><a href="#">Stars (low to hi)</a></li>
      </ul>
    </li>

    <li class="dropdown"><a class="dropBtn" href="#">Review score <i class="fa fa-caret-down" aria-hidden="true"></i></a>
      <ul class="dropMenu">
        <li><a href="#">Score (hi to low)</a></li>
        <li><a href="#">Score (low to hi)</a></li>
      </ul>
    </li>
  </ul>

</div>