0

I have a webpage that shows some news, and a button that when is clicked shows older news doing an AJAX call to the server.

The problem is that if people click too fast, the request is done twice, therefore, I receive 2 equal responses.

  • #mas-noticias-footer is the id of the button that displays older news

  • .noticias-list is the class asigned to each new, using .length I get the number of news displayed, and POST that number to a PHP file that does a SQL query using LIMIT(numItems,3) (I get 3 news at a time).

  • #noticias-display is the ul that contains the news

This is the code

$(document).ready(function() {
  $("#mas-noticias-footer").on('click',function() {
var numItems = $('.noticias-list').length;
$.ajax({
        type: "POST",
        url: "mas-noticias.php",
    data: "num-noticias="+numItems,
    success: function(data) {
            $('#noticias-display').append(data);
            }
}); 
  });
});

I have tried using off() and unbinding the event at the beginning of the on callback, to avoid the multiple calls (that works), the problem is when I delegate the event using on() at the end of the callback, I can't make it work.

davidaam
  • 443
  • 1
  • 8
  • 17
  • Try event.preventDefault() .... see http://api.jquery.com/event.preventDefault/ – Baba Apr 12 '12 at 01:43
  • I'll give it a shot, but doesn't event.preventDefault() prevents default action, for example in an anchor if you add a click handler with e.preventDefault the default action, that is going to the specified href, is prevented? – davidaam Apr 12 '12 at 01:46
  • put it after `$("#mas-noticias-footer").on('click',function(event) {` – Baba Apr 12 '12 at 01:47
  • just tried, it doesn't work... btw, im using jQuery Mobile (it's a mobile web), the button "#mas-noticias-footer" is actually an anchor that's stylized using a predefined theme. – davidaam Apr 12 '12 at 01:51

5 Answers5

3

You can't conveniently call off and later call on expecting the bound event returned just like that, the event isn't stored in the memory.

You can however, set a data variable inside your DOM:

  $("#mas-noticias-footer").on('click',function() {
     var numItems = $('.noticias-list').length;
     var isAjaxRunning = $(this).data('iar');

     // check flag is set
     if(typeof isAjaxRunning == 'undefined') $(this).data('iar', 'yes'); 
     else if(isAjaxRunning == 'yes') return; // if still running, return

     $.ajax({
        type: "POST",
        url: "mas-noticias.php",
        data: "num-noticias="+numItems,
        success: function(data) {
            $('#noticias-display').append(data);
            $(this).data('iar', 'no'); // after successful run, set to no
        }
     }); 
  });
Andreas Wong
  • 59,630
  • 19
  • 106
  • 123
  • I tried something similar, I checked for a boolean variable at the beginning of the event handler, if it's true then return; then if it's false set it to true and on success of the ajax call I set it back to false. It didn't worked, I'll give it a shot to your solution anyway – davidaam Apr 12 '12 at 01:58
  • It actually worked! I'll keep this in mind whenever I need to avoid multiple event triggering but in other circumstances – davidaam Apr 12 '12 at 02:05
1

I don't believe you really want an asynchronous call here. Set async:false or use $.post() instead of $.ajax().

Malk
  • 11,855
  • 4
  • 33
  • 32
  • Actually I haven't thought about that, that was the problem, by disabling asynchronous calls it doesn't matter if the event is triggered multiple times, because what I need is just to avoid simultaneous AJAX calls. Thanks! – davidaam Apr 12 '12 at 02:02
0
$(document).ready(function() {
    $("#mas-noticias-footer").on('click', getnews);

    function getnews() {
        $("#mas-noticias-footer").off('click', getnews);
        var numItems = $('.noticias-list').length;
        $.ajax({
            type: "POST",
            url: "mas-noticias.php",
            data: "num-noticias="+numItems,
            success: function(data) {
                $('#noticias-display').append(data);
            },
            complete: function() {
                $("#mas-noticias-footer").on('click', getnews);
            }
        });
    }
});

If using on() with delegation, make sure to use off() the same way.

adeneo
  • 312,895
  • 29
  • 395
  • 388
0

Have you tried to disable the button?

$(document).ready(function() {
    $("#mas-noticias-footer").on('click',function() {
        var self=this;
        $(self).attr('disabled','disabled'); //<-Disable
        var numItems = $('.noticias-list').length;
        $.ajax({
            type: "POST",
            url: "mas-noticias.php",
            data: "num-noticias="+numItems,
            success: function(data) {
               $('#noticias-display').append(data);
               $(self).removeAttr('disabled');//<-Enable
            }
        }); 
    });
Ilia Frenkel
  • 1,969
  • 13
  • 19
0

I know this is been answered already, but I've made a solution using $.unbind and also separating the code a little bit

Demo

MilkyWayJoe
  • 9,082
  • 2
  • 38
  • 53