Search code examples
javascriptjqueryhovertimeout

Clearing timeouts with javascript


i'm having some sort of variable out of scope issue or something. in the function below, i'm creating or clearing a timeout based on whether the mouse is entering or exiting. it seems though, that even once the timeout has been created it's returning undefined on re-entry. not sure what i'm doing wrong here, thanks for your help!

jsFiddle example

JavaScript: (particular issue is within else conditional on line 35

var navLinks = $('nav li.sub');

navLinks.mouseenter(function(){

  console.log('hovering on link');

  var thiis   = $(this),
      subList = thiis.find('ul'),
      autoClose;

  if (!thiis.hasClass('out')){

    console.log('isnt out');

    /* Link */

    thiis

    /* Show submenu when entering link */

    .addClass('out')

    /* Hide submenu when exiting link */

    .mouseleave(function(){

      autoClose = setTimeout(function(){

        thiis.removeClass('out');
      }, 1000);


      console.log('exiting link: timeout active', autoClose);
    });
  } else {

    console.log ('is out', autoClose);

    if (autoClose){

      console.log('is out: clear timeout');

      clearTimeout(autoClose);
    }
  }
});

Solution

  • Techno,

    The simple answer is just to move var autoClose to an outer scope, but I think you can (and should) do more.

    More specifically,

    • I don't think you want to attach the mouseleave handler inside the mouseenter handler. It can be permanently attached from the outset.
    • In the mouseenter handler, clearTimeout(autoClose) and thiis.addClass('out') can be executed unconditionally. There's no real economy in testing .hasclass('out').

    Try this :

    var navLinks = $('nav li.sub');
    var autoClose;
    navLinks.hover(function(){
        var thiis = $(this);
        clearTimeout(autoClose);
        thiis.addClass('out');
    }, function(){
        var thiis = $(this);
        autoClose = setTimeout(function(){
            thiis.removeClass('out');
        }, 1000);
    });