James
James

Reputation: 819

JQuery AJAX Event Problem

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.

Upvotes: 0

Views: 391

Answers (3)

Greg
Greg

Reputation: 2229

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();

Upvotes: 1

Aidas Bendoraitis
Aidas Bendoraitis

Reputation: 4003

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)

Upvotes: 0

mikefrey
mikefrey

Reputation: 4681

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
}

Upvotes: 0

Related Questions