2009-06-18 15 views
9

He creado un jQuery content switcher. En general, funciona bien, pero hay un problema con eso. Si hace clic en los enlaces del lado varias veces, a veces se vuelven visibles varias piezas de contenido.Prevenir el evento de clic en jQuery activando varias veces

El problema probablemente se encuentre en algún lugar dentro del evento de clic. Aquí está el código:

$('#tab-list li a').click(
    function() { 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow'); 
       } 
      ); 
     } 
     return false; 
    } 
); 

He intentado añadir un candado para la transición de manera que más clics se ignoran como la transición está ocurriendo, pero fue en vano. También he tratado de evitar que la transición se dispare si algo ya está animando, utilizando la siguiente:

if ($(':animated')) { 
    // Don't do anything 
} 
else { 
    // Do transition 
} 

pero parece que siempre que las cosas están siendo animados. ¿Alguna idea de cómo puedo evitar que la animación se active varias veces?

Respuesta

12

Una idea sería eliminar el evento de clic al comienzo de su función, y luego agregar el evento de clic nuevamente cuando la animación haya finalizado, por lo que los clics durante la duración no tendrían ningún efecto.

Si tiene la capacidad de ejecutar código cuando la animación ha terminado, esto debería funcionar.

+0

Genius. Me salvé el trasero hoy con esta respuesta, no pude entender por qué se registraban los eventos de clics múltiples, pensé que jQuery sería inteligente y dejaría de suceder, jQuery no puede hacer todo por usted. Gracias. –

0

Una forma sería la siguiente:

$('#tab-list ul li').one('click', loadPage); 
var loadPage = function(event) { 
    var $this = $(this); 
    $global_just_clicked = $this; 
    var urlToLoad = $this.attr('href'); 
    $('#content-area').load(urlToLoad, pageLoaded); 
} 
$global_just_clicked = null; 
var pageLoaded() { 
    $global_just_clicked.one('click', loadPage); 
} 

Como se puede ver, este método está plagado de deficiencias: lo que sucede cuando se hace clic en otra pestaña antes de la carga de la página actual? ¿Qué pasa si la solicitud es denegada? ¿y si es luna llena?

La respuesta es: este método es solo una demostración rudimentaria. Una aplicación adecuada sería:

  1. no contiene la variable global $global_just_clicked
  2. no se basan en .load(). Utilizaría .ajax(), y manejaría la cancelación de solicitud, haciendo clic en otras pestañas, etc.

NOTA: En la mayoría de los casos, no necesita tomar este enfoque redondo. Estoy seguro de que puede remediar su código de tal manera que múltiples clics en la misma pestaña no afectarán el resultado final.

jrh.

6

Agregue una variable para usar como un bloqueo en lugar de es (: animating).

Al hacer clic, compruebe si el bloqueo está configurado. De lo contrario, configure el bloqueo, inicie el proceso y luego suelte el bloqueo cuando finalice el fadeIn.

var blockAnimation = false; 

$('#tab-list li a').click(
    function() { 
     if(blockAnimation != true){ 
     blockAnimation = true; 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow', function(){ blockAnimation=false; }); 
       } 
      ); 
     } 
     } 
     return false; 
    } 
); 
+0

Intenté este enfoque, pero parece que no funciona. Pasó la prueba de bloqueo cada vez. –

1

Jugué un poco con el código anterior y se le ocurrió la siguiente modificación que parece funcionar:

$('#tab-list li a').click(
    function() { 
     $('.tab:animated').stop(true, true); 
     var targetTab = $(this).attr('href'); 
     if ($(targetTab).is(':hidden')) { 
      $('#tab-list li').removeClass('selected'); 
      var targetTabLink = $(this).parents('li').eq(0); 
      $(targetTabLink).addClass('selected'); 
      $('.tab:visible').fadeOut('slow', 
       function() { 
        $(targetTab).fadeIn('slow'); 
       } 
      ); 
     } 
     return false; 
    } 
); 

Todo lo que sucede es que, cuando se hace clic en una pestaña nueva, que de inmediato trae la corriente animación hasta el final y luego comienza la nueva transición.

3

Bueno, así es como lo hice, y funcionó bien.

$(document).ready(function() { 
    $(".clickitey").click(function() { 
     if($("#mdpane:animated").length == 0) { 
      $("#mdpane").slideToggle("slow"); 
      $(".jcrtarrow").toggleClass("arrow-open"); 
     } 
    }); 
}); 

esto no es hacer lo que hace el código por supuesto esto es un código de mi sitio, pero yo sólo quiero señalar cómo hice caso los clics que estaban ocurriendo durante la animación. Por favor, avíseme si esto es ineficiente de todos modos. Gracias.

0

Una forma de hacer esto para usar timeStamp propiedad del evento de este tipo de brecha en algún momento entre varios clics:

var a = $("a"), 
    stopClick = 0; 


a.on("click", function(e) { 
    if(e.timeStamp - stopClick > 300) { // give 300ms gap between clicks 
    // logic here 

    stopClick = e.timeStamp; // new timestamp given 
    } 


}); 
Cuestiones relacionadas