如何使用jQuery依次关闭从子菜单到父菜单



首先,忽略CSS。它只是为了样式。

JS代码的作用:

  • 当点击"菜单"或其中一个"+"时激活。
  • 通过赋予自己"active"类,打开位于点击按钮("菜单"或"+")后的ul,然后CSS完成所有其余的工作(打开菜单并通过.dropdown-toggle.active + .toggleable过渡,其中.toggleableul)。
  • 查找同级别的任何打开的菜单,并在打开单击按钮的菜单之前关闭它们。
  • 当按钮被点击关闭时,它首先依次关闭所有子按钮,从最深的打开按钮开始,最后关闭自己,以产生折叠一张纸的效果。

问题是,当我关闭一个菜单,deepset子将关闭,然后其余的将同时关闭在一起。我想让它们依次关闭。我使用transitionend来检查子进程是否在关闭下一个父进程之前关闭,等等。

// Dropdown toggle click event fucntion.
$('.dropdown-toggle').on('click', function() {
  if ($(this).is('.top-toggler:not(.active)')) { // If the top toggler "Menu" was clicked, and it wasn't ative, activate it, and return.
    $(this).addClass('active');
    return;
  }
  function closeToggleables(button, toggleable) { // Function to process what needs to be closed and close it.
    var $activeChildren = toggleable.find('.dropdown-toggle.active'); // Get all active children dropdown buttons.
    if ($activeChildren.length) { // If active children dropdown buttons exist, continue.
      $.each($activeChildren, function(i, activeChild){ // Iterate through every active child button.
          // Hook the ul menu next to the active child with a transitionend to close its parent after the transition ends (to close its parent when it is done closing).
          $(activeChild).next('.toggleable').one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function() { // The transitionend hook.
            $(activeChild).parent().parent().prev('.active').removeClass('active'); // Close parent when transition ends.
          });
      });
      $activeChildren.last().removeClass('active'); // Deactivate the last active button to begin closing from the deepest child to the passed parent.
    } else {
      button.removeClass('active'); // If there are no active children buttons, just deactivate this button to close its menu.
    }
  }
  if ($(this).hasClass('active')) { // If the clicked button is active.
    closeToggleables($(this), $(this).next('.toggleable')); // Send element and its menu to process how it will close.
  } else {  // If this menu button is inactive.
    var $activeSibling = $(this).parent().siblings('.parent').children('.active'); // See if any siblings are open.
    if ($activeSibling.length) { // If an open sibling exists.
      closeToggleables($activeSibling, $activeSibling.next('.toggleable')); // Send the sibling to be processed to close first.
    }
    $(this).addClass('active'); // Activate this menu.
  }
});
body {
    font-family: lato, sans-serif;
    font-size: 1em;
    line-height: 1.5;
    color: #2c3e50;
}
a {
    text-decoration: none;
}
.text-center {
    text-align: center;
}
.hide {
    visibility: hidden;
    overflow: hidden;
    max-height: 0;
}
.dropdown-toggle {
    line-height: inherit;
    padding: 12px;
    color: #ecf0f1;
    outline: 0;
}
.dropdown-toggle.active {
    color: #fbfcfc;
    background: #ea6153;
}
.toggleable {
    -webkit-transition: max-height .75s ease-in-out, -webkit-transform .75s ease-in-out, visibility .75s ease-in-out;
    transition: max-height .75s ease-in-out, transform .75s ease-in-out, visibility .75s ease-in-out;
    -webkit-transform: scaleY(0);
    transform: scaleY(0);
    -webkit-transform-origin: top;
    transform-origin: top;
}
.toggleable .toggleable {
    -webkit-transform: scaleY(1);
    transform: scaleY(1);
    -webkit-transform-origin: center;
    transform-origin: center;
}
.dropdown-toggle.active + .toggleable {
    visibility: visible;
    max-height: 1200px;
    -webkit-transform: scaleY(1);
    transform: scaleY(1);
}
ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}
button {
    font-family: lato, sans-serif;
    font-size: 1em;
    padding: .75em 1.5em;
    -webkit-transition: background-color .75s ease;
    transition: background-color .75s ease;
    vertical-align: middle;
    color: #ecf0f1;
    border: 0;
    border-radius: 3px;
    background-color: #e74c3c;
}
button:focus,
button:hover {
    color: #fbfcfc;
    background-color: #ea6153;
}
#nav-primary {
    position: relative;
    margin: 30px 10px;
}
#nav-primary .dropdown-toggle.active + .toggleable > .menu-item {
    margin: 0;
    -webkit-transform: perspective(320px) rotateX(0deg);
    transform: perspective(320px) rotateX(0deg);
    box-shadow: inset 0 0 20px 0 transparent;
}
#menu-main-toggle {
    width: 100%;
    border-radius: 0;
}
#menu-main {
    position: absolute;
    width: 100%;
}
#menu-main .menu-item {
    -webkit-transition: -webkit-transform .75s ease-in-out, margin .75s ease-in-out, -webkit-box-shadow .75s ease-in-out;
    transition: transform .75s ease-in-out, margin .75s ease-in-out, box-shadow .75s ease-in-out;
    background: #e74c3c;
}
#menu-main .menu-item.odd {
    margin-bottom: -100px;
    -webkit-transform: perspective(320px) rotateX(-90deg);
    transform: perspective(320px) rotateX(-90deg);
    -webkit-transform-origin: top;
    transform-origin: top;
    box-shadow: inset 0 -50px 25px 0 rgba(0, 0, 0, .5);
}
#menu-main .menu-item.even {
    margin-top: -100px;
    -webkit-transform: perspective(320px) rotateX(90deg);
    transform: perspective(320px) rotateX(90deg);
    -webkit-transform-origin: bottom;
    transform-origin: bottom;
    box-shadow: inset 0 50px 25px 0 rgba(0, 0, 0, .5);
}
#menu-main .menu-link {
    display: inline-block;
    width: 100%;
    height: 50px;
    padding: 12px;
    color: #ecf0f1;
    border-top: 1px dashed #bf2718;
    box-sizing: border-box;
}
#menu-main .parent .dropdown-toggle.active + .toggleable > .menu-item {
    margin: 0 5px;
}
#menu-main .parent .dropdown-toggle.active + .toggleable > .menu-item.last {
    margin-bottom: 5px;
}
#menu-main .parent > .menu-link {
    margin-right: -54px;
}
#menu-main .dropdown-toggle {
    width: 50px;
    height: 48px;
    vertical-align: bottom;
    border-radius: 0;
    background: transparent;
}
#menu-main .toggleable {
    background: #bf2718;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css" rel="stylesheet"/>
