2009-12-17 19 views
35

Come disattivare temporaneamente il listener di eventi onclick, (jQuery preferito), dopo che l'evento è stato attivato?jQuery - Come posso disattivare temporaneamente il listener di eventi onclick dopo che l'evento è stato attivato?

Esempio:

Dopo l'utente fa clic sul pulsante e incendi questa funzione qui sotto, voglio disabile l'ascoltatore onclick, quindi non sparare lo stesso comando per mio punto di 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      
    }); 
    } 
}); 

Grazie mille,

Aldo

+0

in quale modo? cosa deve accadere prima di voler accettare di nuovo gli eventi di clic? –

+9

(PS non consentire alle richieste GET di eseguire cambiamenti di stato). – bobince

+2

@bobince: Oh, non sarebbe bello se tutti noi rispettassimo questa semplice regola ... @OP: Di più su cosa sta parlando Bob (in modo spaventoso turgid prose) qui: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 –

risposta

64

Ci sono molti modi per farlo. Per esempio:

$(".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); 
    }); 
} 

Possiamo anche utilizzare la delega per il codice evento più chiara e una migliore performance:

$(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"); 
    }); 
}); 

Se non abbiamo bisogno per riattivare il gestore dopo che è stato eseguito, allora possiamo usare il metodo .one(). Lega i gestori che devono essere eseguiti una sola volta. Vedi documenti jQuery: http://api.jquery.com/one

+0

Questo ha funzionato per me . Potrei tranquillamente separarlo, perché una volta terminata la parte di fare roba, il pulsante dell'immagine viene distrutto. – aldux

+3

In questo caso è necessario utilizzare il metodo .one() per eseguire il binding dei gestori da eseguire una sola volta. Vedi documenti jQuery: http://docs.jquery.com/Events/one – thorn

+0

Sì, non sapevo del metodo one(). Questo lo farà in un modo più elegante! Grazie. – aldux

5

perché non disabilitare il pulsante? Qual è il motivo specifico che si desidera disabilitare questa listner da solo? BTB, dal tuo codice, vedo che stai effettuando una chiamata Ajax. Quindi, in particolare, vuoi bloccare l'utente fino a quando la chiamata non ritorna? Se sì, si può provare blockUI, un plugin jQuery

1

Io suggerirei di disattivare il pulsante, quindi riabilitare nei vostri routine di completamento Ajax (successo o fallimento, ricordate). Se sei preoccupato che il browser non rispetti la disattivazione del pulsante, puoi farlo con il tuo flag sul pulsante (ad esempio, imposta un attributo chiamato data-disabled, usando il prefisso data- come buona pratica e compatibile con HTML5). Ma escludendo in realtà un problema con i browser che non disabilitano il pulsante, probabilmente lo considererei abbastanza buono.

18

Per quanto tempo si desidera disabilitare il listener dell'evento click? Un modo è quello di separare il listener di eventi usando jQuery's unbindhttp://docs.jquery.com/Events/unbind.

Ma è una buona pratica non separare un evento solo per riassociarlo più tardi. Usa invece un booleano.

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

edit: per essere sicuri si dovrebbe anche preoccuparsi delle altre routine di completamento ajax (ci sono solo tre: success, error, completesee docs) oppure active potrebbero rimanere falsa.

+0

come fa questo lavoro, attivo non è altro che un booleano che viene letto all'inizio – TStamper

+2

'active' rimane false fino a quando la richiesta ajax termina con successo. durante quel tempo il click-handler ritorna immediatamente all'inizio, quindi in pratica non è in esecuzione. – RamboNo5

+0

non ho capito che dentro..grazie – TStamper

1

È possibile eseguire l'azione all'interno del clic in base a un valore booleano. Quando viene cliccato, cambia il valore booleano e usa setTimeout() per cambiarlo dopo pochi secondi. Ciò limiterebbe efficacemente l'utente a fare clic sul pulsante solo una volta ogni pochi secondi.

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 
    } 
}); 
+0

Mi piace molto questo approccio, molto semplice e poco overhead. Grazie Jonathan! –

1
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); 
+0

In realtà stavo per aggiungere esattamente questo. Molto più pulito per nominarlo e separare/rebind internamente rispetto a tutti gli altri cerchi che sono stati inseriti in questi esempi. –

3

vorrei impostare una variabile globale per tenere traccia delle richieste AJAX ...

var myApp = { 
    ajax: null 
} 

e quindi avere questo po 'di magia per fermare richieste simultanee ...

// 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 questo approccio, non si dovrebbe tornare indietro attraverso il codice e modificare ogni singola delle chiamate AJAX. (qualcosa che chiamo una soluzione "append")

+0

A partire da jQuery 1.9, tutti i gestori degli [eventi Ajax globali jQuery] (http://api.jquery.com/category/ajax/global-ajax-event-handlers/), inclusi quelli aggiunti con .ajaxStart () metodo, deve essere allegato al documento. – ooXei1sh

2

Vorrei usare una classe, ad esempio "ajax-running". L'evento click verrebbe eseguito solo se l'elemento cliccato non ha la classe 'ajax-running'. Appena terminata la chiamata ajax, è possibile rimuovere la classe 'ajax-running' in modo che possa essere nuovamente cliccata.

$(".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'); 
      }); 
     }; 
    } 
}); 
1

Se si registra tramite ajax, è possibile disattivare il pulsante al clic e abilitarlo al termine del processo. Ma se stai postando, non puoi semplicemente disabilitare il pulsante. La disattivazione del pulsante fa sì che l'evento di clic sul lato server non venga attivato. Quindi basta nascondere il pulsante sul click e mostrare un messaggio user friendly. Il post su how to disable asp.net button on postback aiuta.

0

si potrebbe anche solo nascondere il pulsante (o il div che contiene)

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

e si può chiamare .Show() se è necessario visualizzare nuovamente.

Inoltre, a seconda del caso d'uso, dovresti considerare l'utilizzo di un overlay di caricamento invece

Problemi correlati