// JavaScript Document
function Signal(scope, type){
	this._scope = scope;
	this._listeners = [];
	if(this.isNative(type)){
		this.registerNativeEvent(type, false);
	}
	this._once = [];
}
Signal.prototype.isNative = function(type){
	switch(type){
		case "abort":
		case "blur":
		case "change":
		case "click":
		case "error":
		case "focus":
		case "load":
		case "mousedown":
		case "mousemove":
		case "mouseover":
		case "mouseout":
		case "mouseup":
		case "reset":
		case "resize":
		case "scroll":
		case "select":
		case "submit":
		case "unload":
		case "DOMActivate":
		case "DOMFocusIn":
		case "DOMFocusOut":
		return true;
	}
	return false;
}
Signal.prototype.registerNativeEvent = function(type, usecapture){
	var isIE = false;
	var self = this;
	var proxy = function(e){
		if(!e){
			e= window.event;
		}
		if(isIE){
			var _event = {
				orig: e,
				target: e.srcElement,   
                currentTarget: element, 
                relatedTarget: e.fromElement?e.fromElement:e.toElement,
                eventPhase: (e.srcElement==element) ? 2:3,
                clientX: e.clientX, clientY: e.clientY,
                screenX: e.screenX, screenY: e.screenY,
                altKey: e.altKey, ctrlKey: e.ctrlKey,
                shiftKey: e.shiftKey, charCode: e.keyCode,
                stopPropagation: function( ) {this._event.cancelBubble = true;},
                preventDefault: function( ) {this._event.returnValue = false;}
			}
			self.dispatch(_event);
		}else{
			self.dispatch(e);
		}
	}
	
	if(document.attachEvent){
		isIE = true;
		this._scope.attachEvent("on"+type, proxy);
	}else{
		this._scope.addEventListener(type, proxy, usecapture);
	}
	
}
Signal.prototype.unregisterEvent = function(func){
}
Signal.prototype.registerEvent = function(func, once){
	if(once){
		this._once.push(func);
	}else{
		this._listeners.push(func);
	}
}

Signal.prototype.add = function(func){
	this.registerEvent(func);	
}
Signal.prototype.addOnce = function(func){
	this.registerEvent(func, true);
}
Signal.prototype.remove = function(func){
	this.unregisterEvent(func);
}
Signal.prototype.removeAll = function(){
	delete this._listeners;
	delete this._once;
	this._once = [];
	this._listeners = [];
}
Signal.prototype.dispatch = function(param){
	if(param == null){
		param = {};
	}
	var len = this._listeners.length;
	if(param && param.target == null || param.target == undefined){
		param.target = this._scope;
	}
	for(var i = 0;i < len;i++){
		this._listeners[i].call(this._scope, param);
	}

	while(this._once.length){
		this._once.pop().call(this._scope, param);
	}
}
