The DOM & Events

Learning Competencies

By the end of this section, you should be familiar with and able to:

  • Explain events and event handlers in relation to the DOM

Time Box

ActivityTime
Events30 minutes

Events

We want our web pages and applications to be interactive, right? To accomplish this goal, we need to have some way of recognising when a user interacts with our page.

We need to be able to capture other clicks, keystrokes, mouse moves, and more. What about when the user resizes the window? Or when they drag and drop an item? Or they right click on an item?

Each of these occurrences is an "event". The most frequently used mouse or keyboard events are:

  • 'click'
  • 'mouseenter'
  • 'keyup'

There are many more. You can check out the list on the MDN Event reference.

We handle events by attaching an "event handler" to the object we want to keep track of and providing that event handler with a "callback" function that we want it to use when the event occurs.

So, essentially, we can write some code which says to the browser, "When the user clicks on this button, we want you to call this function and give it an 'event object' with lots of information about the event that occurred."

Making an Event Handler

Let's add a button to our page, and give it an id so it's easy to grab hold of it in the DOM.
Note: If you're following along at home, I've just removed the <p> elements from the body of our previous page and replaced them with the button.

HTML page with button

Figure 9: HTML for our page with a button.

Now let's add an event handler to the button using the .addEventListener() method, and we'll pass it a function to call when the button is clicked. In this instance we will just ask it to log the event object that gets passed to the callback.

document.querySelector('#test-button').addEventListener(
'click',
(event) => { console.log(event) },
)

Then, once we've run that code, we can click on the button and we should see the following:

Console logging the event object

Figure 10: The console logged event object.

You can see that there's a lot of stuff in the event object. Let's have a closer look at one useful part of that object - the target key. Let's change our console log to see what's inside it.

document.querySelector('#test-button').addEventListener(
'click',
(event) => { console.log(event.target) },
)

Console logging 'event.target'

Figure 11: The target is the button element.

Okay, so now that we know that event.target is a thing, let's use some of the skills we learned earlier to make the text on the button change when we click on it:

document.querySelector('#test-button').addEventListener(
'click',
(event) => { event.target.innerHTML = "Woah!" },
)

Let's see what happens when we click on the button now:

using 'addEventListener' to change the innerHTML of a button

Figure 12: Sweet, the button changed.

What if we don't care about the target of the event and want to affect other elements instead? Easy! Check this example out:

document.querySelector('#test-button').addEventListener(
'click',
() => { document.querySelector('h1').innerHTML = "I'm a header, and I have changed" },
)

So here we aren't actually using the event object. (Note we didn't even put it into the parameters of our callback function.) All we care about is that the event has happened. Then inside the function we are grabbing the <h1> element and changing the innerHTML of it.

using 'addEventListener' to change the inner HTML of an <h1> element

Figure 13: Yay, we've changed the header!

Keystroke Events

Okay, now it's time to try something a little more complex.
What if we wanted to capture keystrokes in a text field and output them immediately to a <p> below the text field. You've probably seen something like this before, right?

First, let's modify our page:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<div id="app">
<header>
<h1>My keystroke test page</h1>
</header>
<main>
<p>
<input id="keystroker">
</p>
<p id="outputter"></p>
</main>
</body>
</html>

HTML page with simple text input field

Figure 14: It should look like this in your browser.

Now we can grab our input and attach an event handler to it to capture keystrokes. We can capture the stroke on the way down (keydown), the way up (keyup), or both (keypress). We want to check the innerHTML after it has been updated with the new value, so we'll use keyup.

With each keyup event, we'll update the paragraph below the input so that its content is the value of the input:

let input = document.querySelector("#keystroker")
let output = document.querySelector("#outputter")
function updater (event) {
output.innerHTML = input.value
}
input.addEventListener("keyup", updater)

Here we've done 4 things:

  • We've grabbed the <input> with the id of 'keystroker' and assigned it to the variable 'input'
  • We've grabbed the <p> element with the id of 'outputter' and assigned it to the variable 'output'
  • We've created a function called 'updater' which takes the value of the 'input' and pastes it into the innerHTML of 'output'
  • We've added an event handler to 'input', so that every time a keyup event happens, it calls the 'updater' function. This means every keypress, the contents of the 'outputter' <p> element will be updated.
Keyboard events being used to duplicate text from an input field

Figure 15: Check it out.

Break time

We're nearly done! Take some time to let this info sink in. Post questions or blocks on Discord so your cohort and online community can help you. Continue onto the next block when you feel ready to.