1
votes

I have a menu bar with a number of parent and child menu items:

<nav>
  <ul>
    <li class="menu-item-has-children">
      <a href="#">Parent item</a>
      <ul>
        <li><a href="#">Child item</a></li>
        <li><a href="#">Child item</a></li>
      </ul>
   </li>
   <li class="menu-item-has-children">
      <a href="#">Parent item</a>
      <ul>
        <li><a href="#">Child item</a></li>
        <li><a href="#">Child item</a></li>
      </ul>
   </li>
  </ul>
</nav>

The child submenu is by default hidden:

.menu-item-has-children > ul {
  display: none;
}

I'd like to achieve the following:

  1. When the top level menu item is clicked, I would like to toggle (show/hide) its associated submenu and hide any other submenus that might be opened.
  2. When anywhere else on the page is clicked other than the submenu or its parent item, I'd like to hide all submenus.

I'm using the following code, but instead of showing the correct submenu it shows/hides all submenus:

$(document).on('click', function(e) {
  if($(e.target).parent().hasClass('menu-item-has-children')) { 
    $(this).find('ul').show();
  } else {
    $('.menu-item-has-children > ul').toggle();
  }
});

See fiddle: https://jsfiddle.net/gs9q6kwh/

Any idea what I am doing wrong?

2

2 Answers

2
votes

This can easily be achieved by hiding all the submenus first, and then showing only the submenu which is sibling of the clicked parent:

$(document).on('click', function(e) {
  $('.menu-item-has-children > ul').hide();

  if ($(e.target).parent().hasClass('menu-item-has-children')) {
    $(e.target).siblings('ul').toggle();
  }
});
.menu-item-has-children>ul {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
  <ul>
    <li class="menu-item-has-children">
      <a href="#">Parent item</a>
      <ul>
        <li><a href="#">Child item</a></li>
        <li><a href="#">Child item</a></li>
      </ul>
    </li>
    <li class="menu-item-has-children">
      <a href="#">Parent item</a>
      <ul>
        <li><a href="#">Child item</a></li>
        <li><a href="#">Child item</a></li>
      </ul>
    </li>
  </ul>
</nav>
0
votes

There are a few problems with the jQuery code:

  1. Clicking on the submenu items causes all the menus to collapse. You need to restructure the jQuery to check for those items as well as the parent items.
  2. jQuery is searching for all instances of 'ul' and showing them, not just the children of the target. Instead of using .find(), try using children().
  3. Clicking on the parent item doesn't toggle between show and hide. I suggest adding a class to the parent item that lets the code know its state (shown or hidden) and then toggles accordingly.