1
votes

I have two different dropdown menus that show on hover. They show with delay function setTimeout, and fadeOut with delay function setTimeout.

Problem is if I hover on first li element to second, first submenu stays shown and doesn't fadeOut. And from second li element to first is the same problem. I know that it is a problem because there is setTimeout function. Function clearTimeout is activated when hovering on li element.

I want on hover to do FadeIn submenu and then when mouseover from first li element to second, first submenu hides (without fadeOut) and at the same time shows second submenu. When mouse leaves li element and isn't hovering on second element, submenu fadeOut with delay.

My question is: How do I solve this problem when this hover function is dynamic for both submenus with same class?

Thanks for help!

    // Menu-hover-script
    var setTimeoutFadeIn, setTimeoutFadeOut

    function fadeIn_Menu(thisObj) {
      setTimeoutFadeIn = setTimeout(function() {
        thisObj.children('ul.level1').stop(false, false).fadeIn(220);
      }, 300);
    }

    function fadeOut_Menu(thisObj) {
      setTimeoutFadeOut = setTimeout(function() {
        thisObj.children('ul.level1').stop(false, false).fadeOut(180);
      }, 600);
    }

    $('li.submenu').hover(function() {

        clearTimeout(setTimeoutFadeOut);
        fadeIn_Menu($(this));

      },

      function() {

        clearTimeout(setTimeoutFadeIn);
        fadeOut_Menu($(this));

      });
    // END--Menu-hover-script
body li a {
  text-decoration: none;
}

li.nav-item {
  display: inline-block;
  list-style-type: none;
  width: 70px;
  height: 30px;
  line-height: 26px;
  text-align: center;
  border: 1px solid black;
  cursor: pointer;
}

li.nav-item:first-child {
  margin-left: 100px;
}

ul.level1 {
  display: none;
  position: absolute;
  padding-left: 0;
}

ul.level1 li {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="level1 nav-item submenu">
  <a class="nav-link" href="#">menu1</a>
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>
<li class="level1 nav-item submenu">
  <a class="nav-link" href="#">menu2</a>
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>
3
Please don't post demo's to 3rd party sites. You can just click the code snippet button while creating/editing a question and include working code right here as I've done for you.Scott Marcus
because the setTimeoutFadeOut is cleared.... needs to be based on the element, not a globalepascarello
@ScottMarcus I am sorry. Thanks.Adiss7k
@epascarello How should I do that please?Adiss7k

3 Answers

0
votes

Since you call clearTimeout on each hover it won't trigger anymore once you hover over the other submenu. Either store them in different variables or simply remove the clearTimeout in both of your functions.

0
votes

setTimeout() and fadeIn()/fadeOut() is redundant. Just simply set up mouseover and mouseout event handlers for the top-level menu items that cause the fade in/out.

$("li.level1").on("mouseover", function(){
  $("ul.submenu", this).fadeIn(220);
});

$("li.level1").on("mouseout", function(){
  $("ul.submenu", this).fadeOut(180);
});
body li a {
  text-decoration: none;
}

li.nav-item {
  display: inline-block;
  list-style-type: none;
  width: 70px;
  height: 30px;
  line-height: 26px;
  text-align: center;
  border: 1px solid black;
  cursor: pointer;
}

li.nav-item:first-child {
  margin-left: 100px;
}

ul.level1 {
  display: none;
  position: absolute;
  padding-left: 0;
}

ul.level1 li {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="level1 nav-item submenu">
  menu1
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>
<li class="level1 nav-item submenu">
  menu2
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>
0
votes

Could also do this without any jQuery at all. Just CSS

body li a {
  text-decoration: none;
}

li.nav-item {
  display: inline-block;
  list-style-type: none;
  width: 70px;
  height: 30px;
  line-height: 26px;
  text-align: center;
  border: 1px solid black;
  cursor: pointer;
}

li.nav-item:first-child {
  margin-left: 100px;
}

ul.level1 {
  opacity: 0;
  padding-left: 0;
  transition: opacity 180ms ease;
}

ul.level1 li {
  list-style-type: none;
}

.nav-item:hover > .submenu {
  display: block;
  opacity: 1;
  transition: opacity 220ms ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="level1 nav-item submenu">
  <a class="nav-link" href="#">menu1</a>
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>
<li class="level1 nav-item submenu">
  <a class="nav-link" href="#">menu2</a>
  <ul class="level1 submenu">
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
    <li class="level2"><a href="#">li element</a></li>
  </ul>
</li>