Pytanie img onload nie działa dobrze w IE7


Mam tag img w mojej aplikacji webapp, która używa programu obsługi onload do zmiany rozmiaru obrazu:

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

Działa to dobrze w Firefoksie 3, ale kończy się niepowodzeniem w IE7, ponieważ obiekt obrazu jest przekazywany do SizeImage() funkcja ma szerokość i wysokość 0 z jakiegoś powodu - może IE wywołuje funkcję zanim zakończy ładowanie ?. Podczas badania tego odkryłem, że inni ludzie mieli ten sam problem z IE. Odkryłem również, że nie jest to poprawny HTML 4. To jest nasz typ dokumentu, więc nie wiem, czy jest prawidłowy czy nie:

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

Czy istnieje rozsądne rozwiązanie do zmiany rozmiaru obrazu podczas jego ładowania, najlepiej zgodnego ze standardami? Obraz jest używany do przesłania przez użytkownika zdjęcia, które może mieć prawie dowolny rozmiar, a my chcemy wyświetlić go maksymalnie w rozmiarze 150x150. Jeśli twoim rozwiązaniem jest zmiana rozmiaru serwera po załadowaniu, wiem, że to poprawne rozwiązanie, ale nie mogę go wdrożyć :( To musi być zrobione po stronie klienta, i musi być zrobione na ekranie.

Dzięki.

Edytować: Ze względu na strukturę naszej aplikacji niepraktyczne (graniczące z niemożliwością) jest uruchomienie tego skryptu w jego pobraniu. Mogę rozsądnie edytować tag obrazu i kod w jego pobliżu (na przykład mogę dodać <script> tuż poniżej). Ponadto mamy już biblioteki Prototype i EXT JS ... zarządzanie wolałoby nie dodawać kolejnych (niektóre odpowiedzi sugerują jQuery). Jeśli można to rozwiązać za pomocą tych frameworków, byłoby świetnie.

Edytuj 2: Niestety, musimy obsługiwać przeglądarki Firefox 3, IE 6 i IE 7. Pożądane jest również wsparcie dla wszystkich przeglądarek opartych na Webkit, ale ponieważ nasza witryna obecnie ich nie obsługuje, możemy tolerować rozwiązania, które działają tylko w Big 3 .


14
2017-10-13 20:18


pochodzenie


Pytanie: czy SizeImage () po prostu zmienia rozmiar obrazu na 150x150? Mam różne rozwiązania, oba lepsze niż te poniżej, ale to zależy od tego, czego potrzebujesz do zrobienia SizeImage (). - Eric Nguyen
@Eric: nie, powinien zachować proporcje obrazu. Dodatkowo, jeśli oryginalny obraz jest mniejszy niż 150x150, w ogóle nie należy zmieniać rozmiaru (nie chcę rozciągać i obrazować). - rmeador


Odpowiedzi:


IE7 próbuje zmienić rozmiar obrazu przed pełnym renderowaniem drzewa DOM. Musisz uruchomić go na document.onload ... musisz tylko upewnić się, że twoja funkcja może obsłużyć przekazanie odniesienia do elementu, który nie jest "tym".

Alternatywnie ... i mam nadzieję, że to nie jest płomienny obraz ... jQuery robi takie rzeczy naprawdę, naprawdę łatwe.

EDYTUJ w odpowiedzi na EDYT 1:

Możesz włożyć document.onload(runFunction); w dowolnym znaczniku skryptu, w dowolnym miejscu w ciele. będzie nadal czekać, aż do załadowania dokumentu zostanie uruchomiona funkcja.


6
2017-10-13 20:23



zwykle próbuje zmodyfikować część domeny zanim jej załadowanie spowoduje dreaded wiadomość "operacja przerwana". - StingyJack
@Steve, jak to jest "naprawdę łatwe" z jQuery? Używam jQuery w moim projekcie, ale nie jest to wcale łatwiejsze! Dokumentacja jQuery zgadza się, że IE nie przetwarza onLoad poprawnie, nawet po zdarzeniu load jQuery / See połączyć - akapit "Ostrzeżenia o zdarzeniu obciążenia podczas używania z obrazami.". Użyłem jQuery, ale wciąż musiałem napisać cały długi kod do obsługi IE. - Fred


Jeśli nie musisz obsługiwać IE 6, możesz po prostu użyć tego CSS.

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

7
2017-10-13 20:34



To naprawdę dobry pomysł ... Nie wiedziałem nawet, że jest to dostępna opcja CSS. Niestety, musimy wspierać IE6. Zaktualizowałem pytanie, aby o tym wspomnieć. - rmeador
Oto jak obsługiwać IE6: <! - [if lt IE 7]> <style> yourImageSelector {width: expression (this.width> 150? 150: true); wysokość: wyrażenie (this.height> 150? 150: true); } </ style> <! [endif] -> - casey


Zauważyłem, że zarówno Firefox, jak i Safari uruchamiają zdarzenia "ładujące" na nowych obrazach bez względu na to, ale IE 6 i 7 tylko "ładują" ogień, jeśli faktycznie muszą pobrać obraz z serwera - nie robią tego, jeśli obraz jest już w lokalnej pamięci podręcznej. Grałem z dwoma rozwiązaniami:

1) Podaj obrazowi niepowtarzalny argument http za każdym razem, który serwer WWW ignoruje, np.

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

