在打开另一个下拉菜单之前完全关闭一个下拉菜单

Posted

技术标签:

【中文标题】在打开另一个下拉菜单之前完全关闭一个下拉菜单【英文标题】:Close a dropdown completely before open another one 【发布时间】:2018-10-18 23:23:54 【问题描述】:

我正在构建一个下拉菜单,需要向其中添加以下功能:

当一个下拉菜单打开并且您打开另一个下拉菜单时,无论下拉菜单设置的速度有多快或多慢,前一个下拉菜单都需要在新的下拉菜单开始打开之前完全关闭。

Click to see DEMO

JQuery

$(document).ready(function() 

$(".click").on("click", function(evt) 
   evt.stopPropagation();
  var th = $(this);

  if (th.hasClass("active")) 
    th.removeClass("active");
   th.parent().find(".showup").slideUp(900);
   $(".main-container").removeClass("black-bg");
  else
    $(".active").removeClass("active");
    $(".showup").slideUp(900);
    $(".main-container").removeClass("black-bg");
    setTimeout(function()
    th.addClass("active");
    th.parent().find(".showup").slideDown(900);
$(".main-container").addClass("black-bg");
    ,250);

  

);
$(".showup").on("click", function(evt) 
    evt.stopPropagation();
);

);

$(document).on("click", function() 
    $(".active").parent().find(".showup").slideUp(900);
    $(".active").toggleClass("active");
    if ($(".main-container").hasClass("black-bg")) 
      $(".main-container").toggleClass("black-bg");
    
);

感谢您的帮助。

【问题讨论】:

已经为内容(黑框)和菜单的隐藏添加了代码,如果只在导航之外点击而不是在点击文档时显示 【参考方案1】:

您需要使用.stop(clearQueue,jumpToEnd) 以及slideUp()slideDown() 的第二个参数,即complete 回调函数,以便在动画完成后调用,每个匹配元素调用一次。

你应该先隐藏所有打开,然后在slideUp的完整回调中调用slideDown,这样一旦打开的菜单完全关闭,新的下拉菜单就会打开。

注意传递给 stop() 的 2 个参数,这样当您同时单击时,动画不应继续播放,而是跳到显示或隐藏的最后一个状态

请看下面的演示。

$(document).ready(function() 
  $(".click").on("click", function(e) 
    var menu = $(this);
    toggleDropDown(menu);
  );

  $(document).on('mouseup',function(e) 
    var container = $("nav");

    // if the target of the click isn't the container nor a descendant of the container
    if (!container.is(e.target) && container.has(e.target).length === 0) 
      $('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() 
        $(".main-container").removeClass("black-bg");
        if ($('a.active').hasClass('active')) 
          $('a.active').removeClass('active');
        
      );
    
  );

);


function toggleDropDown(menu) 
  var isActive = $('a.active').length;
  $('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() 
    $(".main-container").removeClass("black-bg");
    if (menu.hasClass('active')) 
      menu.removeClass('active');
     else 
      $('a.active').removeClass('active');
      menu.addClass('active');
      menu.parent().find('.showup').stop(true, true).slideDown(500, function() 
        $(".main-container").addClass("black-bg");
      );
    
  );
  if (!isActive) 
    menu.addClass('active');
    menu.parent().find('.showup').stop(true, true).slideDown(500, function() 
      $(".main-container").addClass("black-bg");
    );
  

* 
  box-sizing: border-box;


body 
  margin: 0;
  font-size: 12px;
  font-family: Arial;


.nav-wrapper 
  width: 100%;
  overflow: hidden;
  background: #424242;


nav 
  width: 100%;
  margin: auto;
  overflow: hidden;
  background: #424242;


.nav-content 
  width: 100%;
  z-index: 999;
  background: #ccc;


.top-bar-section 
  float: right;


.top-bar-section a.active 
  background: #c8c8c8;
  color: #000;


.showup 
  display: none;
  background: #ccc;
  position: absolute;
  width: 100%;
  top: 50px;
  left: 0;
  z-index: 99;
  padding: 30px 15px 30px 20px;


p 
  font-size: 14px;
  line-height: 1.4;


