if(document.createElement("div").contains == null)
{
	Element.prototype.contains = function(child)
	{
		while(child != null && child != this)
			child = child.parentNode;
		return (child == this);
	}
}



var Events = {
	
	_fakeMouseEnterLeave :function (fn)
	{
		return function(e)
		{
			var relTarget = e.relatedTarget;
			if (this === relTarget || this.contains(relTarget)) 
				return;
			fn.call(this, e);	
		}
	},
	_IEFixEvents: function (obj, fn)
	{
		var o = obj, f = fn;
		return function()
		{
			f.call(o, window.event);
		}
	},
	_IEGetUniqueId: function (elem)
	{
		if(elem == window) return "TheWindow";
		if(elem == document) return "TheDocument";
		return elem.uniqueID;
	},
	_IECleanUpEvents: function()
	{
		for(var i in Events.attachedEvents)
		{
			Events.attachedEvents[i].o.detachEvent("on" + Events.attachedEvents[i].t, Events.attachedEvents[i].f);
		}
	},
	_IEGetEventSignature: function(element, type, fn)
	{
		return "IEEvent" + Events._IEGetUniqueId(element) + type + fn;
	},
	_FixMouseScroll: function(fn)
	{
		return function(e)
		{
			if(e.wheelDelta != null)
				e.direction = -e.wheelDelta / Math.abs(e.wheelDelta);
			else
				e.direction = e.detail;
			return fn(e);
		}
	},
	attachedEvents:new Object(),
	add: function( obj, type, fn, instance ) 
	{
		if ( obj.attachEvent ) 
		{
//			var k = Events._IEGetEventSignature(obj, type,fn);
//			if(Events.attachedEvents[k] != null) return;
			
			if(type == "mousewheel")
				fn = Events._FixMouseScroll(fn);
//			var fToCall = Events._IEFixEvents(obj, fn);
//			Events.attachedEvents[k] = {o: obj, t: type, f: fToCall};
//			obj.attachEvent( 'on' + type, fToCall );
			obj.attachEvent( 'on' + type, fn );
		} 
		else
		{
			if(type == "mouseenter")
				obj.addEventListener("mouseover", Events._fakeMouseEnterLeave(fn), false);
			else if(type == "mouseleave")
				obj.addEventListener("mouseout", Events._fakeMouseEnterLeave(fn), false);
			else if(type == "mousewheel")
				obj.addEventListener("DOMMouseScroll", Events._FixMouseScroll(fn), false);				
			else
				obj.addEventListener( type, fn, false );
		}
	},
	remove: function( obj, type, fn ) 
	{
		if (obj.detachEvent) 
		{
			var k = Events._IEGetEventSignature(obj, type,fn);
			if(Events.attachedEvents[k] != null)
			{
				obj.detachEvent( 'on' + type, Events.attachedEvents[k].f );
				Events.attachedEvents[k] = null;
			}
		} 
		else
			obj.removeEventListener( type, fn, false );
	},
	getSender: function(e)
	{
		if(e.srcElement)
		{
			if(Element.applyAllProperties)
				Element.applyAllProperties(e.srcElement);
			return e.srcElement;
		}
		else
			return e.currentTarget;
	},
	getOrigSender: function(e)
	{
		if(e.fromElement)
			return Element.applyAllProperties(e.fromElement);
		else
			return e.originalTarget;
	},
	stop: function(e)
	{
		e.cancelBubble = true;
		if (e.stopPropagation) 
			e.stopPropagation();
	},
	getKeyCode:function(e)
	{
		if(e.keyCode)
			return e.keyCode;
		if(e.which)
			return e.which;
		return null;
	},
	getMouseCoords: function (e)
	{
		return new Point(e.clientX, e.clientY);
	},
	getMouseCoordsElement: function (e)
	{
		if(e.layerX)
			return new Point(e.layerX - e.currentTarget.offsetLeft, e.layerY - e.currentTarget.offsetTop);
		return new Point(e.offsetX, e.offsetY);
	},
	getMouseCoordsScreen: function (e)
	{
		if(navigator.appName == "Microsoft Internet Explorer")
			return new Point(e.screenX - 3, e.screenY - 3);
		return new Point(e.screenX, e.screenY);
	},
	getMouseButton: function (e)
	{
		if(e.which)
			return e.which;
		switch(e.button)
		{
			case 1: return 1;
			case 4: return 2;
			case 2: return 3;
		}
		return 1;
	}
	, CheckHandler: function(handlerName, throwOnError)
	{
		if(handlerName != null && handlerName != "")
		{
			if(eval("typeof " + handlerName) != "function" && eval("typeof " + handlerName) != "object")
			{
				if(throwOnError)
					throw new Error("Undefined handler: " + handlerName);
				else
					return false;
			}
			else
				return true;
		}
		else
			return false;
	}
};

function HandlerUndefinedException(message)
{
	this.base(message);
}
inherit(Error, HandlerUndefinedException);

if(window.attachEvent != null)
	window.attachEvent("onunload", Events._IECleanUpEvents);
if(typeof(Element) != "undefined")
{
	Element.prototype.addEvent = function(type, handler)
	{
		Events.add(this, type, handler);
	}
	Element.prototype.removeEvent = function(type, handler)
	{
		Events.remove(this, type, handler);
	}
}
window.addEvent = function(type, handler)
{
	Events.add(window, type, handler);
}
window.removeEvent = function(type, handler)
{
	Events.remove(window, type, handler);
}
document.addEvent = function(type, handler)
{
	Events.add(document, type, handler);
}
document.removeEvent = function(type, handler)
{
	Events.remove(document, type, handler);
}

























function EventType()
{
	this.Handlers = new Array();
}
EventType.prototype.Handlers = null;

function EventSender()
{
	this.Events = new Object();
}
EventSender.prototype.Events = null;
EventSender.prototype.addEventListener = EventSender.prototype.addEvent = function(type, fn)
{
	if(fn == "" || fn == null) return;
	if(this.Events[type] == null)
	{
		this.Events[type] = new EventType();
	}
	if(typeof(fn) == "string")
	{
		Events.CheckHandler(fn, true);
		fn = eval(fn);
	}
	this.Events[type].Handlers.push(fn);
}
EventSender.prototype.fireEvent = function(type, args)
{
	if(this.Events[type] == null) return;
	
	if(args == null) args = new Object();
	
	args.currentTarget = this;
	args.target = this;
	
	for(var i = 0; i < this.Events[type].Handlers.length; ++i)
		this.Events[type].Handlers[i](args);
}

























