Обработка JavaScript событий при загрузке изображения

27.12.2009 00:10 Автор 
Оцените материал
(1 Голосовать)

Любая страница и DOM-элемент на ней могут инициировать различные события. И работа JavaScript приложения это своего рода ответная реакция на те события, которые происходят на странице.

Я не буду углубляться в суть этого процесса, как происходит взаимодействие элементов на сайте и JavaScript-сценария и т.д. Я лишь хочу в этой статье показать какие трудности могут возникнуть при разработке JavsScript-приложения во взаимодействии с объектом Image. Ну а сначала немного теории, чтобы было понятно что к чему.

Как вы уже знаете элемент или тег <img> является своего рода контейнером для вставки изображения на странице. Подобно любому HTML-элементу, тег <img> является частью модели DOM и потому им можно управлять, как и любым другим элементом документа. Изображения были одним из первых управляемых HTML-элементов, и модель DOM позволяет обращаться к ним посредством массива images[] объекта Document. Каждый элемент данного массива – это объект Image, представляющий свой тег <img> в документе. Каждый из объектов Image поддерживает три обработчика:

  1. onLoad — вызывается, когда произошла загрузка изображения;
  2. onError — вызывается в случае ошибки в процессе загрузки изображения (например, когда URL-адрес ссылается на поврежденный файл изображения);
  3. onAbort — вызывается, когда пользователь отменяет загрузку изображения (например, щелкнув на кнопке Остановить в браузере) до того, как она завершится.

Каждый объект Image обладает также свойством complete. В этом свойстве находится значение false, пока изображение не загружено; оно изменяется на true, когда изображение полностью загружается или когда браузер останавливается при попытке загрузить изображение. Другими словами, свойство complete получает значение true только после того, как будет вызван один из трех обработчиков событий.

Другие свойства объекта Image являются просто отражениями атрибутов тега <img>: src, height, width, alt, title, border. В современных браузерах эти свойства доступны и для чтения, и для записи, а потому могут использоваться JavaScript-сценариями для динамического изменения размеров изображения, заставляя браузер растягивать или сжимать картнку.

А сейчас перейдем к сути проблемы и к тому, что меня сподвигло к написанию данной статьи. Передо мной стояла следующая задача: нужно было динамически отображать в заданном поле нужное изображение в зависимости от выбранного значения нисподающего списка (элемента select). Другими словами повесить обработчик на событие onChange. Задача тривиальная и решается достаточно просто:

 
<script language="JavaScript" type="text/javascript">
function changeImage(value){
  var selectObj = document.getElementById('select01');
  var imageObj = document.getElementById('image01');
 
  switch(value) {
    case '1':
      imageObj.src = "zima.jpg";
      break;
    case '2':
      imageObj.src = "zakat.jpg";
      break;
    case '3':
      imageObj.src = "holmy.jpg";
      break;
  }  
}
</script>
 
 
<select id="select01" onchange="changeImage(this.options[this.selectedIndex].value)"> 
  <option selected="selected" value="1">Zima</option> 
  <option value="2">Zakat</option> 
  <option value="3">Holmy</option> 
</select>
 
<img id="image01" src="zima.jpg" />
 

Необходимо сделать так, что если изображение отсутствует, то нужно вывести изображение noimage.jpg. Данная задача решается достаточно просто средствами php, так как он находится на стороне сервера. Но мне не хотелось прибегать к его помощи, поэтому хотелось решить используя только JavaScript код. Вот здесь я как раз и вспомнил о таком чудесном событии как onError.

Как уже говорилось выше данное событие возникает в случае ошибки загрузки изображения, в нашем случае это отсутсвие изображения. Код будет выглядеть следующим образом:

 
<script language="JavaScript" type="text/javascript">
function setNoImage() {
  var imageObj = document.getElementById('image01');
  imageObj.src = "noimage.jpg";
}
 
function changeImage(value){
  var selectObj = document.getElementById('select01');
  var imageObj = document.getElementById('image01');
 
  switch(value) {
    case '1':
      imageObj.src = "zima.jpg";
      break;
    case '2':
      imageObj.src = "zakat.jpg";
      break;
    case '3':
      imageObj.src = "holmy.jpg";
      break;
  }  
}
</script>
 
 
<select id="select01" onchange="changeImage(this.options[this.selectedIndex].value)"> 
  <option selected="selected" value="1">Zima</option> 
  <option value="2">Zakat</option> 
  <option value="3">Holmy</option> 
</select>
 
<img id="image01" src="zima.jpg" onerror="setNoImage()" />
 

Удаляем для примера одно из изображений — выводится картинка noimage.jpg. Все прекрасно — данный код работает во всех современных браузерах включая Internet Explorer 6, но только не в Opera!.. В ней событие onerror срабатывает только один раз при первой загрузке изображения. При последующих обращениях к изображению данное событие игнорируется. Похоже Opera не считает обязательным по несколько раз обрабатывать один и тот же ошибочный адрес.

Но нужно доводить задумку с отсутсвующими изображениями до конца, не дело так все оставлять. Немного погуглив я так и не нашел вразумительного ответа на данный вопрос — почему так происходит. Поэтому решил немного схитрить — выводить адреса изображений с каким нибудь рандомным значением по типу:

 
"zima.jpg?rand=" + Math.random();
"zakat.jpg?rand=" + Math.random();
"holmy.jpg?rand=" + Math.random();
 

Запускаем, смотрим — все отлично работает, теперь событие onerror обрабатывается столько, сколько нужно. Единственный минус такого подхода — забивается кэш браузера, так как url изображения будет всегда различный. Чтобы этого не происходило — делаем проверку браузера. Если у пользователя Opera — выводим как было описано выше, если используется другой обозреватель — делаем обычный вывод изображения.

Авторизуйтесь, чтобы получить возможность оставлять комментарии