SitePoint Sponsor

User Tag List

Results 1 to 2 of 2
  1. #1
    SitePoint Member
    Join Date
    Jun 2010
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Code Review] JavaScript Event Binding Script

    Hey, was just trying to write a vanilla js solution to event binding. After looking at some examples online I came up with this script.

    Some benefits of this:
    • Can be passed either a node or a node list to attach handlers too
    • It checks once to see if the addEventListener and removeEventListener are available and just wraps those if they are.
    • If those methods are not available, it falls back to the Dean Edwards addEvent solution but without the Global pollution.
    • Normalizes the event object passed to the handler a bit so as to ease event delegation and target checks


    Code JavaScript:
    function BigAB(window, document) {
    	this.addEvent = (function( window, document ) {
    		if ( document.addEventListener ) {
    		return function( elem, type, cb ) {
    			if ( (elem && !elem.length) || elem === window ) {
    			elem.addEventListener(type, cb, false );
    			}
    			else if ( elem && elem.length ) {
    			var len = elem.length;
    			for ( var i = 0; i < len; i++ ) {
    				this.addEvent( elem[i], type, cb );
    			}
    			}
    		};
    		}
    		else if ( document.attachEvent ) {
    		return function ( elem, type, cb ) {
    			if ( (elem && !elem.length) || elem === window ) {
    			if (!cb.$$guid) cb.$$guid = this.addEvent.guid++;
    			if (!elem.events) elem.events = {};
    			var cbs = elem.events[type];
    			if (!cbs) {
    				cbs = elem.events[type] = {};
    				if (elem['on' + type]) cbs[0] = elem['on' + type];
    				elem['on' + type] = handleEvent;
    			}
    			cbs[cb.$$guid] = cb;
    			}
    			else if ( elem.length ) {
    			var len = elem.length;
    			for ( var i = 0; i < len; i++ ) {
    				this.addEvent( elem[i], type, cb );
    			}
    			}
    		};
    		}
    	})( window, document );
    	this.addEvent.guid = 1;
     
    	this.removeEvent = (function( window, document ) {
    		if ( document.removeEventListener ) {
    		return function( elem, type, cb ) {
    			if ( (elem && !elem.length) || elem === window ) {
    			elem.removeEventListener(type, cb, false );
    			}
    			else if ( elem && elem.length ) {
    			var len = elem.length;
    			for ( var i = 0; i < len; i++ ) {
    				this.removeEvent( elem[i], type, cb );
    			}
    			}
    		};
    		}
    		else if ( document.detachEvent ) {
    		return function ( elem, type, cb ) {
    			if ( (elem && !elem.length) || elem === window ) {
    			if (elem.removeEventListener) {
    				elem.removeEventListener(type, cb, false);
    			}
    			else if (elem.events && elem.events[type] && cb.$$guid) {
    				delete elem.events[type][cb.$$guid];
    			}
    			}
    			else if ( elem.length ) {
    			var len = elem.length;
    			for ( var i = 0; i < len; i++ ) {
    				this.removeEvent( elem[i], type, cb );
    			}
    			}
    		};
    		}
    	})( window, document );
     
    	function handleEvent(event) {
    		event = event || fixEvent(window.event, this);
    		var returnValue = true;
    		var handlers = this.events[event.type];
     
    		for (var i in handlers) {
    		if (!Object.prototype[i]) {
    			this.$$handler = handlers[i];
    			if (this.$$handler(event) === false) returnValue = false;
    		}
    		}
     
    		if (this.$$handler) this.$$handler = null;
     
    		return returnValue;
    	}
     
    	function fixEvent(event,currentTarget) {
    		event.currentTarget = currentTarget;
    		event.target = event.srcElement;
    		event.preventDefault = fixEvent.preventDefault;
    		event.stopPropagation = fixEvent.stopPropagation;
    		return event;
    	}
     
    	fixEvent.preventDefault = function() {
    		this.returnValue = false;
    	}
     
    	fixEvent.stopPropagation = function() {
    		this.cancelBubble = true;
    	}
     
    }
     
    // example usage:
    var lib = new BigAB(window,document),
        listItems =  document.getElementsByTagName('li');
     
    lib.addEvent(listItems, 'click', function(e) { alert('clicked: '+this.id) });

    Any comments or suggestinos would be appreciated.

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,696
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Overall well done.

    Some notes are:

    • var declarations should not be scattered throughout each function
    • Inconsistent indenting can be confusing, as are control statements without braces
    • What does BigAB stand for, add binding? And what are cbs and cb? Callbacks?


    Some parts of the code could do with bring broken down in to smaller functions too, for example with the addEvent function:

    Code javascript:
    this.addEvent = (function (window, document) {
        function addW3CEventListener(elem, type, callback) {
            ...
        }
        function addIEEventListener(elem, type, callback) {
            ...
        }
        if (document.addEventListener) {
            return addW3CEventListener;
        } else if (document.attachEvent) {
            return addIEEventListener;
        }
    }(window, document));

    Before making the above change, it wasn't clear whether addEvent did some work, or only returned a function for later use.

    I've also moved the invocation inside of the parenthesis, as it is the function that you are invoking, not the parenthesis themself.

    Oh gods, I just noticed. BigAB isn't add binding, it's your account name.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •