2010-08-12 8 views
23

Estoy tratando de evitar clics múltiples en enlaces y elementos, lo que está causando problemas.jQuery previene otros eventos después de un clic

Estoy utilizando jQuery para enlazar eventos de clics a botones (jQuery UI) y enlaces de imagen (<a><img /></a>).

¿Hay alguna manera de hacer, una vez por todas, evitar que otros eventos se activen después de un clic?

¿O tengo que mantener una variable global llamada _isProcessing y establecerla en verdadero para cada manejador de eventos?

Gracias

Editar: (clarificación) Gracias por sus respuestas, mi problema no es impedir la propagación del evento, pero la prevención de varios clics concurrentes.

+1

¿Qué quiere decir con * "otros eventos" *? ¿Hay otros manejadores de eventos en el mismo elemento? ¿O en sus elementos ancestrales? ¿O en toda la página? ¿Podría aclarar su necesidad específica? – user113716

+0

Entonces, si tengo un enlace de imagen llamado "Agregar servicio", que agrega una fila a una tabla en mi página. Si hago clic más de una vez, agrega dos. No se deben agregar otras filas en el momento posterior al clic y antes de que se haya creado la fila. – Russell

+0

@Russell - Sí, agregué una respuesta a continuación para abordar eso. – user113716

Respuesta

29

Existen varias formas de evitar que los clics simultáneos ejecuten el código.

Una forma es unbind('click') en el elemento, luego .bind() de nuevo cuando esté listo.

Prefiero usar algún tipo de bandera. Podría ser una variable, pero prefiero asignar una clase al elemento, como .processing, y eliminarlo cuando haya terminado. Entonces, haría que el controlador verifique la existencia de esa clase para determinar si el código debe ejecutarse.

$('someElement').click(function() { 
    var $th = $(this); 
    if($th.hasClass('processing')) 
      return; 
    $th.addClass('processing'); 
    // normal code to run 
    // then when done remove the class 
    $th.removeClass('processing'); 
}); 

Otra opción es utilizar los elementos .data() para establecer una bandera similar, como $(this).data('processing', true); A continuación, establezca en false cuando haya terminado.

+0

@ elo80ka - Gracias. Ojalá jQuery tuviera algo como '.disableHandler ('click')' y '.enableHandler ('click')' como alternativa a '.bind()/unbind()' y soluciones algo desordenadas/pirateadas como usar clases o variables como banderas. : o) – user113716

+0

Debe usar la función .data() en lugar de agregar una clase que pueda afectar accidentalmente la visualización del elemento. – bcherry

+0

@bcherry - Lo bueno de usar una clase es que es (estoy bastante seguro) una operación más liviana que usar '.data()'. Si tiene cuidado al nombrar su clase, no debe haber ramificaciones en la pantalla. – user113716

7

¿has comprobado preventDefault?

$("a").click(function(e) { 
    e.preventDefault(); 
} 

también se podría tratar stopImmediatePropagation() o stopPropagation()


También podría mirar en el evento one().

Adjuntar un controlador a un evento para los elementos . El controlador se ejecuta al más una vez por elemento.

+0

El método 'e.preventDefault()' realmente no detiene a los controladores. Impide que el comportamiento predeterminado de un elemento se active (como un '' que lo lleva a su ubicación 'href'). – user113716

+1

utilizado e.stopImmediatePropagation(); trabajó. ¡Gracias! Además, usa desvinculación. – techdude

+0

uno() ayudó a mi caso donde el evento se activaba por cada clic. ¡Gracias! – planetregin

3

Devuelva false desde sus controladores de eventos, o llame al ev.stopPropagation() en cada controlador.

+0

Usar .stopPropagation() – Mark

+0

@Mark - Volver a leer la pregunta. * "mi problema no impide el burbujeo del evento", * * – user113716

+0

Aclaré la pregunta después de que publicó su respuesta. – Russell

19

Hay event.preventDefault, event.stopPropagation y devuelve falso como ya se ha indicado.

$("a").click(function(e) { 
    e.preventDefault(); 
    e.stopPropagation(); 
    return false; 
} 
+0

:-) por si acaso ... (aunque la pregunta es diferente, supongo ...) –

+0

sí, cuando respondí, la pregunta aún no había sido aclarada. – TehOne

+0

Sí, lo siento @TehOne, no expresé mi pregunta correctamente la primera vez. – Russell

2

usted tiene un par de opciones:

  1. Si los botones/enlaces que se recargue la página , simplemente puede desenlazar el controlador de eventos clic:

    $('input:submit').click(fumction() { 
        $(this).unbind('click'); 
        // Handle event here 
    }) 
    
  2. Usted puede deshabilitar los botones, y volver a habilitarlos una vez que haya terminado (creo que esto también debería funcionar con <input type="image">):

    $('input:submit').click(function() { 
        $(this).attr('disabled', 'disabled'); 
        // It also helps to let the user know what's going on: 
        $(this).val('Processing...'); 
        // Handle event here 
        $(this).removeAttr('disabled'); 
    }) 
    

    No creo que esto funcione en los enlaces.

+0

¿Sabes si hay una forma de desactivar eventos (no desvincular, solo deshabilitar)? – Russell

+0

@Russell: puede desactivar los elementos de entrada. Hasta donde yo sé, los elementos deshabilitados no generan eventos. – elo80ka

+0

Sí, pero un enlace de imagen (ancla), por ejemplo, podría generar un evento de clic pero no es un campo de entrada (como dijiste, la desactivación de elementos de anclaje no funciona). – Russell

2

Otra manera sería utilizar event.stopPropagation() y event.isPropagationStopped() para la señalización:

Ejemplo:

$(button).click(function(e){ 
    if(e.isPropagationStopped()) 
     return; // propagation was stopped, so stop further execution 

    // if you got this far - this event handler was called first 
    // custom logic goes here 

    // stop event propagation to signal other handlers 
    e.stopPropagation(); 

    // if you need, call e.preventDefault() to prevent default behaviour 
}); 

Repita misma lógica para otros controladores de eventos.

Cuestiones relacionadas