Event in Javascript Part 2

Vikash Agarwal
6 min readDec 29, 2015

--

This is in continuation of Event in Javascript Part 1.

Event Object

Browser creates an event object, which has complete information about the event, flow, path, target element, x y coordinates of the target element and a lot more. It also provides function such has stopPropagation(), preventDefault(), stopImmediatePropagation(). Lets look at the properties first and then functions

  • target :- event object keep a reference of the element, which has generated the event. It never changes and remain same through out the flow.
  • currentTarget :- currentTarget keep a reference of the element which is currently dealing with the event object. It keeps changing at each level. It represent the current DOM element, whose listener function is executed.
  • eventPhase :- it has value 1,2,3 depending the phase the event is handled. 1 says it currently handled in the capturing phase, 2 is for targeting and 3 for bubbling. You can use this value if you are not sure the listener function is executed in which phase.
  • path :- it represent the path from targeting to the bubbling phase. It’s useful in event delegation. Event delegation is the right way to register event handlers for large number of DOM elements.

Lets see about the above properties based on our example.

<p> This is a paragraph </p>
<div id="div">
<button id="frst"> First button inside div</button>
<button id="second"> Second button inside div</button>
</div>
//JS Codevar secondButtonElem = document.getElementById("second");
var divElem = document.getElementById("div");
var bodyElem = document.getElementsByTagName("body")[0];
bodyElem.addEventListener("click",function(event){
console.log("body is clicked, Phase:",event.eventPhase," target:", event.target.id, " currentTarget:",event.currentTarget, " path:",event.path);
});
divElem.addEventListener("click",function(event){
console.log("div is clicked, Phase:",event.eventPhase," target:", event.target.id, " currentTarget:",event.currentTarget, " path:",event.path);
}, true);
secondButtonElem.addEventListener("click",function(event){
console.log("button is clicked, Phase:",event.eventPhase," target:", event.target.id, " currentTarget:",event.currentTarget, " path:",event.path);
});

JS Fiddle Link :- https://jsfiddle.net/vikash20186/ymj9srat/3/

I have added an event listener for the body elem in the bubbling phase, event listener for div elem in the capture phase and button also in bubbling phase.

When second button is clicked, browsers creates an event, event is passed from window to div and its event handler would be executed, then button click handler would be executed and then body click handler. body click handler is registered in the bubbling phase, therefore its executed at the end.

event handler at div :- it logs in the console