<nav id="nav-primary" class="text-center">
  <button id="menu-main-toggle" class="top-toggler dropdown-toggle">Menu</button>
  <ul id="menu-main" class="toggleable hide">
    <li class="menu-item odd">
      <a class="menu-link" href="http://example.com/">About</a>
    </li>
    <li class="menu-item even">
      <a class="menu-link" href="http://example.com/">Something</a>
    </li>
    <li class="menu-item odd parent">
      <a class="menu-link" href="http://example.com/">Information Technology</a>
      <button class="dropdown-toggle">+</button>
      <ul class="toggleable hide">
        <li class="menu-item odd parent">
          <a class="menu-link" href="http://example.com/">Web Development</a>
          <button class="dropdown-toggle">+</button>
          <ul class="toggleable hide">
            <li class="menu-item odd">
              <a class="menu-link" href="http://example.com/">HTML</a>
            </li>
            <li class="menu-item even">
              <a class="menu-link" href="http://example.com/">CSS</a>
            </li>
            <li class="menu-item odd last">
              <a class="menu-link" href="http://example.com/">Javascript</a>
            </li>
          </ul>
        </li>
        <li class="menu-item even last">
          <a class="menu-link" href="http://example.com/">Unix</a>
        </li>
      </ul>
    </li>
    <li class="menu-item even parent">
      <a class="menu-link" href="http://example.com/">Level One</a>
      <button class="dropdown-toggle">+</button>
      <ul class="toggleable hide">
        <li class="menu-item odd last parent">
          <a class="menu-link" href="http://example.com/">Level Two</a>
          <button class="dropdown-toggle">+</button>
          <ul class="toggleable hide">
            <li class="menu-item odd last parent">
              <a class="menu-link" href="http://example.com/">Level Three</a>
              <button class="dropdown-toggle">+</button>
              <ul class="toggleable hide">
                <li class="menu-item odd last parent">
                  <a class="menu-link" href="http://example.com/">Lorem</a>
                  <button class="dropdown-toggle script-dependant">+</button>
                  <ul class="toggleable hide">
                    <li class="menu-item odd parent">
                      <a class="menu-link" href="http://example.com/">Ipsum</a>
                      <button class="dropdown-toggle script-dependant">+</button>
                      <ul class="toggleable hide">
                        <li class="menu-item odd last">
                          <a class="menu-link" href="http://example.com/">Dolor</a>
                        </li>
                      </ul>
                    </li>
                    <li class="menu-item even last">
                      <a class="menu-link" href="http://example.com/">Situs</a>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="menu-item odd">
      <a class="menu-link" href="http://example.com/">Snippets</a>
    </li>
    <li class="menu-item even last">
      <a class="menu-link" href="http://example.com/">Contact</a>
    </li>
  </ul>
