У меня есть тег 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.
@Eric: нет, он должен сохранять соотношение сторон изображения. Кроме того, если исходное изображение меньше 150x150, изменять размер вообще не нужно (я никогда не хочу растягивать и изображать).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


IE7 пытается изменить размер изображения до того, как дерево DOM будет полностью отрисовано. Вам нужно запустить его на document.onload ... вам просто нужно убедиться, что ваша функция может обрабатывать передачу ссылки на элемент, который не является «this».
В качестве альтернативы ... и я надеюсь, что это не является неприкрытым преступлением ... jQuery делает подобные вещи действительно очень простыми.
ИЗМЕНИТЬ в ответ на РЕДАКТИРОВАТЬ 1:
Вы можете поместить document.onload(runFunction); в любой тег скрипта в любом месте тела. он все равно будет ждать загрузки документа, чтобы запустить функцию.
обычно попытка изменить часть dom до его загрузки вызывает ужасное сообщение «операция прервана».
@ Стив, как «действительно легко» работать с jQuery? Я использую jQuery в своем проекте, но это отнюдь не проще! Документация jQuery соглашается с тем, что IE не обрабатывает onLoad правильно даже с событием загрузки jQuery / См. связь - параграф «Предостережения относительно события загрузки при использовании с изображениями». Я использовал jQuery, но мне все же пришлось написать целый длинный фрагмент кода для поддержки IE.
Я бы сделал это с помощью 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. Я обновил вопрос, чтобы упомянуть об этом.
Вот как поддерживать IE6: <! - [if lt IE 7]> <style> yourImageSelector {width: expression (this.width> 150? 150: true); height: выражение (this.height> 150? 150: true); } </style> <! [endif] ->
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, поэтому я называю ее в стиле .применять, ваш пробег может отличаться.
Большое спасибо за этот ответ! Я бы никогда не подумал об этом сам!
Спасибо. Возникли раздражающие проблемы с загрузчиком ресурсов в игре HTML5 ... (проверенная высота> 0 вместо полной, но та же идея)
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')
}
Вопрос: SizeImage () просто изменяет размер изображения до 150x150? У меня есть разные решения, оба лучше, чем приведенные ниже, но это зависит от того, что вам нужно для SizeImage ().