Question

L'objectif

Je souhaite affecter dynamiquement des gestionnaires d'événements à certaines divs sur des pages d'un site.

Ma méthode

J'utilise jQuery pour lier des fonctions anonymes en tant que gestionnaires des événements div sélectionnés.

Le problème

Le code itère un tableau de noms de div et d’URL associées. Le nom de div est utilisé pour définir la cible de liaison, c'est-à-dire attacher ce gestionnaire d'événements à cet événement div.

Bien que les gestionnaires d'événements soient liés avec succès à chacun des événements div, les actions déclenchées par ces gestionnaires d'événements ne ciblent que le dernier élément du tableau.

L’idée est donc que si l’utilisateur passe la souris sur une div donnée, il doit exécuter une animation coulissante pour cette div. Mais au lieu de cela, passer la souris sur div1 (rangeTabAll) déclenche une animation coulissante pour div4 (rangeTabThm). Il en va de même pour les divs 2, 3, etc. L'ordre est sans importance. Modifiez les éléments du tableau et les événements cibleront toujours le dernier élément du tableau, div4.

Mon code - (Utilise jQuery)

var curTab, curDiv;
var inlineRangeNavUrls=[['rangeTabAll','range_all.html'],['rangeTabRem','range_remedial.html'],
                ['rangeTabGym','range_gym.html'],['rangeTabThm','range_thermal.html']];
        for (var i=0;i<inlineRangeNavUrls.length;i++)
        {
            curTab=(inlineRangeNavUrls[i][0]).toString();
            curDiv='#' + curTab;
            if  ($(curDiv).length)
            {
                $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
                $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
            }
        }

Ma théorie

Je ne vois pas d'erreur de syntaxe aveuglante ou c'est un problème de passe par référence. Initialement, j'avais la déclaration suivante pour définir la valeur de curTab:

curTab=inlineRangeNavUrls[i][0];

Ainsi, lorsque le problème est survenu, j’ai pensé que lorsque je changeais (via la boucle for itération) la référence à curTab, j’étais en fait en train de changer la référence de tous les gestionnaires d’événements de fonctions anonymes précédents vers le nouveau curTab. value as well .... c’est pourquoi les gestionnaires d’événements ont toujours ciblé le dernier div.

Il me fallait donc transmettre la valeur curTab aux gestionnaires d'événements de fonctions anonymes et non à la référence à l'objet curTab .

Alors j'ai pensé:

curTab=(inlineRangeNavUrls[i][0]).toString();

résoudrait le problème, mais ce n’est pas le cas. Même affaire. Il est donc clair que je manque des connaissances essentielles et probablement très basiques sur le problème. Merci.

Était-ce utile?

La solution

Vous devez créer une nouvelle variable à chaque passage dans la boucle, afin qu'elle soit capturée dans les fermetures que vous créez pour les gestionnaires d'événements.

Cependant, le simple fait de déplacer la déclaration de variable dans la boucle n'apportera rien, car JavaScript n'introduit pas de nouvelle portée pour les blocs arbitraires .

Un moyen simple de forcer l'introduction d'un nouveau périmètre consiste à utiliser une autre fonction anonyme:

for (var i=0;i<inlineRangeNavUrls.length;i++)
{
  curDiv='#' + inlineRangeNavUrls[i][1];
  if ($(curDiv).length)
  {
    (function(curTab)
    {
      $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
      $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
    })(inlineRangeNavUrls[i][0]); // pass as argument to anonymous function - this will introduce a new scope
  }
}

En tant que Jason suggère , vous pouvez en fait nettoyer un peu ce problème en utilisant hover () fonction:

for (var i=0;i<inlineRangeNavUrls.length;i++)
{
  (function(curTab) // introduce a new scope
  {
  $('#' + inlineRangeNavUrls[i][1])
    .hover(
      function(){showHideRangeSlidingTabs(curTab, true);},
      function(){showHideRangeSlidingTabs(curTab, false);} 
    );
  // establish per-loop variable by passsing as argument to anonymous function
  })(inlineRangeNavUrls[i][0]); 
}

Autres conseils

Ce qui se passe ici, c’est que vos fonctions anonymes forment une fermeture et prennent leur portée extérieure avec elles. Cela signifie que lorsque vous référencez curTab dans votre fonction anonyme, lorsque le gestionnaire d'événements l'exécute, il va rechercher la valeur actuelle de curTab dans votre étendue externe. Ce sera ce que vous avez assigné en dernier à curTab. (pas ce qui était assigné au moment où vous avez lié la fonction)

ce que vous devez faire est de changer ceci:

$(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );

à ceci:

$(curDiv).bind("mouseover", 
    (function (mylocalvariable) { 
        return function(){
            showHideRangeSlidingTabs(mylocalvariable, true);
        } 
    })(curTab) 
);

Ceci copiera la valeur de curTab dans la portée de la fonction externe, que la fonction interne prendra avec elle. Cette copie se produit en même temps que vous liez la fonction interne au gestionnaire d'événements, donc "mylocalvariable". reflète la valeur de curTab à cette époque. Ensuite, lors de la prochaine boucle, une nouvelle fonction externe, avec une nouvelle portée, sera créée et la prochaine valeur de curTab sera copiée dans celle-ci.

La réponse de

shog9 accomplit fondamentalement la même chose, mais son code est un peu plus austère.

c'est un peu compliqué, mais c'est logique si vous y réfléchissez. Les fermetures sont bizarres.

edit: oops, j'ai oublié de retourner la fonction interne. Fixe.

Je pense que vous rendez cela plus compliqué que nécessaire. Si vous ne faites qu'attribuer un effet de survol de la souris au-dessus / à l'extérieur, essayez alors le survol effet avec jquery.

$("#mytab").hover(function(){
    $(this).next("div").slideDown("fast");},
  function(){
    $(this).next("div").slideUp("fast");
});

Si vous avez posté votre code HTML complet, je pourrais vous dire exactement comment le faire:)

Vous pouvez mettre la valeur de votre variable dans une balise non existante, et plus tard, vous pourrez la lire à partir de là. Cet extrait fait partie d'un corps de boucle:

 s = introduction.introductions[page * 6 + i][0]; //The variables content
 $('#intro_img_'+i).attr('tag' , s);              //Store them in a tag named tag
 $('#intro_img_'+i).click( function() {introduction.selectTemplate(this, $(this).attr('tag'));}  );  //retrieve the stored data
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top