Как стать автором
Обновить

Порядок выполнения событий в DOM

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






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

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



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


Консорциум W3C благоразумно решили что разработчикам может быть удобно в любую сторону направлять события (event propagation), поэтому по стандарту две модели объединены — событие сначала захватывается, а потом возвращается как пузырёк.


Таким образом разработчик может привязать вызываемый метод к фазе события:
$('form_bg').addEventListener('click',hideBackground,true); // true - говорит о фазе capturing $('form').addEventListener('click',doNothing,false); // false - говорит о фазе bubbling



Получается что при клике на form_bg происходит сразу hideBackground, form на фазе capturing не вызывается, затем возвращаясь, в фазе bubbling вызывается doNothing.


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

Модель 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".

+оригинал с комментариями
Теги:
Хабы:
Всего голосов 13: ↑10 и ↓3+7
Комментарии8

Публикации