Atualização do DOM na função de longa duração
Eu tenho um botão que executa uma função de longa duração quando é clicado. Agora, enquanto a função está em execução, eu quero mudar o texto do botão, mas estou tendo problemas em alguns navegadores como o Firefox, IE.
html:
<button id="mybutt" class="buttonEnabled" onclick="longrunningfunction();"><span id="myspan">do some work</span></button>
javascript:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
//long running task here
document.getElementById("myspan").innerHTML = "done";
}
Agora isso tem problemas no Firefox e no IE, (no chrome funciona ok)
Então eu pensei em colocá-lo em um settimeout:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
setTimeout(function() {
//long running task here
document.getElementById("myspan").innerHTML = "done";
}, 0);
}
mas isso não funciona para o firefox! o botão fica desabilitado, muda de cor (devido à aplicação do novo css), mas o texto não muda.
Eu tenho que definir o tempo para 50ms em vez de apenas 0ms, a fim de fazê-lo funcionar (alterar o texto do botão). Agora eu acho isso estúpido pelo menos. Eu posso entender se funcionaria com apenas 0ms de atraso, mas o que aconteceria em um computador mais lento? talvez o firefox precisaria de 100ms no settimeout? soa bastante estúpido. Eu tentei muitas vezes, 1ms, 10ms, 20ms ... não, não vai atualizá-lo. apenas com 50ms.
Então eu segui o conselho neste tópico:
Forçando uma atualização DOM no Internet Explorer após a manipulação do javascript dom
então eu tentei:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
var a = document.getElementById("mybutt").offsetTop; //force refresh
//long running task here
document.getElementById("myspan").innerHTML = "done";
}
mas não funciona (FIREFOX 21). Então eu tentei:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
var a = document.getElementById("mybutt").offsetTop; //force refresh
var b = document.getElementById("myspan").offsetTop; //force refresh
var c = document.getElementById("mybutt").clientHeight; //force refresh
var d = document.getElementById("myspan").clientHeight; //force refresh
setTimeout(function() {
//long running task here
document.getElementById("myspan").innerHTML = "done";
}, 0);
}
Eu até tentei clientHeight em vez de offsetTop mas nada. o DOM não é atualizado.
Alguém pode oferecer uma solução confiável, preferivelmente não-hacky?
desde já, obrigado!
como sugerido aqui eu também tentei
$('#parentOfElementToBeRedrawn').hide().show();
sem sucesso
Forçar redesenho / atualização de DOM no Chrome / Mac
TL; DR:
procurando por um método cross-browser CONFIÁVEL para ter uma atualização DOM forçada sem o uso de setTimeout (solução preferida devido a diferentes intervalos de tempo necessários dependendo do tipo de código de execução longa, navegador, velocidade do computador e setTimeout requer de 50 a 100ms dependendo na situação)
jsfiddle:http://jsfiddle.net/WsmUh/5/