Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   progress bar для JS (https://javascript.ru/forum/misc/3603-progress-bar-dlya-js.html)

Dagger 06.05.2009 15:12

progress bar для JS
 
Здравствуйте!
Помогите, пожалуйста, в решении следующей задачи. Бьюсь уже два дня, но ничего не выходит.

Имеется элемент div, который реагирует на событие onclick:

Код:

<div onclick='doStretch(1)'> &rt;&rt; </div>
Функция doStretch() выполняется длительное время, и для утешения пользователя нужно нарисовать progress bar. В моем случае все просто: progress bar - просто анимированный gif, который должен появиться при клике на этот div, и исчезнуть в конце работы функции doStretch():

Код:

<script language='javascript'>
  function doStretch(i) {
        initProgress();
 /* здесь идет очень долгий процесс, для которого нужно отобразить progress bar*/
        releaseProgress();
  }

  function initProgress() {
        var progressDiv = document.getElementById("stretchProgress");
        progressDiv.style.visibility = "visible";
  }

  function releaseProgress() {
        var progressDiv = document.getElementById("stretchProgress");
        progressDiv.style.visibility = "hidden";
  }
</script>

...

<body>
  <img src='images/progress.gif'  style="visibility: hidden;"  id="stretchProgress"/>

...

Однако этот прямой подход не работает. Браузер сначала полностью выполняет функцию doStretch() и только после этого отображает результат выполнения функций initProgress() и releaseProgress(), т.е. показывает и прячет картинку, символизирующую progress bar. Я понял это поведение следующим образом: браузер не скидывает свой буфер (где картинка уже стала visible) на отображение, но функции подобных flush() я в JS не нашел (я новичок в JavaScript).

Желаемый, но абсолютно неприемлемый результат получается, если написать функцию initProgress() с alert'ом:

Код:

  function initProgress() {
        var progressDiv = document.getElementById("stretchProgress");
        progressDiv.style.visibility = "visible";
                        alert("все что угодно");
  }

Т.к. alert() является блокирующим вызовом, то браузер прерывает исполнение скрипта и выводит текущий результат на экран, а затем уже продолжает выполнять сценарий после исчезновения alert'а. Но alert, как вы понимаете, здесь недопустим, а других блокирующих вызовов типа sleep(), насколько я знаю, в JavaScript нет.

Может кто-нибудь знает, как можно выйти из этой ситуации? Помогите, пожалуйста.

ZoNT 06.05.2009 15:15

я бы предложил тебе привести сюда код функции doStretch, и мы бы помогли тебе её оптимизировать, чтобы она выполнялась быстро.

Kolyaj 06.05.2009 15:24

Браузер все равно будет зависать, и никакого анимированного гифа все равно не будет видно.

Dagger 06.05.2009 15:26

Проблема в том, что у меня используется тулзовина (CodeThatGrid), которая позволяет генерить интерактивные гриды, как в Excel'е. Функция doStretch() должна пройтись по строке с индексом i и выставить в каждую ячейку некоторое значение (распространить одно и то же введенное пользователем значение). Ситуация становится критической, когда грид содержит большое число столбцов (это необходимо заказчику).

Вот сама функция:
function doStretch(i) {
  initProgress();

      if ( !(cg instanceof CCodeThatGrid) ) return;
      if ( Undef(window.lastStretchPositions) ) 
	window.lastStretchPositions = new Array(NUM_ROWS - 1);

  var lastVisibleCellIndex = getLastVisibleCellIndex();
  var stretchVal, stretchInitialPos;
      for ( var j = 3; j <= lastVisibleCellIndex; j++ ) {
              if ( Undef(cg.cells[i][j]) ) continue;
          var currentVal = parseFloat( cg.cells[i][j].getData() );
    	   if ( isNaN(currentVal) ) continue;
          stretchVal = currentVal;
          stretchInitialPos = j;
      }     
      if ( Undef(stretchInitialPos) ) return;
      if (stretchInitialPos + 1 > lastVisibleCellIndex) return; 
      if ( Def(window.lastStretchPositions[i]) ) {
          delete lastStretchPositions[i];					
      }			
  window.lastStretchPositions[i] = new Array();
  var index = 0;
      for ( var j = stretchInitialPos + 1; j <= lastVisibleCellIndex; j++ ) {
      	  if ( Undef(cg.cells[i][j]) ) break;
      	  if ( cg.cells[i][j].col.isReadOnly || cg.cells[i][j].isReadOnly ) continue;
           cg.cells[i][j].setData(stretchVal);	
      	window.lastStretchPositions[i][index] = j;
      	index++;
      }
  releaseProgress();
}


И вот та ее часть, которая отрабатывает мучительно долго:

...
      for ( var j = stretchInitialPos + 1; j <= lastVisibleCellIndex; j++ ) {
      	  if ( Undef(cg.cells[i][j]) ) break;
      	  if ( cg.cells[i][j].col.isReadOnly || cg.cells[i][j].isReadOnly ) continue;
           cg.cells[i][j].setData(stretchVal);	
      	window.lastStretchPositions[i][index] = j;
      	index++;
      }
  releaseProgress();
}

