Reputation: 2790
(I really didn't know how to title this, feel free to suggest an edit)
Consider the following sample html:
<div class="grid">
<div class="item"><span class="icon"></span></div>
<div class="item"><span class="icon"></span></div>
<div class="item"><span class="icon"></span></div>
<div class="item"><span class="icon"></span></div>
<div class="item"><span class="icon"></span></div>
</div>
Attached to each .icon
is some jQuery:
<script type="text/javascript">
jQuery('.icon').click(function(){
runAjaxStuff();
displayNewContent();
})
</script>
In a nutshell, each time a user clicks an .icon
, the corresponding parent .item
will perform an AJAX request and finish by displaying additional .item
content on the page.
If a user, in this scenario, were to click each of the .item
quickly in succession, the AJAX request from a preceeding click is likely to still be waiting for a response. Of course, the new content is also not displayed yet; however, after a handful of seconds and all the requests have had a chance to complete, the user is then barraged with tons of new content being displayed all at once.
What I am after is a method to simply stop execution of any previous click
bindings if an .icon
is clicked so that only the most recent click ultimately completes.
I am aware that I can make my AJAX call syncronous instead, but I am hoping for a better way that will not seize the user's browser. My jQuery is good enough to get by, but this is something a little more in-depth than I'm used to.
Upvotes: 0
Views: 140
Reputation: 1391
First you have to unbind click
:
<script type="text/javascript">
jQuery('.icon').click(function(){
$('.icon').unbind('click'); // unbind click
runAjaxStuff();
displayNewContent();
})
</script>
Then bind it again in complete
event that has $.ajax
method:
complete: function() {
$('.icon').bind('click'); // will fire either on success or error
}
Upvotes: 0
Reputation: 207501
You got two choices
You can cancel the previous Ajax calls that are open
var xhr = null;
jQuery('.icon').click(function () {
if (xhr && && xhr.readystate != 4) {
xhr.abort();
}
runAjaxStuff();
displayNewContent();
});
and in your ajax call you would store the call to the
xhr = $.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
}
});
or
You can set a "active" flag and not make calls until the last one is complete
var isActive = false;
jQuery('.icon').click(function () {
if (isActive) {
return;
}
isActive = true;
runAjaxStuff();
displayNewContent();
});
and in the success/error/done function
isActive = false;
And you probably want to give the user some notification that either the call is active or that the last call was cancelled just so they know what is happening. Give them a good UX so they do not randomly click.
Upvotes: 3