As a way to really build-up my JavaScript Ninja Skills I have been foregoing luxuries like jquery and prototype for the strange and harsh reality of pure DOM scripting. I can’t really appreciate what a library is doing for me if I don’t understand whay it’s doing it can I? Over the course of these particular posts I want to explore the making of a small cross-browser .js library, looking at what others have done and maybe get some good feedback in the process.

Why do this? Well it really started at work (I’m a web developer for U-Haul) when I was writing a new AJAX text-based chat system. I used Jquery on that, and it works great, nothing against Jquery or Prototype, or Base2 or whatever flavor of .js library you may use, they are all great tools, and surely much more encompassing that what I’ll cobble together here. I’m just a geek who likes to take things apart, and taking apart these large JavaScript libraries is just too damn complicated for me (plus I was just at jConf in Boston and when John Resig was adressing the possibility of a more modular jquery.js he pretty much shrugged and said it was just too damn complicated ;) ).

So where to start then? How about a unified API for dealing with the differences in creating event listeners for standards compliant browsers vs Interner Explorer using feature detection? The presence of the w3 standard method for binding events to elements could be tested for like so:

if (document.addEventListener) {
    //do stuff for standards compliant browser
}

With the IE version, which uses ‘attachEvent’ like this:

else if (document.attachEvent) {
    //do stuff for IE
}

I’m pretty sure you can use any passed in element to test for this, so you can just test whatever you pass in verses referencing the document object again. So at this point we could combine these two if statements (should we use a ternary? Gotta remember to check that…) together:

function addEventHandler(element, type, handler) {
    if (element.addEventListener) {
        element.addEventListener(type, handler, false*);
    }
}
else if (element.attachEvent) {
    element.attachEvent("on" + type, handler);
}

But that would mean that every binding request would have to pass through this statement right? I’ve tried to avoid this by implementing the functions on an object which tests once when it’s instantiated.
So, in a Douglas Crockford kind of way we’ll make an object and append our methods to it as to avoid global namespace pollution. Now, what do we call this global Object of ours? rquery? base3?…Truth is, call it whatever you want (and the aforementioned Mr.Crockford says do it in all CAPS), for brevity I’m goin’ with X (it looks pretty cool while debugging…).

var X = {};
//check for event binding model here
if (document.addEventListener) {
    X.addEventHandler = function(element,type,handler) {
        element.addEventListener(type,handler,false*);
    }
}
else if (document.attachEvent) {
    X.addEventHandler = function(element,type,handler) {
        //note to self:address soon to be memory leak problem...(still?)
        element.attachEvent("on" + type, handler);
    }
}

This way we can put w3 standard events into one block (the ‘if’ block) and all the other IE specific code related to the adding and removing of Event listeners (and that removing part will probably get involved due to the IE memory leak issue) into the ‘else if’ block. I makes sense to me to place the code that way so my global object only has to do the feature detection once rather than each time I try to bind an event to an element.

This is getting long, so I’m going to save the examples and use for the next post. -rob