</nav>

由于元素上有多个属性过渡,因此每当调用transitionend时,我只检查元素的高度。一旦高度为零,我就解除事件的绑定并切换父按钮。

// Dropdown toggle click event fucntion.
$('.dropdown-toggle').on('click', function() {
  // If dropdown-toggle is an inactive top toggler, activate.
  if ($(this).is('.top-toggler:not(.active)')) {
    $(this).addClass('active');
    return;
  }
  // Function to process how to close toggleables; either children first, or just the clicked toggleable.
  function closeToggleables(button, toggleable) {
    // Find all active children and turn them into an array.
    var $activeChildren = toggleable.find('.dropdown-toggle.active');
    // If active children exist.
    if ($activeChildren.length) {
      // Iterate through each active child.
      $activeChildren.each( function(){
        // Bind child's menu to activate function when CSS transition ends.
        $(this).next('.toggleable').on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(event) {
          // Since many transitions occur, we check if the height transition ended by checking the height of the child's menu.
          if ($(this).height() === 0) {
            // Unbind event and deactivate parent of child.
            $(this).off(event).parent().parent().prev('.active').removeClass('active');
          }
        });
      });
      // Deactivate last child to start deactivating all parents up to clicked element.
      $activeChildren.last().removeClass('active');
    } else {
      // Deactivate clicked button.
      button.removeClass('active');
    }
  }
  // If button is active.
  if ($(this).hasClass('active')) {
    // Send button and its menu to be processed for closing.
    closeToggleables($(this), $(this).next('.toggleable'));
  } else {
    // Check for an open sibling.
    var $activeSibling = $(this).parent().siblings('.parent').children('.active');
    // If an open sibling exists.
    if ($activeSibling.length) {
      // Send sibling and its menu to be processed for closing.
      closeToggleables($activeSibling, $activeSibling.next('.toggleable'));
    }
    // Activate inactive button.
    $(this).addClass('active');
  }
  
});
body {
    font-family: lato, sans-serif;
    font-size: 1em;
    line-height: 1.5;
    color: #2c3e50;
}
a {
    text-decoration: none;
}
.text-center {
    text-align: center;
}
.hide {
    visibility: hidden;
    overflow: hidden;
    max-height: 0;
}
.dropdown-toggle {
    line-height: inherit;
    padding: 12px;
    color: #ecf0f1;
    outline: 0;
}
.dropdown-toggle.active {
    color: #fbfcfc;
    background: #ea6153;
}
.toggleable {
    -webkit-transition: max-height .75s ease-in-out, -webkit-transform .75s ease-in-out, visibility .75s ease-in-out;
    transition: max-height .75s ease-in-out, transform .75s ease-in-out, visibility .75s ease-in-out;
    -webkit-transform: scaleY(0);
    transform: scaleY(0);
    -webkit-transform-origin: top;
    transform-origin: top;
}
.toggleable .toggleable {
    -webkit-transform: scaleY(1);
    transform: scaleY(1);
    -webkit-transform-origin: center;
    transform-origin: center;
}
.dropdown-toggle.active + .toggleable {
    visibility: visible;
    max-height: 1200px;
    -webkit-transform: scaleY(1);
    transform: scaleY(1);
}
ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}
button {
    font-family: lato, sans-serif;
    font-size: 1em;
    padding: .75em 1.5em;
    -webkit-transition: background-color .75s ease;
    transition: background-color .75s ease;
    vertical-align: middle;
    color: #ecf0f1;
    border: 0;
    border-radius: 3px;
    background-color: #e74c3c;
}
button:focus,
button:hover {
    color: #fbfcfc;
    background-color: #ea6153;
}
#nav-primary {
    position: relative;
    margin: 30px 10px;
}
#nav-primary .dropdown-toggle.active + .toggleable > .menu-item {
    margin: 0;
    -webkit-transform: perspective(320px) rotateX(0deg);
    transform: perspective(320px) rotateX(0deg);
    box-shadow: inset 0 0 20px 0 transparent;
}
#menu-main-toggle {
    width: 100%;
    border-radius: 0;
}
#menu-main {
    position: absolute;
    width: 100%;
}
#menu-main .menu-item {
    -webkit-transition: -webkit-transform .75s ease-in-out, margin .75s ease-in-out, -webkit-box-shadow .75s ease-in-out;
    transition: transform .75s ease-in-out, margin .75s ease-in-out, box-shadow .75s ease-in-out;
    background: #e74c3c;
}
#menu-main .menu-item.odd {
    margin-bottom: -100px;
    -webkit-transform: perspective(320px) rotateX(-90deg);
    transform: perspective(320px) rotateX(-90deg);
    -webkit-transform-origin: top;
    transform-origin: top;
    box-shadow: inset 0 -50px 25px 0 rgba(0, 0, 0, .5);
}
#menu-main .menu-item.even {
    margin-top: -100px;
    -webkit-transform: perspective(320px) rotateX(90deg);
    transform: perspective(320px) rotateX(90deg);
    -webkit-transform-origin: bottom;
    transform-origin: bottom;
    box-shadow: inset 0 50px 25px 0 rgba(0, 0, 0, .5);
}
#menu-main .menu-link {
    display: inline-block;
    width: 100%;
    height: 50px;
    padding: 12px;
    color: #ecf0f1;
    border-top: 1px dashed #bf2718;
    box-sizing: border-box;
}
#menu-main .parent .dropdown-toggle.active + .toggleable > .menu-item {
    margin: 0 5px;
}
#menu-main .parent .dropdown-toggle.active + .toggleable > .menu-item.last {
    margin-bottom: 5px;
}
#menu-main .parent > .menu-link {
    margin-right: -54px;
}
#menu-main .dropdown-toggle {
    width: 50px;
    height: 48px;
    vertical-align: bottom;
    border-radius: 0;
    background: transparent;
}
#menu-main .toggleable {
    background: #bf2718;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css" rel="stylesheet"/>
