2008-10-13 17 views
14

Ho un tag img nel mio webapp che utilizza il gestore onload per ridimensionare l'immagine:img onload non funziona bene in IE7

<img onLoad="SizeImage(this);" src="foo" > 

Questo funziona bene in Firefox 3, ma non riesce in IE7 perché il l'oggetto immagine passato alla funzione SizeImage() ha una larghezza e un'altezza pari a 0 per qualche motivo - forse IE chiama la funzione prima che finisca il caricamento ?. Nella ricerca di questo, ho scoperto che altre persone hanno avuto questo stesso problema con IE. Ho anche scoperto che questo non è valido HTML 4. Questo è il nostro DOCTYPE, quindi non so se è valido o meno:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

C'è una soluzione ragionevole per il ridimensionamento di un'immagine, come è caricato , preferibilmente uno che è conforme agli standard? L'immagine viene utilizzata per l'utente per caricare una foto di se stessi, che può essere quasi di qualsiasi dimensione, e vogliamo visualizzarla a un massimo di 150x150. Se la soluzione è di ridimensionare l'immagine lato server durante il caricamento, so che è la soluzione corretta, ma mi è vietato implementarla :(Deve essere fatta lato client, e deve essere eseguita in mostra.

. grazie

Edit: a causa della struttura della nostra applicazione, non è pratico (confinante con impossibile) per eseguire questo script in onload del documento posso solo ragionevolmente modificare il tag delle immagini e il codice vicino ad essa (per. istanza potrei aggiungere un <script> proprio sotto di esso.) Inoltre, abbiamo già librerie Prototype ed EXT JS ... la gestione preferirebbe non doverne aggiungere un'altra (alcune risposte hanno suggerito jQuery) .Se questo può essere risolto usando questi framework, sarebbe fantastico.

Edit 2: Purtroppo, dobbiamo sostenere Firefox 3, IE 6 e IE 7. È auspicabile per supportare tutti i browser basati su WebKit come pure, ma come il nostro sito attualmente non li supporta, possiamo tollerare soluzioni che funzionano solo in Big 3.

+0

Domanda: è SizeImage() semplicemente ridimensionando la l'immagine da 150x150? Ho soluzioni diverse, entrambe migliori di quelle sottostanti, ma dipende da cosa devi fare a SizeImage(). –

+0

@Eric: no, dovrebbe mantenere le proporzioni dell'immagine. Inoltre, se l'immagine originale è inferiore a 150x150, non si dovrebbe eseguire alcun ridimensionamento (non voglio mai allungare e immagine). – rmeador

risposta

6

IE7 sta tentando di ridimensionare l'immagine prima che l'albero DOM sia completamente renderizzato. Devi eseguirlo su document.onload ... dovrai solo assicurarti che la tua funzione possa gestire il passaggio di un riferimento all'elemento che non è "questo".

In alternativa ... e spero che non si tratti di un'offesa infiammabile ... jQuery rende queste cose davvero, davvero facili.

EDIT in risposta a MODIFICARE 1:

È possibile inserire document.onload(runFunction); in qualsiasi tag script, in qualsiasi parte del corpo. rimarrà ancora in attesa del caricamento del documento per eseguire la funzione.

+0

di solito cercando di modificare una porzione del dom prima del suo caricamento causerà il temuto messaggio "operazione annullata". – StingyJack

+0

@Steve, com'è "davvero facile" fare con jQuery?Sto usando jQuery nel mio progetto, ma non è più semplice! La documentazione di jQuery concorda sul fatto che IE non elabora correttamente il caricamento anche con l'evento di caricamento jQuery/Vedi [collegamento] (http://api.jquery.com/load-event/) - paragrafo "Avvertenze sull'evento di carico quando utilizzato con le immagini . ". Ho usato jQuery ma ho dovuto comunque scrivere un intero pezzo di codice per supportare IE. – Fred

2

Il modo in cui lo farei è quello di utilizzare jQuery per fare qualcosa di simile:

$(document).load(function(){ 
    // applies to all images, could be replaced 
    //by img.resize to resize all images with class="resize" 
    $('img').each(function(){ 
     // sizing code here 
    }); 
}); 

ma non sono un esperto di Javascript;)

7

Se non si dispone per supportare IE 6, puoi semplicemente usare questo CSS.

yourImageSelector { 
    max-width: 150px; 
    max-height: 150px; 
} 
+0

Questa è davvero una buona idea ... Non sapevo nemmeno che fosse un'opzione CSS disponibile. Sfortunatamente, dobbiamo supportare IE6. Ho aggiornato la domanda per dirlo. – rmeador

