Back

All about JavaScript Events

All about JavaScript Events

According to the Oxford English Dictionary, an Event is an occurrence or something that happens. In the case of Javascript, events are occurrences or something that happens in the browser, and a user’s action triggers it. It can be clicks, loading pages, scrolling, etc. In the browser, Javascript is used to make dynamic and interactive pages, and Event is one of the ways, if not a necessity, to make pages very interactive and dynamic.

Sometimes web developers use the Javascript event incorrectly, thereby not giving their webpages the perfect UI and UX it needs because they don’t understand the concept of Event. Every web developer needs to understand it, and that’s precisely what we will discuss.

Types of event

We will be listing events based on the DOM object it interacts with.

  • Browser Events These events occur in the browser window rather than the HTML page. Event handlers are bound to the window object, not to the element. E.g., load, error, scroll, resize, etc.
  • HTML Events This is the inverse of the browser event. They are the event that occurs in the element, and the event handlers are bound to the element. E.g., click, mouseover, mouseenter, etc.

Events are triggered by the action taken by a user on a web page.

  • When a user clicks on a button, the click event is triggered
  • When a user scrolls a web page, a scroll event is triggered

Event listeners and handlers

Event listeners and handlers are usually thought to mean the same thing; although we can’t use one without the other, they mean different things.

  • Event listener As its name implies, it listens when a particular event is triggered or fired.
  • Event handler They are callback functions called by the listener when a particular event is triggered. Event handlers are often used to update the state of the web page.

Events are listened to by adding an event listener and handler. The listener listens to when the event will be triggered, and when it is triggered, it calls the event handler, which are functions that react to the event being triggered.

How to write an event listener

Event listeners are written using the addEventlistener method. This is a method that every element have. Below is how to write it. We are adding a listener that listens to a click event of a button on the web page.

const button  = document.getElementById('btn')

button.addEventListener('click', eventHandler)

If you look closely, you will find that the addEventListener has two arguments. The first argument is the event, while the second is the handler. As we said, when the listener listening to a click event hears that a user clicked the button, it will call the event handler, which is the second argument.

How to write an event handler

Event handlers are just functions that update the state of a web page, and they are written as a normal Javascript function with the task it should perform. Using our previous instance, which is a button, let’s say when the button is clicked, we want to log Hello World in the console. Below is how to write it.

function LogHelloWorldInConsole(){
    console.log('Hello World')
}

// Adding the event listener in the previous sample 
// The code becomes

const button = document.getElementById('btn')

button.addEventListener('click', LogHelloWorldInConsole)

The code above will log Hello World in the console once a user clicks the button.

We can also add an event handler without using the addEventListener method. This is done by adding the prefix on to each event’s name and accessing it as a property of the element. For example, let’s say we want to listen to a click event; below is how we can write it.

const button = document.getElementById('btn')

function LogHelloWorldInConsole(){
    console.log('Hello World')
} 

button.onclick = LogHelloWorldInConsole

Using an anonymous function, it will be written this way:

const button = document.getElementById('btn')

button.onclick = function(){
    console.log('Hello World')
} 

Using an anonymous arrow function, it will be written this way.

const button = document.getElementById('btn')

button.onclick = ()=>{
    console.log('Hello World')
}

This method might seem easier to write, but it has some drawbacks. We can’t assign multiple handlers to a particular event because adding a new handler overrides the previous one, unlike the addEventListener method, which allows us to add multiple handlers.

Open Source Session Replay

OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data. OpenReplay Start enjoying your debugging experience - start using OpenReplay for free.

User-defined events

The events we have been using in this article, like the click and scroll event, are all predefined events, meaning they exist by default. Developers can define their event to solve a specific problem. This can be done using the Event constructor or the customEvent constructor. The customEvent constructor allows developers to add more data to the events they have created, stating whether it should bubble or not, and also developer can add a value that should be passed to the handler (callback function); the Event constructor doesn’t give developers this option. The code below shows how to create a user-defined event using both the Event constructor and CustomEvent constructor.

// Using Event constructor
const userDefinedEvent = new Event('myevent')

const button = document.getElementById('btn')

// Listen for the event.
button.addEventListener('myevent', (e) => { /* … */ });

// Dispatch the event.
button.dispatchEvent(userDefinedEvent);

// Using customEvent constructor
const userDefinedEvent = new CustomEvent('myevent', { bubbles: true, detail: elem.value })

const button = document.getElementById('btn')

// Listen for the event.
button.addEventListener('myevent', (e) => { /* … */ });

// Dispatch the event.
button.dispatchEvent(userDefinedEvent);

In the code above, we used the dispatchEvent method to dispatch the event when a user triggers it by an action.

