function eventsSetup()
{
	events=new Events()
}

function EventHandler(event,uid)
{
	this.event=event
	this.uid=uid
}

EventHandler.prototype.remove=function EventHandler_remove()
{
	if(events.listeners[this.event][this.uid])delete events.listeners[this.event][this.uid]
}


function Events()
{
	this.listeners={
		keyup:{}
		,drag:{}
		,dragstart:{}
		,scroll:{}
		,keydown:{}
		,keypress:{}
		,click:{}
		,dblclick:{}
		,mousedown:{}
		,mouseup:{}
		,mousemove:{}
		,mouseover:{}
		,mouseout:{}
	};

	this.count={
		keyup:0
		,drag:0
		,dragstart:0
		,scroll:0
		,keydown:0
		,keypress:0
		,click:0
		,dblclick:0
		,mousedown:0
		,mouseup:0
		,mousemove:0
		,mouseover:0
		,mouseout:0
	};
}

Events.prototype.startEvent=function Events_startEvent(event)
{
	if(document.addEventListener)
	{	
		switch(event)
		{
			case 'keydown':
				document.addEventListener("keydown",this.documentKeyDown,false);
			break;
			case 'keyup':
				document.addEventListener("keyup",this.documentKeyUp,false);
			break;
			case 'keypress':
				document.addEventListener("keypress",this.documentKeyPress,false);
			break;
			case 'click':
				document.addEventListener("click",this.documentClick,false);
			break;
			case 'dblclick':
				document.addEventListener("dblclick",this.documentDblClick,false);
			break;
			case 'mousedown':
				document.addEventListener("mousedown",this.documentMouseDown,false);
			break;
			case 'mouseup':
				document.addEventListener("mouseup",this.documentMouseUp,false);
			break;
			case 'mouseover':
				document.addEventListener("mouseover",this.documentMouseOver,false);
			break;
			case 'mouseout':
				document.addEventListener("mouseout",this.documentMouseOut,false);
			break;
			case 'mousemove':
				document.addEventListener("mousemove",this.documentMouseMove,false);
			break;
		}
	}
	else if(document.attachEvent)
	{
		switch(event)
		{
			case 'keyup':
				document.attachEvent("onkeyup",this.documentKeyUp);
			break;
			case 'keydown':
				document.attachEvent("onkeydown",this.documentKeyDown);
			break;
			case 'keypress':
				document.attachEvent("onkeypress",this.documentKeyPress);
			break;
			case 'click':
				document.attachEvent("onclick",this.documentClick);
			break;
			case 'dblclick':
				document.attachEvent("ondblclick",this.documentDblClick);
			break;
			case 'mousedown':
				document.attachEvent("onmousedown",this.documentMouseDown);
			break;
			case 'mouseup':
				document.attachEvent("onmouseup",this.documentMouseUp);
			break;
			case 'mouseover':
				document.attachEvent("onmouseover",this.documentMouseOver);
			break;
			case 'mouseout':
				document.attachEvent("onmouseout",this.documentMouseOut);
			break;
			case 'mousemove':
				document.attachEvent("onmousemove",this.documentMouseMove);
			break;
		}
	}
	else
	{
		alert('not supported');
	}
}

Events.prototype.stopEvent=function Events_stopEvent(event)
{
	if(document.addEventListener)
	{	
		switch(event)
		{
			case 'keydown':
				document.removeEventListener("keydown",this.documentKeyDown,false);
			break;
			case 'keyup':
				document.removeEventListener("keyup",this.documentKeyUp,false);
			break;
			case 'keypress':
				document.removeEventListener("keypress",this.documentKeyPress,false);
			break;
			case 'click':
				document.removeEventListener("click",this.documentClick,false);
			break;
			case 'dblclick':
				document.removeEventListener("dblclick",this.documentDblClick,false);
			break;
			case 'mousedown':
				document.removeEventListener("mousedown",this.documentMouseDown,false);
			break;
			case 'mouseup':
				document.removeEventListener("mouseup",this.documentMouseUp,false);
			break;
			case 'mouseover':
				document.removeEventListener("mouseover",this.documentMouseOver,false);
			break;
			case 'mouseout':
				document.removeEventListener("mouseout",this.documentMouseOut,false);
			break;
			case 'mousemove':
				document.removeEventListener("mousemove",this.documentMouseMove,false);
			break;
		}
	}
	else if(document.attachEvent)
	{
		switch(event)
		{
			case 'keyup':
				document.detachEvent("onkeyup",this.documentKeyUp);
			break;
			case 'keydown':
				document.detachEvent("onkeydown",this.documentKeyDown);
			break;
			case 'keypress':
				document.detachEvent("onkeypress",this.documentKeyPress);
			break;
			case 'click':
				document.detachEvent("onclick",this.documentClick);
			break;
			case 'dblclick':
				document.detachEvent("ondblclick",this.documentDblClick);
			break;
			case 'mousedown':
				document.detachEvent("onmousedown",this.documentMouseDown);
			break;
			case 'mouseup':
				document.detachEvent("onmouseup",this.documentMouseUp);
			break;
			case 'mouseover':
				document.detachEvent("onmouseover",this.documentMouseOver);
			break;
			case 'mouseout':
				document.detachEvent("onmouseout",this.documentMouseOut);
			break;
			case 'mousemove':
				document.detachEvent("onmousemove",this.documentMouseMove);
			break;
		}
	}
	else
	{
		alert('not supported');
	}
}


Events.prototype.addListener=function Events_addListener(event,callback)
{
	var uid=''
	while(this.listeners[event][uid=getUID()]);
	this.listeners[event][uid]=callback
	if(!this.count[event]++)this.startEvent(event)
	return new EventHandler(event,uid);
}

Events.prototype.removeListener=function Events_removeListener(event,uid)
{
	if(this.listeners[event][uid])delete this.listeners[event][uid]
	if(!--this.count[event])this.stopEvent(event)
}

Events.prototype.documentKeyUp=function Events_documentKeyUp(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['keyup'];
	for(x in list)list[x](_e);
}

Events.prototype.documentKeyDown=function Events_documentKeyDown(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['keydown'];
	for(x in list)list[x](_e);
}

Events.prototype.documentKeyPress=function Events_documentKeyPress(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['keypress'];
	for(x in list)list[x](_e);
}

Events.prototype.documentClick=function Events_documentClick(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['click'];
	for(x in list)list[x](_e);
}

Events.prototype.documentDblClick=function Events_documentDblClick(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['dbkclick'];
	for(x in list)list[x](_e);
}

Events.prototype.documentMouseDown=function Events_documentMouseDown(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['mousedown'];
	for(x in list)list[x](_e);
}

Events.prototype.documentMouseUp=function Events_documentMouseUp(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['mouseup'];
	for(x in list)list[x](_e);

}

Events.prototype.documentMouseMove=function Events_documentMouseMove(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['mousemove'];
	for(x in list)list[x](_e);
}

Events.prototype.documentMouseOver=function Events_documentMouseOver(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['mouseover'];
	for(x in list)list[x](_e);
}

Events.prototype.documentMouseOut=function Events_documentMouseOut(e)
{
	if(!e)e=event;
	var _e={element:((typeof e.srcElement!='undefined')?e.srcElement:e.target),shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,keyCode:e.keyCode,x:parseInt((typeof e.x!='undefined')?e.x:e.pageX),y:parseInt((typeof e.y!='undefined')?e.y:e.pageY),button:e.button}
	var x,list=events.listeners['mouseout'];
	for(x in list)list[x](_e);
}
