Продвинутая работа с объектом Event на JavaScript. JavaScript - Всплытие события Получение элемента, который сгенерировал событие

Сейчас мы с вами разберем некоторые продвинутые вещи при работе с объектом Event, а именно: всплытие и перехват, а также делегирование событий.

Всплытие событий

Представьте себе, что у вас есть несколько вложенных друг в друга блоков:

самый внутренний блок

Когда вы кликаете на самый внутренний блок, событие onclick возникает сначала в нем, а затем срабатывает в его родителе, в родителе его родителя и так далее, пока не дойдет то тега body и далее до тега html (затем до document и до window ).

И это логично, ведь кликая на внутренний блок, вы одновременно кликаете на все внешние.

Давайте убедимся в этом на следующем примере: у нас есть 3 блока, к каждому из них привязано событие onclick:

Нажмите на самый внутренний красный блок - и вы увидите, как сначала сработает onclick красного блока, потом голубого, потом зеленого:

Такое поведение называется всплытием событий - по аналогии со всплытием пузырька воздуха со дна. Так же, как и пузырек, наш клик по внутреннему элементу как будто выплывает наверх, каждый раз срабатывая на более высоких блоках.

event.target

Пусть у нас есть два элемента: div и абзац p, лежащий внутри этого дива. Пусть onlick мы привязали в диву:

Когда мы кликаем на этот див, мы можем попасть по абзацу, а можем попасть в место, где этого абзаца нет.

Как такое может быть - посмотрите на следующем примере: зеленый цвет - это наш див, а голубой - наш абзац:

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

Однако, иногда нам хотелось бы знать - клик произошел непосредственно по диву или по его потомку абзацу. В этом нам поможет объект Event и его свойство event.target - в нем хранится именно тот элемент, в котором произошел клик.

В следующем примере у нас есть div , внутри него лежит p , а внутри него - span .

Давайте привяжем событие onclick самому верхнему элементу (диву) и будем кликать на разные элементы: на div, на p, на span. С помощью event.target получим самый нижний элемент, в котором случилось событие и выведем его название с помощью tagName .

Если кликнуть, к примеру, на span - то событие отловит наш div (ведь именно к нему привязан onclick), но в event.target будет лежать именно span :

Покликайте по разным блокам - вы увидите результат:

Прекращение всплытия

Итак, вы уже знаете, что все события всплывают до самого верха (до тега html, а затем до document, а затем до window). Иногда есть нужда это всплытие остановить. Это может сделать любой элемент, через который всплывает событие. Для этого в коде элемента следует вызвать метод event.stopPropagation() .

В следующем примере клик по красному блоку сработает на нем самом, затем на голубом блоке и все - голубой блок прекращает дальнейшее всплытие и зеленый блок уже никак не отреагирует:

Кликните на красный блок - вы увидите результат:

Погружение

Кроме всплытия событий есть еще и погружение (по научному стадия перехвата ). Это значит, что событие сначала идет сверху вниз (стадия перехвата), доходит до нашего элемента (стадия цели) и только потом начинает всплывать (стадия всплытия).

Повесить обработчик события с учетом стадии перехвата можно только с помощью addEventListener . Для этого у него есть третий параметр: если он равен true - событие сработает на стадии перехвата, а если false - на стадии всплытия (это по умолчанию):

Var green = document.getElementById("green"); green.addEventListener("click", func, true); function func(event) { }

Стадию, на которой произошло событие можно определить с помощью свойства event.eventPhase . Оно может принимать следующие значения: 1 - стадия перехвата, 2 - стадия цели, 3 - стадия всплытия.

Вступление к делегированию

Представим себе ситуацию: пусть у нас есть ul с несколькими li . К каждой li привязано следующее событие: по нажатию на li ей в конец добавляется "!".

Давайте реализуем описанное:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
var li = document.querySelectorAll("#ul li"); //В цикле вешаем функцию addSign на каждую li: for (var i = 0; i

Понажимайте на li - вы увидите, как им в конец добавляется "!":

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5

Пусть теперь у нас также есть кнопочка, по нажатию на которую в конец ul добавляется новая li с текстом "пункт". Нас ждет сюрприз: привязанное событие не будет работать для новых li! Убедимся в этом:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li

Нажмите на кнопочку для добавления li, а затем на эту новую li - она не среагирует:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li