<nav id="nav-primary" class="text-center">
  <button id="menu-main-toggle" class="top-toggler dropdown-toggle">Menu</button>
  <ul id="menu-main" class="toggleable hide">
    <li class="menu-item odd">
      <a class="menu-link" href="http://example.com/">About</a>
    </li>
    <li class="menu-item even">
      <a class="menu-link" href="http://example.com/">Something</a>
    </li>
    <li class="menu-item odd parent">
      <a class="menu-link" href="http://example.com/">Information Technology</a>
      <button class="dropdown-toggle">+</button>
      <ul class="toggleable hide">
        <li class="menu-item odd parent">
          <a class="menu-link" href="http://example.com/">Web Development</a>
          <button class="dropdown-toggle">+</button>
          <ul class="toggleable hide">
            <li class="menu-item odd">
              <a class="menu-link" href="http://example.com/">HTML</a>
            </li>
            <li class="menu-item even">
              <a class="menu-link" href="http://example.com/">CSS</a>
            </li>
            <li class="menu-item odd last">
              <a class="menu-link" href="http://example.com/">Javascript</a>
            </li>
          </ul>
        </li>
        <li class="menu-item even last">
          <a class="menu-link" href="http://example.com/">Unix</a>
        </li>
      </ul>
    </li>
    <li class="menu-item even parent">
      <a class="menu-link" href="http://example.com/">Level One</a>
      <button class="dropdown-toggle">+</button>
      <ul class="toggleable hide">
        <li class="menu-item odd last parent">
          <a class="menu-link" href="http://example.com/">Level Two</a>
          <button class="dropdown-toggle">+</button>
          <ul class="toggleable hide">
            <li class="menu-item odd last parent">
              <a class="menu-link" href="http://example.com/">Level Three</a>
              <button class="dropdown-toggle">+</button>
              <ul class="toggleable hide">
                <li class="menu-item odd last parent">
                  <a class="menu-link" href="http://example.com/">Lorem</a>
                  <button class="dropdown-toggle script-dependant">+</button>
                  <ul class="toggleable hide">
                    <li class="menu-item odd parent">
                      <a class="menu-link" href="http://example.com/">Ipsum</a>
                      <button class="dropdown-toggle script-dependant">+</button>
                      <ul class="toggleable hide">
                        <li class="menu-item odd last">
                          <a class="menu-link" href="http://example.com/">Dolor</a>
                        </li>
                      </ul>
                    </li>
                    <li class="menu-item even last">
                      <a class="menu-link" href="http://example.com/">Situs</a>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="menu-item odd">
      <a class="menu-link" href="http://example.com/">Snippets</a>
    </li>
    <li class="menu-item even last">
      <a class="menu-link" href="http://example.com/">Contact</a>
    </li>
  </ul>
</nav>

相关内容

  • 没有找到相关文章

最新更新