user15063
user15063

Reputation:

Disable jQuery function after one click, to prevent multiple executions

I have the following function which fetches more comments beyond the 20 that are shown by default:

$('.more_comments_link').live('click', function() {
    $(".more_comments_link").text("Fetching More Comments...");

    var ajaxOpts = {
        type: "get",
        url: "ajax_getcomments.php",
        dataType: 'json',
        data: "&itemid=<? echo $id; ?>&type=1&owner=<? echo $event["data"]["e_creator"]; ?>&more=1",
        success: function(data) {
            $('.discussion-more').after(data);
            $(".discussion-more").hide();
        }
    };

    $.ajax(ajaxOpts);
    return false;
});

It works, but the only problem is, the user can click the button three times really quickly, and it will send three requests to ajax_getcomments.php, getting the same result set every time.

I tried adding

$(".more_comments_link").unbind('click');

but it doesn't do anything.

The initial result set is also fetched with jQuery, hence I’m using .live(click'.

I am not sure if it has anything to do with why it’s not working.

Upvotes: 19

Views: 46885

Answers (10)

Felipe Campanhol
Felipe Campanhol

Reputation: 79

For me this worked:

$('.more_comments_link').live('click', function() {

  if(e.handled !== true) // This will prevent event firing more than one time
  {
    e.handled = true;
    // Your code here...
  }
});

Upvotes: -1

Clamorious
Clamorious

Reputation: 425

You can use:

$('element').off()

This will disable any event of your component that you are listening to.

Upvotes: 2

kxyz
kxyz

Reputation: 842

My solution, working global on all Ajax requests. If it is the active request, new with the same URL will be aborted. It is working fine.

var activeRequests = [];

$(document).ajaxComplete(function(e, jqxhr, settings) {
    var i = activeRequests.indexOf(settings.url);
    if (i != -1) {
        setTimeout(function(){
            activeRequests.splice(activeRequests.indexOf(settings.url), 1); }, 75);
    }
});

$(document).ajaxSend(function(e, jqxhr, settings) {
    var i = activeRequests.indexOf(settings.url)
    if (i != -1) {
        jqxhr.abort();
        activeRequests.push(settings.url);
    }
});

Upvotes: 1

Mike Barwick
Mike Barwick

Reputation: 5367

All of these solutions are far too complex for a very simple solution; use .one():

Simply change live to one. See below:

$('.more_comments_link').one('click', function() {

Upvotes: 16

silent1mezzo
silent1mezzo

Reputation: 2942

Try using the disabled keyword. This way you don't have to unbind the function; you just disable it from being pressed:

$('.more_comments_link').live('click', function() {
    $(this).attr("disabled", true);
    $(".more_comments_link").text("Fetching More Comments ...");

    var ajaxOpts = {
        type: "get",
        url: "ajax_getcomments.php",
        dataType: 'json',
        data: "&itemid=<? echo $id; ?>&type=1&owner=<? echo $event["data"]["e_creator"]; ?>&more=1",
        success: function(data) {
            $('.discussion-more').after(data);
            $(".discussion-more").hide();
        }
    };

    $.ajax(ajaxOpts);
    return false;
});

Upvotes: 1

Manpreet
Manpreet

Reputation: 57

You Can use for a single click on a button over the webpage

 $('button id or classs').one('click',function(){    
 });

Upvotes: 0

quasistoic
quasistoic

Reputation: 4687

Depending on your use case, you might not have to use live, in which case one would do exactly what you want it to do.

Upvotes: 1

lonesomeday
lonesomeday

Reputation: 238115

live doesn't work with unbind -- you need die instead.

However there is a better solution. Since you probably want to be able to update the content more than once, you can set a variable to see whether a request is currently running:

var requestRunning = false;
$('.more_comments_link').live('click', function () {
    if (requestRunning) { // don't do anything if an AJAX request is pending
        return;
    }

    $(".more_comments_link").text("Fetching More Comments ...");

    var ajaxOpts = {
        type: "get",
        url: "ajax_getcomments.php",
        dataType: 'json',
        data: "&itemid=<? echo $id; ?>&type=1&owner=<? echo $event["
        data "]["
        e_creator "]; ?>&more=1",
        success: function (data) {
            $('.discussion-more').after(data);
            $(".discussion-more").hide();
        },
        complete: function() {
            requestRunning = false;
        }

    };

    requestRunning = true;
    $.ajax(ajaxOpts);
    return false;
});

Upvotes: 34

daryl
daryl

Reputation: 15237

$('.more_comments_link').live('click', function(e) {

    if($(e.target).data('oneclicked')!='yes') {

        $(this).text("Fetching More Comments ...");

        var ajaxOpts = {
            type: "get",
            url: "ajax_getcomments.php",
            dataType: 'json',
            data: "&itemid=<? echo $id; ?>&type=1&owner=<? echo $event["data"]["e_creator"]; ?>&more=1",
            success: function(data) {
                $('.discussion-more').after(data);
                $(".discussion-more").hide();
            }
        };

        $.ajax(ajaxOpts);
        return false;
    }

    $(e.target).data('oneclicked','yes');

}); 

Upvotes: 0

Rob
Rob

Reputation: 7717

You can use .die() to unbind .live() events.

Or set a flag elsewhere that says the request is in progress and check that at the beginning of the click handler.

Upvotes: 3

Related Questions