---
title: Порядок выполнения событий в DOM
date: 2008-03-22T10:00
tags: [javascript]
---

Столкнулся с проблемой в своём календарике - есть два элемента, один из которых позиционируется абсолютно на весь экран, полупрозрачная затемняющая занавеска а второй - форма. Вы наверняка видели такие решения при показе картинок в lightbox или аутидентификации на habrahabr'е..

`<div id='form_bg' onclick="$('form_bg').hide();$('form').hide();"> <div id='form'></div> </div>`

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

---

### Две с половиной модели

Как оказывается, существует две модели передачи событий в объектно-ориентированной иерархии

- Пузырьковый метод (_bubbling_), когда событие возникает внутри и затем передаётся родительским элементам наружу. MS Internet Explorer, Opera, Firefox
- Захват события (_capturing_), событие обрабатывается сначала у родителей, а потом проникает глубже. Opera, Firefox

Консорциум [W3C благоразумно решили](http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/) что разработчикам может быть удобно в любую сторону направлять события (event propagation), поэтому по стандарту две модели объединены - событие сначала захватывается, а потом возвращается как пузырёк.

Таким образом разработчик может привязать вызываемый метод к фазе события:

`$('form_bg').addEventListener('click',hideBackground,true);   // true - говорит о фазе capturing      $('form').addEventListener('click',function(){},false);   // false - говорит о фазе bubbling`  
Получается что при клике на _form_bg_ происходит сразу _hideBackground_, и _form_ на фазе capturing не вызывается, затем возвращаясь, в фазе bubbling вызывается анонимная функция. 

### Традиции по умолчанию

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

`$('form_bg').onclick = hideBackground; // или как выше - в <div id='form_bg' onclick=..`

То любое событие без остановки вызывает у всех родительских элементов обработку onclick-события. Есть у них оно или нет, вплоть до корня - document.

### Заплыв без пузырьков

В кросс-браузерном варианте для остановки распространения обработки события к родительским элементам, надо поменять параметр _cancelBubble_ на true (для IE) и вызывать функцию _stopPropagation_ (W3C модель):

`function hideBackground(e){   if (!e) var e = window.event;   e.cancelBubble = true;   if (e.stopPropagation) e.stopPropagation();   }`

Теперь мне интересно как устроена модель обработки событий в других языках и платформах - Java, NET, Flash..

Написано по мотивам статьи "[Event order](http://www.quirksmode.org/js/events_order.html)".

## Related

- [Backbone.js](/ru/blog/tech/frontend/javascript/backbonejs/)
- [Excel через javascript](/ru/blog/tech/frontend/javascript/excel-cherez-javascript/)
- [JSDoc](/ru/blog/tech/frontend/javascript/jsdoc/)
