2009-01-29 11 views
1

J'ai un menu multiple sur ma page qui utilisent tous les mêmes événements mouseover et click, j'ai donc décidé de l'intégrer dans une fonction. Cependant, les vars semblent toujours être affectés au dernier argument de la fonction hover (fonction, fonction).jQuery et la fermeture

$(document).ready(function() { 
menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
    } 
} 
menuMouseOver({ parent: '#menu1', 
       active: 'menu1_active', 
       childSelect: ':gt(0)'}, 
      { parent: '#menu2', 
       active: 'menu2_active', 
       childSelect: ':gt(0)'}); 
}); 

Pourquoi est que le dernier console.log sera enregistre toujours le dernier actif au lieu de celui qui appartient aux arguments [i] .active. (Dans cet exemple, il enregistre toujours le actif des arguments [1] .active) Qu'est-ce que je fais mal?

En outre, la fonction réelle est plus complexe, mais le problème est également présent dans cette variante.

Répondre

1

Votre problème est que l'événement hover se produit en dehors de la portée de votre méthode d'exécution. Ainsi, au moment où le pointeur exécute votre variable active a déjà traversé l'ensemble et reste à l'état actif de votre dernier élément. Vous voyez donc ce problème parce que ce dernier journal est un événement qui est hors de portée et les deux autres sont in-scope dans les boucles.

Essayez ceci:

 $(parent).children(childSelect) 
      .not('.'+active).each(function(i, e) { 
       console.log(active); 
       $(this).data("active", active); 
      }) 
      .hover(function() { 
       $(this).addClass($(this).data("active")); 
      }, function() { 
       $(this).removeClass($(this).data("active"))); 
      }); 

Cela fait stocker la valeur « active » à l'intérieur de l'élément DOM afin qu'il puisse être accessible portée.

+0

Merci beaucoup. –

0

Je me creuser la cervelle parce qu'il est une question bizarre mais je refactorisé la fonction un peu, pourrait être utile (oh, quelqu'un de beaucoup répondu par l'habile entre-temps):

$("#menu1,#menu2").each(function(){ 
    var id = $(this).attr("id"); 
    $(">li",this).not("."+id+"_active,:eq(0)").hover(function(){ 
     $(this).addClass(id+"_active"); 
    },function(){ 
     $(this).removeClass(id+"_active"); 
    }); 
}); 
4

JavaScript n'a pas bloc de portée, donc les variables que vous déclarez dans la boucle for ont leurs valeurs changées à chaque itération et toutes ces fonctions font référence aux mêmes variables. L'astuce consiste à créer une nouvelle fonction dans la boucle for afin que les variables que vous déclarez soient liées pendant cette itération.

Vous pouvez accomplir cela en exécutant une fonction anonyme dans la boucle:

menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     (function(){ // anonymous function to create new scope 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
     })(); // execute the anonymous function 
    } 
} 

La façon dont vous l'aviez avant, vous tous fonctions fermées sur les mêmes références variables, et ainsi utilisé ce que jamais la dernière valeur était, pas la valeur de quand la fonction a été créée. L'utilisation de la portée de la fonction la fera se comporter comme prévu.

Questions connexes