Hey everyone 👋 Let's talk about Event Handling in JavaScript.
Table of content
Introduction
When I started learning JavaScript (JS), I read somewhere that JS is an event-driven programming language, and that the use of JS in the browser was to add interactivity to the web pages.
But what are events in JS? Well, events are just actions that happen when the user is accessing the web pages and it could be the loading of the document, the fetching of data, the clicking of elements inside the document, the pressing of keys or touchscreen and many more.
These actions are known as events in JS and we can respond to these events by calling functions and manipulate the DOM to provide that interactivity and feedback to the user.
Event Listener and Event Handler
Imagine you have a button, and you would like to know when the user has clicked this button so that you can run a block of code. You can attach an event listener to any element you would like to "listen" for an event type by using .addEventListener()
. This method typically takes two parameters, the first being the event type you would like to listen out for (as a string) and the second is the callback function you would like to run when the event occurs (sometime referred to as "fires"). The function that runs when the event "fires" is sometimes called the event handler.
Typically, you would grab the element from the HTML DOM by using something like document.getElementById()
or document.querySelector()
. I like to use the .querySelector
because it feels easier since it is the same selector as CSS.
const button = document.querySelector("button");
button.addEventListener("click", (e)=> {
// some code to manipulate the DOM here
});
You may notice that in the example, the anonymous function takes in an argument e
. This argument is the event object, it is an object which contains details about the event that occurred so you can capture things like the target of the event, or the coordinate of the cursor, etc.
You can attach more than one event listener to an element and if they are the same type, the callback function will run in the order the event listener was defined.
There is also another way to apply event listener to an element, and that is setting the event handler property to a function to handle that event. For example, buttton.onclick = doMagic
but by adding event listener this way you can only add one handler.
Capture and Bubble Phase
Sometimes, you may have an event listener on the parent element but not on the child, or you have it for both. So, to deal with nested elements situation and when each event handler will run, you need to be aware of the Capture phase and the Bubble phase. "Bubbling" means that the event "propagate", aka move up and outward from the inner most element all the way to the <html>
element. And "Capturing" is the opposite, the browser will call the event handler for the outer most element (<html>
) down to the inner most element.
The Capture phase always gets called before the Bubble phase, which means that any element with the event listener set to use capture will fire before all element set with bubble. To use capture, we shall return to .addEventListener()
, you can add a third argument when attaching the event listener { capture: true }
.
Example
I have made something silly with the codepen below. I used window.onload
event handler property to make bubbles show up on the screen once the window has loaded. I added an event listener to each bubble so upon mouse entering the element, the bubble would disappear. I also added a small example of capturing and bubbling at the bottom of the JS file, console logging some words when the element is clicked. You can see the code snippet below, take a guess what the console will log, then click anywhere on the screen and check the console to see if you were correct 😀. Note: canvas is the variable name holding the <main>
element of the page.
function sparkle() {
console.log("sparkle");
}
function sparkleTwice() {
console.log("sparkle, sparkle");
}
function dazzle() {
console.log("dazzle");
}
document.addEventListener("click", sparkle, {capture: true});
document.addEventListener("click", sparkleTwice)
canvas.addEventListener("click", dazzle);
Summary
So, to recap everything, if you want to listen out for certain actions, events, then you can attach an event listener to the element. When the event fires the event listener will call the event handler, a callback function taking the event object as a parameter and will run a block of code. If you have nested elements, you now know that bubbling will cause the event to propagate up so if you find an odd behavior or issues with your event listener, this could be the reason why. You are also aware of using capture to trigger your event handlers in a specific order.
I believe that the best way to understand any concept is to get out there and try to implement something. If you need a starting point, you can break my code, add more event listeners, change the function, play around with it. Or just create your own from scratch! 😀
Thank you for reading, if you have any comments or feedback please leave them down below.