Ma to wadę, że faktycznie pokonuje buforowanie, więc marnujesz przepustowość. Ale może rozwiązać problem bez konieczności wkręcania JavaScriptu.

2) W mojej aplikacji obrazy wymagające procedur obsługi ładunków są wstawiane dynamicznie przez JavaScript. Zamiast tylko dołączać obraz, a następnie budować program obsługi, korzystam z tego kodu, który jest sprawdzony w Safari, FF i IE6 i 7.

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

Używam YUI (oczywiście), ale możesz załączyć handler'a używając tego, co działa w twojej strukturze. Funkcja doStuff spodziewa się działać z to dołączony do elementu IMG, którego dotyczy ten problem, dlatego nazywam go w .zastosować styl, twój przebieg może się różnić.


4
2017-12-11 19:26



Dziękuję bardzo za tę odpowiedź! Nigdy bym o tym nie pomyślał! - Igor Zinov'yev
Dziękuję Ci. Miał irytujące problemy z ładowarką zasobów w grze HTML5 ... (testowana wysokość> 0 zamiast kompletnej, ale sam pomysł) - Tangent 128


Kod jQuery. Łatwo jest jednak nawiązać połączenie z innymi frameworkami. Naprawdę pomocny.

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
}

3
2017-10-16 23:14





Sposób, w jaki bym to zrobił, to użycie jQuery do zrobienia czegoś takiego jak:

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

Ale nie jestem ekspertem od javascript;)


2
2017-10-13 20:25





setTimeout () może być obejściem, jeśli naprawdę utkniesz. Wystarczy ustawić go na 2 lub 3 sekundy - lub po załadowaniu strony.

EDYCJA: Możesz chcieć rzucić okiem Ten artykuł - cały czas na dole o wyciekach memów IE ...


1
2017-11-06 20:06





Edycja: ze względu na strukturę naszej aplikacji,   jest niepraktyczny (graniczący dalej)   niemożliwe), aby uruchomić ten skrypt w   załadowanie dokumentu.

Zawsze można dodać obsługę do window.onload (lub każde zdarzenie naprawdę), nawet jeśli inne frameworki, biblioteka lub kod dołączają do niego obsługę procedur.

<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>

Ta odpowiedź ma nieco inną wersję mojego addOnloadHandler() kod za pomocą attachEvent. Ale odkryłem to podczas testowania attachEvent Wydaje się, że nie gwarantuje to, że strażnicy strzelają w kolejności ich dodania, co może być ważne. Przedstawiona funkcja gwarantuje, że procedury obsługi są uruchamiane w kolejności dodania.

Zauważ, że mijam evt do dodanych programów obsługi zdarzeń. Nie jest to bezwzględnie konieczne i kod powinien działać bez niego, ale pracuję z biblioteką, która oczekuje, że zdarzenie zostanie przekazane do onload obsługi i ten kod nie działa, chyba że włączę go do mojej funkcji.


1
2018-05-04 19:58





Możesz zrobić coś takiego:

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

0
2018-06-14 08:51