Глава 4.11. Обработка событий в DOM4.11.1. Основные понятия4.11.1.1. Генерация и распространение событийВ этой главе мы описываем модель обработки событий, принятую в DOM 2. Именно реакция на внешние события делает документы динамическими, поэтому методы и свойства, описанные в этой главе, служат клеем, соединяющим описанные ранее элементы DOM в единое и живое целое, реагирующее на различные события. Начнем с самого понятия событие. Все события в DOM 2 подразделяются на следующие:
Модель событий DOM 2 пока реализована только в Gecko. Internet Explorer имеет свою модель генерации и обработки событий, которая описана в гл. 4.12. О различиях в обработке событий этими обозревателями см. WDH+: Прерывание скрипта. Любое событие связано с конкретным узлом документа (цель события), доступным через интерфейс EventTarget, который указывается в свойстве target объекта Event, описывающего данное событие. Когда событие достигает своей цели, активизируются все обработчики событий данного узла, описываемые интерфейсом EventListener. При этом гарантируется, что все обработчики будут активизированы, но не оговаривается порядок, в котором это будет происходить. Если не произойдет перехвата или просачивания события, то процесс генерации события завершится, когда все обработчики будут активизированы. Этот процесс называется распространением события (event propagation). Если происходит перехват события или его просачивание, то процесс обработки события изменяется, как описано ниже. Исключения, возникающие в процессе обработки события, не прекращают его распространения: управление просто передается следующему обработчику событий. Если обработка события генерирует новые события, то они должны обрабатываться синхронно. 4.11.1.2. Перехват событияПерехват события (event capture) состоит в следующем. Обработчик события любого предка цели может перехватить событие прежде, чем оно достигнет своей цели. Процесс перехвата действует сверху вниз от корня дерева документа, т. е. от объекта Document. В момент генерации события фиксируется цепочка его существующих обработчиков от корня дерева до узла-цели; если во время обработки события какие-то обработчики будут удалены или добавлены, то это не окажет влияния на процесс обработки данного события. Для включения механизма перехвата событий нужно установить аргумент useCapture метода addEventListener в true. После этого обработчик событий будет перехватывать все события заданного типа, направленные к потомках узла, в котором он зарегистрирован. Это приведет к тому, что все обработчики данного события у всех узлов цепочки от данного узла до цели будут активизированы. При этом события, целью которых является узел, в котором зарегистрирован перехватывающий обработчик, его не активизируют. Если перехватывающий обработчик хочет прекратить дальнейшую обработку события, то он должен вызвать метод stopPropagation объекта Event. Тем самым он прекратит передачу события по цепочке узлов вниз. Однако, обработчики событий в узлах того же уровня иерархии все равно будут активизированы. 4.11.1.3. Просачивание событияПросачивание события (event bubbling) это процесс, который происходит в направлении, противоположном перехвату. Он состоит в том, что после активизации обработчиков события узла-цели происходит активизация обработчиков этого события у элементов, являющихся предками этого узла вверх по дереву документа вплоть до его корня. Обработчики событий, зарегистрированные для перехвата событий, при этом не активизируются. В момент генерации события фиксируется цепочка его существующих обработчиков от узла-цели до корня дерева; если во время обработки события какие-то обработчики будут удалены или добавлены, то это не окажет влияния на процесс просачивания данного события. Любой обработчик может прекратить дальнейшее просачивание события вызовом метода stopPropagation объекта Event. Тем самым он прекратит передачу события по цепочке узлов вверх. Однако, обработчики событий в этом узле будут активизированы. Является событие просачивающимся или нет, определяется свойством bubbles его интерфейса Event. 4.11.1.4. Отмена событияНекоторые события являются отменяемыми (cancelable). Для таких событий обычно предусмотрена типовая обработка. Примером может служить щелчок мышью на гиперссылке, где действием по умолчанию является загрузка ресурса, на который указывает гиперссылка. Перед выполнением типовой обработки реализация DOM должна вызвать обработчики данного события, если таковые зарегистрированы. Обработчики имеют возможность либо отменить типовую обработку события, либо разрешить ее. В примере с гиперссылкой отмена события означает, что загрузка ресурса не произойдет. Является событие отменяемым или нет, определяется свойством cancelable его интерфейса Event. Отмена типовой обработки события производится вызовом метода preventDefault этого интерфейса. 4.11.1.5. Исключения: интерфейс EventExceptionВ процессе обработки события может быть сгенерировано исключение, описываемое интерфейсом EventException. Этот интерфейс имеет единственное свойство code типа Number, которое содержит номер исключения согласно следующей таблицы:
4.11.2. Регистрация обработчиков событий: интерфейс EventTargetПоддержка: Не поддерживается. Соответствует стандарту. Интерфейс EventTarget реализуется всеми узлами документа, которые поддерживают обработку событий. Иными словами, его методы являются дополнительными методами объектов Node.
Метод addEventListenerСинтаксис: узел.addEventListener(type, listener, useCapture) Аргументы: type выражение типа DOMString listener выражение типа EventListener useCapture логическое выражение Поддержка: Не поддерживается. Соответствует стандарту. Метод addEventListener регистрирует новый обработчик listener события type для данного узла. Если аргумент useCapture равен true, то этот обработчик будет перехватывать событие type. Если новый обработчик регистрируется во время обработки события, то он будет активизироваться только следующими событиями. Повторная регистрация уже существующего обработчика для данного события игнорируется. Следующий пример перехватывает все щелчки мыши на Веб-странице и выводит тег HTML-элемента, на котором мы щелкнули. function mouseClick(event) { var tag = event.target.tagName ? event.target.tagName : event.target.parentNode.tagName; alert(tag); } document.addEventListener("click", mouseClick, true); Если узел копируется методом cloneNode, то зарегистрированные для него обработчики событий не присоединяются к копии. При необходимости они должны быть вновь зарегистрированы для нового узла. Метод dispatchEventСинтаксис: узел.dispatchEvent(evt) Аргументы: evt выражение типа Event Исключения: UNSPECIFIED_EVENT_TYPE_ERR Поддержка: Не поддерживается. Соответствует стандарту. Метод dispatchEvent генерирует событие evt. Обработка события, созданного этим методом, происходит так же, как обработка событий, сгенерированных исполняющей системой. Целью события является узел, из которого вызван данный метод. Пример: var evt = new Event; evt.initEvent("click", true, true); document.body.dispatchEvent(evt); Метод removeEventListenerСинтаксис: узел.removeEventListener(type, listener, useCapture) Аргументы: type выражение типа DOMString listener выражение типа EventListener useCapture логическое выражение Поддержка: Не поддерживается. Соответствует стандарту. Метод removeEventListener удаляет обработчик события для данного узла. Аргументы listener, type и useCapture имеют тот же смысл, что в методе addEventListener. Если обработчик удаляется во время обработки события, то он уже не будет активизирован текущим событием. Попытка удалить обработчик с параметрами, не соответствующими ни одному из зарегистрированных обработчиков игнорируется. Пример: document.removeEventListener("click", mouseClick, true); 4.11.3. Обработчики событий: интерфейс EventListenerПоддержка: Нестандартная. Соответствует стандарту. Интерфейс EventListener соответствует обработчикам событий в DOM. Обработчик событий это подпрограмма, которая вызывается всякий раз, когда происходит событие, для которого зарегистрирован данный обработчик. Активизация обработчика вызывается внутренним методом handleEvent: Метод handleEventСинтаксис: обработчик.handleEvent(evt) Аргументы: evt выражение типа Event Поддержка: Нестандартная. Соответствует стандарту. Метод handleEvent вызывается в процессе обработки события evt. Пример обработчика события приведен в описании метода addEventListener. 4.11.4. Обработчики событий HTML 4.0В HTML 4.0 обработчики событий задаются как атрибуты соответствующих элементов, например: <BODY onclick="mouseClick()"> При таком подходе задание нового обработчика события заменяет его старый обработчик. DOM допускает регистрацию нескольких обработчиков для одного события, поэтому в нем произошел отказ от задания обработчиков в атрибутах. Однако, в целях совместимости все действующие реализации DOM поддерживают форму регистрации обработчиков событий в синтаксисе HTML. Она считается совпадающей с заданием обработчика методом addEventListener с аргументом useCapture, равным false. Например, приведенное выше задание обработчика событий эквивалентно оператору document.body.addEventListener("click", mouseClick, false); DOM не предусматривает доступа к контексту события для обработчиков прерываний, заданных через атрибуты элементов. Однако, в Gecko в момент вызова обработчика события создается объект event, соответствующий интерфейсу Event для данного события. Пример: function checkKey(evt) { var key = evt.which; // код нажатой клавиши ... } <BODY onkeydown="checkKey(event)"> Перечень событий HTML приведен в п. 4.11.10. 4.11.5. События: интерфейс EventПоддержка: Нестандартная. Соответствует стандарту. Интерфейс Event передает обработчику события информацию о событии, которое его активизировало. В зависимости от типа события, его контекстная информация может отличаться, но все интерфейсы, описывающие конкретные события, являются производными от интерфейса Event.
Свойство bubblesСинтаксис: событие.bubbles Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство bubbles возвращает true, если данное событие является просачивающимся, и false в противном случае. Свойство cancelableСинтаксис: событие.cancelable Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство cancelable возвращает true, если данное событие является отменяемым, и false в противном случае. Свойство currentTargetСинтаксис: событие.currentTarget Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство currentTarget возвращает объект EventTarget, соответствующий узлу, чьи обработчики событий сейчас активизируются. Это свойство особенно полезно при перехвате и просачивании событий. Свойство eventPhaseСинтаксис: событие.eventPhase Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство eventPhase возвращает текущую фазу обработки события, которая задается целым числом в соответствии со следующей таблицей:
Свойство targetСинтаксис: событие.target Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство target возвращает объект EventTarget, соответствующий узлу, для которого это событие было сгенерировано. Свойство timeStampСинтаксис: событие.timeStamp Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство timeStamp возвращает объект DOMTimeStamp, соответствующий времени генерации данного события. Для некоторых операционных систем и типов событий это значение может быть недоступно; в таких случаях данное свойство должно возвращать 0. Свойство typeСинтаксис: событие.type Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство type возвращает название данного события в формате DOMString. Это название должно быть именем языка XML, не зависящим от регистра, но и MSHTML, и Gecko возвращают название события строчными буквами, например: "click", "keydown", "resize". Метод initEventСинтаксис: узел.initEvent(eventType, canBubble, isCancelable) Аргументы: eventType выражение типа DOMString canBubble, isCancelable логические выражения Поддержка: Не поддерживается. Соответствует стандарту. Метод initEvent используется для инициализации параметров события, созданного методом createEvent. Он должен вызываться до того, как данное событие будет сгенерировано методом dispatchEvent, и изменяет только те параметры события, которые задаются его аргументами. Аргумент eventType задает название данного события в формате DOMString; это название должно быть именем языка XML. Аргументы canBubble и isCancelable указывают соответственно, является ли данное событие просачивающимся и отменяемым. Метод preventDefaultСинтаксис: узел.preventDefault() Поддержка: Не поддерживается. Соответствует стандарту. Метод preventDefault сообщает системе, что нужно отменить обработку данного события, принятую по умолчанию. Если событие не является отменяемым, то вызов этого метода игнорируется. Этот метод может быть вызван в любой фазе обработки события. Метод stopPropagationСинтаксис: узел.stopPropagation() Поддержка: Не поддерживается. Соответствует стандарту. Метод stopPropagation сообщает системе, что нужно прекратить распространение данного события. После его вызова завершается активация обработчиков событий текущего узла, и дальнейшее распространение события не происходит. Этот метод может быть вызван в любой фазе обработки события. 4.11.6. События пользовательского интерфейса: интерфейс UIEventПоддержка: Не поддерживается. Соответствует стандарту. Интерфейс UIEvent является производным от интерфейса Event и содержит дополнительную информацию о событиях пользовательского интерфейса.
Свойство detailСинтаксис: событие.detail Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство detail возвращает число, содержащее дополнительные сведения о данном событии. Его значение зависит от типа события, как описано ниже. Свойство viewСинтаксис: событие.view Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство view возвращает указатель на объект AbstractView, соответствующий окну отображения документа, в котором сгенерировано данное событие. Метод initUIEventСинтаксис: узел.initUIEvent(eventType, canBubble, isCancelable, view, detail) Аргументы: eventType выражение типа DOMString canBubble, isCancelable логические выражения view выражение типа AbstractView detail числовое выражение Поддержка: Не поддерживается. Не поддерживается. Метод initUIEvent используется для инициализации параметров события пользовательского интерфейса, созданного методом createEvent. Он должен вызываться до того, как данное событие будет сгенерировано методом dispatchEvent, и изменяет только те параметры события, которые задаются его аргументами. Аргумент eventType задает название данного события в формате DOMString; это название должно быть именем языка XML. Аргументы canBubble и isCancelable указывают соответственно, является ли данное событие просачивающимся и отменяемым. Аргумент view задает окно отображения документа, а аргумент detail дополнительные сведения о событии. Типы событий пользовательского интерфейсаDOM 2 определяет три типа событий пользовательского интерфейса (которые пока обозревателями не поддерживаются):
4.11.7. События мыши: интерфейс MouseEventПоддержка: Не поддерживается. Соответствует стандарту. Интерфейс MouseEvent является производным от интерфейса UIEvent и содержит дополнительную информацию о событиях, генерируемых мышью.
Свойство altKeyСинтаксис: событие.altKey Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство altKey возвращает true, если в момент генерации события была нажата клавиша Alt, и false в противном случае. Свойство buttonСинтаксис: событие.button Изменяемое: нет Поддержка: Нестандартная. Соответствует стандарту. Свойство button возвращает номер кнопки мыши, нажатие или отпускание которой вызвало генерацию события. При этом 0 означает левую кнопку, 1 среднюю кнопку, 2 правую кнопку. Если мышь сконфигурирована для левой руки, то значения этого свойства присваиваются в обратном порядке. Свойство clientXСинтаксис: событие.clientX Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство clientX возвращает число, равное горизонтальной координате точки, в которой произошла генерация события, относительно клиентской области обозревателя. Свойство clientYСинтаксис: событие.clientY Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство clientY возвращает число, равное вертикальной координате точки, в которой произошла генерация события, относительно клиентской области обозревателя. Свойство ctrlKeyСинтаксис: событие.ctrlKey Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство ctrlKey возвращает true, если в момент генерации события была нажата клавиша Ctrl, и false в противном случае. Свойство metaKeyСинтаксис: событие.metaKey Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство metaKey возвращает true, если в момент генерации события была нажата клавиша Meta, и false в противном случае. Свойство relatedTargetСинтаксис: событие.relatedTarget Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство relatedTarget возвращает вторичный объект EventTarget, связанный с данным событием. В настоящее время этот атрибут используется в событии mouseover для указания узла, который курсор мыши покинул, и в событии mouseout для указания узла, на который курсор мыши попал. Свойство screenXСинтаксис: событие.screenX Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство screenX возвращает число, равное горизонтальной координате точки, в которой произошла генерация события, относительно экрана. Свойство screenYСинтаксис: событие.screenY Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство screenY возвращает число, равное вертикальной координате точки, в которой произошла генерация события, относительно экрана. Свойство shiftKeyСинтаксис: событие.shiftKey Изменяемое: нет Поддержка: Соответствует стандарту. Соответствует стандарту. Свойство shiftKey возвращает true, если в момент генерации события была нажата клавиша Shift, и false в противном случае. Метод initMouseEventСинтаксис: узел.initMouseEvent(eventType, canBubble, isCancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) Аргументы: eventType выражение типа DOMString canBubble, isCancelable логические выражения view выражение типа AbstractView detail, screenX, screenY, clientX, clientY, button числовые выражения ctrlKey, altKey, shiftKey, metaKey логические выражения relatedTarget выражение типа EventTarget Поддержка: Не поддерживается. Не поддерживается. Метод initMouseEvent используется для инициализации параметров события мыши, созданного методом createEvent. Он должен вызываться до того, как данное событие будет сгенерировано методом dispatchEvent, и изменяет только те параметры события, которые задаются его аргументами. Аргумент eventType задает название данного события в формате DOMString; это название должно быть именем языка XML. Аргументы canBubble и isCancelable указывают соответственно, является ли данное событие просачивающимся и отменяемым. Аргумент view задает окно отображения документа, аргумент detail количество щелчков мыши, а остальные аргументы задают значения одноименных свойств события. Типы событий мышиDOM 2 определяет следующие типы событий мыши:
4.11.8. События клавиатуры: интерфейс KeyEventПоддержка: Нестандартная. Нестандартная. Интерфейс KeyEvent является производным от интерфейса UIEvent и содержит дополнительную информацию о событиях, генерируемых клавиатурой. DOM 2 не содержит спецификации этого интерфейса, она будет включена в DOM 3. Поэтому здесь мы приводим описание реализации интерфейса KeyEvent в Gecko (см. "Key Events in SeaMonkey").
Свойство charCodeСинтаксис: событие.charCode Изменяемое: нет Поддержка: Не поддерживается. Соответствует стандарту. Свойство charCode действительно только для события keypress. Если нажатая клавиша соответствует символу Unicode, то данное свойство возвращает код этого символа. Если же клавиша является служебной или событие отлично от keypress, то возвращается 0. Свойство keyCodeСинтаксис: событие.keyCode Изменяемое: нет Поддержка: Нестандартная. Соответствует стандарту. Свойство keyCode возвращает виртуальный код клавищи, вызвавшей событие, или 0, если charCode не равно нулю. Список виртуальных кодов клавиш содержится в Таблице П18.1. Типы событий клавиатурыКлавиатура всегда генерирует три отдельных события: keydown (нажатие клавиши), keypress (удержание нажатой клавиши) и keyup (отпускание клавиши). Длительное нажатие клавиши приводит к тому, что событие keypress генерируется многократно.
4.11.9. События изменения документа: интерфейс MutationEventПоддержка: Не поддерживается. Не поддерживается. Интерфейс MutationEvent является производным от интерфейса Event и содержит дополнительную информацию о событиях, порожденных изменением структуры документа.
Свойство attrChangeСинтаксис: событие.attrChange Изменяемое: нет Поддержка: Не поддерживается. Не поддерживается. Свойство attrChange возвращает тип изменения атрибута для события DOMAttrModified. Тип изменения атрибута задается целым числом в соответствии со следующей таблицей:
Свойство attrNameСинтаксис: событие.attrName Изменяемое: нет Поддержка: Не поддерживается. Не поддерживается. Свойство attrName возвращает строку, содержащую название изменившегося атрибута для события DOMAttrModified. Свойство newValueСинтаксис: событие.newValue Изменяемое: нет Поддержка: Не поддерживается. Не поддерживается. Свойство newValue возвращает строку, содержащую новое значение узла Attr для события DOMAttrModified или новое значение узла CharacterData для события DOMCharacterDataModified. Свойство prevValueСинтаксис: событие.prevValue Изменяемое: нет Поддержка: Не поддерживается. Не поддерживается. Свойство prevValue возвращает строку, содержащую предыдущее значение узла Attr для события DOMAttrModified или предыдущее значение узла CharacterData для события DOMCharacterDataModified. Свойство relatedNodeСинтаксис: событие.relatedNode Изменяемое: нет Поддержка: Не поддерживается. Не поддерживается. Свойство relatedNode возвращает указатель на объект Node, соответствующий вторичному узлу, связанному с данным событием. Какой именно узел является вторичным, зависит от события и описано ниже для каждого из событий. Метод initMutationEventСинтаксис: узел.initMutationEvent(eventType, canBubble, isCancelable, relatedNode, prevValue, newValue, attrName, attrChange) Аргументы: eventType, prevValue, newValue, attrName выражения типа DOMString canBubble, isCancelable логические выражения relatedNode выражение типа Node attrChange числовое выражение Поддержка: Не поддерживается. Не поддерживается. Метод initMutationEvent используется для инициализации параметров события изменения документа, созданного методом createEvent. Он должен вызываться до того, как данное событие будет сгенерировано методом dispatchEvent, и изменяет только те параметры события, которые задаются его аргументами. Аргумент eventType задает название данного события в формате DOMString; это название должно быть именем языка XML. Аргументы canBubble и isCancelable указывают соответственно, является ли данное событие просачивающимся и отменяемым. Остальные аргументы задают значения одноименных свойств события. Типы событий изменения документаDOM 2 определяет следующие типы событий изменения документа (которые обозревателями пока не поддерживаются):
4.11.10. События HTMLDOM 2 поддерживает следующие события HTML 4.0:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||