javascript - 通过单击其他区域(包括其他下拉菜单)关闭下拉菜单

标签 javascript jquery html css drop-down-menu

我正在尝试制作一个下拉菜单,其中 .dropdown-content 在点击 .dropbtn 时显示,如果用户点击该菜单的任何其他部分则消失页面,包括另一个 .dropbtn。我在这里找到的大多数解决方案都需要检测页面上任意位置的点击并停止在 .dropdown 类中传播。问题是我有多个带有 .dropdown 类的按钮,我认为我不需要那么复杂的解决方案。我想我只是需要帮助来修改我现有的 javascript。

CSS

<style>
ul.topnav .dropdown {display: inline-block;}
ul.topnav .dropbtn {background-color: black;}
ul.topnav .dropbtn:after {/*inject down caret*/}
ul.topnav .dropbtn.active:after {/*inject up caret*/}
ul.topnav .dropdown-content {display: none;}
ul.topnav .dropdown-content.show {display:block;}
</style>

HTML

<ul class="topnav" id="myTopnav">
    <li><a href="#">Home</a></li>
    <li class="dropdown">
        <a href="#" class="dropbtn">Locations</a>
        <div class="dropdown-content">
            <a href="#">Location 1</a>
            <a href="#">Location 2</a>
        </div>
    </li>
    <li class="dropdown">
        <a href="#" class="dropbtn">Photos</a>
        <div class="dropdown-content">
            <a href="#">Folder 1</a>
            <a href="#">Folder 2</a>
            <a href="#">Folder 3</a>
        </div>
    </li>
    <li><a href="#about">About Us</a></li>
</ul>

JavaScript

<script>
/*controls topnav accordion*/
var acc = document.getElementsByClassName("dropbtn");
var i;
for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
    }
}
</script>

这使得 .dropdown-content 在其父级 .dropbtn 被点击时出现和消失,但我仍然可以一次打开多个下拉菜单,并且没有当我点击另一个或点击页面本身时关闭。我试图编写一段 javascript,当我点击当前事件的 .dropbtn< 以外的任何地方时,它会切换 .dropbtn.active.dropdown-content.show/em>,但它不起作用。这是我失败的尝试:

<script>
window.onclick = function(e) {
    if (!e.target.matches('.dropbtn.active')) {
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show”);
}
</script>

我怀疑有一个简单的修复方法,但我是 javascript 的新手。同样,我希望在单击新的下拉按钮时关闭所有打开的下拉菜单,并在单击下拉菜单以外的任何位置时关闭该下拉菜单。也许这段代码和上面的(有效的)javascript 可以结合使用?请帮忙。

最佳答案

试试这个例子,使用 for 循环只切换被点击的元素,并为其他使用 e.target.nextElementSiblinge.target.previousElementSibling 的元素移除 .show

<style>
  ul.topnav .dropdown {
    display: inline-block;
  }
  ul.topnav .dropbtn {
    background-color: black;
  }
  ul.topnav .dropbtn:after {
    /*inject down caret*/
  }
  ul.topnav .dropbtn.active:after {
    /*inject up caret*/
  }
  ul.topnav .dropdown-content {
    display: none;
  }
  ul.topnav .dropdown-content.show {
    display: block;
  }
</style>

<ul class="topnav" id="myTopnav">
  <li><a href="#">Home</a>
  </li>
  <li class="dropdown">
    <a href="#" class="dropbtn">Locations</a>
    <div class="dropdown-content">
      <a href="#">Location 1</a>
      <a href="#">Location 2</a>
    </div>
  </li>
  <li class="dropdown">
    <a href="#" class="dropbtn">Photos</a>
    <div class="dropdown-content">
      <a href="#">Folder 1</a>
      <a href="#">Folder 2</a>
      <a href="#">Folder 3</a>
    </div>
  </li>
  <li><a href="#about">About Us</a>
  </li>
</ul>
<script>
  window.onclick = function(e) {
    var targ = e.target;
    var drp = document.getElementsByClassName("dropdown-content");
    for (var i = 0; i < drp.length; i++) {
      if (drp[i].previousElementSibling == targ) {
        targ.nextElementSibling.classList.toggle("active");
        targ.nextElementSibling.classList.toggle("show");
      } else {
        drp[i].className = drp[i].className.replace(/\bshow\b/, '');
      }
    }

  }
</script>

关于javascript - 通过单击其他区域(包括其他下拉菜单)关闭下拉菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40319946/

相关文章:

html - 使 Wordpress 站点 100% 浏览器宽度

html - 平板电脑/手机屏幕上的网站页面仅显示左上角(需要 : page is minimized to fit the screen and can be zoom-ed)

javascript - 发布到 URL 而不使用 ajax 的简单方法?

javascript - jQuery 的 ajax 函数在 Android PhoneGap 应用程序中不起作用

javascript - 如何将参数从链接传递到jquery方法

javascript - 为什么单个 document.write 语句同时加载 jquery 缩小文件和完整的 jquery 文件?

javascript - float 窗口和 zindex 应用的问题

javascript - 通过类名获取div并在javascript中返回它

javascript - JS/JQuery 中的复选框计数

JavaScript 获取当前时间不工作 Firefox