views:

41

answers:

3

Hi, I am having trouble fixing a bug in an existing ASP.NET MVC web site.

One of the views has a series of text boxes where the user enters data. Each text box has some javascript attached to the blur event in order to post back to the server when the text is changed. More specifically the code is using the JQuery $.ajax method to make these calls. This is in order to save temporary data to the session.

In the same view there is also a save button which also posts data via AJAX in the click event. The problem I am having is that if the user clicks the save button when one of the text boxes has focus, the blur event gets triggered at the same time as the button click event and two ajax posts get called simultaneously. This results in unreliable behaviour.

I know that the current design isn't great but I am looking for the easiest solution. Is it somehow possible to queue these two events or is there another solution? Thanks.

A: 

You could delay the ajax call when the blur event fires using setTimeout, then when the function referenced by setTimeout fires, check a variable to see if the save button was clicked first:

var isSaved = false;
function onblur(ev) {
    setTimeout(function(){
        if (!isSaved) {
            // make ajax call
        }
    }, 200);
}

function onsave(ev) {
    isSaved = true;
    // make ajax call
}
Freyday
Ha. The same idea at the same time.
Aidas Bendoraitis
A: 

You can set the ajax call onblur just after some timeout if some status variable is not yet set to true, and that status variable can be set to true, when the form is submitted. Something like this:

$(document).ready(function() {
    var form_processed = false;
    $('input:text').blur(function() {
        var $el = $(this);
        setTimeout(function() {
            if (!form_processed) {
                // do ajax call with $el ...
            }
        }, 500);
    })
    $('form').submit(function() {
        form_processed = true;
        // submit form via ajax ...
        return false;
    });
});

(this code is untested, but hopefully it works)

Aidas Bendoraitis
+1  A: 

Instead of using timers that keep polling you can just use an actual queue. This makes sure each ajax call gets executed in the correct order if someone is just tabbing through fields, not which happens to fire its timer at the right moment.

var queue = new Array(0);
$(function() { 
  $('#inputID').blur(function() { AjaxQueue(this); });
});

function AjaxQueue(element) { 
  var length = queue.push(element);
  if (length == 1) {
    ExecuteNextQueueItem();
  }
}

function ExecuteNextQueueItem() {
  var queueElement = queue.shift();
  if (queueElement != null) {
    // ajax call with queueElement
  }
}

then at the end of your result callback function just make a call to ExecuteNextQueueItem();

Greg
to ensure the correct data is sent you can even create an object based on the field and its value and place that in the queue instead of just queuing up the element itself.
Greg