martedì, ottobre 10, 2006

Observer Subscriber in Base

I was playing with Dean Edwards Base and I would to implement
the Observer Subscriver pattern.
I wrote this Observer implementation:


//Clone method
Base.prototype.clone=function(){return new Base(this);}

//Define the Observer class
var Observer= Base.extend({
subscribe:function (obj,evt){
//if(!this["on"+evt])this["on"+evt]=[];
if(typeof(this["on"+evt]) === "undefined")this["on"+evt]=[];
this["on"+evt].push(obj);
},
raise:function (evt){
var list=this["on"+evt];

if(list){
var max=list.length;
for(var i=0;i<max;i++)
//if(list[i].update)list[i].update();
if(typeof(list[i].update)!=="undefined")list[i].update();
}
}
});
//Define the subscriber class
var Subscriber = Base.extend({update:function(){alert("update() must be implemented");}});


and this little test

/*Simple example of implementation*/

//Istantantiate a Observer
var observer= new Observer();

//Define a Event
observer.evt=function(){
//do stuff
this.raise("evt");
}

//Istantiate a Subscriber
var subscriber1=new Subscriber();
//Clone a Subscriber
var subscriber2=subscriber1.clone();

//define a custom update function
subscriber2.update=function(){
alert("here update() was implemented");
}

//subscribe our 2 object
observer.subscribe(subscriber1,"evt");
observer.subscribe(subscriber2,"evt");

//Raise the event
observer.evt();


Base is Great, it was so simple!




Update!
As I said in the comment this wasn't a correct implementation.

A correct(I hope) is the follow implementation:

//Clone method
Base.prototype.clone=function(){return new Base(this);}

var Observer = Base.extend({
update:function(evt){
alert("update() must be defined");
}
});
var Subject = Base.extend({
observers:[],
constructor:function(){this.observers=new Array();},
registerObserver:function(obj){
this.observers.push(obj);
return obj;
},
unregisterObserver:function(obj){
if(this.observers.length>0)
var tmp=this.observers.pop();
if (tmp!==obj){
var max=this.observers.length;
for(var i=0;i<max;i++)
if(this.observers[i]===obj){this.observers[i]=tmp;break;}
}
return this;
},
notifyObserver:function(evt){
var max=this.observers.length;
for(var i=0;i<max;i++)
this.observers[i].update(evt);
}
});

And so the Test:

/*Example:*/
var subject = new Subject();
subject.x=0;
subject.add=function(){
this.x++;
this.notifyObserver();
}
var observer1 = new Observer();
var observer2 =observer1.clone();
observer1.update=function(){alert("now x is "+subject.x);}
observer2.update=function(){alert("something happened on subject")}

subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.add();
subject.unregisterObserver(observer2);
subject.add();

venerdì, ottobre 06, 2006

typeof and Typeof

Dean Edwards point me out that typeof doesn’t always work so I come to a solution to this issue.

function isFunction(x){
return
typeof(x)==="function" &&
(typeof(x.toSource)==="undefined" || x.toSource().charAt(0)!="/")

}

basically it control if is a function (typeof(x)==="function")
and if is a gecko browser (typeof(x.toSource)==="undefined")
it control if is a RegExp(x.toSource().charAt(0)!="/").

So I wrote my simple Typeof function

function Typeof(what){
switch(what){
case Object:return "Object";
case Function:return "Function";
case Array:return "Array";
case String:return "String";
case Boolean:return "Boolean";
case Number:return "Number";
case RegExp:return "RegExp";
case Date:return "Date";
case Error:return "Error";
case Math:return "object";
case null:return "null";
}
if(typeof(what)==="function" && (typeof(what.toSource)!=="undefined" && what.toSource().charAt(0)=="/"))return "object"; //regex for moz
return typeof(what);
}


Enjoy ;)