// Handler.js
// This object will handle all event registration/deregistration. It is taken directly from JavaScript the definitive guide 5th edition.
//
// com.jchristy.Handler.add(element, eventType, handler);
// com.jchristy.Handler.remove(element, eventType, handler);


//First check the name space...

var com;
if (!com || !com.jchristy) { throw new Error("com.jchristy: Required object 'com.jchristy.Support' does not exist."); }

//Name space is ready.

com.jchristy.Handler = {};

if (document.addEventListener) {
	com.jchristy.Handler.add = function(element, eventType, handler) {
		element.addEventListener(eventType, handler, false);
	}
	com.jchristy.Handler.remove = function(element, eventType, handler) {
		element.removeEventListener(eventType, handler, false);
	}
} else if (document.attachEvent) {
	// This is for IE 5+
	com.jchristy.Handler.add = function(element, eventType, handler) {
		if (com.jchristy.Handler._find(eventType, handler, false) != -1) { return; }
		
		var wrapperHandler = function(e) {
			if (!e) { e = window.event; }
			
			var event = {
				_event: e,
				type: e.type,
				target: e.srcElement,
				currentTartet: element,
				relatedTarget: (e.fromElement) ? e.fromElement : e.toElement,
				
				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; }
			};
			
			if (Function.prototype.call) {
				handler.call(element, event);
			} else {
				element._currentHandler = handler;
				element._currentHandler(event);
				//element._currentHandler = null;
			}
			
		}
		
		element.attachEvent("on" + eventType, wrapperHandler);
		
		var h = {
			element: element,
			eventType: eventType,
			handler: handler,
			wrapperHandler: wrapperHandler
		}
		
		var d = element.document || element;
		var w = d.parentWindow;
		
		var id = com.jchristy.Handler._uid();
		if (!w._allHandlers) { w._allHandlers = {}; }
		w._allHandlers[id] = h;
		
		if (!element._handlers) { element._handlers = []; }
		element._handlers.push(id);
		
		if (!w.onunloadHandlerRegistered) {
			w._onunloadHandlersRegistered = true;
			w.attachEvent("onunload", com.jchristy.Handler._removeAllHandlers);
		}
		
	}
	com.jchristy.Handler.remove = function(element, eventType, handler) {
		var i = com.jchristy.Handler._find(element, eventType, handler);
		if (i == -1) { return; }
		
		var d = element.document || element;
		var w = d.parentWindow;
		
		var handlerId = element._handlers[i];
		var h = w._allHandlers[handlerId];
		
		element.detachEvent("on" + eventType, h.wrapperHandler);
		element._handlers.splice(i, 1);
		delete w._allHanders[handlerId];
	}
	
	com.jchristy.Handler._find = function(element, eventType, handler) {
		var handlers = element._handlers;
		if (!handlers) { return -1; }
		
		var d = element.document || element;
		var w = d.parentWindow;
		
		for (var i = handlers.length - 1; i >= 0; i--) {
			var handlerId = handlers[i];
			var h = w._allHandlers[handlerId];
			if (h.eventType == eventType && h.handler == handler) { return i; }
		}
		return -1;
	}
	
	com.jchristy.Handler._removeAllHandlers = function() {
		var w = this;
		
		for (id in w._allHandlers) {
			var h = w._allHandlers[id];
			h.element.detachEvent("on" + h.eventType, h.wrapperHandler);
			delete w._allHandlers[id];
		}
	}
	
	com.jchristy.Handler._counter = 0;
	com.jchristy.Handler._uid = function() { return "h" + com.jchristy.Handler._counter++; }
	
}