domingo, 26 de agosto de 2007

Microsoft Internet Explorer - Bug de cache em imagens dinâmicas

Sempre que se desenvolve uma aplicação Ajax existe a preocupação da funcionalidade CrossBrowser.

O Internet Explorer tem um problema sério com criação de imagens dinâmicas. Ao criar elementos img, seja por innerHTML ou DOM (createElement, appendChild), o Internet Explorer esquece de verificar em seu cache local a presença da imagem, fazendo um GET ao servidor para cada elas.

Ou seja, se você carregar uma árvore dinâmica por Ajax, cheia de ícones de pastas, o Internet Explorer demorará a uma eternidade para renderizar tudo.

A Microsoft descreve esse problema, segundo eles "by design". (ótimo)
http://support.microsoft.com/?scid=kb%3Ben-us%3B319546&x=8&y=8

A solução, apesar de extremamente deselegante, é simples:

Faça um preload de TODAS as imagens à serem criadas dinamicamente, através de uma DIV com display none:






Depois, dê um tempo para o Internet Explorer fazer o cache das imagens, daí sim proceda com a criação das tags dinâmicas:

window.setTimeout('addImgs()', 1000);

O grande problema aqui é que o timeout sempre terá que ser maior do que o tempo que o cliente levará para baixar as imagens, e como cada um tem uma conexão diferente, você obrigatoriamente terá que prejudicar os mais rápidos...

3 comentários:

Phenøm disse...

Creio que você também pode fazer isso de forma automática com o new Image(). Depois basta adicionar uma checagem do carregamento com o onload e acionar sua função addImgs() após todas serem carregados.

André Cupini disse...
Este comentário foi removido pelo autor.
André Cupini disse...

A sugestão do Phenom funcionou perfeitamente.
Receita do bolo:
- Div, com várias tags "img" dentro.
- Javascript:
var contador_img = 0;
var preload_imgs = document.getElementById("div_com_as_imagens").getElementsByTagName("img");
var total_img = preload_imgs.length;
for (var i = 0; i < total_img; i++) {
preload_imgs[i].onLoad = countImgs();
}

function countImgs() {
contador_img++;
if (contador_img == total_img) {
addImgs();
}
}