下拉菜单将响应点击其他内容

时间:2017-10-25 19:52:10

标签: javascript html css

我有这个下拉菜单解决方案。 http://jsfiddle.net/ftymhs8s/

当我点击不同的行并显示它的下拉菜单时,我需要隐藏显示的一个下拉菜单。我还需要在人们访问网站时始终显示第一行下拉菜单。

我希望我能正确描述我的问题,能帮助我吗?



// Dropdown Menu
var dropdown = document.querySelectorAll('.dropdown');
var dropdownArray = Array.prototype.slice.call(dropdown, 0);
dropdownArray.forEach(function(el) {
  var button = el.querySelector('a[data-toggle="dropdown"]'),
    menu = el.querySelector('.dropdown-menu'),
    arrow = button.querySelector('i.icon-arrow');

  button.onclick = function(event) {
    if (!menu.hasClass('show')) {
      menu.classList.add('show');
      menu.classList.remove('hide');
      arrow.classList.add('open');
      arrow.classList.remove('close');
      event.preventDefault();
    } else {
      menu.classList.remove('show');
      menu.classList.add('hide');
      arrow.classList.remove('open');
      arrow.classList.add('close');
      event.preventDefault();
    }
  };
})

Element.prototype.hasClass = function(className) {
  return this.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(this.className);
};

ul {
  list-style: none
}

.dropdown a {
  text-decoration: none;
}

.dropdown [data-toggle="dropdown"] {
  position: relative;
  display: block;
  color: black;
  padding: 10px;
}

.dropdown .dropdown-menu {
  max-height: 0;
  overflow: hidden;
}

.dropdown .dropdown-menu li {
  padding: 0;
}

.dropdown .dropdown-menu li a {
  display: block;
  padding: 10px 10px;
}

.dropdown .show {
  display: block;
  max-height: 9999px;
  margin-left: 50px;
}

.dropdown .hide {
  max-height: 0;
}

<div class="container">
  <ul>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">First Menu</a>
      <ul class="dropdown-menu">
        <li><a href="#">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </li>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">Second Menu</a>
      <ul class="dropdown-menu">
        <li><a href="#">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </li>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">Third Menu </a>
      <ul class="dropdown-menu">
        <li><a href="#">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </li>
  </ul>
</div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

多个可折叠元素的行为(其中只有一个可以同时打开)是手风琴的行为。一般的想法是首先关闭所有可折叠,然后打开用户选择的那个。以下演示通过Event Delegation展示了该行为。

BTW我注意到你做了一个hasClass ......类。这不是必需的,只需使用:node.classList.contains('class')

详情在演示

中发表了评论

演示

/* Added .main class to parent <ul>
|| By adding the eventListener to the
|| parent of multiple clickable nodes
|| and using e.target property to find
|| the exact node actually clicked, we
|| have just needed the <ul> to listen
|| rather than 3 separate <li>
|| This is part of Event Delagation
*/
var main = document.querySelector('.main');

main.addEventListener('click', accordion, false);

function accordion(e) {

  /* Gather all .dropdown-menu to a NodeList
  || then covert it to an array
  */
  var dropArray = Array.from(document.querySelectorAll('.dropdown-menu'));

  /* Gather all links in the .dropdown-menus to
  || a NodeList then convert it to an array
  */
  var linxArray = Array.from(document.querySelectorAll('a + .dropdown-menu a'));

  /* if the clicked node (e.target) is NOT the
  || node listening for event (e.currentTarget
  || ul.main) then...
  */
  if (e.target !== e.currentTarget) {

    // Assign e.target to var tgr
    var tgr = e.target;

    /* if tgr has data-toggle attribute...
    || Find tgr next sibling (.dropdown-menu)
    || Iterate through dropArray wth a
    || for...of loop
    || Remove .show and add .hide on
    || each .dropdown-menu in dropArray
    || Then add .show and remove .hide
    || on tgt
    || Finally stop the click event from
    || bubbling, thereby preventing anything
    || else from being triggered.
    */
    if (tgr.hasAttribute('data-toggle')) {

      // Stop <a> from jumping
      e.preventDefault();
      var tgt = tgr.nextElementSibling;
      for (let drop of dropArray) {
        drop.classList.remove('show');
        drop.classList.add('hide');
      }
      tgt.classList.add('show');
      tgt.classList.remove('hide');
    } else {
      return;
    }
    e.stopPropagation();
  }
}
html,
body,
.contain {
  height: 100%;
  width: 100%;
}

.main,
section,
article {
  margin-bottom: 100vh;
}

ul {
  list-style: none
}

.dropdown a {
  text-decoration: none;
}

.dropdown [data-toggle="dropdown"] {
  position: relative;
  display: block;
  color: black;
  padding: 10px;
}

.dropdown .dropdown-menu {
  max-height: 0;
  overflow: hidden;
}

.dropdown .dropdown-menu li {
  padding: 0;
}

.dropdown .dropdown-menu li a {
  display: block;
  padding: 10px 10px;
}

.dropdown .show {
  display: block;
  max-height: 9999px;
  margin-left: 50px;
}

.dropdown .hide {
  max-height: 0;
}
<div id='home' class="container">
  <ul class='main'>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">First Menu</a>
      <ul class="dropdown-menu">
        <li><a href="#home">Home</a></li>
        <li><a href="#about">About Us</a></li>
        <li><a href="#services">Services</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </li>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">Second Menu</a>
      <ul class="dropdown-menu">
        <li><a href="#1">Section I</a></li>
        <li><a href="#2">Section II</a></li>
        <li><a href="#3">Section III</a></li>
        <li><a href="#4">Section IV</a></li>
      </ul>
    </li>
    <li class="dropdown">
      <a href="#" data-toggle="dropdown">Third Menu</a>
      <ul class="dropdown-menu">
        <li><a href="https://example.com">Example</a></li>
        <li><a href="https://example.com">Example</a></li>
        <li><a href="https://example.com">Example</a></li>
        <li><a href="https://example.com">Example</a></li>
      </ul>
    </li>
  </ul>
  <article id='about'>
    <h2>About</h2>
  </article>

  <article id='services'>
    <h2>Services</h2>
  </article>

  <article id='contact'>
    <h2>Contact</h2>
  </article>

  <hr>

  <section id='1'>
    <h2>Section I</h2>
  </section>


  <section id='2'>
    <h2>Section II</h2>
  </section>


  <section id='3'>
    <h2>Section III</h2>
  </section>


  <section id='4'>
    <h2>Section IV</h2>
  </section>

</div>