views:

317

answers:

4

I've got the following code that shows a lightbox 'please wait' box, then does a synchronous ajax request which removes the lightbox when it finishes. Works fine everywhere else, but in IE, the lightbox doesn't show. The Ajax request works fine, but it just seems to ignore the lightbox.

The showLightbox function just does that, show a modal lightbox with the passed in text.

showLightbox("Please Wait");

$.ajax({
    async: true,
    dataType: 'json',
    type: 'GET',
    url: checkValidUrl,
    data: submitData,
    error: function(request, textStatus, errorThrown) {
     valid = false;
    },
    success: function(data, textStatus) {
     valid=true;
    },
    complete: function(request, textStatus) {
     hideLightbox();
    }
});

If I make the ajax requst async it works fine, but I need it to be synchronous because this is a validation method.

Update: Also, if I wrap the whole ajax request in a setTimeout it also works in IE, but that is asynchronous too

Update 2: I just replaced the lightbox with a simple div and did a jQuery .show() on beforeSend and .hide() on complete, and it didn't show that either, so it doesn't seem to have anything to do with the lightbox. If I whack an alert() immediately after showLightbox() it does show the lightbox

A: 

This smells funny.

Firstly, I can't think of any good reason for using a synchronous request -- doing so locks the user's browser until the response is returned. It's a terrible user experience which would make most users think your website is killing their browser.

Secondly, you say you're doing this for validation? Any user who is malicious enough to try to alter a form while they wait for the asynchronous response would also be smart enough to just change your "async: false" to "async: true". Remember that all validation on the client side is only there for the benefit of the user, and all proper validation should be done server-side. I don't see why you'd need to do things this way.

nickf
Yes it locks, that's what the please wait lightbox is for. Yes we do server side validation, but we want to be able to tell the user at the top of the form that this data is wrong, before they get to the end and have to go back and start again. JS validation is always done for user convienience, not data security
Glenn Slaven
so if you've got a lightbox over the page, then why not just use asynchronous requests?
nickf
Because it's not the user I'm needing to block, it's the function return, this is inside a validation method using the jQuery validate plugin. I need to know what the return status of the ajax request is before I return from the function
Glenn Slaven
Yeah, I still don't think you're doing it right. You should be using callbacks to handle the response from AJAX, not synchronous requests.
nickf
How can you use callbacks in the middle of a validate function?
Glenn Slaven
step 1, user enters data, step 2, you send the data to the server for validation, step 3, server responds with some data and your callback function displays a tick or a cross depending if it worked.
nickf
The validation call is a blocking event, they're clicking on a box that will close an accordian interface and proceed the user forward. It *has* to wait and check first
Glenn Slaven
In that case, I think depending on the validation framework is actually your problem. Why not intercept the "clicking on a box" and run a normal async ajax call instead of whatever it's doing now? Then if the return value indicates a success, your callback can trigger the action that the click currently triggers (closing the accordion interface and proceed the user forward).
Joel Mueller
@Glenn: Ok, you can still block the user until the request completes **without** freezing their browser. A simple lightbox overlay, like you already have, would be more than sufficient.
nickf
+1  A: 

My guess is that IE either is too busy doing the request to show the lightbox or that it thinks it's supposed to stop to do the request. Try adding the showLightbox() function to the $.ajax function itself, to the beforeSend option.

$.ajax({
    async: true,
    dataType: 'json',
    type: 'GET',
    url: checkValidUrl,
    data: submitData,
    beforeSend: showLightbox(),
    error: function(request, textStatus, errorThrown) {
        valid = false;
    },
    success: function(data, textStatus) {
        valid=true;
    },
    complete: function(request, textStatus) {
        hideLightbox();
    }
});
Anthony
Unfortunately I tried that, it still doesn't work
Glenn Slaven
Have you tried some dummy function? Have the beforeSend turn the body background yellow, and then green on complete. You need to determine if the issue is with the lightbox plugin or if IE simply doesn't want to do anything other than make the request.
Anthony
Yeah, it does call those sort of methods. It's only the dynamic show/hide of elements that seems to be the problem. I've run into this before, not using a lightbox, but just showing a hidden div before a synchronous request, so I don't think it's the lightbox itself
Glenn Slaven
I just replaced the lightbox with a simple div and did a jQuery .show() on beforeSend and .hide() on complete, and it didn't show that either
Glenn Slaven
This may be grasping a bit, but what about if you use `$.ajaxSetup` for the before, during, after functions, and a `$.get` for the ajax call. Obviously IE doesn't want to do DOM mods on sync requests, so your next best option is to trick it somehow. Maybe have the ajax request as part of the showLightbox function?
Anthony
This may be a total cop-out, as it wouldn't explain the issue, but does any non-"jiggly" stall in the script fix the issue? Instead of throwing an alert, could you just declare a variable or have the script do some math?
Anthony
You could even make it slightly less hacky if you can make it throw two lightboxes. The first one says "If you can read this, you're on IE" the second "Please Wait". :p
Anthony
A: 

Perhaps you should show the lightbox, and then do a setTimeout before you actually begin the synchronous request. I suspect that IE doesn't render your DOM changes until it gets control back from your JS function, and that doesn't happen until after the ajax request, and the box is hidden again. Give it a chance to render the lightbox, and then start your ajax request.

showLightbox("Please Wait");

setTimeout(function() {
    $.ajax({
        async: false,
        dataType: 'json',
        type: 'GET',
        url: checkValidUrl,
        data: submitData,
        error: function(request, textStatus, errorThrown) {
            valid = false;
        },
        success: function(data, textStatus) {
            valid=true;
        },
        complete: function(request, textStatus) {
            hideLightbox();
        }
    });
}, 100);
Joel Mueller
Unfortunately that makes the request asynchronous, I need it to wait until the ajax request comes back.
Glenn Slaven
How does that make the request asynchronous? The user would have a grand total of a tenth of a second to mess with things before the synchronous ajax call locked up the browser.
Joel Mueller
Personally, what I do in situations like this is cover the entire page with a grey div that has its opacity set to 1%. This prevents the user from clicking anything while I make an ordinary asynch ajax call, and remove the covering div in the callback. If the ajax call is likely to take a while, a "Please Wait" message along with preventing clicks goes a long way.
Joel Mueller
This isn't blocking the user, it's blocking the interface from progressing forward. As I mentioned, the lightbox Please wait text is already blocking the user from doing anything, I need to make the JS wait for a response before it moves the user onto the next section
Glenn Slaven
A: 

Why is everybody trying to convince Glenn Slaven not to use SJAX? Let is please concentrate on finding a workaround to make this code work on IE. I have the same issue and AJAX is not an option for me. Any help will be appreciated.

Omid Mufeed