img onload не очень хорошо работает в IE7 - PullRequest
14 голосов
/ 14 октября 2008

В моем веб-приложении есть тег img, который использует обработчик загрузки для изменения размера изображения:

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

Это прекрасно работает в Firefox 3, но не работает в IE7, потому что объект изображения, передаваемый в функцию SizeImage(), имеет ширину и высоту 0 по какой-то причине - может быть, IE вызывает функцию до того, как завершит загрузку? Исследуя это, я обнаружил, что у других людей была такая же проблема с IE. Я также обнаружил, что это недопустимый HTML 4. Это наш тип документа, поэтому я не знаю, действителен он или нет:

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

Существует ли разумное решение для изменения размера изображения по мере его загрузки, предпочтительно, которое соответствует стандартам? Изображение используется для того, чтобы пользователь мог загрузить свою фотографию, которая может быть практически любого размера, и мы хотим, чтобы она отображалась с максимальным размером 150x150. Если ваше решение заключается в изменении размера изображения на стороне сервера при загрузке, я знаю, что это правильное решение, но мне запрещено его применять :( Это должно быть сделано на стороне клиента, и это должно быть сделано на дисплее.

Спасибо.

Редактировать : Из-за структуры нашего приложения нецелесообразно (граничит с невозможным) запускать этот сценарий при загрузке документа. Я могу только разумно редактировать тег изображения и код рядом с ним (например, я могу добавить <script> прямо под ним). Кроме того, у нас уже есть библиотеки Prototype и EXT JS ... руководство предпочло бы не добавлять другую (в некоторых ответах предлагается jQuery). Если это можно решить с помощью этих структур, это было бы здорово.

Редактировать 2 : К сожалению, мы должны поддерживать Firefox 3, IE 6 и IE 7. Желательно также поддерживать все браузеры на основе Webkit, но наш сайт в настоящее время их не поддерживает, мы можем терпеть решения, которые работают только в Большой 3.

Ответы [ 8 ]

7 голосов
/ 14 октября 2008

Если вам не нужно поддерживать IE 6, вы можете просто использовать этот CSS.

yourImageSelector {
    max-width: 150px;
    max-height: 150px;
}
6 голосов
/ 14 октября 2008

IE7 пытается изменить размер изображения до полной визуализации дерева DOM. Вам нужно запустить его на document.onload ... вам просто нужно убедиться, что ваша функция может обрабатывать передаваемую ссылку на элемент, который не является "this".

В качестве альтернативы ... и я надеюсь, что это не огненное преступление ... jQuery делает такие вещи действительно очень легкими.

РЕДАКТИРОВАТЬ в ответ на РЕДАКТИРОВАНИЕ 1:

Вы можете поместить document.onload(runFunction); в любой тег сценария в любом месте тела. он все еще будет ждать загрузки документа для запуска функции.

4 голосов
/ 11 декабря 2008

Я заметил, что Firefox и Safari запускают события «загрузки» на новых изображениях, несмотря ни на что, но IE 6 и 7 запускают «загрузку» только в том случае, если им действительно нужно получить изображение с сервера - они этого не делают, если изображение уже находится в локальном кэше. Я играл с двумя решениями:

1) Каждый раз присваивайте изображению уникальный аргумент http, который веб-сервер игнорирует, например

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

У этого недостатка есть то, что он на самом деле побеждает кеширование, поэтому вы тратите трафик. Но это может решить проблему, не прибегая к помощи вашего JavaScript.

2) В моем приложении изображения, для которых нужны обработчики загрузки, динамически вставляются с помощью JavaScript. Вместо того, чтобы просто добавлять изображение, а затем создавать обработчик, я использую этот код, который хорошо протестирован в Safari, FF и IE6 & 7.

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

Я использую YUI (очевидно), но вы можете прикрепить обработчик, используя все, что работает в вашей среде. Ожидается, что функция doStuff будет работать с этим , подключенным к соответствующему элементу IMG, поэтому я называю это в стиле .apply , ваш пробег может отличаться.

3 голосов
/ 17 октября 2009

код для jQuery. Но это легко сделать с помощью других рамок. Действительно полезно.

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
}
2 голосов
/ 14 октября 2008

Я бы использовал jQuery, чтобы сделать что-то вроде:

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

Но я не эксперт по JavaScript;)

1 голос
/ 04 мая 2009

Редактировать: из-за структуры нашего приложения, это нецелесообразно (граничит с невозможно) запустить этот скрипт в загрузка документа.

Всегда можно добавить обработчики к window.onload (или любому другому событию), даже если другие инфраструктуры, библиотеки или код присоединяют обработчики к этому событию.

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

Этот ответ имеет немного другую версию моего addOnloadHandler() кода с использованием attachEvent. Но в ходе тестирования я обнаружил, что attachEvent не гарантирует, что обработчики сработают в том порядке, в котором вы их добавили, что может быть важно. Представленная функция гарантирует запуск обработчиков в добавленном порядке.

Обратите внимание, что я передаю evt в добавленные обработчики событий. Это не является строго необходимым, и код должен работать без него, но я работаю с библиотекой, которая ожидает, что событие будет передано обработчику onload, и этот код завершится ошибкой, если я не включу его в свою функцию.

1 голос
/ 06 ноября 2008

setTimeout () может быть временным решением, если вы действительно застряли. Просто установите его на 2 или 3 секунды - или после загрузки страницы.

РЕДАКТИРОВАТЬ: Возможно, вы захотите взглянуть на эту статью - полностью внизу о утечках памяти IE ...

0 голосов
/ 14 июня 2012

Вы можете сделать что-то вроде:

var img = new Image();
img.src = '/output/preview_image.jpg' + '?' + Math.random();
img.onload = function() {
  alert('pass')
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...