/**
 * Event handler
 */
if(typeof Events == 'undefined') {
	var Events = new function () {
		this.key_separator = '__';	// separator for event index generator
		this.key_count = 0;			// counter for event index generator
		this.saved = {};			// for event saving

		/**
		 * add event
		 * @param	object		element object
		 * @param	string		type (click, mouseover, mouseout, keyup etc... )
		 * @param	reference	to function
		 * @param	object		scope object
		 * @examble	Events.add(element_obj,'click',openSomeWindow);
		 */
		this.add = function(obj,type,fn,scope) { 
			scope = scope || obj;
			var index = this.genEventIndex(obj,type,fn);
			this.save(index,fn,scope);

			if (obj.addEventListener) { 
				obj.addEventListener( type, this.getBufFunc(index), false ); 
			} else if (obj.attachEvent) { // for ie
				obj.attachEvent('on'+type,this.getBufFunc(index)); 
			} else {
				obj['on'+type] = this.getBufFunc(index);
			}

			// Reset variables:
			obj = fn = scope = null;
			return true;
		};

		/**
		 * Save listener
		 */
		this.save = function (index,fn,scope) {
			if (this.saved[index])
				return false;
			this.saved[index] = {
				fn: fn,
				scope: scope,
				buffer:	function(event) { Events.bufferFunc(index,event); }
			};
			return true;
		};

		/**
		 * Return buffer listener from saved listeners by index
		 */
		this.getBufFunc = function (index) {
			return this.saved[index].buffer;
		};

		/**
		 * Buffer function
		 * Call "original" listener by saved data
		 */
		this.bufferFunc = function (index,event) {
			if(!this.saved[index])
				return null;

			var handler = this.saved[index];
			var scope = handler.scope;
	//		var_dump(event);
			scope.blah = handler.fn;
	//		scope.blah(this.getObj(event));
			scope.blah(event);
			scope.blah = null;
		};

		/**
		 * remove event
		 * @param	object		element object
		 * @param	string		type (click, mouseover, mouseout, keyup etc... )
		 * @param	reference	to function
		 * @param	object		scope object
		 * @examble	Events.remove(element_obj,'click',openSomeWindow);
		 */
		this.remove = function(obj,type,fn,scope) { 
			scope = scope || obj;

			var index = this.genEventIndex(obj,type,fn);		
			if (this.saved[index] == null)
				return false;

			if ( obj.detachEvent ) { // for ie
				obj.detachEvent( 'on'+type, this.getBufFunc(index) ); 
	//			obj[type+fn] = null; 
			} else if (obj.removeEventListener) {
				obj.removeEventListener( type, this.getBufFunc(index), false ); 
			} else {
				obj['on'+type] = null;
			}
			this.saved[index] = null; // delete saved data
			return true;
		};


		/**
		 * Generate index for event
		 * @param	object		target element object
		 * @param	string		event type
		 * @param	reference	function reference
		 * @return	string		generated key
		 */
		 this.genEventIndex = function (obj,type,fn) {
			 // get id
			 if (obj == document)
				 var id = 'idDoc';
			 else if (obj == window)
				 var id = 'idWin';
			 else if (obj.getAttribute('id'))
				 var id = obj.getAttribute('id');
			 else if (obj.uniqueID)
				 var id = obj.uniqueID;
			 else
				var id = '__eventcount'+ (this.key_count++);
			return id + this.key_separator + type + this.key_separator + fn;
		};

		/**
		 * Return event source object
		 */
		this.getObj = function (e) {
			var el = window.event ? window.event : e;
			return el.target ? el.target : el.srcElement;
		};
		
		/**
		 * Return mouse coordinates in array
		 */
		this.getMouseCoords = function (event) {
			var pos = new Array();
			if (typeof event.pageX != "undefined" && typeof event.x != "undefined") { // ff, mozilla, opera
				pos[0] = event.pageX; 
				pos[1] = event.pageY; 
			} else {  // ie, opera
				pos[0] = event.clientX;
				pos[1] = event.clientY; 
			}
	/*
			if (document.body.scrollLeft > 0 && !window.opera)
				pos[0] += document.body.scrollLeft;
			if (document.body.scrollTop > 0 && !window.opera)
				pos[1] += document.body.scrollTop;
			*/
			var scrolled = this.getPageScroll();
			pos[0] += scrolled[0];
			pos[1] += scrolled[1];
			return pos;
		};

		/**
		 * Returns window's current scroll coordinates
		 * @return array   An array
		 */
		this.getPageScroll = function () {
			var X, Y;
			if ('number' == typeof window.pageXOffset) {
				X = window.pageXOffset;
				Y = window.pageYOffset;
			} else {
				if (window.document.compatMode && window.document.compatMode == 'CSS1Compat') {
					X = window.document.documentElement.scrollLeft;
					Y = window.document.documentElement.scrollTop;
				} else {
					X = window.document.body.scrollLeft;
					Y = window.document.body.scrollTop;
				}
			}
			
			return Array(X,Y);
		};
	}
}