tags:

views:

455

answers:

3

What is a good way to block until a previous ajax event is completed?

I followed http://stackoverflow.com/questions/719194/how-can-you-make-a-vote-up-down-button-like-in-stackoverflow but if I click the button fast enough, it'll send multiple (and maybe inconsistent) events to the server. How do I make it so it'll forcethe user to wait before another click can be registered?

Edit: I also do not want it to block globally - just for that button/item. Do I'll need to maintain a hash?

A: 

use the begin and end AJAX events to set a global var stating busy until the request is complete. Show a message that the action is executing to advise the user too.

Jquery has a load of functions to help if it suits your app:

http://docs.jquery.com/Ajax

Richard
I also do not want it to block globally - just for that button. I'll need to maintain a hash?
Timmy
global vars - not good.
redsquare
+3  A: 

Well since I wrote that I guess I might as well answer this too ;)

The 'common' way of doing this is by having an indicator variable that the request is in progress and updating it accordingly before/after everything happens. For my code in that question, you would edit it as follows:

Outside of the click function, add this:

var voting = false; // not initially voting

Inside the click function, at the very top, add this:

if(voting) return false; // if voting, return
voting = true; // if not, set voting to true

Inside of both post callbacks, add this:

voting = false; // done voting, set back to false

If you want to maintain an indicator on a per-question/answer/item basis, you could do this:

First, replace this code:

var id = $(this).parents('div.answer').attr('id').split('_')[1];

With this:

var parent = $(this).parents('div.answer'); // get the parent div
if(parent.data('voting')) return false; // if voting, return
parent.data('voting', true); // if not, update the marker
var id = parent.attr('id').split('_')[1]; // get the id

Then inside both post callbacks, add this:

parent.data('voting', false); // done voting, set back to false

In this case we'd be using jQuery's data to store the voting status of a particular question/answer/item inside the containing DIV and updating it accordingly whenever something happens.

Hope this helps.

Paolo Bergantino
+2  A: 

Bind the event once using jQuery.fn.one then bind it again in the callback function

myFunc = function() {
   $.post(url, data, function(data){
      $('#button').one('click', myFunc)
   }
};

$('#button').one('click', myFunc);
Nadia Alramli