Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop main <li> from closing when clicking an <li> within it

Ran into a snag and hoping the community can provide some insight to help enlighten a fellow coder. Here is a breakdown:

Setup:

  • 3 tier menu with jQuery click handlers to display/hide the second and third tier menus.

Issue:

  • I have a click handler in jQuery for menu and sub menu items however when clicking on a sub menu item it closes the main menu item hiding the submenu.

Code Sample: https://codepen.io/DigitalDesigner/pen/azvozOP

Objective:

  • Main Menu Items with submenu display/hide submenu on click (Working)
  • Opening a Main menus submenu closes all other sub menus (Working)
  • Submenu Items with submenu display/hide submenu on click

This last objective is working except closes Main Submenu.

How can I successfully have the display/hide work on the various tiered menu items when clicking within one another?

$(function() {
  $('.nav-container').each(function() {
    let nav = new Nav($(this));
  });
});

let Nav = function Nav(this$obj) {
  this.$obj = this$obj; // .nav-container

  this.primaryNavTriggers();
};

Nav.prototype.primaryNavTriggers = function primaryNavTriggers() {
  $('.menu-has-children').each(function() {
    $(this).on('click', function() {
      if ($(this).hasClass('menu-level-1')) {
        if ($(this).find('.sub-sub-menu').hasClass('sub-sub-menu--active')) {
          $(this).find('.sub-sub-menu').removeClass('sub-sub-menu--active');
        } else {
          $(this).find('.sub-sub-menu').addClass('sub-sub-menu--active');
        }
      } else if ($(this).hasClass('menu-level-0')) {
        if ($(this).find('.sub-menu').hasClass('sub-menu--active')) {
          $(this).find('.sub-menu').removeClass('sub-menu--active');
        } else {
          $('.sub-menu').each(function() {
            $(this).removeClass('sub-menu--active');
          });
          $(this).find('.sub-menu').addClass('sub-menu--active');
        }
      }
    });
  });
};
.nav-container {
  background: #f2f2f2;
  padding: 32px 24px;
}

.nav-container .menu,
.nav-container .sub-menu,
.nav-container .sub-sub-menu {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

.nav-container .menu .menu-item,
.nav-container .sub-menu .menu-item,
.nav-container .sub-sub-menu .menu-item {
  padding: 12px 0;
}

.nav-container .menu .menu-item:not(:last-of-type),
.nav-container .sub-menu .menu-item:not(:last-of-type),
.nav-container .sub-sub-menu .menu-item:not(:last-of-type) {
  border-bottom: 1px solid #9e9e9e;
}

.nav-container .menu .menu-item .menu-link,
.nav-container .sub-menu .menu-item .menu-link,
.nav-container .sub-sub-menu .menu-item .menu-link {
  color: #000;
  font-family: sans-serif;
  text-decoration: none;
}

.nav-container .sub-menu,
.nav-container .sub-sub-menu {
  display: none;
}

.nav-container .sub-menu--active,
.nav-container .sub-sub-menu--active {
  display: block;
}

.nav-container .sub-menu {
  padding-left: 8px;
}

.nav-container .sub-sub-menu {
  padding-left: 16px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<nav class="nav-container">
  <ul class="menu main-menu">
    <li class="menu-item menu-level-0">
      <a href="#" class="menu-link">Menu Item 1</a>
    </li>
    <li class="menu-item menu-level-0 menu-has-children">
      <a href="#" class="menu-link">Menu Item 2</a>
      <ul class="sub-menu">
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 1</a>
        </li>
        <li class="menu-item menu-level-1  menu-has-children">
          <a href="#" class="menu-link">Submenu Item 2</a>
          <ul class="sub-sub-menu">
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 1</a>
            </li>
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 2</a>
            </li>
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 3</a>
            </li>
          </ul>
        </li>
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 3</a>
        </li>
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 4</a>
        </li>
      </ul>
    </li>
    <li class="menu-item menu-level-0">
      <a href="#" class="menu-link">Menu Item 3</a>
    </li>
    <li class="menu-item menu-level-0 menu-has-children">
      <a href="#" class="menu-link">Menu Item 4</a>
      <ul class="sub-menu">
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 1</a>
        </li>
        <li class="menu-item menu-level-1  menu-has-children">
          <a href="#" class="menu-link">Submenu Item 2</a>
          <ul class="sub-sub-menu">
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 1</a>
            </li>
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 2</a>
            </li>
            <li class="menu-item menu-level-2">
              <a href="#" class="menu-link">Sub Submenu Item 3</a>
            </li>
          </ul>
        </li>
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 3</a>
        </li>
        <li class="menu-item menu-level-1">
          <a href="#" class="menu-link">Submenu Item 4</a>
        </li>
      </ul>
    </li>
  </ul>
</nav>
like image 818
DigitalDesigner Avatar asked Dec 19 '25 15:12

DigitalDesigner


1 Answers

I think your issue might be due to using .find method for toggling the lists as it may lead to irregularities since multiple elements have similar classnames' you could try the same using .children or .first method for child lists
try this:

Nav.prototype.primaryNavTriggers = function primaryNavTriggers() {
  $('.menu-has-children').each(function () {
    $(this).on('click', function (e) {
      e.preventDefault();        // Prevent default link action
      e.stopPropagation();       // Stop event from bubbling up

      const $menuItem = $(this);

      if ($menuItem.hasClass('menu-level-1')) {
        const $subSubMenu = $menuItem.children('.sub-sub-menu');

        if ($subSubMenu.hasClass('sub-sub-menu--active')) {
          $subSubMenu.removeClass('sub-sub-menu--active');
        } else {
          $subSubMenu.addClass('sub-sub-menu--active');
        }

      } else if ($menuItem.hasClass('menu-level-0')) {
        const $subMenu = $menuItem.children('.sub-menu');

        if ($subMenu.hasClass('sub-menu--active')) {
          $subMenu.removeClass('sub-menu--active');
        } else {
          // Close all other top-level open submenus
          $('.menu-level-0 .sub-menu').not($subMenu).removeClass('sub-menu--active');

          // Open the current submenu
          $subMenu.addClass('sub-menu--active');
        }
      }
    });
  });
};
like image 61
wasabi09 Avatar answered Dec 21 '25 06:12

wasabi09