Posts Tagged module pattern
Dispatcher followup : A more compact way of writing prototypes + module pattern + test
Posted by Erik Karlsson in JavaScript, Web development on July 27th, 2009
The previous post I added some prototype methods to the Dispatcher class, but It could has well been written on the following syntax instead
function Dispatcher(){} Dispatcher.prototype = { addEventlistener : function(event, callback){ //code here }, removeEventlistener : function(event, callback){ //code here } //add more methods here... don't forget to comma-separate them and do not add a comma last! }
So how about writing up this with the module pattern on the same time. I’ll also show a simple way to write an automatic unit-alike test for this.
/** * @author: Erik Karlsson, www.nonobtrusive.com **/ var nonobtrusive = nonobtrusive ||{}; //create the "namespace" like object if it doesnt exist nonobtrusive.events = nonobtrusive.events || {}; //create the sub-namespace events where we'll place our Dispatcher class nonobtrusive.events.Dispatcher = (function(){ var undefined; //speed up references to undefined + allows munging function Dispatcher(){ this.events=[]; } Dispatcher.prototype = { addEventlistener : function(event, callback){ if ( event == undefined || callback == undefined ) return false; //verify that we have parameters sent in var listeners = this.events[event] = this.events[event] || []; //create a new array to hold listeners if first time listeners[listeners.length]=callback; }, removeEventlistener : function(event, callback){ if ( event == undefined || callback == undefined ) return false; //verify that we have parameters sent in var listeners = this.events[event]; if ( listeners ) { for ( var i = listeners.length-1; i>=0; --i ){ //go through all listeners for this specific event if ( listeners[i] === callback ) { listeners.splice( i, 1 ); //remove the eventcallback if we found it return true; } } } return false; }, dispatch : function(event){ if ( event == undefined ) return false; if ( this.events[event] ) { var listeners = this.events[event], len = listeners.length; while ( len-- ) { listeners[len](this); //callback with self } } } //add more methods here... don't forget to comma-separate them and do not add a comma last! } return Dispatcher; })(); function DispatcherTest(){ nonobtrusive.events.Dispatcher.call(this); //Some internal variables to keep track of the test-process. var dispatchOk = false, afterRemovalOk = false; this.dispatchCallback = function(){ dispatchOk = !dispatchOk; } this.setup = function(){ this.addEventlistener("TestEvent", this.dispatchCallback); } this.run = function(){ this.dispatch("TestEvent"); afterRemovalOk = this.removeEventlistener("TestEvent", this.dispatchCallback); this.dispatch("TestEvent"); //nothing should happen since we're not listening to this event anymore. if ( dispatchOk && afterRemovalOk ) { alert("DispatcherTest was ok!"); } } } DispatcherTest.prototype = new nonobtrusive.events.Dispatcher(); //Run the test var test = new DispatcherTest(); test.setup(); test.run();
If you want to use this class, download the minified script here :
http://www.nonobtrusive.com/wp-content/uploads/2009/07/nonobtrusive.events.Dispatcher-min.js
or try out the test yourself by visiting this page :
http://www.nonobtrusive.com/wp-content/uploads/2009/07/dispatcher-test.html