Pergunta

O objetivo

Quero atribuir dinamicamente manipuladores de eventos a algumas divs nas páginas em um site.

Meu método

Estou usando o jQuery para vincular funções anônimas como manipuladores para eventos DIV selecionados.

O problema

O código itera uma matriz de nomes de div e URLs associados. O nome do DIV é usado para definir o alvo de ligação, ou seja, conectar este manipulador de eventos a este evento DIV.

Enquanto os manipuladores de eventos estão vinculados a cada um dos eventos da DIV, as ações desencadeadas por esses manipuladores de eventos apenas visam o último item da matriz.

Portanto, a idéia é que, se o usuário mouse sobre uma determinada div, ele deve executar uma animação deslizante para essa div. Mas, em vez disso, o Mousing sobre o Div1 (RangeTaball) aciona uma animação deslizante para o Div4 (RangeTabthm). O mesmo vale para as divs 2, 3, etc. A ordem não é importante. Altere os elementos da matriz e os eventos sempre visam o último elemento na matriz, div4.

Meu código - (usa 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);} );
            }
        }

Minha teoria

Não estou vendo um erro de sintaxe cegamente óbvio ou é um problema por um problema de referência. Inicialmente, eu tinha a seguinte declaração para definir o valor do Curtab:

curTab=inlineRangeNavUrls[i][0];

Então, quando ocorreu o problema, imaginei que, à medida que mudei (via iteração de loop) a referência ao curtab, eu estava de fato mudando A referência para todos os manipuladores de eventos de função anônima anteriores também para o novo valor do Curtab .... É por isso que os manipuladores de eventos sempre direcionavam a última div.

Então, o que eu realmente precisava fazer era passar no curtab valor Para os manipuladores de eventos da função anônima, não o curtab objeto referência.

Então eu pensei:

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

resolveria o problema, mas não. Mesmo negócio. Tão claramente estou perdendo alguma chave, e provavelmente muito básica, conhecimento sobre o problema. Obrigado.

Foi útil?

Solução

Você precisa criar uma nova variável em cada passagem pelo loop, para que ela seja capturada nos fechamentos que você está criando para os manipuladores de eventos.

No entanto, apenas mover a declaração variável para o loop não conseguirá isso, porque O JavaScript não introduz um novo escopo para blocos arbitrários.

Uma maneira fácil de forçar a introdução de um novo escopo é usar outra função anônima:

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
  }
}

Como Jason sugere, você pode realmente limpar isso um pouco usando o jQuery's embutido hover() função:

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]); 
}

Outras dicas

O que está acontecendo aqui é que suas funções anonmesas estão formando um fechamento e levando seu escopo externo com eles. Isso significa que, quando você faz referência ao curtab dentro de sua função anomímica, quando o manipulador de eventos executa essa função, ele vai procurar o atual Valor do curtab em seu escopo externo. Isso será o que você designou pela última vez ao Curtab. (não o que foi atribuído no momento em que você bateu a função)

O que você precisa fazer é mudar isso:

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

para isso:

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

Isso copiará o valor do curtab no escopo da função externa, que a função interna levará com ela. Essa cópia acontece ao mesmo tempo em que você está vinculando a função interna ao manipulador de eventos; portanto, "MyLocalVariable" reflete o valor do Curtab naquele momento. Então, da próxima vez no loop, uma nova função externa, com um novo escopo será criado e o próximo valor do Curtab copiado nela.

A resposta de Shog9 realiza basicamente a mesma coisa, mas seu código é um pouco mais austero.

É meio complicado, mas faz sentido se você pensar sobre isso. Os fechamentos são estranhos.

Editar: Oops, esqueci de devolver a função interna. Fixo.

Eu acho que você está tornando isso mais complicado do que precisa. Se tudo o que você está fazendo é atribuir um efeito deslizante no MouseOver/Out, tente o flutuar efeito com jQuery.

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

Se você postou seu html completo, eu poderia dizer exatamente como fazê -lo :)

Você pode colocar o valor da sua variável em uma tag não existente e, posteriormente, pode lê -los a partir daí. Este trecho faz parte de um corpo de loop:

 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top