В API Level 0 можно зарегистрировать обработчик события, установив значение атрибута в HTML_коде или значение свойства объекта в JavaScript_коде. В моде_ ли событий Level 2 обработчик события регистрируется для определенного эле_ мента вызовом метода addEventListener() этого объекта. (Хотя стандарт DOM оп_ ределяет для этого прикладного интерфейса (API) термин слушатель (listener), для единообразия мы по_прежнему будем оперировать термином обработчик (handler).) Этот метод принимает три аргумента. Первый – имя типа события, для которого регистрируется обработчик. Тип события должен быть строкой, со_ держащей имя HTML_атрибута обработчика в нижнем регистре без начальных букв «on». Другими словами, если в модели Level 0 используется HTML_атрибут onmousedown или свойство onmousedown, то в модели событий Level 2 необходимо ис_ пользовать строку "mousedown".
Второй аргумент addEventListener() представляет собой функцию_обработчик (или слушатель), которая должна вызываться при возникновении событий указанного типа. Когда вызывается ваша функция, ей в качестве единственного аргумента передается объект Event. Этот объект содержит информацию о событии (напри_ мер, какая кнопка мыши была нажата) и определяет методы, такие как stopPro_ pagation(). Позднее мы подробнее рассмотрим интерфейс Event и его подынтер_ фейсы.
Последний аргумент метода addEventListener() – логическое значение. Если оно равно true, указанный обработчик события перехватывает события в ходе их распространения на этапе перехвата. Если аргумент равен false, значит, это нор_ мальный обработчик события, который вызывается, когда событие происходит непосредственно в данном элементе или в потомке элемента, а затем всплывает обратно к данному элементу.
17.2. Развитые средства обработки событий в модели DOM Level 2
Например, вот как при помощи функции addEventListener() можно зарегистри_ ровать обработчик события submit элемента <form>:
document.myform.addEventListener("submit",
function(e) { return validate(e.target); }
false);
Можно перехватить все события mousedown, происходящие внутри элемента <div> с определенным именем, вызвав функцию addEventListener() следующим образом:
В этих примерах предполагается, что функции validate() и handleMouseDown() оп_ ределены в каком_либо другом месте вашего JavaScript_кода.
Обработчики событий, зарегистрированные с помощью функции addEventListe_ ner(), выполняются в той области видимости, в которой они определены. Они не вызываются с расширенной цепочкой областей видимости, используемой для обработчиков событий, определенных в виде HTML_атрибутов, как это было описано в разделе 17.1.6.
Обработчики событий в модели Level 2 регистрируются вызовом метода, а не ус_ тановкой атрибута или свойства, поэтому можно зарегистрировать несколько обработчиков для данного типа события в данном объекте. Если вызвать функ_ цию addEventListener() несколько раз для регистрации нескольких функций_об_ работчиков одного типа события в одном объекте, то при возникновении собы_ тия этого типа в данном объекте (или при всплывании к данному объекту, или при перехвате этого события данным объектом) будут вызваны все зарегистри_ рованные вами функции. Однако здесь важно понимать, что стандарт DOM не гарантирует порядок вызова функций_обработчиков данного объекта, поэтому не следует рассчитывать, что они будут вызваны в том порядке, в котором вы их зарегистрировали. Заметьте также, что если для одного элемента несколько раз зарегистрировать одну и ту же функцию_обработчик, то все регистрации, кроме первой, игнорируются.
Зачем может потребоваться регистрировать более одной функции_обработчика одного события в одном объекте? Это может быть очень полезно для структуриза_ ции вашего программного кода. Предположим, что вы пишете универсальный модуль JavaScript_кода, использующий событие mouseover в изображениях для смены изображений. Теперь предположим, что у вас есть еще один модуль, с по_ мощью которого вы собираетесь задействовать то же событие mouseover для выво_ да дополнительной информации об изображении во всплывающей DHTML_под_ сказке. В случае применения API Level 0 придется объединить два модуля в один, чтобы они могли совместно использовать одно свойство onmouseover объекта Image. В то же время в API Level 2 каждый модуль может зарегистрировать нужный ему обработчик события, не зная о другом модуле и не вмешиваясь в его работу.
Пару с методом addEventListener() образует метод removeEventListener(), требую_ щий тех же трех аргументов, но не добавляющий, а удаляющий функцию обра_ ботки события из объекта. Часто бывает полезно временно зарегистрировать об_ работчик события, а потом удалить его. Например, при наступлении события mousedown можно зарегистрировать временные перехватывающие обработчики
418 Глава 17. События и обработка событий
для событий mousemove и mouseup, чтобы видеть, перемещает ли пользователь ука_ затель мыши. Затем, когда будет получено событие mouseup, можно отменить ре_ гистрацию этих обработчиков. При этом код удаления обработчика события мо_ жет выглядеть следующим образом:
Методы addEventListener() и removeEventListener() определены интерфейсом Event_ Target. В веб_броузерах, поддерживающих модуль Events модели DOM Level 2, этот интерфейс, реализованный для узлов Element и Document, предоставляет ука_ занные методы регистрации.1 В IV части книги они описываются в тех же разде_ лах, в которых описываются узлы Document и Element, но там отсутствует описа_ ние интерфейса EventTarget.