Home > Software engineering >  Toggle Sub-menu on Parent Click & Close Other Open Sub-menu
Toggle Sub-menu on Parent Click & Close Other Open Sub-menu

Time:01-10

I have two parent items with sub-menus and have the code firing to open the current sub-menu while closing the other open ones.

But I can't seem to get the .toggleClass() to fire on the open menu to close it (I want to toggle a menu item open/close).

<ul>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Thing 1</a></li>
            <li><a href="#">Thing 2</a></li>
        </ul>
    </li>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Widget 1</a></li>
            <li><a href="#">Widget 2</a></li>
        </ul>
    </li>
</ul>

And here is my current jquery

// main menu toggle of sub-menu
  $(".menu-item-has-children > a").click(function(e) {
    // remove .visible from other .sub-menu
    $(".sub-menu").removeClass('visible');

    // toggle the .visible class on the current parent item
    $(this).next(".sub-menu").toggleClass('visible');

    // prevent the <a> from default behavior
    e.preventDefault();
  });

CodePudding user response:

This doesn't work, because $(".sub-menu") selects all sub-menus and removes the visible class from each. Next toggleClass adds again (toggle) the removed visible class.

If you want to remove visible from the other elements only, you must go up the hierarchy and fetch all sibling elements from the parent. Now visible is removed from the other sub-menu only:

$(this).parent().siblings().children(".sub-menu").removeClass('visible');

// main menu toggle of sub-menu
$(".menu-item-has-children > a").click(function(e) {
  // remove .visible from other .sub-menu
  $(this).parent().siblings().children(".sub-menu").removeClass('visible');

  // toggle the .visible class on the current parent item
  $(this).next(".sub-menu").toggleClass('visible');

  // prevent the <a> from default behavior
  e.preventDefault();
});
.sub-menu {
  display: none;
}

.sub-menu.visible {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li >
    <a href="#">Services</a>
    <ul >
      <li><a href="#">Thing 1</a></li>
      <li><a href="#">Thing 2</a></li>
    </ul>
  </li>
  <li >
    <a href="#">Services</a>
    <ul >
      <li><a href="#">Widget 1</a></li>
      <li><a href="#">Widget 2</a></li>
    </ul>
  </li>
</ul>

CodePudding user response:

What you've described seems to work, do you have a link to a non-working example?

// main menu toggle of sub-menu
  $(".menu-item-has-children > a").click(function(e) {
    // remove .visible from other .sub-menu
    $(".sub-menu").removeClass('visible');

    // toggle the .visible class on the current parent item
    $(this).next(".sub-menu").toggleClass('visible');

    // prevent the <a> from default behavior
    e.preventDefault();
  });
.sub-menu {
  display: none;
}

.visible {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Thing 1</a></li>
            <li><a href="#">Thing 2</a></li>
        </ul>
    </li>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Widget 1</a></li>
            <li><a href="#">Widget 2</a></li>
        </ul>
    </li>
</ul>

CodePudding user response:

toggleClass is always do add class if use after removeClass

// main menu toggle of sub-menu
  $(".menu-item-has-children > a").click(function(e) {
    // check active
    var isCurrentActive = $(this).next('.sub-menu').hasClass('visible')
    
    // remove .visible from other .sub-menu
    $(".sub-menu").removeClass('visible');

    // if current menu deactive add visible 
    if(!isCurrentActive){
      $(this).next(".sub-menu").addClass('visible');
    }

    // prevent the <a> from default behavior
    e.preventDefault();
  });
.sub-menu{  display:none }
.sub-menu.visible{  display:block }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Thing 1</a></li>
            <li><a href="#">Thing 2</a></li>
        </ul>
    </li>
    <li >
        <a href="#">Services</a>
        <ul >
            <li><a href="#">Widget 1</a></li>
            <li><a href="#">Widget 2</a></li>
        </ul>
    </li>
</ul>

  • Related