加载动画直到在Safari / Chrome中完成ajax调用后才会显示

时间:2010-08-20 22:48:11

标签: javascript ajax google-chrome safari webkit

我遇到了一个我尚未找到解决方案的问题。

我正在创建一个资源预订应用程序,它使用AJAX处理用户提供给后端数据库的信息。每当用户想要创建预订时,他们就会填写一份包含相关信息的表单,该表单通过AJAX发送到处理信息并更新数据库的servlet。因为我们已经包含了预订重复选项,有时数据库可能需要一段时间才能更新。因此,我们实现了一个“处理...”图形,以便在servlet完成它时显示。

我们实现处理图形和ajax调用的方式在firefox,opera中运行良好,即问题在于safari和chrome ......所以可能与WebKit有关。

在Safari / Chrome中,处理图形不会显示在页面上,直到数据库完成其工作并且ajax调用返回...才能完成“处理...”图形的整个目的。

有没有人知道为什么图形(在调用AJAX请求之前插入的图形)在ajax调用返回之后才会显示?

以下是我们如何实现图形和ajax调用。这是调用创建图形的函数和发送ajax请求的函数:

/**
 * Implements AJAX calls to add/remove bookings from the database
 */
function processBooking(selection, responseID, formElement, removing, fromManager, resourceType) {

 if (!removing) {
 purpose = formElement.purpose.value;
 email = formElement.email.value;

            /* These values should only be set if the user is an admin otherwise they do not exist so send in the default empty
             * values to the processing servlet
             */
            if (formElement.repeatEveryUnits != undefined && formElement.repeatFor != undefined && formElement.repeatForUnits != undefined)
            {
                repeatEvery = formElement.repeatEveryUnits.value;
                repeatForAmount = formElement.repeatFor.value;
                if (repeatForAmount == '') {
                        repeatForAmount = '0';
                }
                repeatForUnit = formElement.repeatForUnits.value;
            }
            else
            {
                repeatEvery = '0';
                repeatForAmount = '0';
                repeatForUnit = '0';
            }

 }

    /* Function to be passed in as the callback to our asynchronous request */
    callback = function() {
        document.getElementById(responseID).innerHTML += '<p class="button-small" onclick="removeDiv(\'' + responseID + '\')>Clear</p>';
        document.getElementById(responseID).style.padding = '0 0 5px 0';
    }

    /* Parameters that are to be used in our asynchronous request */
    postData += parseArray(selection);
    postData += '&removing=' + removing;
    postData += '&availability=false';
    postData += '&type=' + resourceType;

    /* Play the loading graphic */
    startLoading();

    /* Make the call to the servlet */
    response = sendAsyncRequest(url,postData,callback,false);

    /* reset global variables used */
    reset();

    if ((!removing) || (!fromManager))
    {
        week = document.getElementById("selectedWeek").value;

        window.location = "../../servlet/ResourceBooking?action=schedule&type=" + resourceType + "&week=" + week;
    }

    return response;
 }

这是插入图形的代码:

/**
 *      Begins a loading animation that is to be played while the database does its work 
 */
function startLoading() {

    document.getElementById("container").style.opacity = "0.2";
    document.getElementById("cover").style.display = "block";
    var newDiv = document.createElement("div");

    newDiv.setAttribute("id", "loading");
    newDiv.style.height = 120 + "px";
    newDiv.style.width = 350 + "px";

    newDiv.innerHTML = "<div id='progress'><p id='progress'><img id='progress_image' src='/intranet/images/ajax-loader.gif' alt=''><br/><h3>Processing database...</h3></p></div>";
    document.body.appendChild(newDiv);

    ignoreClicks = true;
 }

这是为AJAX调用生成XMLHttpRequest的代码:

function sendAsyncRequest(servletUrl, postData, callback, async) {

try {
      asyncRequest = new XMLHttpRequest();
}
catch (e) {
        // Internet Explorer Browsers
        try {
                asyncRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
                try {
                asyncRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch(e){
                        // Something went wrong
                        alert('Request Failed');
                        return false;
                }
        }
}

asyncRequest.onreadystatechange = function() {
    if (asyncRequest.readyState == 4 && asyncRequest.status == 200) {
                try {
                                callback();
                }
                catch (e) {
                         // IE fails unless we wrap the string in another element.
                        var childDiv = current_element.getElementsByTagName("div");
                        if (childDiv.length == 0) {
                                var wrappingDiv = document.createElement('div');
                                //wrappingDiv.setAttribute("id", current_element.id+"Div");
                                wrappingDiv.innerHTML = asyncRequest.responseText;
                                current_element.appendChild(wrappingDiv);
                        }
                        else {
                                var wrappingDiv = document.createElement('div');
                                //wrappingDiv.setAttribute("id", current_element.id+"Div");
                                wrappingDiv.innerHTML = asyncRequest.responseText;
                                current_element.replaceChild(childDiv[0], wrappingDiv);
                                //childDiv[0].innerHTML = asyncRequest.responseText;
                        }
                }
        }
};

asyncRequest.open('POST', servletUrl, async);

if (postData == null)
{
    asyncRequest.send(null);
}
else
{
    asyncRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    asyncRequest.setRequestHeader("Content-length", postData.length);
    asyncRequest.setRequestHeader("Connection", "close");
    asyncRequest.send(postData);
}

return response;
}

有什么关于WebKit会阻止在发出请求之前将startLoading div动态添加到页面中吗?

我已经尝试在加载图形后注释掉请求本身(sendAsyncRequest(...))并且图形看起来非常好,所以当我们跟进请求时似乎发生了一些事情

感谢任何帮助,我不知所措......

克里斯汀

2 个答案:

答案 0 :(得分:2)

它是一个老线程,但就在今天我有类似的问题。也许它会帮助某人:)。

我在IE中遇到了类似的问题 - 我有我自己的加载类型div,我在ajax请求之前显示并在加载数据后隐藏它。数据已经加载后,我的div只显示了一段时间(它只是闪烁)。

这样的事情:

document.getElementById('pnLoaderPanel').style.display = 'block';
Task.Refresh(); //method that calls ajax
document.getElementById('pnLoaderPanel').style.display = 'none';

所以我注意到如果我在显示div之后立即发出提示,我的div就可见了。我猜IE在某种程度上没有正确刷新,所以我做的就是这个,现在它完美地工作了:

document.getElementById('pnLoaderPanel').style.display = 'block';
setTimeout(Task.Refresh(), 1); //method that calls ajax
document.getElementById('pnLoaderPanel').style.display = 'none';

答案 1 :(得分:0)

您可以为图像加载事件设置回调,然后仅在加载时执行ajax POST。像这样......

function processBooking(selection, responseID, formElement, removing, fromManager, resourceType) {
    //...some stuff
    startLoading(function(){
        sendAsyncRequest(url,postData,callback,false);
    });
    //...some more stuff
}

function startLoading(callback) {
    document.getElementById("container").style.opacity = "0.2";
    document.getElementById("cover").style.display = "block";
    var img = new Image();
    img.onload=callback;
    img.src="/intranet/images/ajax-loader.gif";
    var newDiv = document.createElement("div");

    newDiv.setAttribute("id", "loading");
    newDiv.style.height = 120 + "px";
    newDiv.style.width = 350 + "px";

    newDiv.innerHTML = "<div id='progress'><p id='progress'><img id='progress_image'     src='/intranet/images/ajax-loader.gif' alt=''><br/><h3>Processing database...</h3></p>     </div>";
    document.body.appendChild(newDiv);

    ignoreClicks = true;
 }