views:

35

answers:

3

I have a search form with inputs and selects, and when any input/select is changed i run some js and then make an ajax query with jquery. I want to stop the user from making further changes to the form while the request is in progress, as at the moment they can initiate several remote searches at once, effectively causing a race between the different searches.

It seems like the best solution to this is to prevent the user from interacting with the form while waiting for the request to come back. At the moment i'm doing this in the dumbest way possible by hiding the form before making the ajax query and then showing it again on success/error. This solves the problem but looks horrible and isn't really acceptable. Is there another, better way to prevent interaction with the form? To make things more complicated, to allow nice-looking selects, the user actually interacts with spans which have js hooked up to them to tie them to the actual, hidden, selects. So, even though the spans aren't inputs, they are contained in the form and represent the actual interactive elements of the form.

Grateful for any advice - max. Here's what i'm doing now:

function submitQuestionSearchForm(){
  //bunch of irrelevant stuff  
  var questionSearchForm = jQuery("#searchForm");
  questionSearchForm.addClass("searching");
  jQuery.ajax({
    async: true, 
    data: jQuery.param(questionSearchForm.serializeArray()), 
    dataType: 'script', 
    type: 'get', 
    url: "/questions", 
    success: function(msg){ 
      //more irrelevant stuff
      questionSearchForm.removeClass("searching");                           
    },
    error: function(msg){ 
      questionSearchForm.removeClass("searching");                           
    }    
  }); 
  return true;
}

where the 'searching' class currently has just {display: none}

+1  A: 

You could display a div taking all the page space when an AJAX request start (you can put a loading background in the middle and made it transparent) and hide it when done.

I think that you can also made the calls synchronous and not asynchronous, i think it will "block" the navigator until the request is done.

Adirael
A: 

How about using a boolean to prevent multiple AJAX request from firing? You can also use the boolean to disable/enable elements.

Something like the following (see comments for my additions):

// set initial boolean state
var isRequestFinished = true;

function submitQuestionSearchForm(){

    // check if previous request has finished
    if(isRequestFinished){
        // request just started, so set boolean to false
        isRequestFinished = false;

        jQuery.ajax({
            async: true, 
            data: jQuery.param(questionSearchForm.serializeArray()), 
            dataType: 'script', 
            type: 'get', 
            url: "/questions", 
            success: function(msg){ 
              questionSearchForm.removeClass("searching");
              // request just finished, so set boolean to true
              isRequestFinished = true;
            },
            error: function(msg){ 
              questionSearchForm.removeClass("searching");                           
            }    
        });
    }
    return true;
};

I didn't test this code, but it should point you in the right direction. Before you call jQuery.ajax() you can disabled whatever elements you want, and then re-enable them in the success callback.

Intelekshual
Thanks Intelekshual. Wouldn't this mean though that the user was making changes to the form which were just being ignored? So, it literally stops them submitting another request, but they would just think it was broken? I'm not attacking your proposal, just discussing :) thanks, max
Max Williams
Well, yeah. That's why I left it up to you to visually change what the form looks like during the request! ;) But now I see that you were asking for advice on how best to visually disable the form (which is essentially what the BlockUI plugin that Omar suggested does) and not necessarily disable further requests. Personally I'd just throw an activity indicator from http://ajaxload.info/ somewhere (maybe near the button used to submit the form?) and call it a day.
Intelekshual
+1  A: 

I use this plugin http://jquery.malsup.com/block/, it implement a semitransparent img that can be apply to a Div or the full page, its pretty good and cross browser supported.

Omar
That looks perfect, thanks Omar.
Max Williams