Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

jQuery nested hover events removeClass() on mouseleave issue

I have a nested list that looks like this:

<ul class="menu-wrapper">
    <li>
        <a href="#">Menu item</a>
        <ul class="sub-menu">
            <li>
                <a href="#">Subitem-1</a>
                <ul>
                <li>Sub-Subitem-1</li>
                <li>Sub-Subitem-2</li>
                <li>Sub-Subitem-3</li>
                </ul>
            </li>
            <li>
                <a href="#">Subitem-2</a>
                <ul>
                <li>Sub-Subitem-1</li>
                <li>Sub-Subitem-2</li>
                <li>Sub-Subitem-3</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

When hovering the ul.menu-wrapper > li item, an .active class is applied to the first ul.sub-menu and the first li item within the submenu list:

$('ul.menu-wrapper').children().hover(
    function() {
        let subMenu = $(this).find('ul.sub-menu').first()
        subMenu.addClass('active')
        subMenu.children().first().addClass('active')
    },
    function() {
        let subMenu = $(this).find('ul.sub-menu').first()
        subMenu.removeClass('active')
    }
)

Now I need to hover the li items within the ul.sub-menu and change the .active class to the item being hovered.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I can do this by adding a .hover() method on the subMenu.children() items.

$('ul.menu-wrapper').children().hover(
    function() {
        ...
        subMenu.children().hover(
            function() {
                $(this).addClass('active')
            },
            function() {
                $(this).removeClass('active')
            }
        )
    },
    function() {
        ...
    }
)

When a submenu item has been hovered and the pointer goes back to the ul.menu-wrapper > li item, I want to have at least one ul.sub-menu > li item with the .active class.

Currently the mouseleave method is removing the class when pointer is moved from a submenu back to the parent list item. How can I prevent this to always have one ul.sub-menu > li with .active class at all times?

Demo https://jsfiddle.net/5Lwyh3xs/

>Solution :

On mouse out add active class to the first li if no li items have active class.

$('ul.menu-wrapper').children().hover(
  function() {
    let subMenu = $(this).find('ul.sub-menu').first()

    subMenu.addClass('active')
    subMenu.children().first().addClass('active')

    subMenu.children().hover(
      function() {
        $(this).addClass('active').siblings().removeClass('active')
      },
      function() {
        $(this).removeClass('active')
        if($('.sub-menu > li.active').length == 0) {
             subMenu.children().first().addClass('active')
        }
      }
    )
  },
  function() {
    let subMenu = $(this).find('ul.sub-menu').first()

    subMenu.removeClass('active')
  }
)
body {
  margin: 0;
  padding: 0;
}

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

ul.menu-wrapper {
  height: 80px;
}

ul.menu-wrapper {
  background: gray;
}

ul.menu-wrapper>li {
  height: 100%;
  display: flex;
  align-items: center;
}

ul.menu-wrapper ul.sub-menu {
  visibility: hidden;
  position: absolute;
  top: 80px;
}

ul.menu-wrapper ul.sub-menu.active {
  visibility: visible;
}

ul.menu-wrapper ul.sub-menu.active>li.active {
  background: darkmagenta;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav role="navigation" id="navigation-wrapper">
  <ul class="menu-wrapper">
    <li>
      <a href="#">Menu item</a>
      <ul class="sub-menu">
        <li>
          <a href="#">Subitem-1</a>
          <ul>
            <li>Sub-Subitem-1</li>
            <li>Sub-Subitem-2</li>
            <li>Sub-Subitem-3</li>
          </ul>
        </li>
        <li>
          <a href="#">Subitem-2</a>
          <ul>
            <li>Sub-Subitem-1</li>
            <li>Sub-Subitem-2</li>
            <li>Sub-Subitem-3</li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</nav>

https://jsfiddle.net/y5qkb7mv/

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading