« YSlow Review | Main | Give Intelli J a Try »

Lessons from my 1st Encounter with Event Handling in Javascript

When I first started writing Javascript code (not long ago), the first few things that I started to play with were onclick and onload events. So, how did I use to attach event to elements. Well, I would simply do this:


  element.onclick = foo;
  function foo()
  {
    …
  }

As I found out, this kind of event handling would not cut it. For instance, how would I add more than one event handler to the same element.

  element.onclick = foo;
  element.onclick = bar;

That was my first attempt to solve that problem and failed miserably since only bar() would be executed. So I thought, maybe I could delegate those two functions; that seemed like the perfect solution.

  element.onclick = foobar;
  function foobar()
  {
    foo();
    bar();
  }

Hey, it worked so I was happy. However, it did not took long to find out that this method of event handling was error prone, and it would create nasty bugs in the very likely case that some of other developer had already registered an onclick event on the same element in the same way I did. Well, then I started to look to more advanced ways to do this. The solution came from the W3C event-handler registration model. The W3C provides two methods: addEventListener and removeEventListener. This model would allow me to register many events to an element without totally wiping out someone else’ code. Ok, I know some of you are like “This doesn’t work in with IE”, and you are 110% right. I found out this serious browser incompatibility the hard way. But it was not hard to find an answer, use IE’s attachEvent and detachEvent methods! Putting it all together would look something like this:

  function registerMyEvent(element, event, fn)
  {
    …
    if(element.addEventListener)
    {
      …
      //false allows event bubbling, while true allows event capturing
      element.addEventListener(event, fn, false);
    }
    else if(element.attachEvent)
    {
      …
      //in W3C model the events are not preceded by the ‘on’ word
      element.attachEvent(‘on’+event, fn);
    }
  }
  function removeMyEvent(element, event, fn)
  {
    …
    if(element.removeEventListener)
    {
      …
      //false allows event bubbling, while true allows event capturing
      element.removeEventListener(event, fn, false);
    }
    else if(element.detachEvent)
    {
      …
      //in W3C model the events are not preceded by the ‘on’ word
      element.detachEvent(‘on’+event, fn);
    }
  }

This script allowed registering and removing event handlers. It is important to note that I did not use browser sniffing at all. Instead, I use object detection, so when IE sees if(element.addEventListener), it will return false, and it would go into the next condition, and that is the behavior I want. Now going back to event handling, that solution is nice and simple, and most importantly it works (beware another ‘but’coming). But, there is a serious problem that lies in the use of Javascript’s keyword this within a event handler function.

  //registering an event with the code found above
  x.registerMyEvent(myElement, ‘click’, foo);
  function foo()
  {
    this.something = ...;
  }

In IE’s model, using this refers to the window object!!! It does not refers to the object in which the event is registered on!!! Why? The explanation would be that IE considers attachEvent and detachEvent as a global function, and not a method belonging to the object that is invoking them. So, just be careful with the this keyword usage in the event-handling functions. Also, you can also opt for more advanced approaches which I will not discuss here, or perhaps use of other solutions like the ones that YUI or Dojo offer. However, for me it was a great exercise to experiment with event-handling the way I did. It did not only teach me about event handling, but it also introduced me to serious browser incompatibilities, but most importantly taught me a lot about how Javascript works.

TrackBack

TrackBack URL for this entry:
http://configure.goodadvice.theladders.com/mt-tb.cgi/4814

Comments

Thanks for the useful info, it'll come in handy for people that are new to web development, like me. It looks like a very effective way to overcome issues with different browsers easily. Great read.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)