← Back to Chapters

JavaScript DOM Event Listeners

?️ JavaScript DOM Event Listeners

⚡ Quick Overview

addEventListener() lets you attach JavaScript code to DOM events (like clicks, key presses, focus, etc.) in a clean and flexible way. It:

  • Keeps JavaScript separate from HTML (no inline onclick attributes).
  • Allows multiple listeners on the same element and event type.
  • Supports advanced control like capturing, bubbling, and one-time execution.

? Key Concepts

  • Event type: e.g. "click", "focus", "keydown", "mouseover".
  • Event handler: the function that runs when the event occurs.
  • Anonymous vs named functions: named functions can be reused and removed.
  • Event object: provides info like type, target, position, etc.
  • Bubbling & capturing: which phase of the event flow you handle.
  • Options like { once: true } for one-time listeners.
  • Multiple listeners: you can attach several different listeners to the same element.
  • Removing listeners: done with removeEventListener() and a named function.

? Syntax / Theory

General syntax of addEventListener():

? View Syntax
element.addEventListener(eventType, handler, useCaptureOrOptions);

// eventType           → string, e.g. "click", "keydown"
// handler             → function to run when the event fires
// useCaptureOrOptions → optional:
//   - Boolean (true = capture, false = bubble)
//   - OR options object (e.g. { once: true, capture: true })

To remove a listener, the function must be the same reference:

? View removeEventListener Syntax
function handleClick() {
  console.log("Clicked!");
}

button.addEventListener("click", handleClick);

// Later:
button.removeEventListener("click", handleClick);

? Basic Example

Attach a simple click event listener to a button:

? View Basic Click Example
<button id="myBtn">Click Me</button>

<script>
document.getElementById("myBtn").addEventListener("click", function() {
  alert("Button was clicked!");
});
</script>

? Named vs Anonymous Functions

Named functions are reusable and easier to remove later. Anonymous functions are convenient for short, one-off handlers.

? View Named Function Example
<button id="btnNamed">Greet</button>

<script>
function greetUser() {
  console.log("Hello, user!");
}

document.getElementById("btnNamed").addEventListener("click", greetUser);
</script>

? Using the Event Object

The handler receives an event object with details about what happened.

? View Event Object Example
<button id="infoBtn">Show Info</button>

<script>
document.getElementById("infoBtn").addEventListener("click", function(e) {
  console.log("Event type:", e.type);
  console.log("Clicked element:", e.target.tagName);
});
</script>

? Removing Event Listeners

To remove a listener, you must pass the same named function reference to removeEventListener().

? View Remove Listener Example
<button id="add">Start</button>
<button id="remove">Stop</button>

<script>
function greet() {
  alert("Hi there!");
}

const addBtn = document.getElementById("add");
const removeBtn = document.getElementById("remove");

addBtn.addEventListener("click", function() {
  // Attach mouseover listener
  addBtn.addEventListener("mouseover", greet);
});

removeBtn.addEventListener("click", function() {
  // Remove mouseover listener
  addBtn.removeEventListener("mouseover", greet);
});
</script>

? Multiple Events on the Same Element

You can attach multiple listeners to react to different events on the same element.

? View Multiple Events Example
<input id="inputBox" placeholder="Hover or type">

<script>
const box = document.getElementById("inputBox");

box.addEventListener("focus", () => {
  box.style.borderColor = "green";
});

box.addEventListener("blur", () => {
  box.style.borderColor = "";
});
</script>

? One-Time Listeners with once: true

Using the options object, you can make a listener automatically remove itself after running once.

? View once: true Example
<button id="onceBtn">Click Once</button>

<script>
document.getElementById("onceBtn").addEventListener("click", () => {
  alert("This will only happen once!");
}, { once: true });
</script>

? Capturing vs Bubbling Phase

By default, events are handled in the bubbling phase (from inner to outer elements). Passing true or { capture: true } switches to capturing (outer to inner).

? View Capturing Example
<div id="outer" style="padding:20px;background:#ccc;">
  <button id="inner">Inner</button>
</div>

<script>
document.getElementById("outer").addEventListener("click", () => {
  console.log("Outer Div clicked - Capturing");
}, true);

document.getElementById("inner").addEventListener("click", () => {
  console.log("Inner Button clicked - Bubbling");
});
</script>

? When to Use Event Listeners

  • Handling user interactions like clicks, typing, focus, scrolling, and resizing.
  • Creating interactive UI components such as modals, dropdowns, and sliders.
  • Reacting to form events (validation, submit, input changes).
  • Building games, dashboards, and applications that respond to user actions in real time.

? Live Output / Explanation

The following mini demo uses addEventListener() to count how many times a div was clicked.

? Click Counter Demo

Click the box below and watch the counter update using a DOM event listener.

Click me!

Total clicks: 0

Under the hood, JavaScript listens for the click event on the box and updates the text content each time.

? Tips

  • Use named functions when you may need to remove or reuse the listener later.
  • Use { once: true } for one-time events like welcome popups.
  • Call e.stopPropagation() when you want to prevent bubbling to parent elements.
  • Attach listeners after the DOM is ready (e.g. inside DOMContentLoaded or at the bottom of the page).

? Try It Yourself

  • Create a button that shows a message using addEventListener().
  • Use { once: true } to restrict an alert to one-time only.
  • Highlight an input field on focus and blur using addEventListener().
  • Add a keypress logger to an input field and print pressed keys in the console.
  • Implement a counter that increases every time a div is clicked.
  • Stop an event from bubbling using event.stopPropagation().
  • Test bubbling vs capturing using nested elements with different listeners.