li.nav-item 
  display: inline-block;
  background: #f5f5f5;


li.nav-item a 
  display: block;
  text-decoration: none;
  padding: 10px;


.main-container 
  width: 80%;
  height: 400px;
  margin: auto;


.black-bg 
  background: #000;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-wrapper">
  <nav>
    <div class="top-bar-section">
      <ul>
        <li class="nav-item">
          <a href="#" class="click">Nav item 1</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 1.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 2</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 2.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 3</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 3.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 4</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 4.
              </p>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </nav>
</div>
<div class="main-container">

</div>

【讨论】:

看起来不错,谢谢.. 但是缺少其他功能,例如单击时显示黑框和单击外部时关闭下拉菜单 添加添加和删除类的行应该不是问题,但我已将它们添加回来,主要问题是动画完成后滑动面板,我编辑了@Tiago 太棒了。谢谢!!【参考方案2】:

检查是否有.active,如果有,setTimeout() 有 900 毫秒,如果没有,setTimeout() 有 0 毫秒(实际上应该是4 miliseconds,但它永远不会 100% 准确)。

$(document).ready(function() 

  $(".click").on("click", function(evt) 
    evt.stopPropagation();
    var th = $(this);

    if (th.hasClass("active")) 
      th.removeClass("active");
      th.parent().find(".showup").slideUp(900);
      $(".main-container").removeClass("black-bg");
     else 
      let ms = $(".active").length>0 ? 900:0;
      $(".active").removeClass("active");
      $(".showup").slideUp(900);
      $(".main-container").removeClass("black-bg");
      setTimeout(function() 
        th.addClass("active");
        th.parent().find(".showup").slideDown(900);
        $(".main-container").addClass("black-bg");
      , ms);

    

  );
  $(".showup").on("click", function(evt) 
    evt.stopPropagation();
  );

);

$(document).on("click", function() 
  $(".active").parent().find(".showup").slideUp(900);
  $(".active").toggleClass("active");
  if ($(".main-container").hasClass("black-bg")) 
    $(".main-container").toggleClass("black-bg");
  
);
* 
  box-sizing: border-box;


body 
  margin: 0;


.nav-wrapper 
  width: 100%;
  overflow: hidden;
  background: #424242;


nav 
  /*width: 1024px;*/
  margin: auto;
  overflow: hidden;
  background: #424242;


.nav-content 
  width: 100%;
  z-index: 999;
  background: #ccc;


.top-bar-section 
  float: right;


.top-bar-section a.active 
  background: #f00;


.showup 
  display: none;
  background: #ccc;
  position: absolute;
  width: 100%;
  top: 70px;
  left: 0;
  z-index: 99;
  padding: 30px 15px 30px 20px;


p 
  font-size: 14px;
  line-height: 1.4;


li.nav-item 
  display: inline-block;
  background: #f5f5f5;


li.nav-item a 
  display: block;
  text-decoration: none;
  padding: 10px;


.main-container 
  width: 80%;
  height: 400px;
  margin: auto;


.black-bg 
  background: #000;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-wrapper">
  <nav>
    <div class="top-bar-section">
      <ul>
        <li class="nav-item">
          <a href="#" class="click">Nav item 1</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 1.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 2</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 2.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 3</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 3.
              </p>
            </div>
          </div>
        </li>
        <li class="nav-item">
          <a href="#" class="click">Nav item 4</a>
          <div class="showup">
            <div class="nav-content">
              <p>
                Dropdown for Nav Item 4.
              </p>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </nav>
</div>
<div class="main-container">

</div>

【讨论】:

以上是关于在打开另一个下拉菜单之前完全关闭一个下拉菜单的主要内容,如果未能解决你的问题,请参考以下文章

当打开一个下拉菜单时关闭另一个

Jquery下拉菜单单击始终打开

Bootstrap 导航栏,新的下拉菜单不会关闭移动视图中已打开的下拉菜单

Bootstrap 下拉菜单在悬停时关闭

多级下拉引导

如果空格键在所有浏览器中打开下拉菜单,为啥我的 onchange 触发菜单被认为无法访问