β ππ§πππ«π¬πππ§ππ’π§π ππ―ππ§πs π’π§ πππ―ππππ«π’π©π
Learn all about events in JavaScript!
What are events?
Events allow you to write JavaScript code that reacts to certain situations. Examples of events include:
- The user clicking the mouse button
- The Web page loading
- A form field being changed
- Playing video content
- Typing inside a search bar
To react with those events we assign an event handler which is a callback function that runs when that event occurs.
Event Handlers
To allow you to run your bits of code when these events occur, JavaScript provides us with the event handler. All the JavaScript handler starts with the word on
, and each event handler deals with the specific event. Some examples of the event handlers are:
- onChange - The data in the form element is changed by the user.
- onClick - The object is clicked on.
- onSubmit - The user clicks the formβs Submit button.
- onError - A JavaScript error occurs.
- onMove - The user moves the browser window or frame.
Here is an example of using one event called onclick
.
<button class="btn">Click me!</button>
const button = document.querySelector(".btn")
button.onclick = () => {
console.log("Button clicked.");
};
The onclick
event is triggered when the user clicks on the button. As a result Button clicked is output into the console.
Event Listeners
This is the modern way. To listen the events on elements, we first need to fetch the element. We can then use the addEventListener()
method. The syntax to add a handler is this:
element.addEventListener(event, handler, [options]);
- element - specified element from HTML elements, but also any other DOM object.
- event - specified event type (eg: βclickβ, βscrollβ, βsubmitβ)
- handler - the function to be called and executed when the event occurs.
- options - optional object[capture, once, passive] specifies characteristics about the event listener.
{capture: false}
is the default value and it watches an event in a bubbling phase.{capture: true}
watches an event in a capturing phase.{once: true}
is a useful option if you want to execute only once. So the attached event listener would be automatically removed when invoked. {passive: true} indicates that the function will never call thepreventDefault()
method.
You can listen on window
to intercept βglobalβ events, like the usage of the keyboard, and you can listen on specific elements to check events happening on them, like a mouse click on a button.
to learn more about options please refer to the MDN document.
To get how it works let's see some code,
<button class="myButton">Click me!</button>
const button = document.querySelector('.myButton'); // go get something
button.addEventListener('click', function(){ // listen for something
console.log('button clicked'); // do something
});
Although the above code will work, but we can create a function before the event listener.
function handleClick() {
console.log('button clicked');
}
button.addEventListener('click', handleClick);
Event Object
To properly use event we donβt just want to know if there was a βclickedβ, βscrollβ or βkeydownβ. Weβd like to know what was clicked? Where was the Y position when scrolled? Which key was pressed? Event Object is where we can get some answers.
When an event happens, the browser creates an Event Object that holds information on that event and passes it as an argument to the handler.
Properties of event
object:
event.type
- Event type, such as "click", "keydown"event.currentTarget
: Element that the event was attached to.event.target
: Element where the event actually happened. ( this is useful in Event delegation where you have a single handler for the repetitive event on a common parent.)event.isTrusted
: Boolean tells whether the event was generated by a user action or created or modified by a script.
Let's jump right into the code,
<button class="coupon">Coupon code for <strong>shoes</strong></button>
<button class="coupon">Coupon code for <strong>clothes</strong></button>
const couponButtons = document.querySelectorAll('button.coupon')
function handleCouponButtonClick(){
console.log(event.target); // logs <strong>shoes</strong>
console.log(event.currentTarget); // logs <button class="coupon">Coupon code for <strong>shoes</strong></button>
console.log('coupon button clicked');
}
couponButtons.forEach(function(couponButton){
couponButton.addEventListener('click', handleCouponButtonClick);
});
The log of event.target
outputs the node that triggered the event, in this case itβs the strong tag and its contents.
event.currentTarget
logs the element that the event listener is attached to, so we get a log of the entire button markup.
Event propagation
Event propagation is a term used when talking about event capturing and event bubbling. It relates to the order in which event handlers are called when an element is nested inside another element and both have event listeners registered for the same type of event, for example, a click.
To understand propagation we need to understand how events are dispatched in the DOM. Event objects are dispatched to an event target, but before the dispatch can happen a propagation path needs to be determined.
The propagation path is a list of current event targets that the event object needs to pass through. This path reflects the DOM structure of the document and the elements in order. The last item in this list is called the event target. Anything before the event target is often referred to as a target ancestor, with the last item before the target being the targetβs parent.
Once a propagation path has been calculated the event object passes through one or more event phases. The three phases are as follows:
- Capture phase - the event object trickles down through the DOM from the
window
, through the targetβs ancestors until it reaches the parent. - Target phase - the event object arrives at the event target.
- Bubbling phase - the event object propagates through the targetβs ancestors back up to the window.
A nice way of remembering this is that events trickle down and bubble up.
Source: w3.org
<button class="myButton">Click me!</button>
const myButton = document.querySelector('.myButton');
function handleButtonClick() {
console.log('Button clicked');
}
myButton.addEventListener('click', handleButtonClick);
window.addEventListener('click', function(event) {
console.log('Window clicked');
console.log(event.bubbles); // logs true
});
When running the above code, if I click anywhere in the browser window the console.log
returns Window clicked, however, if I click on the button then the logs return both Button clicked and Window clicked, in that order. As a result of bubbling, the event is captured and handled by the inner element first (the button) and then propagated to the outer element (the window).
Itβs worth noting that event bubbling doesnβt occur with every kind of event. During propagation it is possible for a listener to know if an event bubbles by reading the .bubbles boolean property of the event object. The above code contains the line console.log(event.bubbles)
; which in this instance logs true.
We can stop event propagation within any listener to prevent an ancestor elementβs event handlers from being notified about an event. We do this with the stopPropagation()
method.
Features of Event Listener
Some of the features of the event listener method include:
The addEventListener() method attaches an event handler to the specified element.
This method attaches an event handler to an element without overwriting existing event handlers.
- You can add many event handlers to one element.
- You can add many event handlers of the same type to one element, i.e two βclickβ events.
- Event listeners can be added to any DOM object not only HTML elements. i.e the window object.
- The addEventListener() method makes it easier to control how the event reacts to bubbling.
Which Should I Use, event listener or event handler?
Generally, it is advised to use event listeners over event handlers because you can add multiple event listeners for the same event.
References
Happy codingπ