﻿/* ############################################################ */
/*
// John Campbell's EventManager JavasScript Library
*/
/* ############################################################ */
/*
// Based on code from: http://talideon.com/weblog/2005/03/js-memory-leaks.cfm
*/
var EventManager = {
	_registry: null,

	Initialise: function() {
		if (this._registry == null) {
			this._registry = [];
			// Register the cleanup handler on page unload.
			EventManager.Add(window, "unload", this.CleanUp);
		}
	},

	/**
	* Registers an event and handler with the manager.
	*
	* @param  obj         Object handler will be attached to.
	* @param  type        Name of event handler responds to.
	* @param  fn          Handler function.
	* @param  useCapture  Use event capture. False by default. (If you don't understand this, ignore it.)
	*
	* @return True if handler registered, else false.
	*/
	AddW3C: function(obj, type, fn, useCapture) {
		this.Initialise();
		// If a string was passed in, it's an id.
		if (typeof obj == "string") { obj = document.getElementById(obj); }
		if (obj == null || fn == null) { return false; }
		// Mozilla/W3C listeners?
		if (obj.addEventListener) {
			obj.addEventListener(type, fn, useCapture);
			this._registry.push({ obj: obj, type: type, fn: fn, useCapture: useCapture });
			return true;
		}
		// IE-style listeners?
		if (obj.attachEvent && obj.attachEvent("on" + type, fn)) {
			this._registry.push({ obj: obj, type: type, fn: fn, useCapture: false });
			return true;
		}
		return false;
	},

	Add: function(obj, type, fn, useCapture) {
		this.Initialise();
		// If a string was passed in, it's an id.
		if (typeof obj == "string") { obj = document.getElementById(obj); }
		if (obj == null || fn == null) { return false; }
		if (!obj.eventHandlers) { obj.eventHandlers = []; }
		if (!obj.eventHandlers[type]) {
			obj.eventHandlers[type] = [];
			if (obj['on' + type]) obj.eventHandlers[type].push(obj['on' + type]);
			obj['on' + type] = this.handleEvent;
		}
		obj.eventHandlers[type].push(fn);
		this._registry.push({ obj: obj, type: type, fn: fn, useCapture: useCapture });
		//alert("Added " + type + " event for " +  obj.id.toString());
		return true;
	},


	Remove: function(obj, type, fn, useCapture) {
		var handlers = obj.eventHandlers[type];
		for (var i in handlers) if (handlers[i] == fn) delete handlers[i];
		return true;
	},


	handleEvent: function(e) {
		var returnValue = true;
		if (!e) e = EventManager.fixEvent(event);
		var handlers = this.eventHandlers[e.type]
		for (var i in handlers) {
			this.$$handleEvent = handlers[i];
			returnValue = !((returnValue && this.$$handleEvent(e)) === false);
		}
		return returnValue;
	},

	fixEvent: function(event) {
		// add W3C standard event methods
		event.preventDefault = EventManager.fixEvent.preventDefault;
		event.stopPropagation = EventManager.fixEvent.stopPropagation;
		return event;
	},

	fireEvent: function(obj, event) {
		if (document.createEventObject) {
			// dispatch for IE
			var evt = document.createEventObject();
			return obj.fireEvent('on' + event, evt)
		}
		else {
			// dispatch for firefox + others
			var evt = document.createEvent("HTMLEvents");
			evt.initEvent(event, true, true); // event type,bubbling,cancelable
			return !obj.dispatchEvent(evt);
		}
	},

	/**
	* Cleans up all the registered event handlers.
	*/
	CleanUp: function() {
		for (var i = 0; i < EventManager._registry.length; i++) {
			with (EventManager._registry[i]) {
				//alert("obj = " + obj + "\ntype = " + type);
				EventManager.Remove(obj, type, fn, useCapture);
				// Mozilla/W3C listeners?
				if (obj.removeEventListener) {
					obj.removeEventListener(type, fn, useCapture);
				}
				// IE-style listeners?
				else if (obj.detachEvent) {
					obj.detachEvent("on" + type, fn);
				}
			}
		}
		// Kill off the registry itself to get rid of the last remaining references.
		EventManager._registry = null;
	}
};
EventManager.fixEvent.preventDefault = function() { this.returnValue = false; };
EventManager.fixEvent.stopPropagation = function() { this.cancelBubble = true; };
/* ############################################################ */
/* ############################################################ */

