Img onload не работает в IE7

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

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

Вопрос: SizeImage () просто изменяет размер изображения до 150x150? У меня есть разные решения, оба лучше, чем приведенные ниже, но это зависит от того, что вам нужно для SizeImage ().

Eric Nguyen 09.10.2009 11:09

@Eric: нет, он должен сохранять соотношение сторон изображения. Кроме того, если исходное изображение меньше 150x150, изменять размер вообще не нужно (я никогда не хочу растягивать и изображать).

rmeador 09.10.2009 20:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
14
2
29 866
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Ответ принят как подходящий

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

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

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

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

обычно попытка изменить часть dom до его загрузки вызывает ужасное сообщение «операция прервана».

StingyJack 06.11.2008 23:02

@ Стив, как «действительно легко» работать с jQuery? Я использую jQuery в своем проекте, но это отнюдь не проще! Документация jQuery соглашается с тем, что IE не обрабатывает onLoad правильно даже с событием загрузки jQuery / См. связь - параграф «Предостережения относительно события загрузки при использовании с изображениями». Я использовал jQuery, но мне все же пришлось написать целый длинный фрагмент кода для поддержки IE.

Fred 28.03.2012 21:38

Я бы сделал это с помощью 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;)

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

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

Это действительно хорошая идея ... Я даже не знал, что это доступный вариант CSS. К сожалению, нам нужна поддержка IE6. Я обновил вопрос, чтобы упомянуть об этом.

rmeador 14.10.2008 00:39

Вот как поддерживать IE6: <! - [if lt IE 7]> <style> yourImageSelector {width: expression (this.width> 150? 150: true); height: выражение (this.height> 150? 150: true); } </style> <! [endif] ->

outcassed 03.04.2010 07:31

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

Обновлено: вы можете взглянуть на эта статья - полностью внизу об утечках памяти IE ...

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

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, поэтому я называю ее в стиле .применять, ваш пробег может отличаться.

Большое спасибо за этот ответ! Я бы никогда не подумал об этом сам!

Igor Zinov'yev 01.04.2010 16:02

Спасибо. Возникли раздражающие проблемы с загрузчиком ресурсов в игре HTML5 ... (проверенная высота> 0 вместо полной, но та же идея)

Tangent 128 26.02.2012 10:58

Edit: Due to the structure of our app, it is impractical (bordering on impossible) to run this script in the document's onload.

Всегда можно добавить обработчики к 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, и этот код не работает, если я не включу его в свою функцию.

Код для 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
}

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

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

Другие вопросы по теме