Теперь мы знаем, что для элементов документа можно указать события и их обработчиков, на которые они должны реагировать. Например, если требуется, чтобы элемент реагировал на щелчок кнопкой мыши выполнением некоторой функции myfunc(), то в тег этого элемента следует вставить запись: onclick = "myfunc()". Однако нам известно, что большинство тегов в HTML являются контейнерными и, следовательно, могут содержать в себе другие теги. При этом может оказаться так, что одно и то же событие будет обозначено в различных, но вложенных друг в друга тегах. Что произойдет при наступлении этого события? Как оно распространяется по объектам и как оно перехватывается элементами
документа?
Создадим HTML-документ, содержащий одну кнопку.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Прохождение событий</title>
</head>
<body onclick="alert('Щелчок на body')" >
<button onClick="alert('Щелчок на button')">Нажми здесь</button>
</body>
</html>
В окне веб-браузера это будет выглядеть ТАК.
Особенность этого документа в том, что одно и то же событие (с различными обработчиками) привязано к различным тегам, один из которых содержит в себе другой (<button>содержится в <body>). Щелчок на кнопке приведет к выполнению сначала обработчика щелчка для кнопки, а затем обработчика для <body>. Если щелкнуть где-нибудь в рабочей области окна браузера вне кнопки, то сработает только обработчик для <body>. Ниже мы рассмотрим, как можно избавиться от этого нежелательного эффекта.
Модель прохождения событий в IE4 называется «всплыванием событий». События, подобно воздушным пузырькам в воде, как бы всплывают от целевого объскта самого нижнего уровня вверх по иерархии объектов. В рассмотренном выше примере событие onclick «всплывает» от объекта кнопки к объекту тела документа. В NN4 модель прохождения событий называют захватом событий. Согласно этой модели событие распространяется, наоборот, от самого верхнего в иерархии объекта window к целевому объекту. Чтобы события обрабатывались на уровне текущих объектов, требуется включить для них режим захвата. Это делается с помощью специального метода captureEvent(). В IE4 для управления всплыванием событий используют свойство прерывания всплывания cancelBubble.
В современных браузерах IE5.5+ и NN6 реализована модель, объединяющая в себе и всплывание. и захват событий. Всплывание организовано как в IE4+, а захват — как в NN4. По умолчанию событие всплывает, однако вы можете включить его захват. Тогда событие сначала достигает целевого объекта, а затем начинает всплывать в обратном направлении.
ВIE4+ управлять прохождением событий можно с помощью свойства cancelBubble объекта события event. Когда в документе (на веб-странице) происходит какое-либо событие, объект event первым получает информацию о нем и решает, какому элементу его передать. Например, когда объект event получает событие onclick (щелчок кнопкой мыши), он выясняет, какой элемент находился в тот момент под указателем мыши. Если там было два элемента (один над другим), то выбирается элемент с наименьшим z-индексом, то есть нижний. Напомню, что z-index является одним из параметров позиционирования элементов с помощью таблиц
стилей. Установив элемент, связанный с событием, объект event ищет обработчик этого события и выполняет его. Например, если элемент имеет уникальное имя (ID) myelement, то ищется функция myelement.onclick(). Далее объект event выясняет, какой объект является контейнером для данного элемента. Если таковой имеется, то событие переходит внутрь этого контейнера. Если, например, контейнером является объект, созданный тегом <div> с именем mydiv, то будет предпринята попытка выполнить функцию mydiv.onclick(). Этот процесс продолжается, пока
имеются доступные контейнеры. Например, последним доступным контейнером может оказаться документ (объект document), и тогда объект event ищет функцию document.onclick().
Чтобы определить главного виновника события (объект, инициировавший событие), используется свойство srcElement. Мы уже говорили о нем выше. Например, может потребоваться одинаковая реакция на одно и то же событие всех элементов, за исключением некоторых. В таких случаях для элементов, на которых процесс всплывания события должен закончиться, создаются специальные функции-обработчики. В этих функциях помимо прочего должно быть выражение присвоения свойству cancelBubble значения true, чтобы прервать дальнейшее прохождение события. Например, если мы хотим разорвать цепную передачу события на элементе с именем myelement, необходимо создать для него функцию-обработчик события следующего вида:
function myelement. onclick(){
// код обработки события onclick
window.event. cancelBubble = true
}
Делать такое в функции-обработчике для объекта document бессмысленно, поскольку выше событие все равно всплыть не может, а отменить реакцию на это событие элемента-инициатора (первого звена цепочки) невозможно.
В рассмотренном выше примере, если пользователь щелкнет на кнопке, сработает обработчик не только кнопки, но и тела документа (элемента, заданного тегом <body>). Если мы хотим это предотвратить, то можно переписать код следующим образом:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Прохождение событий</title>
</head>
<body onclick="alert('Щелчок на body')" >
<button onClick="alert('Щелчок на button');
window.event.cancelBubble=true">Нажми здесь</button>
</body>
</html>
В окне веб-браузера это будет выглядеть ТАК.
Tеперь щелкнув на кнопке мы получим
Щелкнув в рабочей области окна браузера получим
Возможен и такой вариант.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Прохождение событий</title>
</head>
<body onclick="alert('Щелчок на body')" >
<button id="mybot">Нажми здесь</button>
</body>
<script language="JavaScript">
function mybot.onclick(){
alert('Щелчок на button')
window.event.cancelBubble=true //прекратить всплывание события
}
</script>
</html>
В окне веб-браузера это будет выглядеть ТАК.