Назад Вперед Зміст


1. Фази подій в JavaScript. Додаткова теорія (перейди за посиланням!!!) ⬇

2. Прослуховування подій в JavaScript(перейди за посиланням!!!) ⬇


Прослуховування подій


Практично все, що ми робимо всередині програми, закінчується спрацюванням подій. Іноді наша програма буде запускати події автоматично, наприклад при завантаженні. В інших випадках воно буде запускати їх у вигляді реакції на наші дії, наш додаток постійно бомбардується подіями незалежно від того, хочемо ми, щоб вони спрацьовували, чи ні. Наше ж завдання — вказати додатку прослуховувати ті події, які нас цікавлять.

Вся робота щодо прослуховування потрібних подій повністю обробляється функцією, яка називається addEventListener. Ця функція завжди напоготові, тому може в потрібний час повідомити іншу частину додатки про те, що сталася певна подія. Використовується вона так: source.addEventListener(eventName, eventHandler, false);

Source (джерело)

Ми викликаємо addEventListener через елемент чи об'єкт, у якому хочемо прослуховувати події. Як правило, це буде елемент DOM, але ним також може бути document, window чи інший об'єкт, спеціально створений для запуску подій.

Event Name (ім'я події)

У вигляді першого аргументу для функції addEventListener ми вказуємо ім'я події, яку хочемо прослуховувати.

Обробник подій

У другому аргументі потрібно вказати функцію, яка буде викликана, коли подія буде почута.

Захоплювати або не захоплювати

Останній аргумент складається з true чи false. Щоб повноцінно зрозуміти наслідки визначення того чи іншого значення, треба розібратися з темою «Сплив і занурення подій», яка саме розглядатиметься нижче.

Усередині функції addEventListener() ми вказуємо два параметри - ім'я події, для якої ми хочемо зареєструвати цей обробник, і код, що містить функцію обробника, яку ми хочемо запустити у відповідь. Зверніть увагу, що доцільно буде помістити весь код всередині функції addEventListener() в анонімну функцію.

Сплив і занурення

Уявімо, що клацаємо по елементу buttonOne, при цьому запуститься подія кліка. Виникає питання звідки Саме буде запущено цю обставину. Воно (як майже кожна подія JavaScript) не виникає в елементі, з яким сталося взаємодія.

Натомість подія стартує з кореня вашого документа:

Починаючи з кореня, подія проходить шлях по вузлах DOM і зупиняється біля елемента, який його викликав, а саме buttonOne (також відомого як цільова подія)

Подія здійснює прямий шлях, але при цьому повідомляє кожен елемент на своєму шляху. Це означає, що якби ви прослуховували подію кліка в body, one_a, two або three_a, то спрацював би пов'язаний із ними обробник подій. Як тільки наша подія досягне своєї мети, вона не зупиниться і, продовжує рух своїми слідами назад до кореня.

Не має значення, де в DOM ініціюється подія. Воно завжди починає рух від кореня, спускається вниз до зустрічі з метою, а потім повертається до кореня. Цей шлях має офіційне визначення, тому давайте розглянемо його з цієї позиції

Випливання

Коли на елементі відбувається подія, обробники спочатку спрацьовують на ньому, потім на його батькові, потім вище і так далі, вгору по ланцюжку предків.

Майже всі події спливають. Ключове слово у цій фразі – «майже». Наприклад, подія focus не спливає. Однак, варто розуміти, що це скоріше виняток, ніж правило, все-таки більшість подій спливає.

Завжди можна дізнатися, на якому конкретному елементі сталася подія. Глибокий елемент, який викликає подію, називається цільовим елементом, і він доступний через event.target.

Приклад 1

Уявіть собі, що у вас є кілька вкладених один в одного блоків:

Натисніть на самий внутрішній рожевий блок - і ви побачите, як спочатку спрацює onclick рожевого блоку, потім блакитного, потім помаранчевого. Така поведінка називається спливанням подій - за аналогією зі спливанням бульбашки повітря з дна. Так само, як і пляшечку, наш клік по внутрішньому елементу ніби випливає нагору, щоразу спрацьовуючи на більш високих блоках.

Код із слухачем подій із третім параметром "false" спрацьовує також:

Всі події спливають до верху (до тега html, а потім до document, а потім до window). Іноді є потреба це спливання зупинити. Це може зробити будь-який елемент, через який спливає подія. Для цього в коді елемента потрібно викликати метод event.stopPropagation().

У наступному прикладі клік по жовтому блоку спрацює на ньому самому, потім на салатовому блоці і все-бузковий блок припиняє подальше спливання і бузковий блок вже ніяк не відреагує:

Далі в наступному прикладі клік по кожному блоку спрацює на ньому самому, припиняється подальше випливання:

Відмінність від this (=event.currentTarget):

event.target – це «цільовий» елемент, на якому сталася подія, в процесі випливання він незмінний. this - це «поточний» елемент, до якого дійшло спливання, на ньому зараз виконується обробник.

Наприклад, якщо стоїть лише один обробник form.onclick, він «зловить» всі кліки всередині форми. Де б не був клік усередині – він випливе до елемента form, на якому спрацює обробник.

При цьому всередині обробника form.onclick: this (=event.currentTarget) завжди буде елемент form, тому що обробник спрацював на ній. event.target міститиме посилання на конкретний елемент усередині форми, на якому стався клік.

Але будь-який проміжний обробник може вирішити, що подія повністю оброблена, і зупинити спливання.

Для цього потрібно викликати метод event.stopPropagation().

Занурення

Частина, в якій ви ініціюєте подію і вона, починаючи з кореня, здійснює спуск вниз по DOM, називається фазою занурення події. Вона дуже рідко використовується в реальному коді, проте також може бути корисною.

Стандарт DOM Events описує 3 фази проходу події:

  1. Фаза занурення (capturing phase) – подія спочатку йде зверху донизу.
  2. Фаза мети (target phase) – подія досягла цільового (вихідного) елемента.
  3. Фаза спливання (bubbling stage) – подія починає спливати.
Вибір фази – це тонка деталь, яку ви визначаєте за допомогою true або false у виклику addEventListener. Цей аргумент вказує, чи ви хочете прослуховувати подію під час фази занурення. У цьому сенсі значення true означає, що саме так ви хочете. І навпаки, аргумент false означатиме, що потрібно прослуховувати подію у час фази спливання.

Отже, існують два варіанти значень опції capture:

  1. Якщо аргумент false (за умовчанням), то подія буде спіймана при спливанні.
  2. Якщо аргумент true, то подія буде перехоплена під час занурення.

Якщо ви не вкажете третій аргумент, то стандартною поведінкою буде прослуховування вашої події під час фази висхідного ланцюжка. Це еквівалентно передачі як аргумент помилкового значення.

Приклад 1

Продовжимо розглядати приклад 1:

Тепер напишемо три обробники і призначимо їх кожному блоку за допомогою addEventListener:

Найадекватніший варіант, при натисканні на кожному блоці спрацьовує відповідний обробник.

Далі експериментуємо з третім параметром, отримуємо спрацювання одразу двох оброблювачів.

Отримуємо спрацювання одразу трьох обробників.

Приклад 2

Щоб упіймати подію на стадії занурення, потрібно використовувати третій аргумент capture ось так:

Приклад 2

Створимо таку сторінку:

Розмітка виглядає так:

CSS виглядає так:

Пишемо скрипт:

Отже в коді вище ми включаємо об'єкт події event у функцію, а функції — налаштування стилю фону для event.target, який є кнопкою, текстовим полем, div, form(той елемент, у якому натискаємо). Властивість об'єкта події target завжди є посиланням на елемент, з яким щойно відбулася подія.

Тут обробники навішуються на кожен елемент у документі, щоб побачити, в якому порядку вони викликаються в міру проходу події.

При настанні події – найглибше вкладений елемент, на якому вона відбулася, позначається як «цільова» (event.target).

Потім подія спочатку рухається вниз від кореня документа до event.target, шляхом викликаючи обробники, поставлені через addEventListener(...., true), де true - це скорочення для {capture: true}.

Далі обробники викликаються на цільовому елементі.

Далі подія рухається від event.target вгору до кореня документа, шляхом викликаючи обробники, поставлені через on і addEventListener без третього аргументу або з третім аргументом рівним false.

Кожен обробник має доступ до властивостей події event:

  1. event.target – найглибший елемент, у якому сталася подія.
  2. event.currentTarget (=this) – елемент, на якому в даний момент спрацював обробник (той, на якому «висить» конкретний обробник)
  3. event.eventPhase - на якій фазі він спрацював (занурення = 1, фаза мети = 2, спливання = 3).

Будь-який обробник може зупинити подію викликом event.stopPropagation(), але робити це не рекомендується, так як надалі ця подія може знадобитися, іноді для несподіваних речей.

У сучасній розробці стадія занурення використовується дуже рідко, зазвичай події обробляються під час випливання.

Якщо закоментувати у скрипті код, позначений зеленою рамочкою, завжди буде спрацьовувати обробник події для форми.

ВИДАЛЕННЯ СЛУХАЧА ПОДІЙ

Інколи потрібно видаляти слухача подій з елемента. Робиться це за допомогою найлютішого ворога addEventListener функції removeEventListener: something.removeEventListener(eventName, eventHandler, false);

Як видно з прикладу, ця функція отримує точно такі ж типи аргументів, як і функція addEventListener. Причина цього проста. Коли ми прослуховуємо подію в елементі або об'єкті, JavaScript використовує eventName, eventHandler і значення true/false, щоб упізнати слухача подій. Щоб видалити цього слухача подій, нам потрібно вказати точно такі ж аргументи. Ось приклад:

document.addEventListener("click", changeColor, false);

document.removeEventListener("click", changeColor, false);

function changeColor() {

document.body.style.backgroundColor = "#FFC926";

}

Слухач подій, якого ми додали у першому рядку, повністю нейтралізовано викликом removeEventListener у виділеному другому рядку. Якщо виклик removeEventListener використовує аргументи, відмінні від зазначених у відповідному виклику addEventListener, то його зусилля будуть проігноровані та прослуховування продовжиться.

Приклад 3

По небу літає пташка.Користувач ловить її мишкою. Якщо спіймав, картинка з пташкою змінюється на кота, на траву.

Пізніше, коли розглядатимемо інші події миші, ми ще раз згадаємо цей приклад, але поки що нас цікавить тільки ситуація, коли потрібно видаляти слухача подій з елемента.


Назад Вперед Зміст