Для решения проблемы можно в момент создания новой li повесить на нее функцию addSign через addEventListener. Давайте реализуем это:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li var li = document.querySelectorAll("#ul li"); for (var i = 0; i

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li

Существует и второй способ обойти проблему - делегирование событий. Давайте его разберем.

Делегирование событий

Суть делегирования в следующем: навесим событие не на каждую li, а на их родителя - на ul .

При этом работоспособность нашего скрипта должна сохраниться: по-прежнему при клике на li ей в конец будет добавляться "!". Только событие в новом варианте будет навешано на ul:

Var ul = document.getElementById("ul"); //Вешаем событие на ul: ul.addEventListener("click", addSign); function addSign() { }

Как мы это провернем: так как событие навешано на ul, то внутри функции мы можем поймать li с помощью event.target . Напомню, что такое event.target - это именно тот тег, в котором случился клик, в нашем случае это li .

Итак, вот решение нашей задачи через делегирование:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5

Результат выполнения кода:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5

При этом наше решение будет работать автоматически даже для новых li , ведь событие навешено не на li, а на ul:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li var ul = document.getElementById("ul"); ul.addEventListener("click", addSign); function addSign() { event.target.innerHTML = event.target.innerHTML + "!"; } //Реализация кнопочки добавления новой li: var button = document.getElementById("button"); button.addEventListener("click", addLi); function addLi() { var li = document.createElement("li"); li.innerHTML = "новая li"; ul.appendChild(li); }

Нажмите на кнопочку для добавления li, а затем на эту новую li - она среагирует:

  • пункт 1
  • пункт 2
  • пункт 3
  • пункт 4
  • пункт 5
Добавить li

Наш код рабочий, однако не без недостатков. Давайте разберем эти недостатки и напишем более универсальное решение.

Универсальное делегирование событий

Недостаток нашего кода проявится в том случае, когда внутри li будут какие-то вложенные теги. В нашем случае пусть это будут теги i :

В этом случае нажатие на i приведет к добавлению восклицательного знака в конец тега i , а не тега li , как мы хотели бы (если нажать на li вне курсива - то все будет ок):

  • пункт курсив 1
  • пункт курсив 2
  • пункт курсив 3
  • пункт курсив 4
  • пункт курсив 5
var ul = document.getElementById("ul"); ul.addEventListener("click", addSign); function addSign() { event.target.innerHTML = event.target.innerHTML + "!"; }

Нажмите на курсив - вы увидите как "!" добавится ему в конец (нажатие вне курсива будет работать нормально):

Проблема исправляется следующим образом (описанный способ не единственный, но самый простой): с помощью метода closest найдем ближайшую li, котоорая является родителем для event.target вот так: event.target.closest("li") .

Как это работает: если клик был на i , то в event.target лежит этот i, а в event.target.closest("li") - наша li, для которой должно сработать событие.

Если же клик был на самой li , то и в event.target , и в event.target.closest("li") будет лежать наша li.

Давайте проверим:

  • пункт курсив 1
  • пункт курсив 2
  • пункт курсив 3
  • пункт курсив 4
  • пункт курсив 5
var ul = document.getElementById("ul"); ul.addEventListener("click", function(event) { var li = event.target.closest("li"); if (li) { //проверяем, вдруг li-родителя вообще нет li.innerHTML = li.innerHTML + "!"; } });

Результат выполнения кода:

Не важно, какая глубина вложенности: тег i может лежать в теге b , а тот в теге span и только потом в li - это не имеет значения: конструкция event.target.closest("li") найдет родителя из любого уровня вложенности.

Перехват события

Одна из важных особенностей языка - перехват события. Если кто-то, к примеру, щелкает на кнопке, то вызывается программа обработки события onClick, соответствующая этой кнопке. С помощью обработки событий Вы можете добиться того, чтобы объект, соответсвующий вашему окну, документу или слою, перехватывал и обрабатывал событие еще до того, как для этой цели объектом указанной кнопки будет вызван обработчик событий. Точно так же объект вашего окна, документа или слоя может обрабатывать сигнал о событии еще до того, как он достигает своего обычного адресата.
Чтобы увидеть, для чего это может пригодиться, давайте рассмотрим следующий пример:



window.onclick= handle;

function handle(e) {­
alert("Объект window перехватывает это событие!");
return true; // т.е. проследить ссылку
}




Click on this link

Как видно, мы не указываем программы обработки событий в тэге . Вместо этого мы пишем

window.captureEvents(Event.CLICK);

с тем, чтобы перехватить событие Click объектом window. Обычно объект window не работает с событием Click . Однако, перехватив, мы затем его переадресуем в объект window. Заметим, что в Event.CLICK фрагмент CLICK должен писаться заглавными буквами. Если же Вы хотите перехватывать несколько событий, то Вам следует отделить их друг от друга символами |. Например:

window.captureEvents(Event.CLICK | Event.MOVE);

Помимо этого в функции handle() , назначенной нами на роль обработчика событий, мы пользуемся инструкцией return true; . В действительности это означает, что браузер должен обработать и саму ссылку, после того, как завершится выполнение функции handle() . Если же Вы напишете вместо этого return false; , то на этом все и закончится.

Если теперь в тэге Вы зададите программу обработки события onClick , то поймете, что данная программа при возникновении данного события вызвана уже не будет. И это не удивительно, поскольку объект window перехватывает сигнал о событии еще до того, как он достигает объекта link. Если же Вы определите функцию handle() как

function handle(e) {­
alert("The window object captured this event!");
window.routeEvent(e);
return true;
}

то компьютер будет проверять, определены ли другие программы обработки событий для данного объекта. Переменная e - это наш объект Event, передаваемый функции обработки событий в виде аргумента.

Кроме того, Вы можете непосредственно послать сигнал о событии какому-либо объекту. Для этого Вы можете воспользоваться методом handleEvent() . Это выглядит следующим образом:


window.captureEvents(Event.CLICK);

window.onclick= handle;

function handle(e) {­
document.links.handleEvent(e);
}


"Кликните" по этой ссылке

Вторая ссылка

Все сигналы о событиях Click, посылаются на обработку по второй ссылке - даже если Вы вовсе и не щелкнули ни по одной из ссылок!

Следующий скрипт демонстрирует, как Ваш скрипт может реагировать на сигналы о нажатии клавиш. Нажмите на какую-либо клавишу и посмотрите, как работает этот скрипт.


window.captureEvents(Event.KEYPRESS);

window.onkeypress= pressed;

function pressed(e) {­
alert("Key pressed! ASCII-value: " + e.which);
}

Здравствуйте! В этом уроке я хочу рассказать о таком важном понятии как всплытие и перехват событий. Всплытие это такое явление при котором, если вы щелкаете по дочернему элементу, то событие распространяется и на его родитель.

Бывает очень полезно при обработке больших вложенных списков или таблиц, чтобы не назначать каждому элементу обработчик события можно назначить один обработчик на родительский элемент, а событие уже будет распространяться на все вложенные элементы в родитель. Давайте рассмотрим на примере.

Этот обработчик для сработает, если вы кликните по вложенному тегу или :

Кликните на EM, сработает обработчик на DIV

Как видите при клике на вложенном элементе em срабатывает обработчик на div. Почему так происходит? Читайте дальше и узнаете.

Всплытие

Итак основной принцип всплытия:

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

Например, пусть имеется 3 вложенных элемента FORM > DIV > P, с обработчиком собьытия на каждом:

body * { margin: 10px; border: 1px solid blue; } FORM DIV

Всплытие гарантирует, что клик по внутреннему элементу

Вызовет обработчик click (если он конечно есть) сначала на самом

Такой процесс называется всплытием, потому что события как бы «всплывают» от внутреннего элемента вверх через своих родителей, подобно тому, как всплывает пузырек воздуха в воде, поэтому можно встретить еще определение бабблинг ну это просто от английского слова bubbling — всплывать.

Доступ к целевому элементу event.target

Для того, чтобы узнать на каком именно элементе мы поймали то или иное событие и существует метод event.target. (о объекте event читайте ).

  • event.target – это собственно исходный элемент, на котором и произошло событие.
  • this – это всегда текущий элемент, до которого дошло всплытие, и на нём сейчас выполняется обработчик.

Например, если у вас установлен только один обработчик form.onclick, то он и «поймает» все клики внутри формы. При этом где бы ни был клик внутри – он все равно всплывёт до элемента , на котором и сработает уже обработчик.

При этом:

  • this (=event.currentTarget) всегда будет сама форма, так как обработчик сработал именно на ней.
  • event.target будет содержать ссылку на конкретный элемент внутри формы, самый вложенный, на котором произошёл клик.

В принципе this может совпадать с event.target если кликнули по форме и в форме больше нет никаких элементов.

Прекращение всплытия

Как правило всплытие события идет прямо наверх и доходит до корневого объекта window.

Но есть возможность остановить всплытие на каком-то промежуточном элементе.

Для того, чтобы остановить всплытие надо вызвать метод event.stopPropagation().

Рассмотрим пример, при клике на кнопку обработчик body.onclick не сработает:

Кликни меня

Если у элемента установлено несколько обработчиков на одно и тоже событие, то даже при прекращении всплытия все они будут выполнены.

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

Для того, чтобы остановить обработку на текщем элементе, браузеры поддерживают метод event.stopImmediatePropagation(). Этот метод не только предотвратит всплытие, но и останавит обработку событий на текущем элементе.

Погружение

В стандарте, кроме «всплытия» событий, есть ещё и «погружение».

Погружение в отличие от всплытия менее востребованно, но все же знать о нем будет полезно.

Итак имеются 3 стадии прохода события:

  • Событие идет сверху вниз. Эта стадия называется «стадия перехвата».
  • Событие достигло конкретного элемента. Это – «стадия цели».
  • После всего событие начинает всплывать. Это – «стадия всплытия».
  • В стандарте это продемонстрировано так:

    Таким образомь, при клике на TD событие будет путешествовать по цепочке родителей сначала вниз к элементу («погружается»), а потом наверх («всплывает»), по пути соотвественно задействуя обработчики.

    Выше я писал только о всплытии, потому что собственно другие стадии, не используются и проходят незаметно для нас.

    Обработчики ничего не знают о стадии перехвата, а начинают работать со всплытия.

    А Чтобы поймать событие на стадии перехвата, как раз и нужно использовать :

    • Аргумент true, то событие будет перехвачено по дороге вниз.
    • Аргумент false, то событие будет поймано при всплытии.
    Примеры

    В примере на , ,

    Стоят те же обработчики, что и раньше, но на сей раз – на стадии погружения. Ну а чтобы увидеть перехват в действии, кликните в нём на элементе

    Обработчики сработают в порядке «сверху-вниз»: FORM → DIV → P.

    JS-код здесь такой:

    Var elems = document.querySelectorAll("form,div,p"); // на каждый элемент повесим обработчик на стадии перехвата for (var i = 0; i < elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); }


    Никто вам не мешает назначить обработчики для обеих стадий, вот так:

    Var elems = document.querySelectorAll("form,div,p"); for (var i = 0; i < elems.length; i++) { elems[i].addEventListener("click", highlightThis, true); elems[i].addEventListener("click", highlightThis, false); }

    Кликните по внутреннему элементу

    Чтобы увидеть порядок прохода события:
    Должно быть FORM → DIV → P → P → DIV → FORM. Заметим, что элемент

    Будет участвовать в обоих стадиях.

    Итоги
    • При наступлении события – элемент, на котором произошло событие, помечается как event.target.
    • Событие сначала двигается вниз от корня документа к event.target, по пути вызывая обработчики, поставленные через addEventListener(…., true).
    • Событие двигается от event.target вверх до начала документа, по пути оно вызывает обработчики, поставленные через addEventListener(…., false).

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

    • event.target – самый глубокий элемент, на котором собственно и произошло событие.
    • event.currentTarget (=this) – элемент, на котором в данный момент сработал самобработчик (до которого «дошло» событие).
    • event.eventPhase – на какой фазе сработал обработчик события (погружение =1, всплытие = 3).

    Всплытие можно остановить вызовом метода event.stopPropagation(), но делать это не рекомендуется, поскольку событие может вам понадобится для самых неожиданныъ целей.

    Events are actions or occurrences that happen in the system you are programming, which the system tells you about so you can respond to them in some way if desired. For example, if the user clicks a button on a webpage, you might want to respond to that action by displaying an information box. In this article, we discuss some important concepts surrounding events, and look at how they work in browsers. This won"t be an exhaustive study; just what you need to know at this stage.

    Prerequisites: Objective:
    Basic computer literacy, a basic understanding of HTML and CSS, JavaScript first steps .
    To understand the fundamental theory of events, how they work in browsers, and how events may differ in different programming environments.
    A series of fortunate events

    As mentioned above, events are actions or occurrences that happen in the system you are programming - the system produces (or "fires") a signal of some kind when an event occurs, and also provides a mechanism by which some kind of action can be automatically taken (that is, some code running) when the event occurs. For example in an airport when the runway is clear for a plane to take off, a signal is communicated to the pilot, and as a result, they commence piloting the plane.

    In the case of the Web, events are fired inside the browser window, and tend to be attached to a specific item that resides in it - this might be a single element, set of elements, the HTML document loaded in the current tab, or the entire browser window. There are a lot of different types of events that can occur, for example:

    • The user clicking the mouse over a certain element or hovering the cursor over a certain element.
    • The user pressing a key on the keyboard.
    • The user resizing or closing the browser window.
    • A form being submitted.
    • A video being played, or paused, or finishing play.
    • An error occurring.

    You can gather from this (and from glancing at the MDN Event reference) that there are a lot of events that can be responded to.

    Each available event has an event handler , which is a block of code (usually a JavaScript function that you as a programmer create) that will be run when the event fires. When such a block of code is defined to be run in response to an event firing, we say we are registering an event handler . Note that event handlers are sometimes called event listeners - they are pretty much interchangeable for our purposes, although strictly speaking, they work together. The listener listens out for the event happening, and the handler is the code that is run in response to it happening.

    Note : Web events are not part of the core JavaScript language - they are defined as part of the APIs built into the browser.

    A simple example

    Let"s look at a simple example to explain what we mean here. You"ve already seen events and event handlers used in many of the examples in this course already, but let"s recap just to cement our knowledge. In the following example, we have a single , which when pressed, makes the background change to a random color:

    Change color

    Button { margin: 10px };

    The JavaScript looks like so:

    Const btn = document.querySelector("button"); function random(number) { return Math.floor(Math.random() * (number+1)); } btn.onclick = function() { const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; }

    In this code, we store a reference to the button inside a constant called btn , using the Document.querySelector() function. We also define a function that returns a random number. The third part of the code is the event handler. The btn constant points to a element, and this type of object has a number of events that can fire on it, and therefore, event handlers available. We are listening for the click event firing, by setting the onclick event handler property to equal an anonymous function containing code that generates a random RGB color and sets the background-color equal to it.

    This code is run whenever the click event fires on the element, that is, whenever a user clicks on it.

    The example output is as follows:

    It"s not just web pages

    Another thing worth mentioning at this point is that events are not unique to JavaScript - most programming languages have some kind of event model, and the way the model works often differs from JavaScript"s way. In fact, the event model in JavaScript for web pages differs from the event model for JavaScript as it is used in other environments.

    Inline event handlers - don"t use these

    You might also see a pattern like this in your code:

    Press me function bgChange() { const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; }

    The earliest method of registering event handlers found on the Web involved event handler HTML attributes (or inline event handlers ) like the one shown above - the attribute value is literally the JavaScript code you want to run when the event occurs. The above example invokes a function defined inside a element on the same page, but you could also insert JavaScript directly inside the attribute, for example:

    Press me

    You can find HTML attribute equivalents for many of the event handler properties; however, you shouldn"t use these - they are considered bad practice. It might seem easy to use an event handler attribute if you are just doing something really quick, but they very quickly become unmanageable and inefficient.

    For a start, it is not a good idea to mix up your HTML and your JavaScript, as it becomes hard to parse - keeping your JavaScript all in one place is better; if it is in a separate file you can apply it to multiple HTML documents.

    Even in a single file, inline event handlers are not a good idea. One button is OK, but what if you had 100 buttons? You"d have to add 100 attributes to the file; it would very quickly turn into a maintenance nightmare. With JavaScript, you could easily add an event handler function to all the buttons on the page no matter how many there were, using something like this:

    Const buttons = document.querySelectorAll("button"); for (let i = 0; i < buttons.length; i++) { buttons[i].onclick = bgChange; } buttons.forEach(function(button) { button.onclick = bgChange; });

    Note : Separating your programming logic from your content also makes your site more friendly to search engines.

    addEventListener() and removeEventListener()

    The newest type of event mechanism is defined in the Document Object Model (DOM) Level 2 Events Specification, which provides browsers with a new function - addEventListener() . This functions in a similar way to the event handler properties, but the syntax is obviously different. We could rewrite our random color example to look like this:

    Const btn = document.querySelector("button"); function bgChange() { const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; } btn.addEventListener("click", bgChange);

    Inside the addEventListener() function, we specify two parameters - the name of the event we want to register this handler for, and the code that comprises the handler function we want to run in response to it. Note that it is perfectly appropriate to put all the code inside the addEventListener() function, in an anonymous function, like this:

    Btn.addEventListener("click", function() { var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; });

    This mechanism has some advantages over the older mechanisms discussed earlier. For a start, there is a counterpart function, removeEventListener() , which removes a previously added listener. For example, this would remove the listener set in the first code block in this section:

    Btn.removeEventListener("click", bgChange);

    This isn"t significant for simple, small programs, but for larger, more complex programs it can improve efficiency to clean up old unused event handlers. Plus, for example, this allows you to have the same button performing different actions in different circumstances - all you have to do is add or remove event handlers as appropriate.

    Second, you can also register multiple handlers for the same listener. The following two handlers wouldn"t both be applied:

    MyElement.onclick = functionA; myElement.onclick = functionB;

    The second line overwrites the value of onclick set by the first line. This would work, however:

    MyElement.addEventListener("click", functionA); myElement.addEventListener("click", functionB);

    Both functions would now run when the element is clicked.

    In addition, there are a number of other powerful features and options available with this event mechanism. These are a little out of scope for this article, but if you want to read up on them, have a look at the addEventListener() and removeEventListener() reference pages.

    What mechanism should I use?

    Of the three mechanisms, you definitely shouldn"t use the HTML event handler attributes - these are outdated, and bad practice, as mentioned above.

    The other two are relatively interchangeable, at least for simple uses:

    • Event handler properties have less power and options, but better cross-browser compatibility (being supported as far back as Internet Explorer 8). You should probably start with these as you are learning.
    • DOM Level 2 Events (addEventListener() , etc.) are more powerful, but can also become more complex and are less well supported (supported as far back as Internet Explorer 9). You should also experiment with these, and aim to use them where possible.

    The main advantages of the third mechanism are that you can remove event handler code if needed, using removeEventListener() , and you can add multiple listeners of the same type to elements if required. For example, you can call addEventListener("click", function() { ... }) on an element multiple times, with different functions specified in the second argument. This is impossible with event handler properties because any subsequent attempts to set a property will overwrite earlier ones, e.g.:

    Element.onclick = function1; element.onclick = function2; etc.

    Note : If you are called upon to support browsers older than Internet Explorer 8 in your work, you may run into difficulties, as such ancient browsers use different event models from newer browsers. But never fear, most JavaScript libraries (for example jQuery) have built-in functions that abstract away cross-browser differences. Don"t worry about this too much at this stage in your learning journey.

    Other event concepts

    In this section, we briefly cover some advanced concepts that are relevant to events. It is not important to understand these concepts fully at this point, but they might serve to explain some code patterns you"ll likely come across from time to time.

    Event objects

    Sometimes inside an event handler function, you might see a parameter specified with a name such as event , evt , or simply e . This is called the event object , and it is automatically passed to event handlers to provide extra features and information. For example, let"s rewrite our random color example again slightly:

    Function bgChange(e) { const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; e.target.style.backgroundColor = rndCol; console.log(e); } btn.addEventListener("click", bgChange);

    Here you can see that we are including an event object, e , in the function, and in the function setting a background color style on e.target - which is the button itself. The target property of the event object is always a reference to the element that the event has just occurred upon. So in this example, we are setting a random background color on the button, not the page.

    Note : You can use any name you like for the event object - you just need to choose a name that you can then use to reference it inside the event handler function. e / evt / event are most commonly used by developers because they are short and easy to remember. It"s always good to be consistent - with yourself, and with others if possible.

    e.target is incredibly useful when you want to set the same event handler on multiple elements and do something to all of them when an event occurs on them. You might, for example, have a set of 16 tiles that disappear when they are clicked on. It is useful to always be able to just set the thing to disappear as e.target , rather than having to select it in some more difficult way. In the following example (see useful-eventtarget.html for the full source code; also see it running live here), we create 16 elements using JavaScript. We then select all of them using document.querySelectorAll() , then loop through each one, adding an onclick handler to each that makes it so that a random color is applied to each one when clicked:

    Const divs = document.querySelectorAll("div"); for (let i = 0; i < divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } }

    The output is as follows (try clicking around on it - have fun):

    Hidden example Useful event target example div { height: 100px; width: 25%; float: left; } for (let i = 1; i