Event Bubbling

When an event resides in an element inside another element and both elements have registered a handle to that event, the HTML DOM API uses event bubbling as a form of event propagation. It is a procedure that begins with the element that caused the event and then cascades up to the elements in the hierarchy that contain it. When an event bubbles, the innermost element captures and manages it before passing it along to the surrounding elements, the unordered element that contains the list element.

<ul id="list">
    <li id="child1"> I am </li>
    <li id="child2"> Learning </li>
    <li id="child3"> About </li>
    <li id="child4"> Javscript </li>
    <li id="child5"> Event </li>
</ul>

Assuming the outermost element <ul> listens for a click event and the child element <li> listens for the same event.

Example:

const parentElement = document.getElementById("list")
const child1 = document.getElementById("child1")
const child2 = document.getElementById("child2")
const child3 = document.getElementById("child3")
const child4 = document.getElementById("child4")
const child5 = document.getElementById("child5")

// adding an event listener to the parent element
parentElement.addEventListener('click', ()=>{
    console.log('parent was clicked')
})

// adding event listener to all the child element
child1.addEventListener('click', ()=>{
    console.log('child1 was clicked')
})
child2.addEventListener('click', ()=>{
    console.log('child2 was clicked')
})
child3.addEventListener('click', ()=>{
    console.log('child3 was clicked')
})
child4.addEventListener('click', ()=>{
    console.log('child4 was clicked')
})
child5.addEventListener('click', ()=>{
    console.log('child5 was clicked')
})

If we check the console when a child element is clicked, we will observe that the console will log two times, one for the parent and the other for the child. This is because when the child element was clicked, its event listener was triggered. After triggering the child’s event listener, this event also propagated. It triggered the parent’s event listener, causing the console to log the statement of both the parent and child event handler.

How to stop event propagation

From what we explained in event bubbling, we said that event bubbling is the propagation of an event from a child element up to its outermost parent. Sometimes, we might want to prevent this propagation from reaching the outermost parent. To do this, we use an event method called stopPropagation. This method stops the API from propagating the event to the outermost element. Using our bubbling sample, this stops the event from propagating.

const parentElement = document.getElementById("list")
const child1 = document.getElementById("child1")
const child2 = document.getElementById("child2")
const child3 = document.getElementById("child3")
const child4 = document.getElementById("child4")
const child5 = document.getElementById("child5")

// adding an event listener to the parent element
parentElement.addEventListener('click', ()=>{
    console.log('parent was clicked')
})

// adding event listener to all the child element
child1.addEventListener('click', (e)=>{
    e.stopPropagation() //stopping the event from propagating further
    console.log('child1 was clicked')
})
child2.addEventListener('click', (e)=>{
    e.stopPropagation() //stopping the event from propagating further
    console.log('child2 was clicked')
})
child3.addEventListener('click', (e)=>{
    e.stopPropagation() //stopping the event from propagating further
    console.log('child3 was clicked')
})
child4.addEventListener('click', (e)=>{
    e.stopPropagation() //stopping the event from propagating further
    console.log('child4 was clicked')
})
child5.addEventListener('click', (e)=>{
    e.stopPropagation() //stopping the event from propagating further
    console.log('child5 was clicked')
})

The e inside the function parenthesis represents the event object.

Event delegation

However, event bubbling can be quite helpful and isn’t just irritating, and it makes possible a technique known as event delegation. In this method, rather than having to set the event listener on every child separately, when we want some code to run when the user interacts with any one of a large number of child elements, like the code above, we set the event listener on their parent and have events that happen on them bubble up to their parent. To capture the particular element that fired the event, we use the target method of the event.

Example: Using our bubble example, let’s change the inner text of the clicked child using the event delegation method.

    // Instead of adding an event listener to all element 
    // we add it only to the parent and wait till the event propagates to it.

    parentElement.addEventListener('click', (e)=>{
        /* 
         The e is the event object.
         The e.target gets the actual child (target) that was clicked, 
         even though the event listener was added to the parent element only
        */
        e.target.innerText = 'Someone clicked me' 
    })

Conclusion

In this article, you have learned about Javascript Events and what triggers them. They have listeners and handlers; listeners listen to actions, while handlers are callback functions used when an event is triggered. Handlers, as we said, are normal Javascript functions; any logic can be written inside of it, meaning we can do many things using Javascript events. We also discussed event bubbling, event delegation, how to declare a user-defined event, and how to dispatch it using the dispatchEvent method. Javascript event is powerful in that it can’t be left behind when creating dynamic and interactive web pages.

A TIP FROM THE EDITOR: Check also our JavaScript Event Loop And Call Stack Explained article for more about internal JavaScript details.

newsletter