Deep dive into the browser events with mindmaps
Tags: javascript, dom, events, browser
Published: 2023-03-21 18:04:59

---
title: Deep dive into the browser events with mindmaps 
published: true
description: This is a deep dive into DOM events. We will also discuss some common, but often misunderstood things about DOM events. Finally, we will understand how to create our own custom DOM events.
tags: #javascript #DOM #events #browser
# cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pu2cuxnmvlqsslrdz7pb.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-02-09 03:55 +0000
---
This is an extensive exploration of the intricacies surrounding DOM events. First and foremost, we will delve into the various types of DOM events, examining each of their unique characteristics and how they are triggered. Additionally, we will take a closer look at some of the more commonly misunderstood aspects of DOM events, such as the propagation and bubbling of events.

## What is a browser event?

Let's simply put it this way an event is an object which has the property that contains information about that particular event, such as on what element the event is triggered and many other information about that particular event.

![DOM event mindmap](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pscm0h9v6k4ion00a6pm.png)

## Events can be generalised into 2 categories

- User-agent events
- synthetic events

 User-agent events are dispatched by the browser based on user interactions or any other browser(page) task is completed.

For example

1. The user clicks on the button
2. The user submits the form
3. All the resources have been downloaded.

And may more, we can add a listener to the event in order to listen to the events

```jsx
window.addEventlistner('load',(event)=>{console.log(event));
```

### Synthetic events

![Synthetic events](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehko350m4rjh1jov6ir2.png)

On the other hand, synthetic events are the events that are created/emitted by applications.

For example

```jsx
const event = new Event('myEvent', {bubbles:true, cancelable: true});

//dispatch events
document.dispatchEvent(event);

//events can be dispatched from any element
document.getElementbyId('myDiv').dispatchEvent(event)
```

If we want to pass the data then we can use `CustomEvent()`.

```jsx
const event = new CustomEvent('myCustomEvent', {detail: {message:'hello world'});

elem.addEventListner('myCustomEven', (event)=>{
console.log(event.detial.message)
})
```

The `isTrusted` is the property in the event object that is true for user-agent dispatched events and false for the applications(developers) initiated.

### Event phase

![Event Phase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qw1vsewrt5jyz67ikiyb.png)

When we further inspect the event object we also get a property name `eventPhase`. In order to understand this property let us first understand what is `CAPTURING_PHASE` and `BUBBLEING_PHASE`.

When an event is dispatched it will occur in the event will reach to document(root) and then back to the target element(in the above diagram button). The flow from top to bottom is called **capturing phase** and the bottom to top is called the ********bubbling phase.******** let us take a step forward and understand the above diagram with code

```html
<!DOCTYPE html>
<html>

<head>
	<title>Parcel Sandbox</title>
	<meta charset="UTF-8" />
</head>

<body >
	<form id='submit_form' style="border:1px solid red; padding: 4rem">
    <button type='submit' id='submit_button'>Submit<button>
    </div>
	</form>
	
	<script>

			function eventListener(event) {
						console.log({
					    target: event.target,
					    currentTarget: event.currentTarget,
					    phase: event.eventPhase,
					    type: event.type
				  });
			}

		const form = document.getElementById("submit_form");
		const buttonContainer = document.getElementById("button-wrapper");
		const submit = document.getElementById("submit_button");
		
		form.addEventListener("click", eventListener);
		buttonContainer.addEventListener("click", eventListener);
		submit.addEventListener("click", eventListener);

	</script>
</body>

</html>
```

This is a long example let's break it down. We have a simple form and later we are attaching some event listeners to it. The  `addEventListner()` function takes 3 arguments 

- event name that the event listener should listen
- a callback function that should be called.
- And the last one is an **option** or **useCapture.** It is an optional argument.

All the arguments are pretty much clear by the name the only argument that we care about is **option** and **useCapture.** 

The option has these parameters. 

- capture: The default value is false. The event will first be captured with the current element to which the event listener is attached (i.e element above in the DOM tree) and then later will be dispatched to any event target
- once: The events should be invoked once and removed by default
- passive: If true it tells the browser that the callback functions will not have the `preventDefault().` Even if the `preventDefault` is there in the callback function the browser will only throw and warning in the console.
- signal: It's used for removing the event listener by providing the `AbortSignal`. We will talk about the abort signal later in this blog.

### Capturing and bubbling phase

In the example above we have attached listeners at the document, body, form and button We run the above example the output will be like this

