JavaScript,移动等待栏,意外行为

时间:2010-10-11 14:46:18

标签: javascript settimeout

我正在尝试在JavaScript中实现移动等待栏。 这应该在AJAX请求期间可见。

我的初始代码似乎有效,但有限制,它只能在页面上使用一次,因为只有变量timerW和stateW只出现一次作为全局变量,并且元素id也只出现一次在html文档中。

var timerW;
var stateW = 1;


 function nextW(){

  switch (stateW){
   case 1:
    document.getElementById('d3').style.background = "grey";
    document.getElementById('d1').style.background = "red";
    stateW++;
    timerW = setTimeout("nextW()",250);
    break;
   case 2:
    document.getElementById('d1').style.background = "grey";
    document.getElementById('d2').style.background = "red";
    stateW++;
    timerW = setTimeout("nextW()",250);
    break;
   case 3:

    document.getElementById('d2').style.background = "grey";
    document.getElementById('d3').style.background = "red";
    stateW = 1;
    timerW = setTimeout("nextW()",250);
    break;
  }
 }


 function Wait(mainE){
  document.getElementById(mainE).innerHTML = '<div id="d1" class="d"></div><div id="d2" class="d"></div><div id="d3" class="d"></div>';
  nextW(mainE);

}

所以,从那里我想扩展它以使多个等待块可见。

我尝试解决的第一个问题是生成的html,所以有唯一的ID

 var timerW;
 var stateW = 1;

 function nextW(mainE){


  // Unexplained behaviour
  // for some reason, I get the HTMLDivElement in stead of it's ID in a string,
  // This appears to start when stateW is 3.
  // the setTimeout in case 1 looks identical to the case 2, so I have no clue why
  // I am getting an object in stead of my string.


  var m;
  if (typeof(mainE)=="object") {
   m = mainE;
   mainE = m.id;
  } else {
   m = document.getElementById(mainE);
  }



  if (m == undefined ) return; 
  if (m.style.visibility == "hidden") return;

  for(i=0; i < m.children.length; i++) {
   if (m.children[i].id=="wait") {
    m = m.children[i];
    break;
   }
  }
  if (stateW[mainE]==undefined) stateW[mainE] = 1;

  switch (stateW[mainE]){
   case 1:

    for(i=0; i < m.children.length; i++) {
     var e = m.children[i];
     if (e.id==mainE+'d1'){
      e.style.background = "red";
     } else {
      e.style.background = "gray";
     }
    }
    stateW++;
    timerW = setTimeout("nextW("+mainE+")",250);
    break;
   case 2:

    for(i=0; i < m.children.length; i++) {
     var e = m.children[i];
     if (e.id==mainE+'d2'){
      e.style.background = "red";
     } else {
      e.style.background = "gray";
     }
    }

    stateW++;
    timerW = setTimeout("nextW("+mainE+")",250);
    break;
   case 3:
    for(i=0; i < m.children.length; i++) {
     var e = m.children[i];
     if (e.id==mainE+'d3'){
      e.style.background = "red";
     } else {
      e.style.background = "gray";
     }
    }

    stateW = 1;
    timerW = setTimeout("nextW("+mainE+")",250);
    break;
  }
 }

 function Wait(mainE){
  document.getElementById(mainE).innerHTML = '<div id="wait"><div id="'+mainE+'d1" class="d"></div><div id="'+mainE+'d2" class="d"></div><div id="'+mainE+'d3" class="d"></div></div>';
  nextW(mainE);
 }

此代码导致无法解释的行为。当我使用

设置计时器时
 timerW = setTimeout("nextW("+mainE+")",250);

在每种情况下,第二个块都正确地绘制红色,但在那之后,我得到一个HTMLDivElement而不是我期望的字符串。 HTMLDivElement与我期望的字符串中的ID相对应。我无法解释为什么,只有在第二个块被绘制为红色后,行为才会发生变化。它继续在第二个红色区块后给我一个HTMLDivElement,但我无法解释原因。

到目前为止,我可以围绕这个小问题编写代码,即使我无法解释为什么会这样。

但是,对于同时运行的多个等待计时器,代码还没有准备好。 为此,我尝试创建两个对象

 var timerW = new Object();
 var stateW = new Object();

并替换我的

 switch (stateW){

 if (stateW[mainE]==undefined) stateW[mainE] = 1;
 switch (stateW[mainE]){

并替换

   timerW = setTimeout("nextW("+mainE+")",250);

   timerW[mainE] = setTimeout("nextW("+mainE+")",250);

现在问题是,在第一次运行nextW函数后,我的对象变成了NaN。 我希望它是由垃圾收集引起的。

任何人都可以解释 (1)为什么我在stread of strings中获取HTMLDivElements? (2)为什么我的物体会变成NaN? (3)如何解决这个问题?

我不只是在寻找解决方案,而且还想知道发生了什么。

2 个答案:

答案 0 :(得分:3)

构造函数

function Wait(el) {
    if (typeof el == "string") el = document.getElementById(el);
    this.el = el;
    this.state = 1;
    this.el.innerHTML = '<div id="d1" class="d"></div>\
                         <div id="d2" class="d"></div>\
                         <div id="d3" class="d"></div>';
    this.next();
}

动画步骤

Wait.prototype.next = function () {
    if (this.el.style.visibility == "hidden") return;
    var children = this.el.childNodes;

    for (var i = children.length; i--;) {
        if (children[i].id == "wait") {
            var wait = children[i];
            break;
        }
    }

    children = wait.childNodes;

    for (var i = children.length; i--;) {
        var child = children[i];
        if (child.id == this.el.id + 'd' + this.state) {
            child.style.background = "red";
        } else {
            child.style.background = "gray";
        }
    }

    this.state++;
    if (this.state > 3) this.state = 0;
    this.timer = setTimeout(this.next, 250);
}​

<强>用法

new Wait("element_id");​

答案 1 :(得分:0)

解释一下,错了:

setTimeout("nextW("+mainE+")",250);

首先:不要为setTimeout()提供字符串,它们将被评估。 setTimeout需要函数,而不是字符串。

与函数::

一起使用的示例
setTimeout(function(){nextW(mainE);},250);

您在脚本中提供的字符串将被评估为:

nextW(mainE)

因为setTimeout()是全局window-object的一个方法,所以这将失败,因为(在全局范围内)并不知道名为“mainE”的内容。

如果你使用字符串,它必须如下:

setTimeout("nextW('"+mainE+"')",250);

这将被评估为     nextW( 'theGivenId')

...但正如我之前所说,不要那样做。

你应该阅读关于javascript中对象和闭包的使用的一点点,它们将使你的工作更容易,正如你在galambalazs提供的例子中看到的那样。 你不需要愤怒地使用大量的全局对象和名称冲突:)