Event Listeners

This YouTube video was created by Steve Griffith.

DOM Events are notifications that some action has occurred on the page and can represent a basic user action or the status of the render model. For example, when a user clicks on a button, that is a DOM Event. When the pages loads, that is a DOM Event. When the page is scrolled, the window is resized, or the mouse is moved are all DOM Events. There are DOM Events for the keyboard, mouse, touch, clipboard, media, view, printing, drag & drop, animation, forms, and more.

Event Listeners are JavaScript objects that listens for a specific DOM Event to occur and executes a function when it does. Event Listeners are created using the addEventListener() method.

const button = document.getElementById('button')

button.addEventListener('click', function () {
  alert(`You pressed the button!`)
})

Event Types

Mouse Events

This YouTube video was created by Steve Griffith.

Mouse events occur when the user uses the mouse to interact with the page. While there are many different Mouse Events, the most common used are click, mouseover, and mouseout.

Keyboard Events

This YouTube video was created by Steve Griffith.

Keyboard events occur when the user uses the keyboard to interact with the page. There are only three keyboard events: keydown, keydown, and keypress (ignores modifier keys). When a key is pressed the browser will provide a key code that can be used to identify which key was pressed. These codes are retrieved using a property from the Event object. Unfortunately, this part of the API is in the middle of a transition period, so there are two common properties that can be used to retrieve the key code.

The old property is keyCode, which will provide a number of the represents the key pressed. This number will be different depending on the which the keyboard event.

The new property is key, which provide a string that represents the key pressed.

Other Standard Events

While the most common events types are going to come from the the mouse or keyboard, there are many other Standard Events that can be used.

The change event is fired for <input>, <select>, and <textarea> elements when a change to the element's value is committed by the user.

Event Listeners on Multiple Elements

Sometimes it is necessary to add an event listener to multiple elements. At first you may fear that you will have to add the event listener to each element individual. While this is true to some extent, there are a couple of techniques that make this process much less painful.

Using a Loop

The first way to add an event listener to multiple elements is to use a loop. When retrieving multiple elements using the querySelectorAll() method an array to returned. Using this array and the for...of loop, it possible to add the same event listener to each element. Additional, by defining the event handler function outside of the addEventListener() method, we can make the code our more efficient.

Using Event Delegation

This YouTube video was created by Steve Griffith.

Event delegation refers to the process of using event propagation (bubbling) to handle events at a higher level in the DOM than the element on which the event originated. It allows us to attach a single event listener for elements that exist now or in the future.

Consider the following HTML:


<ul id="list">
    <li class="item">Clean the car</li>
    <li class="item completed">Feed the cat</li>
    <li class="item">Buy milk</li>
</ul>

Using traditional event listener techniques, if we wanted to toggle the completed class when a list item is clicked, we would have to add an event listener to each list item. However, by using event delegation, this can be done with a single event listener added to the list, instead of the list items. However, to make this work, we will need to add an if statement to varify that the event target is a list item and not the list itself. This can be accomplished by using the classList.contains() method.


const $list = document.getElementById('list')

$list.addEventListener('click', function (e) {
    if (e.target.classList.contains('item')) {
      e.target.classList.toggle('completed')
    }
})

However, if there are additional children inside the target element. In the following example, and an icon is added to the list items that are important. If you were click on the icon instead of the item using the javascript code above, nothing will happen. However, this problem is solved using the closest() method.

The closest() method of the Element interface returns the closest ancestor of the current element (or the current element itself) which matches the selectors given in a parameter. If no such element exists, it returns null.


<ul id="list">
    <li class="item">Clean the car</li>
    <li class="item completed"><i class="fas fa-exclamation"></i> Feed the cat</li>
    <li class="item">Buy milk</li>
</ul>


const $list = document.getElementById('list')

$list.addEventListener('click', function (e) {
    const $item = e.target.closest('.item')
    
    if ($item) {
      $item.classList.toggle('completed')
    }
})