¿Cómo puedo deshabilitar temporalmente el detector de eventos onclick (se prefiere jQuery) después de que se haya disparado el evento?

Ejemplo:

Después de que el usuario haga clic en el botón y active esta función a continuación, quiero deshabilitar el oyente onclick, por lo tanto, no activar el mismo comando en mi vista django.

$(".btnRemove").click(function(){
   $(this).attr("src", "/url/to/ajax-loader.gif");
   $.ajax({
        type: "GET",
        url: "/url/to/django/view/to/remove/item/" + this.id,
        dataType: "json",
        success: function(returned_data){
            $.each(returned_data, function(i, item){
              // do stuff                       
     });
   }
});

Muchas gracias,

Aldo

38
aldux 17 dic. 2009 a las 16:39

10 respuestas

La mejor respuesta

Hay muchas formas de hacerlo. Por ejemplo:

$(".btnRemove").click(function() {
    var $this = $(this);
    if ($this.data("executing")) return;
    $this
        .data("executing", true)
        .attr("src", "/url/to/ajax-loader.gif");
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) {
        // ... do your stuff ...
        $this.removeData("executing");
    });
});

O

$(".btnRemove").click(handler);

function handler() {
    var $this = $(this)
        .off("click", handler)
        .attr("src", "/url/to/ajax-loader.gif");
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) {
        // ... do your stuff ...
        $this.click(handler);
    });
}

También podemos usar la delegación de eventos para un código más claro y un mejor rendimiento:

$(document).on("click", ".btnRemove:not(.unclickable)", function() {
    var $this = $(this)
        .addClass("unclickable")
        .attr("src", "/url/to/ajax-loader.gif");
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) {
        // ... do your stuff ...
        $this.removeClass("unclickable");
    });
});

Si no necesitamos volver a habilitar el controlador después de que se haya ejecutado, entonces podemos usar el método .one(). Vincula los controladores que se ejecutarán solo una vez. Consulte los documentos de jQuery: http://api.jquery.com/one

66
thorn̈ 26 ago. 2015 a las 14:29

También puedes ocultar el botón (o el div que lo contiene)

$(".btnRemove").click(function() {
   $(this).hide();
   // your code here...
})

Y puede llamar a .show () si necesita mostrarlo nuevamente.

Además, dependiendo de su caso de uso, debería considerar usar una superposición de carga

0
jules345 30 dic. 2015 a las 12:13

Usaría una clase, por ejemplo, 'ajax-running'. El evento click solo se ejecutará si el elemento cliqueado no tiene la clase 'ajax-running'. Tan pronto como finalice su llamada ajax, puede eliminar la clase 'ajax-running' para que se pueda hacer clic nuevamente.

$(".btnRemove").click(function(){
    var $button         = $(this);
    var is_ajaxRunning  = $button.hasClass('ajax-running');
    if( !is_ajaxRunning ){
        $.ajax({
            ...
            success: function(returned_data) {
                ...
                $button.removeClass('ajax-running');
            });
        };
    }   
});
2
Mariano Cavallo 17 dic. 2009 a las 15:35

Puede realizar la acción dentro del clic en función de un valor booleano. Cuando se hace clic, cambie el valor booleano y use setTimeout () para volver a cambiarlo después de unos segundos. Eso limitaría efectivamente al usuario a hacer clic en el botón solo una vez cada pocos segundos.

var isEnabled = true;

$("a.clickMe").click(function(e){
  e.preventDefault();
  if (isEnabled == true) {
    isEnabled = false; // disable future clicks for now
    do_Something();
    setTimeout(function(){
      isEnabled = true;
    }, 3000); // restore functionality after 3 seconds
  }
});
2
Sampson 17 dic. 2009 a las 14:07

Configuraría una variable global para realizar un seguimiento de las solicitudes de AJAX ...

var myApp = {
  ajax: null
}

Y luego tenga esta pequeña magia para detener las solicitudes simultáneas ...

// Fired when an AJAX request begins
$.ajaxStart(function() { myApp.ajax = 1 });

// Fired when an AJAX request completes
$.ajaxComplete(function() { myApp.ajax = null });

// Fired before an AJAX request begins
$.ajaxSend(function(e, xhr, opt) {
  if(myApp.ajax != null) {
    alert("A request is currently processing. Please wait.");
    xhr.abort();
  }
});

Con este enfoque, no debería tener que volver a revisar su código y modificar cada una de sus llamadas AJAX. (algo que yo llamo una solución "agregar")

3
Josh Stodola 17 dic. 2009 a las 14:23

Sugeriría deshabilitar el botón, luego volver a habilitarlo en sus rutinas de finalización de Ajax (éxito o fracaso, recuerde). Si le preocupa que el navegador no respete su desactivación del botón, puede respaldarlo con su propia bandera en el botón (por ejemplo, establezca un atributo llamado data-disabled, utilizando el prefijo data- como buena práctica y ser compatible con HTML5). Pero salvo tener problemas con los navegadores que no deshabilitan el botón, probablemente lo consideraría lo suficientemente bueno.

1
T.J. Crowder 17 dic. 2009 a las 13:46

Si está publicando a través de ajax, puede deshabilitar el botón al hacer clic y habilitarlo después de que se complete el proceso. Pero si está publicando de nuevo, no puede simplemente deshabilitar el botón. Deshabilitar el botón hace que el evento de clic del lado del servidor no se active. Tan solo oculte el botón al hacer clic y muestre un mensaje fácil de usar. La publicación en cómo deshabilitar asp botón .net en devolución de datos ayuda.

1
sangam 29 sep. 2011 a las 08:53

¿Durante cuánto tiempo desea deshabilitar el detector de eventos de clic? Una forma es desvincular el detector de eventos utilizando unbind http://docs.jquery.com de jQuery / Eventos / desvincular.

Pero es una práctica recomendada no desvincular un evento solo para volver a vincularlo más tarde. Use un booleano en su lugar.

var active = true;
$(".btnRemove").click(function() {
    if (!active) {
        return;
    }
    active = false;
    $(this).attr("src", "/url/to/ajax-loader.gif");
    $.ajax({
        type: "GET",
        url: "/url/to/django/view/to/remove/item/" + this.id,
        dataType: "json",
        success: function(returned_data) {
            active = true; // activate it again !
            $.each(returned_data, function(i, item) {
                // do stuff                       
            });
        }
    });
});

editar: para estar seguro, también debe preocuparse por las otras rutinas de finalización de ajax (solo hay tres: success, error, complete ver documentos) o bien active podría seguir siendo falso.

19
RamboNo5 1 jul. 2018 a las 08:32

¿Por qué no deshabilitar el botón? ¿Alguna razón específica por la que desea deshabilitar este listado solo? BTB, desde su código, veo que está haciendo una llamada ajax. ¿Entonces desea bloquear específicamente al usuario hasta que vuelva la llamada? En caso afirmativo, puede probar blockUI, un complemento de jQuery

5
ram 17 dic. 2009 a las 13:43
var ajaxAction = function() {
    var ele = $(this);
    ele.unbind("click", ajaxAction);
    ele.attr("src", "/url/to/ajax-loader.gif");
    $.ajax({
        type: "GET",
        url: "/url/to/django/view/to/remove/item/" + this.id,
        dataType: "json",
        success: function(returned_data) {
            $.each(returned_data, function(i, item) {
            });
        },
        complete: function() {
            ele.bind("click", ajaxAction);
        }
    });
}
$(".btnRemove").click(ajaxAction);
1
jitter 17 dic. 2009 a las 14:12