开发者

Disable multiple Ajax requests when a link is Cliked

I am trying to implement a way to avoid cli开发者_开发知识库ck spamming. I have a Link button that when clicked sends the request to the server using Jquery $.ajax() command. I want a way to prohibit multiple clicks like the one implemented here in StackOverflow when adding a comment.

Any suggestion ?


jQuery has the .one() method designed for this purpose. An (untested) example:

function doAjax(){
    // Your Ajax call.
    $.ajax({..., success: function() {
        // Ajax call done, re-enabling the button/link
        $("#buttonId").one('click', doAjax);
    }, ...});
}

$("#buttonId").one('click', doAjax);


You can do something like this...

$("#buttonId").click(function(){
    $(this).attr("disabled", true);
    $.ajax({}); // Your ajax call.
});


It really depends on the type of element, but for hyperlinks you probably need to unbind the click event and rebind it when the ajax request has completed:

function ajaxThingie() {
    $(this).unbind("click");

    // do something ajaxy, and in the success callback rebind:
    $.get("foo.html", function() {
        $(this).bind("click", ajaxThingie);
    });
    return false;
}


$(document).ready(function() {
    $("#theLink").click(ajaxThingie);
});


You can block the UI while the ajax request is done. Give a look to the blockUI plugin for this


another option that worked for me ( on links ) is to set a attr on click ( disabled ), then remove after completion of the ajax call.

the only extra step because the click event will still be called on a link, is to check to see if that attr exists before firing the ajax call.

if ($form.attr("disabled")!=="disabled") { 
$.ajax({

    success: function(data){    
            $form.removeAttr("disabled");

    },
    dataType: "json"
});

}
$form.attr("disabled", "disabled");


I have tried another option just when an item is clicked

beforeSend:function(){
    $(placeholder).addClass('loading');
},

where place holder is usually the highest level element on DOM we can afford usually #cotent or $page or something like that

the css for .loading is as follows

.loading {
    background: #fff url('../images/ajax-loader.gif') center 10px;
    opacity: 1;
}
loading * {
    opacity: .8;
}

I hope using the same thing, we can diable click on that top level element e.g.

beforeSend:function(){
    $(placeholder).addClass('loading');
    $(placeholder).click(function(){preventDefault();});
},
complete:function(){
    $(placeholder).removeClass('loading');
    $(placeholder).click(function(){// now do the default action});
},

hope this resolves the problem


use flag variable and set as defult "0" and after click ,set it's value as "1"


I wrote a class to do such a thing in snapwebsites. My problem was that I wanted possibly many changes to be reported to the server, but avoid having two AJAX requests running simultaneously.

So, the main problem is to know whether there is still a request going and if so, to prevent further requests. However, additional requests may carry additional data which still needs to be sent to the server, only we want to wait until the current request return before sending that additional data.

Not only that, I wanted to have a certain number of seconds between requests. So far that last requirement, I also included a version with a timer. This may cause a loss of data, though, because the latest data is sitting on the client's computer and it may not get sent. I think I will implement the necessary to use a cookie for that last case.

The code is 1200 lines, so I will only give you a link to the GIT on SourceForge.net. The concept is pretty simple though. As mentioned by others, you want to have a flag to know whether a request is still going. The flag gets reset when the complete() callback function gets called.

The "classes" (JavaScript classes uses prototype, but I like to document them as with ActionScript classes) looks like this:

class ServerAccess
{
public:
  function ServerAccess(callback: ServerAccessCallbacks);
  function setURI(uri: string, opt_queryString: Object) : Void;
  function setData(data: Object) : Void;
  function send() : Void;
  static function appendQueryString(uri: string, query_string: Object): string;

private:
  var callback_: ServerAccessCallbacks = null;
  var uri_: string = "";
  var queryString_: Object = null;
  var data_: Object = null;
};

class ServerAccessTimer extends ServerAccessCallbacks
{
public:
  function ServerAccessTimer(request_name: String, timer_callback: ServerAccessTimerCallbacks, interval: Number);

  function send();

  virtual function serverAccessSuccess(result : ResultData) : Void;
  virtual function serverAccessError(result : ResultData) : Void;
  virtual function serverAccessComplete(result : ResultData) : Void;

private:
  var requestName_: String;
  var timerCallback_: ServerAccessTimerCallbacks;
  var interval_: Number;
  var processing_: Boolean;
  var timer_: Number;
  var lastRequest_: Number;
};

I have an example of usage in the e-Commerce JavaScript. The data is expected to be generated by the callback (see the ServerAccessTimerCallbacks references). So you can call send() 1,000 per second, and yet get at most one request per requestInterval_ (i.e. could be once in every 10 seconds.)

snapwebsites.eCommerceCart.prototype.sendCart_ = function()
{
  if(this.initializing_)
  {
    return;
  }
  if(!this.serverAccessTimer_)
  {
    this.serverAccessTimer_ = new snapwebsites.ServerAccessTimer("cart", this,  this.requestsInterval_);
  }
  this.serverAccessTimer_.send();
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