Picking up where I left off in ‘Hacking together’, which we’ll now call Pt.1, Let’s look at the entirety of the addEvents section of the library in browsers which aren’t named IE…

//check for standards support first
if (document.addEventListener) {
    //w3 standard events model
    X.addEventHandler = function(element,type,handler){
        element.addEventListener(type,handler,false);
    };

    X.removeEventHandler = function(element,type,handler){
        element.removeEventListener(type,handler,false);
    };

    X.stop = function(event) {
        event.stopPropagation();
    };

    X.prevent = function(event) {
        event.preventDefault();
    };    
} //end

Now to address the IE events model and the (hopefully) soon-to-be-a-thing-of-the-past memory leak issue. If we stroll back in time to 2005 there was a contest held over at Quirksmode for a JavaScript solution to the addEvent challenge. The winner was (to no great suprise) John Resig. That entire post saga is required reading imho. One of the judges of the contest, Dean Edwards wrote this solution, from which I am using a slightly modified version.

    else {
    //IE or other non standards event model-------------
    X.addEventHandler = function(element,type,handler) {
        //check for guid, assign one if not present
        if(!handler.$guid) handler.$guid = X.addEventHandler.guid++;
        //create a hash for the element's event types
        if(!element.events) element.events = {};
        //create a hash of event handlers for each element/event pair
        var handlers = element.events[type];
        if(!handlers) {
            handlers = element.events[type] = {};
            //store the existing handler if exists
            handler[0] = element["on" + type];
        }
        //store the event handler in the hash
        handlers[handler.$guid] = handler;
        element["on" + type] = X._handleEvent; //called when event fires
    };

    X.addEventHandler.guid = 1; //counter to generate the guids

    X.removeEventHandler = function(element,type,handler) {
        //delete a single handler from the hash table
        if(element.events && element.events[type]) {
            delete element.events[type][handler.$guid];
        }
    };

    X.prevent = function(event) {
        event.returnValue = false;
    };

    X.stop = function(event) {
        event.cancelBubble = true;
    };
   
    X._handleEvent = function(event) {
        //need a return val
        var returnVal = true;
        //IE uses a global event object
        event = event || window.event;
        //get a ref to the hash of event handlers
        var handlers = this.events[event.type];
        //execute each one
        for(var i in handlers) {
            this.$handleEvent = handlers[i];
            if(this.$handleEvent(event) === false) {
                returnVal = false;
            }
        }
        return returnVal;
    };
}

IE has a serious flaw if not corrected: When your attached function gets fired, the ‘this’ reference refers to the worthless ‘window’, when, in fact, it should refer to the parent object (I think I’m paraphrasing J.Resig there). This code addresses that by creating a hash table of event handlers with unique ids bound to your target element, assigning a ‘handleEvent’ method to be called when your event fires. This passes the object correctly and maintains scope (this). You should walk through this series of methods with IE’s developer tools JavaScript debugger, which is the best way to see how this works in real-time. Then there is a removeEventHandler to allow assigned handlers to be removed (more on that in a moment), as well as IE methods for preventing default behavior and stopping event propagation.

So, back to removeEvent and the IE memory leak possibility. This code does not use attachEvent() to handle events, which unless I am mistaken was the biggest problem with IE’s memory manager understanding which event handlers could be reclaimed by the garbage collector. See Douglas Crockford’s post here. Admittedly, this little portion of a discussion on the IE memory leak issue is a tiny drop in one seriously big-assed ocean. There is so much material out there on this subject alone you could get lost in it. I don’t really want to go down that path any further here. We’ll bind events without attachEvent, we’ll set a removeEvent handler on the events we bind and we’ll move on. A real solution would be don’t use IE, but I digress…

I have made a seperate page on the blog called ‘x.js’ for the code so far. Next I want to go into using object literals as a way to organize your code which will use the X library and some syntactic sugar to make for less verbose script, until then…