Gvozd 06.05.2009 15:26

?
function doStretch(i) {
	initProgress();
	setTimeOut(function(){
	/* здесь идет очень долгий процесс, для которого нужно отобразить progress bar*/
	 releaseProgress();
	},500);
 
  }

  function initProgress() {
	var progressDiv = document.getElementById("stretchProgress");
	progressDiv.style.visibility = "visible";
  }

  function releaseProgress() {
	var progressDiv = document.getElementById("stretchProgress");
	progressDiv.style.visibility = "hidden";
  }

Dagger 06.05.2009 15:27

Неужели нет никакого способа отрисовать progress bar?

Dagger 06.05.2009 15:30

Gvozd,
Большое спасибо! Действительно, это помогло. :)

ZoNT 06.05.2009 16:15

Судя по коду функции торомоза складываются в цикле из-за медленой функции (либо Undef, либо setData). Надо попрофилировать выполнение да посмотреть, что тормозит...

Gvozd 06.05.2009 16:34

Firebug и console вам в помощь:
console.time(name)
console.timeEnd(name)

ZoNT 06.05.2009 16:41

Firebug и профилировщик, встроенный в него вам в помощь!

Dagger 06.05.2009 16:43

ZoNT, Gvozd,
Спасибо! Появился повод поставить Firebug :)

Dagger 07.05.2009 20:11

Проблема решена, но осталась непрятная мелкость: браузер, выполняя скрипт, перестает анимировать гиф (который progress bar). Хочется узнать у профессионалов: есть ли способ обойти это гадкое поведение? Висящий в одном кадре гиф (по наблюдениям за пользователями) их совсем не успокаивает, а, наоборот, провоцирует на беспорядочные кликанья мышкой -(

Kolyaj 07.05.2009 20:20

Dagger, сказано же было
Цитата:

Сообщение от Kolyaj
Браузер все равно будет зависать, и никакого анимированного гифа все равно не будет видно.


ZoNT 08.05.2009 13:09

Dagger, я настоятельно тебе советую отпрофилировать скрипт, найти тормозные функции и переписать их, чтобы они работали быстрее.
Ну или дай нам ссылку на тестовую страничку с данным скриптом, мне вот уже инетресно, что такого можно делать в скрипте, чтобы браузер подвисал...

Riim 08.05.2009 14:20

Цитата:

Сообщение от ZoNT
что такого можно делать в скрипте, чтобы браузер подвисал

сортировка большой (очень) таблицы.

генерация ColorMenu.

ZoNT 08.05.2009 14:40

Ну ведь сортировать можно так, что ничего висеть не будет! вот я и хочу посмотреть. чего ж там такого накодили, что всё висит...

Dagger 14.05.2009 09:54

ZoNT, Riim,
Большое спасибо за участие. Вы были правы - гораздо разумнее оптимизировать JavaScript-код, нежели городить виснущие прогресс-гифы. Ссылку на сайт дать не могу, так как это не сайт, а внутреннее приложение нашей конторы для HR-отдела.

Дело было вот в чем. Имеется сторонний продукт http://www.codethat.com/grid/, который мы используем в качестве Excel-подобной таблицы. При внесении данных в какую-либо ячейку необходимо пересчитать некоторые групповые значения (total'ы, cost'ы) и т.д. Чтобы этого добиться человек, поддерживавший это приложение до меня, в обработчик onclick ячейки вставил вызов своей функции типа calcTotal(). Эта функция, заканчивая пересчет для каждой ячейки итоговой суммы, просто перерисовывала весь грид, в котором (уже в моем случае) более 1000 ячеек. Проблема решилась отрисовкой только нужных ячеек, а не всего подряд. Ну и еще некоторые, не столь принципиальные моменты, тоже выкинул.

Очень в этом деле помогла консоль Firebug'а, а также его инспектор, благодаря которому удалость легко отыскать в простыне HTML'я нужные идентификаторы ячеек.

Кстати, очень интересную статью по поводу прогресс-баров нашел здесь:
http://webo.in/articles/habrahabr/13...ve-javascript/

Riim 14.05.2009 13:12

Цитата:

Сообщение от Dagger
Кстати, очень интересную статью по поводу прогресс-баров нашел здесь:

А я то искал ее. И на webo.in искал. А она сама нашлась.

Dagger 14.05.2009 14:02

Riim,
Я ее обнаружил чисто случайно, когда уже уверил себя в том, что информативные прогресс-бары средствами JS невозможны.


Часовой пояс GMT +3, время: 15:07.