Bind Event to HTML Element in js Object

In js object, when an HTML element is binded to an event the executing context will be changed when the executing code is running into the event. An common error maybe occur when you invoke the other properties of the object.

Now, let's explore how to bind an event on an HTML element or a tag.

A simple object

var box = function (){
    this.id = "box1";
    this.backgroundColor = "#23bbcc";
} 

This object is a div box. Currently we know its properties id and backgroundColor. We will add a simple event - click the box and then the background color is changed to #23bbcc color.

Classical Way

function foo(e){
    var o = document.getElementById(this.id); 
    o.style.backgroundColor = "#23bbcc"; 
}

document.getElementById("box1").onclick = foo;

OOP design

The script looks nice using the JSON style of object. The foo function becomes a method of the prototype of the box object.

box.prototype = {
    init : function(){
        addEvent(document.getElementById(this.id), "click", this.foo);
    },

    foo: function(e){
        var o = document.getElementById(this.id); 
        o.style.backgroundColor = "#23bbcc"; 
    }
}

Up to now there's no problem. How about there's the need to use the backgroundColor property in the constructor of box object? For example, click the box and the background color of the box switches between #23bbcc and its original background color "#23bbcc". The following script may first comes to the mind.

   // The following script will not work
box.prototype = {
    init : function(){
        addEvent(document.getElementById(this.id), "click", this.foo);
    },

    foo: function(e){
        var o = document.getElementById(this.id); 
        if (o.style.backgroundColor == this.backgroundColor) { 
            o.style.backgroundColor = "#23bbcc"; 
        } 
        else 
            o.style.backgroundColor = this.backgroundColor; 
        } 
    }
}

But this script will not work because this keyword in the function foo refers to div element rather than the object box after the running of addEvent.

Function bind method

In oder to avoid the error, we could use the following extended method of Function bind (it can also be written as an internal method of box object).

Function.prototype.bind = function(obj) {	
    var _method = this;
    return function() {
        return _method.apply(obj, arguments);
    };    
} 

The meaning of the function is return a new function which will execute the context of the method while keeping this keyword refers to the object consistantly. This attribute can be exactly used to rectify the behavior of the event function.

Object Bind method

A similar way of changing the scope of the executing context is using the following Object Bind method. It does the same work as the Function bind method. Just use slight differently.

Object.prototype.Bind = function( method ){ 
        var _this = this; 
        return function(){ 
            return  method.apply( _this, arguments ); 
        } 
} 

The working object

Now we use the bind method to bind the event to the div element. The working code is as follow,

box.prototype = {
init : function(){
    var closure = this.foo.bind(this); // or
    // var closure = this.Bind(this.foo);
    addEvent(document.getElementById(this.id), "click", closure);
},

foo: function(e){
    var o = document.getElementById(this.id); 
    if (o.style.backgroundColor == this.backgroundColor) { 
        o.style.backgroundColor = "#23bbcc"; 
    } 
    else 
        o.style.backgroundColor = this.backgroundColor; 
    }
}

Back to the classical

Now let's back to the classical way of binding the event. It's simple. Just bind the function when set onclick method.

document.getElementById("box1").onclick = foo.bind(box1);
Test the event

Social Bookmark if it is useful.