Adding events to elements on run-time (JavaScript)

I encounter many situations where I have to add events to element in JavaScript runtime, with each element  having similar event handlers with variables, say keys on a numpad, where each key has to register a different digit value. How would you do that?

I used to handle these situations by adding attributes to HTML and accessing the attributes from the event ‘target’ inside the event handler function. There is a problem with that technique.

  1. The event handler has to fetch the attribute and do string processing to flesh out the original parameters.
  2. Manipulation of HTML attributes adds to code latency and code complexity.
  3. String processing to flesh out the parameters adds complexity (e.g regular expression) even to a simplest event handler.

I have two solutions to overcome this particular problem…

Solution 1 (Using JavaScript’s super generous object model)

Anything in JavaScript is an object, extensible object. So you can actually add a property to the DOM object itself in order to access that in event handler run-time.

(function(){
  var wrapper = document.getElementById('wrapper');

  //Generating elements in run-time
  for(var i = 0; i < 12; i += 1){
    var p = document.createElement('p'); //Creating element p
    p.innerHTML = 'Click me! ' + i;
    wrapper.appendChild(p);
    p.i = i;//Attaching a particular variable with value to the DOM object

    p.addEventListener('click', function(e){
      alert('You clicked ' + this.i); //Getting that particular value inside the event handler
    });
  };
}());

You can see a working version here at http://codepen.io/rivalslayer/pen/irteE.

In this example, you can see that I have attached ‘i’ to the object ‘p’ which I can use as a fixed parameter for the event handler. This solution though effective can pose a few problems.

  1. Name conflicts. You can use variable naming conventions and namespaces to counter this problem.
  2. It’s very effective because most of the code is being handled inside the JavaScript engine. Less code latency.
  3. When working with many coders, you might not want to fiddle with the object itself.
  4. The event handler can access all the object properties of the parent by using ‘this’. No need to use “event.target.i”.

Solution 2 (Creating functions with closures)

You can create unique individual functions while defining the event handlers. JavaScript has a very special property called Closure. Once a object has been created, you cannot change the enclosed variables. This also can be used to create dynamic event handlers on run-time.

(function(){
  var wrapper = document.getElementById('wrapper');

  //Generating elements in run-time
  for(var i = 0; i < 12; i += 1){
    var p = document.createElement('p'); //Creating element
    p.innerHTML = 'Click me! ' + i;
    wrapper.appendChild(p); 

    p.addEventListener('click', new function(e){
      var x = i; //Setting the variable inside enclosure
      return function(){ //The actual event handler
        alert('You clicked ' + x);
      };
    });
  };
}());

Try out the code at http://codepen.io/rivalslayer/pen/KBfDm.

In this example, I have returned the event handler function from an object initialization. Here I have used closure. Each time a new object is initialized, it returns a function as the event handler. And thanks to closure, the ‘x’ inside the parent object stay intact. Points to be noted,

  1. Creating functions inside function is discouraged by JSLint, but I believe it’s quite good if used in moderation.
  2. Closure can be a very useful feature if used properly. But one must be careful about naming and scopes when writing complex event handlers.
  3. This method compare to the previous one is a little more memory hogging, but it doesn’t interfere with the original DOM objects.

In both these cases, each time a event handler is initialized a new function or object is created, which is quite a waste. On my next post I will talk about how to efficiently create objects are deal with events dynamically.

You may try fiddling with the codes on CODEPEN.. JavaScript is an amazing creature you can actually enjoy learning about.

JavaScript Speed Test

I started out to test out the speeds of JavaScript engines in the browsers. I was keen to experiment on the Chrome’s high performance V8 JavaScript engine. I designed this very rudimentary experiment to compare two JS engines (the one in Firefox and the one in Chrome). IE didn’t really support the DOM and the experiment didn’t work out, and I was not keen to make the whole thing work on IE. I am not an IE person.

The experiment is a page that has a math intensive JavaScript program that will compare the starting and ending time in machine timecode and publish the difference on page. The JS script is designed to do Sine, Cosine operations and store the values and then print them on the page. The page also has some CSS elements.

The page can be downloaded.

The results I got on my Core i3 laptop with 3 Gigs of RAM running Windows 7 Home Basic…

On Firefox (click to enlarge),

On Google Chrome,

And on IE where the script didn’t work,

The V8 engine that powers node.js I thought would be a lot faster. Google claims the power of V8 lies on it’s garbage collection system. I didn’t look into garbage collection though. But the speed, as you can see is slower than Firefox.

I didn’t test it on Safari, Opera etc. If anyone compares them, please let me.