2010-09-30 9 views
7

No puedo mostrar un ejemplo en vivo en este momento, pero no veo cómo se llama al slideToggle dos veces. se llama al hacer clic en un enlace.slideToggle ejecutándose dos veces en una llamada

aquí:

// initialize the jquery code 
$(function(){ 
    $('div.slideToggle a').click(function(){ 
    $(this).parent().siblings('div.remaining-comments').slideToggle('slow',function(){ //'this' becomes the remaining-comments. 
    var hidden = $(this).siblings('div.slideToggle').find('input').val(); 
    if($(this).siblings('div.slideToggle').find('a').html().substr(0,4) == 'Show'){ 
    $(this).siblings('div.slideToggle').find('a').html('Hide comments'); 
    } 
    else { 
    $(this).siblings('div.slideToggle').find('a').html(hidden); 
    } 
    }); 
    }); 
}); 

que está destinado a mostrar y ocultar los comentarios adicionales en una página de blog. , sin embargo, se muestra y luego se oculta con un solo clic. He puesto una alerta tanto en 'if' como en 'else' y ambos aparecen, entonces, ¿cómo se invoca dos veces?

obviamente cuando el enlace contiene el texto 'Mostrar' revela el div oculto, y cuando se hace clic de nuevo no encontrará 'Mostrar' y por lo tanto ocultará el div. Lo curioso es que funcionaba perfectamente. Está en la intranet de la compañía, así que supongo que tal vez algo más pueda afectarlo, pero realmente no veo cómo.

Respuesta

30

Es posible que su documento esté listo más de una vez, cuando la página se reinicializa, lo mejor que puede hacer es desvincular el evento click antes de vincular uno nuevo.

esta manera se evita tener el evento click obligado dos veces en 1 elemento

intente esto:

$('div.slideToggle a').unbind('click').click(function(){ 
    // your code here 
}); 

ACTUALIZACIÓN:

El problema con esta situación anterior es que usted tiene que Vuelva a vincularlo a cada elemento adicional que se agrega después de vincular la función de clic la primera vez.

Puede solucionar este problema, vinculando 1 manejador de clic en un elemento principal que permanece en el dom. Dándole un sub selector como argumento.

Resulta que solo se agrega 1 manejador de clics, en lugar de 1 para cada elemento. Por lo tanto, debería ganar en rendimiento, tiempo de ejecución del código y cantidad de javascript que estaba escribiendo.

ejemplo:

Digamos que usted tiene una lista en la que dinámicamente agregar nuevos elementos

<ul id="ContactList"> 
    <li>John Doe <a href="#">Like</a></li> 
    <li>Jane Doe <a href="#">Like</a></li> 
    <li>Josh Doe <a href="#">Like</a></li> 
    <li>Jeff Doe <a href="#">Like</a></li> 
</ul> 

y que ates algunas funciones en la etiqueta de anclaje cuando se hace clic

$(function(){ 

    $('#ContactList').on('click', 'li a', function(e){ 
     // do your thing here... 
     var el = $(e.currentTarget); 
     el.addClass('iLikeYou'); 
    }); 

}); 

ahora , no importa cuántos elementos agregues más adelante, funcionará de todos modos. porque acepta clics en cualquier lugar dentro del ul#ContactList y ejecutará la devolución de llamada solo cuando el elemento al que se hace clic coincida con el selector li a.

mientras$('#ContactList li a')habría primero obtener todos los elementos y luego unir el clic a todos los elementos seleccionados. Los elementos recién añadidos después no tienen el evento click y deberían tenerlo unido primero.

+3

Esta no es la mejor solución ... tratar el problema no los síntomas, si se está ejecutando dos veces, * ¿por qué? No hay razón para ejecutar todo el código del controlador "listo" dos veces, es muy ineficiente. ¿Qué sucede si otros manejadores 'click' están vinculados a ese elemento? –

+0

Creo que tiene que ver con. Ya se está llamando más de una vez. nuestras páginas son amalgamaciones de toneladas de diferentes fragmentos de código. por lo que las funciones reutilizables se ponen en llamadas individuales. listo. la desvinculación hizo el truco para mí, gracias. –

+0

Conozco a Nick, pero no tengo idea de por qué su declaración lista se ejecutó dos veces, por lo que no podía indicar en la dirección de una posible solución para eso. Aunque debería haber agregado que esto fue una solución alternativa en lugar de una solución per se. – Sander

-1

ten cuidado con mover o envolver elementos que contengan bloques de script en ellos. Esto puede hacer que el código se ejecute dos veces. unbind es una solución alternativa, pero es mejor mover su js en la parte superior o inferior de la página.

0

Llego bastante tarde, pero la función slideToggle() llamará a la función complete para cada elemento al que se alternan.

Probablemente haya más de un $(this).parent().siblings('div.remaining-comments').

0

Simplemente usando e.stopPropagation(); al principio (y la función (e) {) me lo arregló.

1

Prólogo

La respuesta a sus preguntas señala algo muy extraño en jQuery. Me encontré con este problema cuando traté de ocultar/deslizar divs y mostrar/deslizar otro (en un sitio de navegación jquery/Ajax), sin saber qué divs ya eran visibles.

Posible respuesta

Cuando un jQuery llama más de un elemento en la misma llamada, la función se ejecuta más de una vez.

Exemple

$("#div_one, #div_two").hide("slow", function() { 
    $("#div_two").show("slow"); 
}); 

-> #div_two va a aparecer, desaparecer y luego aparecer de nuevo, ya que la función encadenado se disparará dos veces.

información Additionnal

Lo mismo sucede con una llamada a una clase con múltiples elementos.

Solución

En mi caso, simplemente me decidí a hacer las cosas de manera diferente. Los primeros divs solo desaparecen (sin efecto de deslizamiento), y el nuevo puede tener un efecto de deslizamiento. De esta forma, no necesito esperar a que los primeros divs se deslicen antes de activar el nuevo div, así que no tengo que encapsular el segundo comando en una función encadenada.

En este exemple, la alerta sólo se disparará una vez:

$("#div_one, #div_two").hide(); 
$("#div_two").show("slow"); 
}); 

Cambia la experiencia del usuario, pero funciona ...