Friday, May 6, 2011

Preventing an duplicate ajax events in jquery

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?

From stackoverflow
  • 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

    Timmy : I also do not want it to block globally - just for that button. I'll need to maintain a hash?
    redsquare : global vars - not good.
  • 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.

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

0 comments:

Post a Comment