2009-09-09 12 views
24

Aquí está la situación. Tengo algo de JavaScript que tiene este aspecto:Forzar una actualización de DOM en Internet Explorer después de la manipulación de JavaScript ja

function onSubmit() { 
    doSomeStuff(); 
    someSpan.style.display="block"; 
    otherSpan.style.display="none"; 
    return doLongRunningOperation; 
} 

Cuando hago esta forma presentar la acción, y ejecutarlo desde un navegador que no sea Internet Explorer, se intercambia rápidamente la visibilidad dos vanos y ejecutar la operación a largo Javascript. Si hago esto en IE, no hace el intercambio hasta después de que onSubmit() vuelva completamente.

puedo forzar un dom redibujar por pegar un cuadro de alerta de este modo:

function onSubmit() { 
    doSomeStuff(); 
    someSpan.style.display="block"; 
    otherSpan.style.display="none"; 
    alert("refresh forced"); 
    return doLongRunningOperation; 
} 

Además, la refactorización jQuery obvio no afecta el comportamiento de IE:

function onSubmit() { 
    doSomeStuff(); 
    $("#someSpan").show(); 
    $("#otherSpan").hide(); 
    return doLongRunningOperation; 
} 

Este comportamiento existe en IE8 e IE6. ¿Hay alguna forma de forzar un redibujado del DOM en estos navegadores?

+0

En primer lugar, ¿qué haces en el longRunningOperation? –

+0

¿Ha intentado mover la visibilidad alternando a su propia función? – seth

+0

longRunningOperation está haciendo la validación del formulario. La forma es grande en un pequeño subconjunto de casos. –

Respuesta

2

Puede su longRunningOperation ser llamado de forma asíncrona?

+1

Terminaste teniendo razón, pero con algo de trabajo. Llamé a la operación de larga ejecución de forma asíncrona, hice que mi evento de envío fuera falso, y luego el evento asíncrono realmente envía mi formulario. Esto condujo a un comportamiento adecuado en todos los navegadores, pero requirió mucho trabajo y se siente algo pesado. –

+1

Puede parecer complicado, pero el mejor diseño del lado del cliente de su aplicación será el que mantenga el navegador en buen estado. Cuando inicie procesos de ejecución larga, bloqueará el navegador (¡NO! Grande) por lo que es mejor dedicar el tiempo a diseñar cómo administrar las operaciones asincrónicas. De todos modos ... ¡diviértete! – misteraidan

17

Mozilla (tal vez IE también) almacenará en caché/retrasará la ejecución de cambios en el DOM que afectan la visualización, para que pueda calcular todos los cambios a la vez en lugar de repetidamente después de cada instrucción.

Para forzar una actualización (para forzar un reflujo o retransmisión síncrono inmediato), su javascript debería leer una propiedad que se ve afectada por el cambio, p. la ubicación de algunosSpan y otrosSpan.

(Este detalle de implementación de Mozilla se menciona en el video Faster HTML and CSS: Layout Engine Internals for Web Developers.)

+0

interesante. no sabía esto –

+0

Voy a probar eso en la mañana. –

+0

Intenté esto, pero no pude hacerlo funcionar. –

3

También puede ajustar su función a largo plazo en setTimeout (function() {longTerm();}, 1);

6

Para continuar con lo que dice ChrisW:

Aquí está el lavado de la escritura a parpadear DOM, por lo que no tiene que alerta de llamada (""); (Que se encuentra en http://amolnw.wordpress.com/category/programming/javascript/):

function flushThis(id){ 
    var msie = 'Microsoft Internet Explorer'; 
    var tmp = 0; 
    var elementOnShow = document.getElementById(id); 
    if (navigator.appName == msie){ 
     tmp = elementOnShow.parentNode.offsetTop + 'px'; 
    }else{ 
     tmp = elementOnShow.offsetTop; 
    } 
} 

Funciona para mí !!! Gracias por la sugerencia.

5

Tuve este problema en Chrome 21 arrastrando una palabra que tenía una letra con un descendiente ('g'). Estaba dejando un rastro de polilla en la pantalla, que desaparecería la próxima vez que algo refrescara la pantalla. La solución de ChrisW (interrogar a una propiedad sensible al diseño) no funcionó.

Lo que hizo el trabajo era añadir un div en blanco de 1 píxel en la parte superior de la página, luego lo elimina una milésima de segundo después, llamando a la raíz de la función al final de la operación de arrastre:

// Needed by Chrome, as of Release 21. Triggers a screen refresh, removing drag garbage. 
function cleanDisplay() { 
    var c = document.createElement('div'); 
    c.innerHTML = 'x'; 
    c.style.visibility = 'hidden'; 
    c.style.height = '1px'; 
    document.body.insertBefore(c, document.body.firstChild); 
    window.setTimeout(function() {document.body.removeChild(c)}, 1); 
} 

Nota: necesita la demora. Simplemente agregando y eliminando el div no funciona. Además, el div debe agregarse encima de la parte de la página que debe volver a dibujarse.

+0

¿Era mejor esta solución que simplemente llamar a la función de forma asíncrona como yo lo hice? –

+0

Tuve un problema con una actualización de pantalla en IE10 y esto hizo el truco, a diferencia de los otros. –

+1

IE8 aquí. Esta es la única solución que funcionó para mí. Gracias. –

1

element.focus() funciona para mí en IE10

function displayOnOff(){ 
    var elm = document.getElementById("myDiv"); 
    elm.style.display="block"; 
    elm.focus(); 
    for(var i=0; i<1000000; i++){ 
     console.log("waiting..............."); 
    } 
    elm.style.display = "none"; 
} 
Cuestiones relacionadas