Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 06.05.2009, 15:12
Новичок на форуме
Отправить личное сообщение для Dagger Посмотреть профиль Найти все сообщения от Dagger
 
Регистрация: 06.05.2009
Сообщений: 8

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 нет.

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

Последний раз редактировалось Dagger, 06.05.2009 в 15:15.
Ответить с цитированием
  #2 (permalink)  
Старый 06.05.2009, 15:15
Флудер
Отправить личное сообщение для ZoNT Посмотреть профиль Найти все сообщения от ZoNT
 
Регистрация: 25.07.2008
Сообщений: 1,271

я бы предложил тебе привести сюда код функции doStretch, и мы бы помогли тебе её оптимизировать, чтобы она выполнялась быстро.
Ответить с цитированием
  #3 (permalink)  
Старый 06.05.2009, 15:24
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Браузер все равно будет зависать, и никакого анимированного гифа все равно не будет видно.
Ответить с цитированием
  #4 (permalink)  
Старый 06.05.2009, 15:26
Новичок на форуме
Отправить личное сообщение для Dagger Посмотреть профиль Найти все сообщения от Dagger
 
Регистрация: 06.05.2009
Сообщений: 8

Проблема в том, что у меня используется тулзовина (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();
}
Ответить с цитированием
  #5 (permalink)  
Старый 06.05.2009, 15:26
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

?
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";
  }
Ответить с цитированием
  #6 (permalink)  
Старый 06.05.2009, 15:27
Новичок на форуме
Отправить личное сообщение для Dagger Посмотреть профиль Найти все сообщения от Dagger
 
Регистрация: 06.05.2009
Сообщений: 8

Неужели нет никакого способа отрисовать progress bar?
Ответить с цитированием
  #7 (permalink)  
Старый 06.05.2009, 15:30
Новичок на форуме
Отправить личное сообщение для Dagger Посмотреть профиль Найти все сообщения от Dagger
 
Регистрация: 06.05.2009
Сообщений: 8

Gvozd,
Большое спасибо! Действительно, это помогло.
Ответить с цитированием
  #8 (permalink)  
Старый 06.05.2009, 16:15
Флудер
Отправить личное сообщение для ZoNT Посмотреть профиль Найти все сообщения от ZoNT
 
Регистрация: 25.07.2008
Сообщений: 1,271

Судя по коду функции торомоза складываются в цикле из-за медленой функции (либо Undef, либо setData). Надо попрофилировать выполнение да посмотреть, что тормозит...
Ответить с цитированием
  #9 (permalink)  
Старый 06.05.2009, 16:34
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Firebug и console вам в помощь:
console.time(name)
console.timeEnd(name)
Ответить с цитированием
  #10 (permalink)  
Старый 06.05.2009, 16:41
Флудер
Отправить личное сообщение для ZoNT Посмотреть профиль Найти все сообщения от ZoNT
 
Регистрация: 25.07.2008
Сообщений: 1,271

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



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Самая лучшая книга по JS? ulandj Оффтопик 2 06.04.2009 11:35
"Классический" ООП в JavaScript Андрей Параничев Общие вопросы Javascript 67 25.03.2009 18:33
Js для переключения картинок Konstantin2009 Ваши сайты и скрипты 1 10.02.2009 00:41
JS'ом поменять textDecoration только для случаев link и visited lancer Элементы интерфейса 3 05.04.2008 20:51