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/

questionAnswers(11)

yourAnswerToTheQuestion