2012-04-25 1 views
0

поэтому у меня есть раскрывающаяся навигация, которая появляется при наведении, и я пытаюсь получить отсрочку там, чтобы улучшить удобство использования. Первоначально я использовал hoverIntent, который отлично работал везде, кроме IE8 и ниже.JQuery .removeClass не работает внутри setTimeout

Так что вместо этого я пытаюсь сделать задержку с простым старым Javascript, но функция setTimeout не вызовет мой jQuery.

var J = jQuery.noConflict();

J(".navigation li").hover(function(){J(this).addClass("hover");},function(){setTimeout("J(this).removeClass('hover');",500);});  

Когда я поставил его так:

function off(){J(this).removeClass("hover"); alert("hello");} 


J(".navigation li").hover(function(){J(this).addClass("hover");},function(){setTimeout("off()",500);}); 

Оповещение работает отлично, но не функцию .removeClass.

Я что-то упустил?

+1

пожалуйста переформатировать код – Alnitak

+3

значение 'this' в вашем«выключен()»функция не будет то, что вам это нужно быть. – Pointy

ответ

5

this внутри setTimeout не элемент li; я рекомендую вам использовать перегрузку SetTimeout, которая принимает функцию, и, прежде чем установить переменную this сохранить ссылку:

J(".navigation li").hover(function(){ 
    J(this).addClass("hover"); 
}, 
function(){ 
    var self = this; 
    setTimeout(function() { 
     J(self).removeClass('hover'); 
    },500); 
}); 
1

Вашей off функции:

function off() { 
    J(this).removeClass("hover"); 
    alert("hello") 
} 

не будет иметь переменную правую this когда вызывается setTimeout() - на большинстве (все?) браузеров он устанавливает this в window.

Вам необходимо дополнительное замыкание, чтобы обернуть исходный this и передать его в этой функции таймера:

J(".navigation li").hover(
    function() { 
     J(this).addClass("hover"); 
    }, 
    function() { 
     var that = this; 
     setTimeout(function() { 
      off.apply(that); 
     }, 500); 
    } 
); 

NB: не используйте строковые параметры для setTimeout()!

0

Проблема заключается в том, что this имеет в виду что-то другое в области для тайм-аута-обратного вызова.

Самым простым решением было бы предоставить старую область с помощью jQuery.proxy([function],[scope])

<html> 
    <head> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
     <script> 
      var f = function(){ 
       console.log(this.id); 
      }; 

      $(function() { 
       $("div").click(function() { 
        setTimeout($.proxy(f,this), 1000); 
       }); 
      }); 
     </script> 
    </head> 
    <body> 
     <div id="a">a</div> 
     <div id="b">b</div> 
    </body> 
</html>