Блог Конфуция
Кастомные события 27.07.2009

Во всех браузерах, кроме сами знаете какого, можно играться с событийным движком браузера, как душе угодно. Гибкость дается наравне с нативными событиями: можно называть их как угодно, настраивать всплываемость и отменяемость, добавлять свои свойства и методы. Такие трюки удобны для создания виджетов со своей моделью событий; и для имитации полезных событий браузера там, где их не поддерживают (типа, onready или onhashchanged); а еще для расширения базовой логики приложения кем-то третьим (например, события hide/show для отключения анимации в скрытых нодах); да мало ли для чего еще могли бы пригодиться свои собственные события. Но не в IE.

Событийную модель можно реализовать на яваскрипте, и воспользоваться всеми этими прелестями. Но только не для нод в дереве документа, а для простых обектов (тут ничего нового — очередная реализация интерфейса EventTarget). А ведь хочется вешать обработчики именно на ноды, документ, окно… на аяксовый запрос, наконец!

Решили научить IE распространять по документу выдуманные типы событий и посмотреть, что из этого выйдет. У этой задачи есть простое решение: достатачно на яваскрипте повторить движок браузера для подписки/отписки и распространения событий. Код получается интересный, так что это решение вполне приемлемо. С другой стороны, зачем дублировать то, что уже реализовали нативно, а значит быстро. Надо всего-то чуть-чуть допилить браузер.

В этом случае можно выбрать некоторое событие как транспорт. Это событие должно по умолчанию всплывать и не иметь никаких встроенных обработчиков. Поискав немного, нашел oneditfocus. Мы его нигде не используем, а по параметрам он подходит как раз. На нем, пока, и остановился — самое сложное позади. Далее дело техники: научить addEventListener и dispathEvent понимать, какие события обрабатывать как есть, а какие оборачивать в oneditfocus. Здесь тоже ничего сложного: ищем событие в списке нативных и, если не нашли — оборачиваем.

В итоге, за наши труды получаем такой код, без проблем работающий в IE 6-7-8:


window.addEventListener("ready", function (e) { alert("got an event type " + e.type) }, false)
var ready = document.createEvent("Event")
ready.initEvent("ready", true, true)
window.dispathEvent(ready)
//=> got event type ready

Конечно, IE не поддерживает ни addEventListener, ни dispathEvent, но их поддержку нетрудно добавить.

UPD: Дин Эдвардс сделал работающую модель событий для IE в своей библиотеке Base2. Она показалась мне громоздкой и сумбурной. Да и стиль кодирования Дина меня тоже не особо прет: все эти точки с запятой, бее ;)

Теги:
  • клиент
  • events
  • fixes
  • IE
Очень жду ваших комментариев на почту или на гитхаб.