Events play a very vital role in developing a dynamic UI. Events are generated as a response to an User Action or to state changes in the Event source. An Event source is the one which notifies that the user has done some action . An Event Listener is the one which waits for notification from Event source and does Event Handling .
Event Delegation
Nowadays, event binding is done completely using Javascript to make it unobtrusive. In this approach event handlers are bound to the respective element when the DOM elements are loaded. One of the problems with this approach is the loss of event handlers when the DOM structure changes. Some of the use cases where traditional event binding is not useful are:
1) Consider a Div element in the document , to which an event handler is bound . if this Div element is removed at the later stages and added again. the event handler will be lost.
2) Binding an event handler to the element, which is going to be added to the document dynamically in later stages.
This opens the door to a new way of event binding, which is called Event Delegation. Events traverse in the document in two phases which are
So, its enough to add event handler to the top most element and identify the element on which event has occurred. To identify the element on which the event has occurred, the following Event methods are used
event.Target; //for firefox
event.srcElement; //for IE
The general idea with Event Delegation is to have just one (or a few) events on elements far higher up in the HTML hierarchy, and from there, trace on what target element the event actually occurred, and then take appropriate action. Let’s explore the API present in the Javascript libraries that support Event Delegation.
Event Delegation Using Prototype.js
Prototype Introduced the following API, to achieve Event Delegation.
$(element).on(eventType,context selector,handler);
Event Delegation Using JQuery.js
Initially, JQuery Introduced the following API, to achieve Event Delegation.
$.live(eventType,handler);
However , the live API method had some performance drawback. since one needs to wait for the event to traverse to the top most element of the document.It has no support for method chaining, to solve this, Delegate API was introduced, Delegate lets us bind the event handler to the nearest parent element
$.delegate(context selector,event Type,handler)
Custom Events
As Browser supports Document Object Model (DOM) , it supports DOM Events. When a user does any interaction on any DOM element,a DOM event is triggered by the browser and Event Listener gets notified.An example of this is a “click” event. whenever a user performs “click” action on the element , the click event is triggered and will notify the Listener, where a event handler function can be added .
Limitation of the DOM Events
Since DOM events are very limited in number, we need Custom Events. Consider the simple use case of adding an event listener for hide, this is difficult to do as there is no DOM event called “hide”.
Custom Events are simple to create and a utility method can be written to handle it. In my experience some of the points to consider while writing an utility function are:
An utility Function containing a variable to store the list of events.
function Event(){
this.events = {};
}
An observe method is added, which binds the event listener with event source. this observe function takes three parameters
i)DOM element on which the event has occurred
ii)Event type which has occurred
iii)Event handler function, which does the event handling
Event.prototype.observe = function(el,evt,handler){
var isDomEvent = checkDomEvent(evt);
if(typeof evt != undefined && typeof evt == "string" ){
if(isDomEvent){
if(el.addEventListener){
el.addEventListener(evt,handler,false);
}else{
el.attachEvent("on"+evt,handler);}
}else{
if(this.events[evt] instanceof Array){
this.events[evt].push(handler);
}else{
this.events[evt] = [handler];
}}}}
A fireEvent method , to fire the event manually and notify the handler
Event.prototype.fireEvent = function(el,evt){
for(var i=0,j=this.events[evt].length;i)
try{
this.events[evt][i](this);
}catch(e){
continue;
}
}}
Element.observe(“custom:event”,Handler);
Element.fire(“custom:event”);
Element.bind(“custom event”,handler);
Element.trigger(“custom event”);