﻿/**
 * Initializes the eventmanager
 */
EventManager = function() {
	this.eventStack = [];
	this.IEevents = (!document.addEventListener);
	this.eventQueue = [];
}

EventManager.prototype.PushEventOnStack = function(eventObj) {
	this.eventStack[this.eventStack.length] = eventObj;
}

/**
 * Clears an event from an object. Only clears event if already on stack
 *
 * @param obj			Object to clear event from
 * @param type			Name of event to clear
 *
 * @return bool			True if successfully cleared (and if event was not previously registered) otherwise false
 */
EventManager.prototype.ClearEvent = function(obj, type) {
	var i = 0;
	var hit = false;
	
	// search through already registered events to locate handlerobject with appropriate type
	while ( i < this.eventStack.length && !hit ) {
		hit = (obj == this.eventStack[i].obj) && (type == this.eventStack[i].type);
		if (!hit) {
			i++;
		}	
	}
	
	if (hit) {
		// we found a handlerobject. now clear listener.
		var eventName = type;
		with (this.eventStack[i]) {
			if (this.IEevents) {
				obj.detachEvent("on" + type, fn);
				eventName = "on" + eventName;
			}
			else {
				obj.removeEventListener(type, fn, capture);
			}
		}
		// nullify handlerobject
		eventhandler = this.eventStack.splice(i,1);
		eventhandler[eventName] = null;
		eventhandler = null;
	}
	
	return true;
}

EventManager.prototype.ClearAllEventsForObject = function(obj) {
	var done = false;
	
	while (	!done ) {
		var i = 0;
		var hit = false;
		
		while ( i < this.eventStack.length && !hit ) {
			hit = (obj == this.eventStack[i].obj);
			if ( !hit ) {
				i++;
			}
		}
		
		if ( hit ) {
			var eventName = "";
			with (this.eventStack[i]) {
				if ( this.IEevents ) {
					obj.detachEvent("on"+type, fn);
					eventName = "on"+type;
				}
				else {
					obj.removeEventListener(type, fn, capture);
					eventName = type;
				}
			}
			eventhandler = this.eventStack.splice(i,1);
			eventhandler[eventName] = null;
			eventhandler = null;
		}
		else {
			done = true;
		}
	}
	return true;
}

/**
 * Registers an event with the EventManager
 * @param obj			Object to attach handler to. If passed as string, the manager will assume id of element
 * @param type			Name of event to attach
 * @param fn			Function to use as event handler
 * @param useCapture	Whether or not to use event capture. For Mozilla/FireFox only
 *
 * @return bool			True if handler successfully registered otherwise false
 */
EventManager.prototype.RegisterEvent = function(obj, type, fn, capture) {
	if (typeof obj == "string") {
		// lookup element
		obj = document.getElementById(obj);
	}
	
	if ( obj == null || fn == null ) {
		// no object or handlerfunction
		return false;
	}
	
	// clear previously registered event (if any)
	this.ClearEvent(obj, type);
	
	if (this.IEevents) {
		// IE event attachment
		if (obj.attachEvent("on" + type, fn)) {
			this.PushEventOnStack({obj: obj, type: type, fn: fn, capture: false});
			return true;
		}
	}
	else {
		// Mozilla/FireFox event attachment
		obj.addEventListener(type, fn, capture);
		this.PushEventOnStack({obj: obj, type: type, fn: fn, capture: capture});
		return true;
	}
	
	// only possible if IE and attachEvent fails
	return false;
}

/**
 * Queues an event for later bulk-registration
 */
EventManager.prototype.QueueEvent = function(obj, type, fn, capture) {
	this.eventQueue[this.eventQueue.length] = {obj: obj, type: type, fn: fn, capture: capture};
}

/**
 * Bulk-registration of queued events
 */
EventManager.prototype.ProcessQueuedEvents = function() {
	// run through queued events and register each one
	// clear queue-object when registered
	for ( var i = 0; i < this.eventQueue.length; i++ ) {
		var qobj = this.eventQueue[i];
		this.RegisterEvent(qobj.obj, qobj.type, qobj.fn, qobj.capture);
		this.eventQueue[i] = null;
	}
	// clear event-queue
	this.eventQueue = [];
}

/**
 * Cleans up registered event handlers
 */
EventManager.prototype.Cleanup = function() {
	for (var i = (this.eventStack.length - 1); i>=0; i--) {
		if ( this.eventStack != null ) {
			with (this.eventStack[i]) {
				eventName = type;
				if (this.IEevents) {
					obj.detachEvent("on" + type, fn);
					eventName = "on" + type;
				}
				else {
					obj.removeEventListener(type, fn, capture);
				}
				obj[eventName] = null;
			}
			this.eventStack[i] = null;
		}
	}
	
	// cleanup remaining references
	this.eventStack = null;
}