+4

Ecco come supportare IE6: casey

1

setTimeout() può essere una soluzione se sei davvero bloccato. Basta impostarlo per 2 o 3 secondi - o dopo che la pagina dovrebbe essere caricata.

MODIFICA: Si consiglia di dare un'occhiata a this article - completamente alla fine su IE mem leaks ...

4

Ho notato che Firefox e Safari attivano eventi di "caricamento" su nuove immagini indipendentemente da cosa, ma IE 6 & 7 si attiva solo "carica" ​​se in realtà devono ottenere l'immagine dal server. Se l'immagine è già nella cache locale. Ho giocato con due soluzioni:

1) dare l'immagine di un argomento unico http ogni volta, che il server Web ignora, come

<img src="mypicture.jpg?keepfresh=12345" /> 

Questo ha lo svantaggio che in realtà sconfigge la cache, quindi sei sprecare larghezza di banda. Ma potrebbe risolvere il problema senza dover rovinare il tuo JavaScript.

2) Nella mia app, le immagini che richiedono gestori di carico vengono inserite dinamicamente da JavaScript. Invece di limitarsi aggiungendo l'immagine, quindi la costruzione di un gestore, io uso questo codice, che viene testato bene in Safari, FF, e IE6 & 7.

document.body.appendChild(newPicture); 
if(newPicture.complete){ 
    doStuff.apply(newPicture); 
}else{ 
    YAHOO.util.Event.addListener(newPicture, "load", doStuff); 
} 

sto usando YUI (ovviamente), ma si può attache il gestore utilizza ciò che funziona nel tuo framework. La funzione doStuff si aspetta di eseguire con questo collegato all'elemento IMG interessato, ecco perché lo chiamo nello stile .apply, il tuo chilometraggio può variare.

+0

Grazie mille per questa risposta! Non avrei mai pensato a me stesso! –

+0

Grazie. Stavo avendo problemi irritanti con un caricatore di risorse in un gioco HTML5 ... (altezza testata> 0 invece di completare, ma la stessa idea) –

1

Edit: A causa della struttura della nostra applicazione, non è pratico (confinante con impossibile) per eseguire questo script in onload del documento .

E 'sempre possibile aggiungere gestori a window.onload (o qualsiasi evento davvero), anche se altri quadri, la biblioteca o il codice attribuisce i gestori a quell'evento.

<script type="text/javascript"> 
function addOnloadHandler(func) { 
    if (window.onload) { 
     var windowOnload = window.onload; 
     window.onload = function(evt) { 
      windowOnload(evt); 
      func(evt); 
     } 
    } else { 
     window.onload = function(evt) { 
      func(evt); 
     } 
    } 
} 

// attach a handler to window.onload as you normally might 
window.onload = function() { alert('Watch'); }; 

// demonstrate that you can now attach as many other handlers 
// to the onload event as you want 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('window.onload'); }); 
addOnloadHandler(function() { alert('runs'); }); 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('many'); }); 
addOnloadHandler(function() { alert('handlers'); }); 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('you'); }); 
addOnloadHandler(function() { alert('want.'); }); 
</script> 

This answer ha una versione leggermente diversa della mia addOnloadHandler() codice utilizzando attachEvent. Ma ho scoperto che il test attachEvent non sembra garantire che i gestori attivino l'ordine in cui li hai aggiunti, il che potrebbe essere importante. La funzione come presentata garantisce che i gestori vengono licenziati nell'ordine aggiunto.

Si noti che passaggio evt nei gestori di eventi aggiunti. Questo non è strettamente necessario e il codice dovrebbe funzionare senza di esso, ma lavoro con una libreria che si aspetta che l'evento venga passato al gestore onload e che il codice non funzioni a meno che non lo includa nella mia funzione.

3

Codice per jQuery. Ma è facile creare dial con altri framework. Davvero utile

var onload = function(){ /** your awesome onload method **/ }; 
var img = new Image(); 
img.src = 'test.png'; 

// IE 7 workarond 
if($.browser.version.substr(0,1) == 7){ 
    function testImg(){ 
     if(img.complete != null && img.complete == true){ 
      onload(); 
      return; 
     } 
     setTimeout(testImg, 1000); 
    } 
    setTimeout(testImg, 1000); 
}else{ 
    img.onload = onload 
} 
0

Si può fare qualcosa di simile:

var img = new Image(); 
img.src = '/output/preview_image.jpg' + '?' + Math.random(); 
img.onload = function() { 
    alert('pass') 
} 
Problemi correlati