# Event Buddling and Capturing

## Overview

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFW3x2aqEO8GF2kr3VU%2Fuploads%2FTOq1WJoKAJzW76ZsJR1u%2Fimage.png?alt=media\&token=34a630fd-eaf3-4bbe-a4ec-9fdf7b2a884b)

1. Capturing phase – the event goes down to the element.
2. Target phase – the event reached the target element.
3. Bubbling phase – the event bubbles up from the element.

## Buddling

* When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.

```html
<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form onclick="console.log('form')">FORM
  <div onclick="console.log('div')">DIV
    <p onclick="console.log('p')">P</p>
  </div>
</form>

Output:
p div form
```

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFW3x2aqEO8GF2kr3VU%2Fuploads%2FTNJjUjUljy35vg2ZAUBN%2Fimage.png?alt=media\&token=f989e367-ab90-47eb-a3ed-60e7f0833912)

## Targeting

* The most deeply nested element that caused the event is called a *target* element, accessible as `event.target`.
* Note the differences from event.currentTarget:
  * event.target – is the “target” element that initiated the event, it doesn’t change through the bubbling process.
  * event.currentTarget  – is the “current” element, the one that has a currently running handler on it.
* In form.onclick handler:
  * event.currentTarget is the \<form> element, because the handler runs on it.
  * event.target is the actual element inside the form that was clicked.
* event.stopPropagation() stop event budding up to parent element

## Capturing

* To catch an event on the capturing phase, we need to set the handler `capture` option to `true`:

```javascript
elem.addEventListener(..., {capture: true})
// or, just "true" is an alias to {capture: true}
elem.addEventListener(..., true)
```

* Example

```html
<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form>FORM
  <div>DIV
    <p>P</p>
  </div>
</form>

<script>
  for(let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => console.log(`Capturing: ${elem.tagName}`), true);
    elem.addEventListener("click", e => console.log(`Bubbling: ${elem.tagName}`));
  }
</script>

// output:
Capturing: html
Capturing: form
Capturing: div
Capturing: p
Buddling: p
Buddling: div
Buddling: form
Buddling: html
```

## Custom Event

```javascript
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

// Create a new event, allow bubbling, and provide any data you want to pass to the "detail" property
const eventAwesome = new CustomEvent("awesome", {
  bubbles: true,
  detail: { text: () => textarea.value },
});

// The form element listens for the custom "awesome" event and then consoles the output of the passed text() method
form.addEventListener("awesome", (e) => console.log(e.detail.text()));

// As the user types, the textarea inside the form dispatches/triggers the event to fire, and uses itself as the starting point
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
```

## Reference

{% embed url="<https://javascript.info/bubbling-and-capturing>" %}
