simple jquery dropdown - clearTimeout, setTimeout issues

本小妞迷上赌 提交于 2019-12-18 17:48:14

问题


HTML:

<ul class="topnav">
    <li><a href="#"><span>One</span></a></li>
    <li><a href="#"><span>Two</span></a></li>
    <li>
        <li><a href="#"><span>Three</span></a></li>
        <ul class="subnav">
            <li><a href="#">A</a></li>
            <li><a href="#">B</a></li>
            <li><a href="#">C</a></li>
        </ul>
    </li>
</ul>

jquery:

var timeout = null;

$(document).ready(function() {

    $("ul.topnav li").mouseover(function() {

        if (timeout) clearTimeout(timeout);

        $(this).find("ul.subnav").slideDown('fast').show();

    }).mouseout(function() {
        timeout = setTimeout(closemenu, 500);
    });

    // sub menu mouseovers keep dropdown open
    $("ul.subnav li").mouseover(function() {
        if (timeout) clearTimeout(timeout);
    }
    ).mouseout(function() {
        timeout = setTimeout(closemenu, 500);
        // alert(timeout);

    });

    // any click closes
    $(document).click(closemenu);
});

// Closes all open menus 
function closemenu() {
    $('ul.subnav:visible').hide();
    if (timeout) clearTimeout(timeout);
} 

I'm having issues with timeout. In use, if i mouseover "Three", the dropdown stays out forever. if i mouseover "A", dropdown will stay out forever, but if I mouseover "B" or anything lower, the menu will close on me. if you uncomment "// alert(timeout);" it gets there for B, (and A) but timeout will have a value. why is this? i thought clearTimeout would null the timeout variable?


回答1:


You can simplify your code overall by using .hover() and .data() like this:

$(function() {
  $("ul.topnav li").hover(function() {
    var timeout = $(this).data("timeout");
    if(timeout) clearTimeout(timeout);
    $(this).find("ul.subnav").slideDown('fast');
  }, function() {
      $(this).data("timeout", setTimeout($.proxy(function() {
          $(this).find("ul.subnav").slideUp();
      }, this), 500));
  });
  $(document).click(function() {
      $('ul.subnav:visible').hide();
  });
});​

You can see a working demo here

Instead of sharing a global timeout variable, this sets a timeout per top level <li>, each one has an independent timer, and when you hover back over that element, only its timer is cleared. Also .hover() uses mouseenter and mouseleave, rather than mouseover and mouseout, the difference is when you go into a child or between children, mouseenter doesn't fire again, and mouseleave doesn't fire on the parent <li> we care about.

You can test this with the demo link above, I added sub-items to the first menu as well, to demonstrate they're independent. If you happen to have question about the $.proxy in there, it's just making this inside that timeout anonymous function refer to what I want it to (the current this)...the element that needs closing after the timeout.




回答2:


youre trying to build a drop down menu? why not use existing jquery plugins for that or better yet, css-only drop down menu like http://purecssmenu.com/?



来源:https://stackoverflow.com/questions/2316213/simple-jquery-dropdown-cleartimeout-settimeout-issues

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!