Custom Events in JavaScript
一个老外写的自定义事件的冒泡.蛮有意思,有兴趣的可以去看看.
地址在这里.http://blog.stephenrushing.com/index.php/javascript/custom-events-in-javascript/
[javascript]
(function(){
var NS = namespace = {};
var EVENTS = NS.events = {};
//eventify - make an object event ready
var eventify = EVENTS.eventify = function(target1, targetN){
for(var t=0; t<arguments.length; t++){
var target = arguments[t];
if(!target.__listeners){
if(!target.events) target.events={};
target.__listeners={};
target.dispatchEvent=function(eventType, eventData){
if(this.events[eventType]) this.events[eventType].dispatch(this, eventData);
};
target.addEventListener=function(eventType, callback, bubbles){
return new EVENTS.Listener(this, eventType, callback, bubbles);
};
target.removeEventListener=function(eventType, callback){
var listeners = this.__listeners[eventType];
for(var l=0;listeners && l<listeners.length;l++)
if(listeners[l]===callback || listeners[l].callback===callback) listeners.splice(l,1);
};
}
}
}
//Event class
var Event = EVENTS.Event = function(type){
this.type=type;
this.history=[];
}
Event.prototype={
bubbleTo:null,
currentTarget:null,
dispatch:function(target, eventData, currentTarget){
this.target=target;
this.currentTarget=currentTarget||target;
var timeStamp = new Date();
this.timeStamp = timeStamp;
this._stopProp=false;
if(!currentTarget){
var histObj = {
eventData:eventData,
timeStamp:timeStamp
};
}else{
var histObj = currentTarget.events[this.type].history[currentTarget.events[this.type].history.length-1];
}
histObj.target = target;
histObj.currentTarget=currentTarget||target;
this.history.push(histObj);
var listeners = target.__listeners[this.type],
result;
for(var l=0; listeners && l<listeners.length; l++){
var listener = listeners[l];
if(eventData) result = listener.callback.call(target, this, eventData);
else result = listener.callback.call(target, this);
if(typeof(result)!=="undefined" && result!==null) this.result=result;
if(this._stopImmProp) break;
}
if(this.bubbleTo!==null && !this._stopProp) this.bubbleTo.events[this.type].dispatch(this.bubbleTo, eventData, this.currentTarget);
},
result:true,
_stopImmProp:false,
stopImmediatePropagation:function(){this._stopImmProp=true},
_stopProp:false,
stopPropagation:function(){this._stopProp=true},
target:null,
type:null,
history:null
}
//Listener class
var Listener = EVENTS.Listener = function(target, eventType, callback, bubbles){
this.target = target;
this.callback = callback;
this.bubbles = (bubbles!==null) ? bubbles : true;
//add the event to the target if it doesn't exist
if(!target.events[eventType]) target.events[eventType] = this.event = new EVENTS.Event(eventType);
this.event = target.events[eventType];
//create the listeners collection for this event type
if(!target.__listeners[eventType]) target.__listeners[eventType]=[];
target.__listeners[eventType].push(this);
}
Listener.prototype={
bubbles:true,
callback:function(evt, data){},
remove:function(){
var idx = Array.indexOf(this.target.__listeners[this.event.type], this);
this.target.__listeners[this.event.type].splice(idx,1);
delete this;
},
event:null,
target:null
}
/*
var grandchild = {events:{hello:new EVENTS.Event("hello")},name:"grandchild"},
parent = {events:{hello:new EVENTS.Event("hello")},name:"parent"},
grandparent = {events:{hello:new EVENTS.Event("hello")},name:"grandparent"};
EVENTS.eventify(grandchild,parent,grandparent);
function lstnr(evt){
console.log(evt.target.name+"/"+evt.currentTarget.name);
if(this.name==="parent") evt.stopPropagation();
}
//grandchild.addEventListener("hello", lstnr);
grandchild.events.hello.bubbleTo=parent;
parent.addEventListener("hello", lstnr);
parent.events.hello.bubbleTo=grandparent;
grandparent.addEventListener("hello", lstnr);
grandchild.dispatchEvent("hello");
grandchild.removeEventListener("hello", lstnr);
console.dir(grandchild);
console.dir(parent);
console.dir(grandparent);
*/
})();
[/javascript]