```jsx
{target: button#submit_button, currentTarget: button#submit_button, phase: 2, type: 'click'}
{target: button#submit_button, currentTarget: div#button-wrapper, phase: 3, type: 'click'}
{target: button#submit_button, currentTarget: form#submit_form, phase: 3, type: 'click'}
```

To understand this we first need to look into the `Event` object. The user agent-generated event object mainly has these properties

![Event Object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xke9n3ml9dwedelc601l.png)

- `type`: The type is the type of event for e.g click, submit etc. You can read more about it [here](https://developer.mozilla.org/en-US/docs/Web/API/Event)
- `eventTaget`: Returns the element on which the event occurred or null.
- `currentTarget`: Returns the element which is listening to the event
- `eventPhase`: This one is the interesting one. The event phase generally returns one of these values 0,1,2,3. What are these values? The event phase has these enums

```env
NONE = 0
CAPTURING_PHASE = 1;
AT_TARGET = 2;
BUBBELING_PHASE = 3;
```

Let us understand each of these values one by one. In the above example context, the `<button />` element is wrapped by a `div`, which is further nested inside a  `form`. So when the button has been clicked the `div` and `from` are in the capturing phase. But in the console, we don't see any `eventPhase` as 1 (i.e capturing) event listener is not being invoked. 

To invoke an event listener callback function in the capturing phase we need to specify `true` in the event listeners 

```jsx
 document.body.addEventListener("click", eventListener, true);

// or
 document.body.addEventListener("click", eventListener, { capture:true });
```

### Propagation

Now that we have a solid understanding of the event phases. Let us further look into how to stop handlers from getting called. We have 2 methods for stopping the propagation of the event.

- `event.stopPropagation()` and
- `event.stopImmediatePropagation()`

Assume we have multiple event handlers attached to an element. We have `stopHandler()` and `eventListenerLogs()`

```jsx

 
<!DOCTYPE html>
<html>
   <head>
      <title>Parcel Sandbox</title>
      <meta charset="UTF-8" />
   </head>
   <body>
      <form id='submit_form' style="border:1px solid red; padding: 4rem">
         <div id='button-wrapper' style="border:1px solid black; padding: 4rem"">
            <button type='button' id='submit_button'>Submit<button>
         </div>
      </form>
      <script>
         function stopHandler(event) {
           event.stopPropagation();
           console.log({
             target: event.target,
             element: event.currentTarget,
             phase: event.eventPhase,
             type: event.type
           });
         }
         
         const form = document.getElementById("submit_form");

					document.body.addEventListener("click", eventListener, false);
         form.addEventListener("click", stopHandler, false);
         form.addEventListener("click", eventListener, false);
               
      </script>  
   </body>
</html>
```

We have attached the event handler to `body`, and `form` element. When we click on the button the event occurs in `BUBBLEING_PHASE` and the order of event propagation should be supposed to be 

![Propogation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ae0ug6cmpfinwms78en0.png)
But since we have `event.stopPropagation()`, at the form level. the console o/p is

```jsx
{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}

{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}
```

As we have to event handler attached to `form` element. 

What if we want to only listen to the event only once then we can use `event.stopImmediatePropagation()` 

```jsx
function stopHandler(event) {
           event.stopImmediatePropagation();
           console.log({
             target: event.target,
             element: event.currentTarget,
             phase: event.eventPhase,
             type: event.type
           });
         }
```

Now the output is 

```jsx
{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}

```

### Cancelable

A cancelable event’s read-only property returns `true` or `false` based on how the event was initialized. Most of the native events are cancelable using `event.preventDefault()` . Calling this function is like the event never happened.  We can create a `syntheticEvent` and make it non-cancelable.

```jsx
const myCoustomEvent = new CoustomEvent("my-coustom",{
cancelable:true
})

document.addEventListener('my-event', function (event) {
   event.preventDefault()
})

console.log(
  document.dispatchEvent(event) ? 'Event was not cancelled' : 'Event was cancelled'
)

//output
//"Event was cancelled"
```

If we change the `cancelable` property to false the output will be `Event was not cancelled` . 

### PreventDefault

`event.preventDefault()` will stop the native element action from happening. This means that the event will not work in the same way as if the event never happened.

### Conclusion.

That concludes our discussion on events and how to create custom ones. We covered the various phases involved in triggering events and explored the cancelable event.

Thank you for reading. Please let me know in the comments section if I missed anything.