# Event Bubbling & Event Delegation in JavaScript

Yesterday, I learned how JavaScript uses **events** to respond to user interactions.

Today, I went one level deeper and explored how events actually travel through the DOM.

I learned about **Event Bubbling, Event Capturing,** `stopPropagation()`**, and Event Delegation**.

These concepts become extremely useful when working with multiple elements and dynamic content.

Let's dive in.

* * *

# 🌊 What is Event Bubbling?

When an event occurs on an element, it doesn't necessarily stay there.

The event can travel upward through its parent elements.

This process is called **Event Bubbling**.

For example:

```html
<div id="parent">
    <button id="child">Click Me</button>
</div>
```

If we click the button, the event can travel:

```text
Button
   ↓
Parent
   ↓
Body
   ↓
HTML
   ↓
Document
```

This upward movement is event bubbling.

* * *

# 🔍 Understanding Event Bubbling

Consider:

```javascript
const parent = document.querySelector("#parent");
const child = document.querySelector("#child");

parent.addEventListener("click", function () {
    console.log("Parent clicked");
});

child.addEventListener("click", function () {
    console.log("Button clicked");
});
```

When the button is clicked, the output will be:

```text
Button clicked
Parent clicked
```

The event starts at the button and then bubbles up to its parent.

* * *

# 🛑 stopPropagation()

Sometimes we don't want an event to continue bubbling.

We can stop it using:

```javascript
child.addEventListener("click", function (event) {
    event.stopPropagation();

    console.log("Button clicked");
});
```

Now the event doesn't continue to the parent.

This can be useful when nested elements have different event behavior.

* * *

# ⬇️ Event Capturing

Event capturing is the opposite direction of event bubbling.

Instead of moving from the target upward, the event travels from the document down toward the target.

The general flow is:

```text
Document
   ↓
HTML
   ↓
Body
   ↓
Parent
   ↓
Button
```

By default, event listeners use the bubbling phase.

* * *

# Capturing Phase

We can enable capturing by passing `true` as the third argument.

```javascript
parent.addEventListener("click", function () {
    console.log("Parent");
}, true);
```

Now the parent listener runs during the capturing phase.

* * *

# 🎯 Event Target vs Current Target

These two properties are important.

### `event.target`

The element that actually triggered the event.

### `event.currentTarget`

The element whose event listener is currently executing.

Example:

```javascript
parent.addEventListener("click", function (event) {
    console.log(event.target);
    console.log(event.currentTarget);
});
```

If the button is clicked:

*   `event.target` → button
    
*   `event.currentTarget` → parent
    

Understanding this difference becomes very useful with event delegation.

* * *

# 🚀 What is Event Delegation?

**Event Delegation** is a technique where we attach one event listener to a parent instead of adding separate listeners to every child.

For example, instead of:

```javascript
button1.addEventListener("click", handler);
button2.addEventListener("click", handler);
button3.addEventListener("click", handler);
```

We can attach one listener to their parent.

* * *

# Event Delegation Example

HTML:

```html
<ul id="list">
    <li>HTML</li>
    <li>CSS</li>
    <li>JavaScript</li>
</ul>
```

JavaScript:

```javascript
const list = document.querySelector("#list");

list.addEventListener("click", function (event) {

    if (event.target.tagName === "LI") {
        console.log(event.target.textContent);
    }

});
```

Now one event listener handles all the list items.

* * *

# Why is Event Delegation Useful?

Imagine a shopping cart with 100 products.

Adding a separate event listener to every button isn't always the best approach.

Instead, we can attach one listener to the parent container and determine which child was clicked.

This can make event handling more efficient and easier to manage.

* * *

# Dynamic Elements

Event delegation becomes especially useful when elements are created dynamically.

For example:

```javascript
const list = document.querySelector("#list");

const item = document.createElement("li");

item.textContent = "JavaScript";

list.appendChild(item);
```

Because the listener is attached to the parent, it can handle events from dynamically added children too.

* * *

# `matches()` Method

We can use `matches()` to check whether an element matches a CSS selector.

```javascript
list.addEventListener("click", function (event) {

    if (event.target.matches("li")) {
        console.log(event.target.textContent);
    }

});
```

This makes event delegation cleaner and more flexible.

* * *

# Common Event Handling Concepts

| Concept | Meaning |
| --- | --- |
| Event Bubbling | Event travels from child to parent |
| Event Capturing | Event travels from parent to child |
| `stopPropagation()` | Stops event propagation |
| `event.target` | Element that triggered the event |
| `event.currentTarget` | Element handling the event |
| Event Delegation | Parent handles events for its children |

* * *

# Best Practices

✔ Use event delegation when many similar elements need the same event handling.

✔ Understand `event.target` and `event.currentTarget`.

✔ Use `stopPropagation()` only when necessary.

✔ Avoid unnecessarily attaching hundreds of individual listeners.

✔ Keep event-handling logic clear and focused.

* * *

# My Biggest Takeaway

Today, I learned that JavaScript events are more than simply clicking a button.

Events travel through the DOM, and understanding that process gives me much more control over how my applications respond to user interactions.

The concept that stood out the most was **Event Delegation**.

Instead of attaching listeners to every individual element, I can use a parent element to handle events from its children.

This is a powerful technique that I'll definitely use when building larger and more dynamic applications.
