14. Обработка событий

Модель событий IE5+

Иллюстрация с сайта www.oszone.net

Иллюстрация с сайта www.oszone.net

Через IE5+ обозначены браузеры фирмы Microsoft от версии 5.0 и выше.

Когда модель W3C была стандартизована и ее поддержка реализована в браузерах, Microsoft, как обычно, снова пошла своим путем, создав собственную модель (назовем ее условно модель IE5+) и дополнительную головную боль web-разработчикам.

Про то, что объект Event в браузерах IE не передается в обработчик, а является глобальным свойством window.event, мы уже говорили, описывая модель уровня 0. Говорили также о разнице в способах, реализующих прерывание распространения события и отмены обработки события по умолчанию.

Все эти отличия (и рассмотренные способы борьбы с ними) остаются в силе и в рамках моделей W3C/IE5+.

Рассмотрим теперь, как регистрируются обработчики в модели IE5+.

В IE5 и более поздних версиях (по крайней мере, по IE-7 включительно) обработчики регистрируются методом attachEvent, а удаляются методом detachEvent. Ниже описаны форматы этих методов (они принадлежат интерфейсам Element и Document в моделе IE5+).

attachEvent(eventType, listener)

Аргументы:

  • eventType — строка, тип события, для которого будет вызываться обработчик. Тип события совпадает с именем событийного свойства или атрибута ранней модели DOM (с префиксом «on»). Например, "onclick", "onmouseover", "onmouseout".
  • listener — ссылка на функцию-обработчик. Функция вызывается без аргументов (то есть объект Event в неё не передается). Кроме того, функция вызывается в контексте глобального объекта window, следовательно, ключевое слово this в обработчике связано с window, а не с объектом, к которому обработчик привязан.
detachEvent(eventType, listener)

Метод удаляет указанную функцию-обработчик события. Аргументы должны иметь те же значения, что и при вызове метода attachEvent.

Вероятно, вы обратили внимание, что среди аргументов методов attachEvent и detachEvent отсутствует аргумент useCupture. Можно считать, что он всегда равен false, ибо в модели IE5+ реализована только фаза всплытия, а фаза захвата отсутствует.

Как быть, если желательно (а это желательно практически всегда) чтобы наше приложение работало во всех браузерах?

Приходится, либо работать только с моделью уровня 0, либо регистрировать обработчики с ветвлением, которое проверяет функциональные возможности браузера. Что-то вроде такого кода:


if (element.addEventListener) // Если работает модель DOM W3C
{
   element.addEventListener(...);
   element.addEventListener(...);
   ...
}
else if (element.attachEvent) // Если работает модель IE5+ 
{
   element.attachEvent(...);
   element.attachEvent(...);
   ...
}   
else // Старый браузер, такой как IE4  
{
 ...
 Либо проигнорировать старый браузер,
 либо зарегистрировать обрабочики, как 
 свойства объекта element 
 ...
}

Как уже отмечалось, модель IE5+ не реализует фазу захвата события. Иногда это может оказаться критично, например, в задаче о перетаскивании элемента по экрану. Элемент может не поспеть за движением мыши, выйти из-под неё, и, следовательно, перестать реагировать на событие mousemove. Чтобы этого не случилось, нужно «ловить» событие на фазе захвата, к какому бы элементу оно не спускалось от корня.

В модели IE5+ фаза захвата не реализована, и Microsoft была вынуждена добавить в интерфейсы Element и Document два метода — setCapture и relaseCapture.

setCapture()
После вызова этого метода события мыши направляются к элементу, который метод вызвал, и он будет эти события захватывать, даже в том случае, когда сам не является источником этих событий.
relaseCapture()
Этот метод отменяет действие метода setCapture, и события распространяются обычным способом.

В большинстве случаев метод setCapture вызывается в ответ на событие mousedown, что гарантирует получение событий мыши тем же самым элементом (в контексте которого метод был вызван). Элемент выполняет действия по перетаскиванию в ответ на событие mousemove и вызывает метод relaseCapture в ответ на событие mouseup.

Захват событий мыши, организованный методом setCapture может быть прерван, если браузер теряет фокус ввода, вызывает модальное окно alert или открывает системное меню. В подобных случаях генерируется событие losecapture (потеря захвата). Приложения, как правило, обрабатывают событие losecapture обработчиком, предусмотренным для события mouseup.

Пример 4, описанный в следующей части этой заметки, демонстрирует работу с методами setCapture, relaseCapture и событием losecapture при построении перетаскивания картинок по экрану, работающего во всех браузерах.