我有一个客户端javascript函数,它是在按钮点击时触发的(基本上,它是一个计算器!!)。有时,由于页面上的大量数据,javascript计算器功能需要很长时间。使页面对用户显示为非活动状态。我打算在整个页面上显示一个透明的div,可能带有一个忙碌的指示器(在中间),直到计算器功能结束,这样用户就会等到过程结束。
function CalculateAmountOnClick() { // Display transparent div // MY time consuming loop! { } // Remove transparent div }
有关如何解决此问题的任何想法?当我的计算器函数启动时,我应该使用javascript将div类分配给div(它包围我的整个页面的内容)吗?我试过了,但没有得到理想的结果。面对IE 6中的透明度问题。另外,我将如何在这样一个透明的div中显示加载消息+图像?
TIA
答案 0 :(得分:11)
Javacript展示了一幕:
function CalculateAmountOnClick () {
var curtain = document.body.appendChild( document.createElement('div') );
curtain.id = "curtain";
curtain.onkeypress = curtain.onclick = function(){ return false; }
try {
// your operations
}
finally {
curtain.parentNode.removeChild( curtain );
}
}
你的CSS:
#curtain {
position: fixed;
_position: absolute;
z-index: 99;
left: 0;
top: 0;
width: 100%;
height: 100%;
_height: expression(document.body.offsetHeight + "px");
background: url(curtain.png);
_background: url(curtain.gif);
}
(根据需要将MSIE 6下划线黑客移动到有条件包含的文件。)
您可以将其设置为幕布的添加/删除功能,或者作为包装器设置:
function modalProcess( callback ) {
var ret;
var curtain = document.body.appendChild( document.createElement('div') );
curtain.id = "curtain";
curtain.onkeypress = curtain.onclick = function(){ return false; }
try {
ret = callback();
}
finally {
curtain.parentNode.removeChild( curtain );
}
return ret;
}
然后你可以这样打电话:
var result = modalProcess(function(){
// your operations here
});
答案 1 :(得分:5)
我将在这里做一些重要的假设,但是听起来我发生的事情是因为你在设置了幕布元素之后立即用强烈的处理直接锁定了浏览器,浏览器从来没有机会拉开窗帘。
每次更新DOM时,浏览器都不会重绘。看看你是否正在做更多事情,然后画出所需要的东西(浏览器改变他们的方法)可能是不合适的。因此,在这种情况下,只有在取下窗帘后才能刷新显示,或者您通过滚动强制重绘。
一个公平的警告:这种强烈的处理对你来说不是很好,因为它不仅会锁定你的页面。因为浏览器通常只为所有选项卡实现一个Javascript线程,所以您的处理将锁定所有打开的选项卡(=浏览器)。此外,您冒着执行超时的风险,浏览器只是停止脚本(这可能低至5秒)。
这是解决这个问题的方法。
如果您可以将处理分解为较小的块,则可以使用超时运行它(以允许浏览器呼吸空间)。这样的事情应该有效:
function processLoop( actionFunc, numTimes, doneFunc ) {
var i = 0;
var f = function () {
if (i < numTimes) {
actionFunc( i++ ); // closure on i
setTimeout( f, 10 )
}
else if (doneFunc) {
doneFunc();
}
};
f();
}
// add a curtain here
processLoop(function (i){
// loop code goes in here
console.log('number: ', i);
},
10, // how many times to run loop
function (){
// things that happen after the processing is done go here
console.log('done!');
// remove curtain here
});
这实际上是一个while循环,但是循环的每次迭代都是在一个定时间隔内完成的,所以浏览器有一点时间在两者之间呼吸。它会减慢处理速度,之后完成的任何工作都需要进入回调,因为循环独立于processLoop调用之后的运行。
另一种变化是设置窗帘,使用setTimeout调用处理函数以允许浏览器绘制窗帘时间,然后在完成后将其删除。
// add a curtain
var curtain = document.body.appendChild( document.createElement('div') );
curtain.id = "curtain";
curtain.onkeypress = curtain.onclick = function(){ return false; }
// delay running processing
setTimeout(function(){
try {
// here we go...
myHeavyProcessingFunction();
}
finally {
// remove the curtain
curtain.parentNode.removeChild( curtain );
}
}, 40);
如果您使用的是js-library,您可能需要查看用于创建窗帘的现成解决方案。这些应该存在于大多数库here is one for jQuery,并且它们可以帮助CSS。
答案 2 :(得分:2)
我会做类似的事情:
display:inline
)position:absolute
z-index:99
100%
display:none
要使其透明,您必须设置Firefox,IE等不同的不透明度。
要显示加载图标,您始终可以创建第二个div并将其放置在页面上的所需位置。完成加载后,将其与透明的一起移除。
答案 3 :(得分:0)
除了以上所有内容之外,不要忘记在垫片后面放置一个不可见的iframe,以便它显示在IE中的选择框上方。
编辑: 该网站虽然提供了解决更复杂问题的解决方案,但确实涵盖了创建模态背景的方法。 http://www.codeproject.com/KB/aspnet/ModalDialogV2.aspx
答案 4 :(得分:0)
对于加载消息,我会使用<div>
position:absolute
,使用left
和top
定位,并将显示设置为none
。
当您想要显示加载指示符时,您将不得不使用div
的超时,直到您的处理完成为止。因此,您应该将代码修改为:
function showLoadingIncidator()
{
// Display div by setting display to 'inline'
setTimeout(CalculateAmountOnClick,0);
}
function CalculateAmountOnClick()
{
// MY time consuming loop!
{
}
// Remove transparent div
}
由于您设置了超时,因此页面将在耗时的循环发生之前重绘。