Complete JavaScript Course Module 9: Intermediate: Events and Forms

JavaScript Events: addEventListener Explained

  • Beginner
  • Lesson 9.1
  • 5 min read
  • 37 of 76 in the course

In short

Events let your page react when people click, type or move the mouse. This lesson explains JavaScript events and how to use addEventListener to run code when they happen. What are events in JavaScript? An event is a signal from the browser that something happened.

Events let your page react when people click, type or move the mouse. This lesson explains JavaScript events and how to use addEventListener to run code when they happen.

What are events in JavaScript?

An event is a signal from the browser that something happened. A user clicked a button, typed a letter, pressed a key, or the page finished loading. Think of a doorbell: nothing happens until someone presses it, and then you go to the door. In JavaScript, you tell an element: "When this event happens, run this function." That function is called an event listener or event handler.

You attach a listener with addEventListener(). It takes two main arguments: the event name as a string, and the function to run.

<!DOCTYPE html>
<html lang="en">
  <body>
    <button id="like">Like</button>
    <p id="count">0 likes</p>

    <script>
      const likeButton = document.querySelector("#like");
      const countText = document.querySelector("#count");
      let likes = 0;

      likeButton.addEventListener("click", () => {
        likes += 1;
        countText.textContent = `${likes} likes`;
        console.log("Clicked!", likes);
      });
    </script>
  </body>
</html>
Clicked! 1
Clicked! 2

Each time you click the button, the arrow function runs. It adds one to likes and updates the paragraph. Notice that we pass the function itself; we do not call it. Writing addEventListener("click", update()) would run update once right away, which is a common mistake.

Common events: click, input, change, keydown and mouseenter

Here are the events you will use most often:

EventWhen it fires
clickThe element is clicked or tapped (also Enter/Space on a focused button)
inputThe value of a text field changes, on every keystroke
changeThe value is committed: a checkbox is ticked, a select changes, or a text field loses focus
keydownA key is pressed down
mouseenterThe mouse pointer moves onto the element
mouseleaveThe mouse pointer leaves the element
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .tip-box { padding: 12px; background: #eef; }
      .active { background: #cde; }
    </style>
  </head>
  <body>
    <label for="name">Your name</label>
    <input id="name" type="text">
    <p id="preview">Hello, stranger!</p>

    <label for="size">Size</label>
    <select id="size">
      <option>Small</option>
      <option>Large</option>
    </select>

    <div class="tip-box" id="tip">Hover over me</div>

    <script>
      const nameInput = document.querySelector("#name");
      const preview = document.querySelector("#preview");
      const sizeSelect = document.querySelector("#size");
      const tip = document.querySelector("#tip");

      nameInput.addEventListener("input", () => {
        preview.textContent = `Hello, ${nameInput.value || "stranger"}!`;
      });

      sizeSelect.addEventListener("change", () => {
        console.log("Size chosen:", sizeSelect.value);
      });

      document.addEventListener("keydown", (event) => {
        if (event.key === "Escape") {
          nameInput.value = "";
          preview.textContent = "Hello, stranger!";
        }
      });

      tip.addEventListener("mouseenter", () => tip.classList.add("active"));
      tip.addEventListener("mouseleave", () => tip.classList.remove("active"));
    </script>
  </body>
</html>
Size chosen: Large

As you type your name, the greeting updates live thanks to input. Picking "Large" logs the choice once with change. Pressing Escape anywhere on the page clears the field; event.key tells you which key was pressed (you will learn more about the event object in the next lesson). Hovering the box changes its colour.

Tip: For things that should feel instant, like live search or a character counter, use input. For things that should happen once the user has decided, like a checkbox or a select menu, use change.

Running code when the page is ready: DOMContentLoaded

The DOMContentLoaded event fires on document when the browser has finished building the DOM. Code inside it can safely select any element.

document.addEventListener("DOMContentLoaded", () => {
  const heading = document.querySelector("h1");
  console.log("DOM ready:", heading.textContent);
});
// Output: DOM ready: Welcome

If you load your script with defer, the DOM is already ready when your code runs, so you usually do not need this event. It is still useful for scripts without defer, and you will see it in many codebases.

How to remove an event listener

Sometimes a listener should stop working, for example a "claim your free gift" button that works only once. Use removeEventListener() with the same event name and the same function. That means you must store the function in a variable; an anonymous arrow function cannot be removed because you have no name to refer to it.

<!DOCTYPE html>
<html lang="en">
  <body>
    <button id="gift">Claim free gift</button>

    <script>
      const giftButton = document.querySelector("#gift");

      const claimGift = () => {
        console.log("Gift claimed!");
        giftButton.textContent = "Gift claimed";
        giftButton.disabled = true;
        giftButton.removeEventListener("click", claimGift);
      };

      giftButton.addEventListener("click", claimGift);
    </script>
  </body>
</html>
Gift claimed!

After the first click, the listener removes itself and the button is disabled. For this "only once" case there is also a shortcut: giftButton.addEventListener("click", claimGift, { once: true }) removes the listener automatically after it runs.

Why not use onclick attributes?

In older code you will see HTML like <button onclick="doSomething()">. This mixes JavaScript into your HTML, only allows one handler per event, and needs the function to be global. Many websites also block inline code with a security setting called a Content Security Policy, so it may not run at all.

Common mistake: Writing onclick attributes in HTML. Keep HTML for structure and attach behaviour in your JavaScript file with addEventListener. You can add several listeners to the same event, and remove them when needed.

Practice exercise

Build a character counter for a tweet-like message. Add a <textarea> and a <p> that shows "0 / 140". On every input event, update the counter with the current length. When the length goes over 140, add a class too-long to the counter that makes the text red; remove it again when the text is short enough.

Hint: textarea.value.length gives the number of characters, and classList.toggle("too-long", length > 140) adds or removes the class based on a condition.

Key takeaways

  • An event is a signal that something happened; addEventListener(eventName, function) reacts to it.
  • Pass the function itself, not the result of calling it.
  • Use input for live updates, change for final choices, keydown for keys and mouseenter/mouseleave for hover.
  • To remove a listener, pass the same named function to removeEventListener, or use { once: true }.
  • Avoid onclick attributes in HTML; use addEventListener in your script.

Frequently asked questions

What is the difference between input and change events?

input fires every time the value changes, on each keystroke. change fires when the user commits the value, for example when a text field loses focus or a checkbox is ticked.

Can I add two listeners for the same event?

Yes. With addEventListener you can attach as many listeners as you like, and they run in the order you added them.

Do click events work on phones?

Yes. A tap on a touch screen fires a click event, so the same code works on desktop and mobile.