JavaScript, движущаяся строка ожидания, неожиданное поведение - PullRequest
0 голосов
/ 11 октября 2010

Я пытаюсь реализовать движущуюся полосу ожидания в JavaScript.Предполагается, что это будет видно во время AJAX-запроса.

Мой исходный код работает, но имеет ограничение, что его можно использовать только один раз на странице, поскольку есть только переменные timerW и только состояниеW.один раз как глобальная переменная, и идентификаторы элементов также могут появляться только один раз в 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, поэтому имейте уникальные идентификаторы

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

в каждом случае, 2-й блок отображается красным, но после этого я получаю HTMLDivElement вместо ожидаемой строки.HTMLDivElement соответствует идентификатору в строке, которую я ожидаю.Я не могу объяснить, почему, только после того, как 2-й блок нарисован красным, поведение меняется.Он продолжает давать мне HTMLDivElement, следовательно, после 2-го красного блока, но я не могу объяснить, почему.

Пока все хорошо, я могу написать код вокруг этой маленькой проблемы, хотя я не могу объяснить, почему это происходит.

Тем не менее, код еще не готов к одновременному запуску нескольких таймеров ожидания.Для этого я попытался создать два объекта

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

with

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

Теперь проблема в том, что мои объекты превращаются в NaN после первого запуска через мою функцию nextW.Я ожидаю, что это вызвано сборкой мусора.

Может кто-нибудь объяснить (1) Почему я получаю HTMLDivElements в цепочке строк?(2) Почему мой объект превращается в NaN?(3) Как решить эту проблему?

Я не просто ищу исправление, но и хочу знать, что происходит.

Ответы [ 2 ]

3 голосов
/ 11 октября 2010

Функция конструктора

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

Usage

new Wait("element_id");​
0 голосов
/ 11 октября 2010

Чтобы объяснить, что не так:

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

сначала: не предоставляйте строки для setTimeout (), они будут оценены.setTimeout ожидает функции, а не строки.

пример для использования с функцией ::

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

Строка, которую вы предоставите в вашем скрипте, будет оценена как:

nextW(mainE)

поскольку setTimeout () является методом глобального оконного объекта, это не удастся, потому что там (внутри глобальной области видимости) ничего не известно с именем "mainE".

Если вы делаете это со строками,это должно выглядеть так:

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

это будет оценено как nextW ('theGivenId')

... но, как я уже говорил, не делайте так.

Вы должны прочитать немного об использовании объектов и замыканий в javascript, они облегчат вашу работу с ним, как вы можете видеть на примере, представленном galambalazs.Вам не нужно злиться на множество глобальных объектов и конфликты имён:)

...