views:

2541

answers:

9

How can I temporarily disable the onclick event listener, (jQuery preferred), after the event has been fired?

Example:

After the user clicks on the button and fires this function below, I want to disabled the onclick listener, therefore not firing the same command to my django view.

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

Thanks a lot,

Aldo

+1  A: 

One way is to disable the button after it has been clicked once:

  $(".btnRemove").attr('disabled', 'disabled');
Sarfraz
Even though i called it btnRemove, it is an image, not really a button or an input. My bad.
aldux
+3  A: 

why not disable the button ?Any specific reason that you want to disable this listner alone ? BTB, from your code, I see that you are making an ajax call. SO you specifically want to block user until the call comes back ? If yes, you can try blockUI, a jQuery plugin

ram
A: 

I'd suggest disabling the button, then re-enabling it in your Ajax completion routines (success or failure, remember). If you're worried about the browser not respecting your disabling the button, you can back that with your own flag on the button (e.g., set an attribute called data-disabled, using the data- prefix as good practice and to be HTML5 compatible). But barring actually running into a problems with browsers not disabling the button, I'd probably consider that good enough.

T.J. Crowder
+5  A: 

for how long do you want to disable the click event listener? one way is to unbind the event listener using jQuery's unbind http://docs.jquery.com/Events/unbind. but it's best-practice not to unbind an event only to rebind it later. use a boolean instead.

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: to be safe you should also care about the other ajax completion routines (there are only three: success, error, complete see docs) or else active might stay false.

RamboNo5
how does this do the job, active is nothing but a boolean being read at the beginning
TStamper
`active` stays false up until the ajax request finishes with a success. during that time the click-handler immediately returns at the beginning, so it is basically not excecuting.
RamboNo5
didnt catch that inside..thanks
TStamper
+4  A: 
$(".btnRemove").click(function() {
   var $this = $(this);
   if ($this.data('executing'))
      return;
   $this.data('executing', true).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) {
         // ... do your stuff ... 
         $this.removeData('executing');
     });
   }
});

or

$(".btnRemove").click(function() {
   var $this = $(this), handler = arguments.callee;
   $this.unbind('click', handler).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) {
         // ... do your stuff ... 
         $this.click(handler);
     });
   }
});
thorn
This one worked for me. I could safely unbind it, because once the do stuff part ends, the image button is destroyed.
aldux
In that case you should use .one() method to bind handlers to be executed only once. See jQuery docs: http://docs.jquery.com/Events/one
thorn
Yep, I did not know about the one() method. That will do in a more elegant way! Thx.
aldux
A: 

You could make the action within the click based upon a boolean value. When it's clicked, change the boolean value and uset setTimeout() to change it back after a few seconds. That would effectively limit the user to clicking the button only once every few seconds.

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
  }
});
Jonathan Sampson
A: 
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);
jitter
+1  A: 

I would setup a global variable to keep track of AJAX requests...

var myApp = {
  ajax: null
}

And then have this little bit of magic to stop simultaneous requests...

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

With this approach, you should not have to go back through your code and modify every single one of your AJAX calls. (something I call an "append" solution)

Josh Stodola
A: 

I would use a class eg 'ajax-running'. The click event would only be executed if the clicked element does not have the 'ajax-running' class. As soon you ajax call finishes you can remove the 'ajax-running' class so it can be clicked again.

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