div is clicked, Phase: 1 target: second currentTarget: <div id=​”div”>​…​</div> path: [button#second, div#div, body, html, document, Window]

phase is 1 which represent the capture phase, target is second button as this is the element which has generated the event, currentTarget is div, the DOM element which is current handling the event and path represent the path of the target element to window object.​

After this is executed, event reaches the button element

event handler at second button :- it logs in the console

button is clicked, Phase: 2, target: second currentTarget: <button id=​”second”>​ Second button inside div​</button>​ path: [button#second, div#div, body, html, document, Window]

Phase is 2 which represent the target phase, target is second button, currentTarget is second button, and path remains same. If you notice, the currentTarget changed from Div, to Button. In the target phase, target and currentTarget both points to the same DOM element which has generated the event. eventPhase also changed from 1 to 2 as event is in target phase compared to the capturing phase earlier.

After this is executed, event starts going back and reaches the body element

event handler at body :- it logs in the console

body is clicked, Phase: 3 target: second currentTarget: <body>​… </body>​ path: [button#second, div#div, body, html, document, Window]

Phase is 3 which represent the bubbling phase, target is second button, currentTarget is body, and path remains same. The currentTarget changed again from Button to Body. eventPhase also changed from 2 to 3.

The same event object is passed from one node to another node and it keeps updating its properties based on the phase and the current node.

event.stopPropagation()

stopPropagation is used to stop the event moving forward in the event flow. We might need to change the flow of the event based on certain condition. In our earlier example, in div click handler, if we execute event.stopPropagation(), then event won’t continue any further and listener function will not execute for the button and body DOM element.

divElem.addEventListener("click",function(event){
event.stopPropagation();
console.log("div is clicked, Phase:",event.eventPhase," target:", event.target.id, " currentTarget:",event.currentTarget, " path:",event.path);
}, true);

JS Fiddle Link :- https://jsfiddle.net/vikash20186/ymj9srat/5/

event.stopImmediatePropagation()

stopImmediatePropagation is same as stopPropagation plus it stops at the same level. Lets say we have two event handlers for div element in the capturing mode,

divElem.addEventListener("click",function(event){
event.stopPropagation();
console.log("div is clicked, Phase:",event.eventPhase);
}, true);
divElem.addEventListener("click",function(event){
console.log("div is clicked, Phase:",event.eventPhase);
}, true);

JS Fiddle Link :- https://jsfiddle.net/vikash20186/ymj9srat/6/

Now when button is clicked, both the div event handler would be executed and event would be stopped. stopPropagation stops the event to flow to the next level. But it cannot the stop the event to execute another handler at the same level. That’s why both the handler is executed right now.

In case we use stopImmediatePropagation(), then it will also stop event to execute the event handler at the same level as well.

divElem.addEventListener("click",function(event){
event.stopImmediatePropagation();
console.log("div is clicked, Phase:",event.eventPhase);
}, true);
divElem.addEventListener("click",function(event){
console.log("div is clicked, Phase:",event.eventPhase);
}, true);

Now, only first div click handler would be called and other will not be executed.

stopImmediatePropagation() is used very less. but its good to know. Lets see an example of stopPropagation().

JS Fiddle Link :- https://jsfiddle.net/vikash20186/8ahrze45/

event.preventDefault()

Some of the event has some default behavior associated with it. Like input keypress event, anchor click event, checkbox click event etc...

We can prevent the default behavior of the event by calling preventDefault() function on the event object. For ex

Input keypress event :- When we type in text input or text area, as soon we hit the keyboard, it triggers the keydown, keypress and keyup event in sequence. The default behavior of the event is to show the character which has pressed by the user.

Checkbox click event :- Another example is when we click on a checkbox, it toggles the state. The click event generated by the checkbox actually toggles the state of it.

Anchor click event :- When we click on an anchor tag, browser redirects us to the address associated with that anchor tag.

These are some of the examples of the default behavior. Javascript gives us the ability to prevent the default behavior of an event. For Ex

Input keypress event :-

var inputElem = document.getElementById("inputText");
inputElem.addEventListener("keypress", function(event){
event.preventDefault();
});
/*
When we call preventDefault(), the text entered by the user won't appear in the input box or text area.
*/

Checkbox click event :-

var checkboxElem = document.getElementById("checkboxElem");
checkboxElem.addEventListener("click", function(event){
event.preventDefault();
});
/*
After this the state of the checkbox will not change.
*/

Anchor click event :-

var anchorElem = document.getElementById("anchorElem");
anchorElem.addEventListener("click", function(event){
event.preventDefault();
});
/*
The user will not be navigated to the address mentioned in anchor href attribute.
*/

preventDefault() is very handy feature and is used a lot in the application depending on the context. For ex, It can be used for designing an input box which accepts only number or event number or only string.

Fiddle Example to show PreventDefault()

Custom Event

We can also create custom event and trigger them. It works exactly same as other events in javascript.

You can use the below code to create an event in javascript

var myEvent = new Event("myEvt");
//or Create a basic event
var myEvent1 = new CustomEvent("myEvt");
//or
var myEvent2 = new MouseEvent("click",{cancelable:true, bubbles: true})

Once you create an event, you can use any DOM element, document or window to dispatch that event. You need to use addEventListener to handle the event.

document.addEventListener("myEvt",function(){
console.log("inside myEvt event handler");
});
document.dispatchEvent(myEvent1);

You can use Event() to create a basic event or you can use CustomEvent() and pass some extra information with the event object. You can also create MouseEvent() or any other inbuilt event. You can specify the cancelable and bubble flag while creating an event.

For Ex :-

<div> this is div
<button>Trigger Event</button>
</div>
var buttonElem = document.querySelector("button");
var divElem = document.querySelector("div");
buttonElem.addEventListener("testEvent", function(evt){
console.log("button is handling the testEvent", evt.target, evt.currentTarget, evt.detail);
});
divElem.addEventListener("testEvent", function(evt){
console.log("button is handling the testEvent", evt.target, evt.currentTarget, evt.detail);
});
document.addEventListener("testEvent", function(evt){
console.log("button is handling the testEvent", evt.target, evt.currentTarget, evt.detail);
});
buttonElem.addEventListener("click", function(evt){
var event = new CustomEvent("testEvent",{
bubbles : true,
cancelable : true,
detail : {
"source" : "button"
}
});
buttonElem.dispatchEvent(event);
});

CustomEvent event behaves the same way as the inbuilt event works. You can use stopPropagation, preventDefault() and other methods. When preventDefault() is called, dispatchEvent will return false.

buttonElem.dispatchEvent(event); // returns true by default.
// if event.preventDefault() is called anywhere then it returns false.
Fiddle example to show the custom event.

More details can be found @

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

Custom Events are great to communicate between the DOM element when used as component. We can divide the application into smaller independent component and use event to communicate within components.

Read about event delegation @ Event In Javascript- Part3

--

--