courtesy of sports & recreation (CC)

Things you should know about JS events

or should I say, things you should know about DOM events.

If you had the chance to do some client-side JS you certainly had to handle events. While libraries such as Jquery have made it very easy and simple to do so, there is still some shady parts that I think are worth looking into.


The event object

Let’s begin by capturing a dummy event object and take a look into it, it is as easy as doing this :

If you look at the object you should end up with something like that :

You can see a lot of properties related to the actual position of the event. The isTrusted property indicate that the event was generated by an actual user and not a script. Today we are not going to cover them all, but only the four inside the red rectangles.

useCapture, or the unknown parameter

So this is how I added the event listener to my body :

This is what my DOM looked like during the capturing of this event :

So by clicking on on a div tag, an handler attached to the body was executed, how is that possible ? I mean, I clicked on a div tag, not on the body. Well, the first answer that come in your mind could be:

“Events traverse dom, end of the story, nothing worth writing an article’’

And you are right, events do traverse the dom, but in what order ? I mean, think about it. Two orders are possible, and both equally make sense.

  • The dom order (unofficial name)

So the DOM is a tree right, and to traverse a tree you go from the root to the leafs right ? So in my case the body tag would be the root, and the div tag would be the leaf, does that seem acceptable ?

“Hum why not ?, what about the other approach’’
  • The UI order (unofficial name)

You could also argue that because you, as a user, see the div above the body, and therefore click on the div and not the body, the event could go from, the div to the body. From leafs to the root. And that would makes sense too.

“ Yes, this makes more sense, and this is what I observed, where is the truth ?’’

The truth is at W3C, let’s review it together and let’s take a look at the addEventListener method.

http://www.w3schools.com/jsref/met_element_addeventlistener.asp

You see that third boolean parameter, this is where all the magic happen. By default this parameter is false, which means, following the semantic, that by default we do not use the capture. Note that this third argument is the reason I couldn’t write this post with Jquery. The click() method (or any other event related method), does not take a third parameter.

“ But what is capture ?’’

Capture is a mode and would be what we referenced before as the DOM order. The other mode, the default mode, is the bubbling mode, the UI order if you prefer. Those two modes will decide if the handler is executed during the capturing phase or bubbling phase.

The bubbling and the capturing phase

When you click on a document, the event first comes from the root of your DOM, the Window node, to the leafs, this is the capturing phase. Once the event has reach the leaf, like a bubble in water that tries to go back to the surface, the event goes back to the root of the DOM, this is the bubbling phase.

courtesy of W3C

By setting this third parameter you simply tell your DOM element to execute the handler during the bubbling phase or during the capturing phase. Because the parameter has a default value that covers most of the use case, it has become quite forgotten. By using it right we can have a lot more control on our event as I’ll show you.

What would happened if we add an event listener, for each phase, in what order would they get triggered ? Lets change the code a little bit.

And as expected, this will be the trace if we click on the div:

You can go and check by yourself here (don’t forget to open the console).

As you can see this is very simple, this third parameter allows you to tell if the outer divs should execute the handler before or after the inner divs. Note that at every moment you can tell the event to stop propagating in one mode or the other by using :

event.stopPropagation()

CurrentTarget and target

Now that you understand that events traverse the DOM in both direction there is one question that is still difficult to answer.

How in my handler can I know where is the event coming from ?

For example in our handler attached to the body, what if I want to execute the handler if we click on the body, and only on the body, not in div above. This is exactly a case where you could use currentTarget and target.

currentTarget is great, currentTarget will always have the value of the DOM element which has the event listener attached to. It means that in our case, currentTarget will always have the body element as value.

target will have as value the DOM element which receive the event in the first place (the element under your mouse). So if you want the handler to be execute only when the body is “really” clicked you can do something like that :