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

发布于 2024-09-26 15:25:35 字数 4042 浏览 4 评论 0原文

我正在尝试用 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();

并将 my 替换

 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) 为什么我会在字符串中获取 HTMLDivElements? (2) 为什么我的Object变成了NaN? (3)如何解决这个问题?

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

I am trying to implement a moving waiting bar in JavaScript.
This is supposed to be visible during an AJAX request.

My initial code seems to work, but has the restriction that it can be used only once on the page, since there is only the variables timerW and stateW only appear once as global variable, and the element ids can also appear only once in the html document.

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

}

So, from there I want to extend it to make it possible to have multiple wait blocks visible.

The first problem I try to solve is the html generated, so have unique ID's

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

This code results in unexplained behaviour. As I set the timer using

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

in each case, the 2nd block is drawn red correctly, but after that, I am getting an HTMLDivElement in stead of the string I expected. The HTMLDivElement corresponds with the ID in the string I expect. I cannot explain why, only after the 2nd block is drawn red, the behaviour changes. It keeps giving me an HTMLDivElement consequently after the 2nd red block, but I cannot explain why.

So far so good, I can write code around this little problem, even though I cannot explain why this is happening.

Still, the code is not ready yet for multiple wait timers running at the same time.
For this, I tried to create two objects

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

and replace my

 switch (stateW){

with

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

and replace

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

with

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

Now, the problem is, my objects turn into NaN after the first run through my nextW function.
I expect it's caused by garbage collection.

Can anyone explain
(1) Why I am getting HTMLDivElements in stread of strings?
(2) Why my Object turns into a NaN?
(3) How to fix this issue?

I am not just looking for a fix, but also wanting to know what is going on.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没有伤那来痛 2024-10-03 15:25:35

构造函数

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");​

Constructor function

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

Animation step

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);
}​

Usage

new Wait("element_id");​
千纸鹤带着心事 2024-10-03 15:25:35

解释一下,有什么问题:

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

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

与函数一起使用的示例::

setTimeout(function(){nextW(mainE);},250);

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

nextW(mainE)

由于 setTimeout() 是全局窗口对象的方法,因此这将失败,因为(在全局范围内)对那里(全局范围内)一无所知名称“mainE”。

如果你用字符串来做,它必须看起来像这样:

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

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

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

您应该阅读一点有关 javascript 中对象和闭包的使用的内容,它们将使您的工作更加轻松,正如您可以在 galambalazs 提供的示例中看到的那样。
您无需对大量全局对象及其名称冲突感到愤怒:)

To explain, whats wrong:

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

first: don't provide strings to setTimeout(), they will be evaluated. setTimeout expects functions, not strings.

example for use with a function::

setTimeout(function(){nextW(mainE);},250);

The string you provide inside your script will be evaluated to :

nextW(mainE)

since setTimeout() is a method of the global window-object, this will fail, because there(inside the global scope) is nothing known with the name "mainE".

If you do it with strings, it must look like that:

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

this will be evaluated to
nextW('theGivenId')

...but as I said before, don't do it like that.

You should read a liitle bit about the use of objects and closures in javascript, they will make your work with it easier, as you can see on the example provided by galambalazs.
You dont need to anger with lots of global objects and name-conflicts with it :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文