Featured post

Closures, Lexical Scoping And Scope chain In JavaScript

Closures...You have heard a lot, or might have tried to study from different sources, but failed to get the point. Well to under...

Wednesday 24 February 2016

Event Handling in JavaScript (Part 2)


We have already covered some basics of Event Handling in Part 1. We have seen how we can register events on objects like window, document or any document elements objects. Before moving further I will recommend you to read that first. This time we will explore Event Handler Invocation process.

Event Handler Invocation:


Once you have registered event handlers, web browser will automatically invoke it when event of specified type occur on specified object. In this section we will cover arguments on event handler, event handler context, event handler scope, return value of event handler, invocation order and last but not the least event propagation and cancellation. This will surely give you better understanding on Event Handling.

Event Handler Argument

Event Handlers are mostly invoked with an event object as their argument. By mostly I mean IE8 and below versions of IE (as usual :/ ) do not pass any object in argument. Instead event object is available through the global variable window.event.
For compatibility we can write our handler function as:

var handler = function(event) {
      event = event || window.event;
}

This || says that if event is undefined (i.e. not passed as argument) then refer to the window.event variable.
The property of the event object provide details about the event. The type property of event object specifies the type of the event that has occured.

Event Handler Context

As we know there are 4 different ways in which function can be invoked. All those ways differ in setting the context/this of the function. Before moving further I recommend you to read this post first for more information on context/this.
By now, I hope you know method invocation and function invocation. We will need that knowledge to understand event handler context.

When you register your event handler by setting a property of element like this:
e.onlick = function() {.....};
then event handlers are invoked as method invocation since element is an object and we are defining property of an object. In this case our context/this refers to the event target on which handler is registered and invoked.

e.onclick = function() {
      console.log(this);      // It will display element on which click event is fired.
}

Even when handler is registered using addEventListener() then also the context/this will be set to event target i.e. element on which event is fired or registered. Unfortunately, it is not true with attachEvent() method. Handlers regisered through with attachEvent() are invoked as functions and sets this/context to global (Window) object. But we can have workaround for this.

function addEvent(target, type, handler) {
      if (target.addEventListener) {
            target.addEventListener(type, handler, false)
      } else {
            target.attachEvent("on" + type, function(event) {
                  return handler.call(target, event);
            });
      }
}
But event handler using this method can nto be removed because second parameter (handler function for attachEvent()) is ananymous and is not retained anywhere to be passed in detachEvent().

Event Handler Scope

We have seen that JavaScript, like Python, is lexically scoped means function able to access the scope chain where it has been defined and not where it has been called. For more clear understanding on scope in JavaScript, follow this post.
So like all the other JavaScript functions, event handlers are also lexically scoped. They are executed in the scope in which they are defined and not the scope from which they are invoked.

However there will always be an weird case since we are talking about JavaScript. Event Handlers which are registered as HTML attributes have access to global variables but not to any local variables. But, for some reasons, they have access to modified scope chain. Event Handlers defined by HTML element have access to element's attribute, the containing form object and the document object as well, as if they are local variables to the handler function.

Handler Return Value

Somethimes, when return value of handler function is set to false then browser does not perform the default action. Means??? Suppose you have submitted a form whose handler is registerd via setting HTML attribute or by setting an object property, and if handler returns false then form will not get submitted. You can write client side validation in handler function.
Another use of returning false could be in onkeypress event's handler function. Check if pressed key is valid or not and return false if not valid (can be used when validation input email or etc.).

But one important point here to notice is, return value false will only work if handler is registered by setting HTML attribute or by object property. It won't work if handlers are registered through addEventListener() or attachEvent() methods. To prevent default actions from handler function registered through these two methods, you must have to call the preventDefault() method or set the returnValue property of the event object. (preventDefault() for addEventListener() and returnValue = false for attachEvent()).

Invocation Order

There might be more than one event handler functon registered on single HTML element or object. When an appropriate event occurs, browser must have to prioritize between the event handler funciton's execution sequence. Browser follows following order to execute a handler funciton in sequence:
  • Handlers registered by setting an object property or HTML attribute will be invoked first.
  • Handlers registered with addEventListener() will be invoked in order they were registered.
  • Handlers registered with attachEvent() can be invoked in any order and you should not be dependent on sequence of this order.

Event Propagation

Whenever an event occurs on Window object, browser executes the handler function of respective event. But for other event targets like document object or any other html element, story is little different. After executing Event Handler function, event bubbles up to the document hierarchy level. Now handler function of upper level element will execute, and this goes on until it reaches to Window Object. (Exception Events which do not bubble up: focus, blur and scroll events.) This Event Bubbling is actually third phase of Event Propagation process. Executing Event Handler function is itself actually second phase. You ask what is first phase? Remember the third Boolean parameter on addEventListener() function? Well, if passed true in that parameter, event handler is registered as an capturing event handler. What difference does capturing event handler function makes? If function registered as capturing Event Handler, the top most hierarchy function will execute first (i.e., handler of Window Object),then its child and this goes on until immediate parent of event target on which event has actually occurred. And main point is it will never execute handler function of event target on which event has actually occurred. (Basically event event Capturing is opposite process of Event Bubbling). Event Capturing is mostly used for debugging purposes.

Event Cancellation

To cancel event propagation, use stopPropagation() method on handlers registered through addEventListener(). IE9 or before does not support stopPropagation(), instead, the IE event object has a property cancelBubble. Set this property to true to prevent any further propagation. There is another method named stopImmediatePropagation(). Like stopPropagation(), this method prevents the propagation of events to any other objects. But it also prevents the invocation of any other event handlers registered on the same object.

Drop comments for any doubts.