Actualización de DOM en función de ejecución larga

Tengo un botón que ejecuta una función de larga ejecución cuando se hace clic. Ahora, mientras se ejecuta la función, quiero cambiar el texto del botón, pero tengo problemas en algunos navegadores como 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";
}

Ahora esto tiene problemas en Firefox e IE, (en Chrome funciona bien)

Así que pensé ponerlo en un 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);
}

¡Pero esto tampoco funciona para Firefox! el botón se deshabilita, cambia de color (debido a la aplicación del nuevo css) pero el texto no cambia.

Tengo que configurar el tiempo en 50 ms en lugar de solo 0 ms para que funcione (cambiar el texto del botón). Ahora encuentro esto al menos estúpido. Puedo entender si funcionaría con solo un retraso de 0 ms, pero ¿qué pasaría en una computadora más lenta? ¿Quizás Firefox necesitaría 100ms allí en el settimeout? suena bastante estúpido Lo intenté muchas veces, 1 ms, 10 ms, 20 ms ... no, no se actualizará. Solo con 50ms.

Así que seguí los consejos en este tema:

Forzar una actualización de DOM en Internet explorer después de la manipulación de dom de javascript

así que intenté:

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";
}

pero no funciona (FIREFOX 21). Entonces intenté:

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

Incluso probé clientHeight en lugar de offsetTop pero nada. el DOM no se actualiza.

¿Alguien puede ofrecer una solución confiable, preferiblemente no hacky?

¡gracias por adelantado!

como se sugiere aquí también lo intenté

$('#parentOfElementToBeRedrawn').hide().show();

en vano

Forzar DOM redibujar / actualizar en Chrome / Mac

TL; DR:

en busca de un método de navegador cruzado CONFIABLE para tener una actualización de DOM forzada SIN el uso de setTimeout (la solución preferida debido a los diferentes intervalos de tiempo necesarios según el tipo de código de ejecución prolongada, el navegador, la velocidad de la computadora y setTimeout requiere de 50 a 100 ms en situación)

jsfiddlehttp://jsfiddle.net/WsmUh/5/

Respuestas a la pregunta(11)

Su respuesta a la pregunta