Salil
Salil

Reputation: 47472

Best way to disable a link after clicking on it so that ajax call should not be made

I am using following code to send an ajax request which works accurately, however when user click on the link more than once it create a problem, so i want to disable my link so that no ajax gets called when user click second time.

.html.erb

<%= link_to("Sports", "#", :class => "school_activity", :p_type => "Sport", :o_type => "")%>

javascript

jQuery(function () {
  jQuery('.school_activity').click(function () {
    link = jQuery(this);
    p_type = link.attr('p_type');
    o_type = link.attr('o_type');
    jQuery('.i-link a').removeClass('stream_wall_select');
    jQuery.ajax({
      type:"GET",
      url:'<%= some_path(@school) %>',
      data:'format=js&p_type=' + p_type + '&tagged_type=' + o_type,
      success:function (response) {
        jQuery('#s_activity_div').html(response);
      }
    });
  })
})

I don't want to do something like setting the parameter true/false and depend on it send ajax request.

I want something which is very generalized and may applicable to all the ajax link on my site.

Upvotes: 0

Views: 6426

Answers (4)

Martin Tonev
Martin Tonev

Reputation: 775

Simple remove and add the trigger class

$(document).on('click', '.click', function(e){
        e.preventDefault();

        $(this).removeClass('click');

        $.ajax({
            url: "/question",
            method: "POST",  
            dataType: 'json',
            cache: false,
            data: form_data,
            success: function (response){

            }
        }).done(function() { $(this).addClass('click');  } );

    });

Upvotes: 0

Vitaly Dyatlov
Vitaly Dyatlov

Reputation: 1872

First simple and general solution - to use synchronious calls:

jQuery.ajax({
      type:"GET",
      async: false,
...

In this case browser will be waiting until call will complete. But it will cause page frozeness at times (in times of awaiting)

Second solution is to use custom flags/attributes, although you hate it (look at in_progress attribute):

jQuery(function () {
  jQuery('.school_activity').click(function () {
    if( $(this).attr('in_progress') ) return;

    link = jQuery(this);
    p_type = link.attr('p_type');
    o_type = link.attr('o_type');
    jQuery('.i-link a').removeClass('stream_wall_select');

    $(this).attr('in_progress', 1);
    var link = this;

    jQuery.ajax({
      type:"GET",
      url:'<%= some_path(@school) %>',
      data:'format=js&p_type=' + p_type + '&tagged_type=' + o_type,
      success:function (response) {
        jQuery('#s_activity_div').html(response);
      }, 
      complete: function(){ $(link).removeAttr('in_progress'); }
    });
  })
})

To make it a robust and general solution, we can create a custom function for such situations:

function waCall( element, ajaxParams, beforeAjaxCallback, afterAjaxCallback ) {

    if( $(element).attr('in_progress') ) return; 

    var link = $(element);
    $(link).attr( 'in_progress' );

    ajaxParams['complete'] = function() { $(link).removeAttr('in_progress');
                             if( afterAjaxCallback ) afterAjaxCallback( link ); };

    if( beforeAjaxCallback ) beforeAjaxCallback(link);

    $.ajax( ajaxParams );
}


jQuery(function () {
      jQuery('.school_activity').click(function () {
          waCall( this, {
              type:"GET",
              url:'<%= some_path(@school) %>',
              data:'format=js&p_type=' + p_type + '&tagged_type=' + o_type,
              success:function (response) {
                  jQuery('#s_activity_div').html(response);
              }
            }, function(link) {
                var p_type = link.attr('p_type');
                var o_type = link.attr('o_type');
                jQuery('.i-link a').removeClass('stream_wall_select');
            }
      }
});

Upvotes: 2

Pranav 웃
Pranav 웃

Reputation: 8477

Remove the href attribute when the click happens, and add it back when it completes.

...
  jQuery('.school_activity').click(function () {
    var link = $(this).attr('href');
    jQuery(this).removeAttr('href');
   ...
    jQuery.ajax({ .... });
   ...
    jQuery(this).attr("href",link);
...

UPDATE

Use the jQuery method one() to make sure something gets executed only once.

Attach a handler to an event for the elements. The handler is executed at most once per element.

jQuery('.school_activity').one('click', function () {
    jQuery.ajax({
        ...
    });
});

Note : This will be run only once, irrespective whether AJAX fails or not.

Upvotes: 2

Dakait
Dakait

Reputation: 2620

you can use a flag like

$(function(){
 $flag=false;

 $("#idOfYourLink").click(function(e){
   e.preventDefault();
   $flag=true;
   if(!$flag){
     $.ajax({
       ...
       success:function(){
           $flag=false;
         }//success ends
       });//ajax ends
    }//flag chk if ends
  });//click handler ends
});//document ready ends

EDIT:

because you specifically mentioned

I don't want to do something like setting the parameter true/false and depend on it send > ajax request.

you can simple unbind the click event handler and re-attach in the success call back of the ajax call;

Upvotes: 1

Related Questions