在动画导航下拉列表上创建点击关闭事件

时间:2018-12-03 22:22:36

标签: javascript jquery html css

我有2个问题:

  1. 我正在尝试创建一个点击事件,在该事件中检测到“导航”菜单的点击,这会触发对打开列表元素的取消选择并收回其相应的下拉内容。
  2. 我当前的代码不允许添加其他没有下拉内容的列表元素/导航项,因为这样做会妨碍整个代码的正常运行。我想添加另一个没有下拉列表内容的“ nav”列表元素,而又不妨碍其他列表元素及其各自下拉列表内容的功能。

这是我的代码(也可以在JSFiddle上找到):

$(function() {

  function animate() {
    $('#nav .nav-ul li').off('click', animate)
    var $detected = $(this).closest('.nav-ul');
    $detected.find('li.detected').removeClass('detected');
    $(this).addClass('detected');

    //figure out which rel to show
    var ulToShow = $(this).attr('rel');

    //hide current rel
    if ($('.substitute .sub-child.active').length > 0) {
      $('.substitute .sub-child.active').hide(700, function() {
        $(this).removeClass('active');
        $('#' + ulToShow).fadeIn(528, function() {
          $(this).addClass('active');
          $('#nav .nav-ul li').on('click', animate)

        });
      });
    } else {
      $('#' + ulToShow).fadeIn(528, function() {
        $(this).addClass('active');
        $('#nav .nav-ul li').on('click', animate)
      });
    }
  }

  $('#nav .nav-ul li').on('click', animate);
});
* {
  margin: 0;
  padding: 0;
}

#nav {
  background-color: /*blue*/
  ;
  float: right;
}

#nav .nav-ul {
  list-style: none;
  float: right;
  background-color: /*yellow*/
  ;
  border-left: solid 2px #000000;
  border-right: solid 2px #000000;
}

#nav .nav-ul li {
  float: left;
  padding: 4px;
  font-weight: bold;
  color: #000000;
}

#nav .nav-ul li:hover {
  cursor: pointer;
  text-decoration: underline;
  color: #E51D27;
}

#nav .nav-ul li.detected {
  color: #E51D27;
}

#nav .substitute {
  float: right;
  background-color: /*pink*/
  ;
  margin-right: 4px;
}

#nav .substitute .sub-child {
  float: left;
  display: none;
}

#nav .substitute .sub-child.active {
  display: block;
}

#nav .substitute .sub-child ul {
  list-style: none;
}

#nav .substitute .sub-child ul li {
  float: left;
  padding: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nav">
  <ul class="nav-ul">
    <li class="" rel="pay1">Color</li>
    <li rel="pay2">Shape</li>
    <li rel="pay3">Size</li>
  </ul>
  <div class="substitute">
    <div id="pay1" class="sub-child">
      <ul>
        <li>Red</li>
        <li>Blue</li>
        <li>Green</li>
      </ul>
    </div>
    <div id="pay2" class="sub-child">
      <ul>
        <li>Square</li>
        <li>Circle</li>
        <li>Triangle</li>
        <li>Diamond</li>
      </ul>
    </div>
    <div id="pay3" class="sub-child">
      <ul>
        <li>Small</li>
        <li>Medium</li>
        <li>Large</li>
      </ul>
    </div>
  </div>
</div>

1 个答案:

答案 0 :(得分:3)

  
      
  1. 我正在尝试创建一个点击事件,在该事件中检测到“导航”菜单的点击,这会触发对打开列表元素的取消选择并收回其相应的下拉内容。
  2.   

为此,您可以在主体上创建一个click事件处理程序,以关闭菜单(如果打开的话)。像这样:

// close menu when clicking anywhere on the document
$(document).on("click", function() {
  $("#nav li.detected").removeClass("detected");
  $("#nav div.active").hide(700, function() { $(this).removeClass("active"); });
});

然后,为了避免在单击菜单时将其关闭,可以在animate函数中使用.stopPropagation()来阻止事件在DOM树上的冒泡。

  
      
  1. 我当前的代码不允许添加其他没有下拉内容的列表元素/导航项,因为这样做会妨碍整个代码的正常运行。我想添加另一个没有下拉列表内容的“ nav”列表元素,而又不妨碍其他列表元素及其各自下拉列表内容的功能。
  2.   

之所以会发生这种情况,是因为您每次单击菜单时都会关联和取消关联事件(这并不是必须的),因此,当其中一个导航项没有与之关联的下拉菜单时,事件处理程序将已删除(与off()函数中的animate一起使用),但没有再次关联,这会导致您不希望出现此行为。

解决方案很简单:每次调用animate函数时,都不需要分离并重新附加click事件处理程序。在off函数中删除对onanimate的调用,就是这样。


在这里您可以看到两种更改都适用于您的代码:

$(function() {

  function animate(e) {
    e.stopPropagation();
    var $detected = $(this).closest('.nav-ul');
    if (!$detected.hasClass("active-animation")) {
      $detected.addClass("active-animation");
      $detected.find('li.detected').removeClass('detected');
      $(this).addClass('detected');

      //figure out which rel to show
      var ulToShow = $(this).attr('rel');

      //hide current rel
      if ($('.substitute .sub-child.active').length > 0) {
        $('.substitute .sub-child.active').hide(700, function() {
          $(this).removeClass('active');
          $('#' + ulToShow).fadeIn(528, function() {
            $(this).addClass('active');
            $detected.removeClass("active-animation");
          });
        });
      } else {
        $('#' + ulToShow).fadeIn(528, function() {
          $(this).addClass('active');
          $detected.removeClass("active-animation");
        });
      }
    }
  }

  $('#nav .nav-ul li').on('click', animate);

  // close menu when clicking anywhere on the page
  $(document).on("click", function() {
    $("#nav li.detected").removeClass("detected");
    $("#nav div.active").hide(700, function() {
      $(this).removeClass("active");
    });
  });
});
* {
  margin: 0;
  padding: 0;
}

#nav {
  background-color: /*blue*/
  ;
  float: right;
}

#nav .nav-ul {
  list-style: none;
  float: right;
  background-color: /*yellow*/
  ;
  border-left: solid 2px #000000;
  border-right: solid 2px #000000;
}

#nav .nav-ul li {
  float: left;
  padding: 4px;
  font-weight: bold;
  color: #000000;
}

#nav .nav-ul li:hover {
  cursor: pointer;
  text-decoration: underline;
  color: #E51D27;
}

#nav .nav-ul li.detected {
  color: #E51D27;
}

#nav .substitute {
  float: right;
  background-color: /*pink*/
  ;
  margin-right: 4px;
}

#nav .substitute .sub-child {
  float: left;
  display: none;
}

#nav .substitute .sub-child.active {
  display: block;
}

#nav .substitute .sub-child ul {
  list-style: none;
}

#nav .substitute .sub-child ul li {
  float: left;
  padding: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nav">
  <ul class="nav-ul">
    <li class="" rel="pay1">Color</li>
    <li rel="pay2">Shape</li>
    <li rel="pay3">Size</li>
    <li>No Dropdown</li>
  </ul>
  <div class="substitute">
    <div id="pay1" class="sub-child">
      <ul>
        <li>Red</li>
        <li>Blue</li>
        <li>Green</li>
      </ul>
    </div>
    <div id="pay2" class="sub-child">
      <ul>
        <li>Square</li>
        <li>Circle</li>
        <li>Triangle</li>
        <li>Diamond</li>
      </ul>
    </div>
    <div id="pay3" class="sub-child">
      <ul>
        <li>Small</li>
        <li>Medium</li>
        <li>Large</li>
      </ul>
    </div>
  </div>
</div>