/********************************************/
/* Copyright 2006-2007 Eliteology Limited   */
/* www.eliteology.com						*/
/********************************************/

/* array extensions */
if (!Array.prototype.push) { Array.prototype.push = function(elem) { this[this.length] = elem; } };
if (!Array.prototype.erase) { Array.prototype.erase = function erase(pos) { if (pos>=0) this.splice(pos,1); else this.splice(0,this.length); return this; } };
if (!Array.prototype.contains) { Array.prototype.contains = function (val) { for (var i=0; i<this.length; i++) { if (this[i] === val) return true; } return false; } };
if (!Array.prototype.removeDuplicates) { Array.prototype.removeDuplicates = function () { for(i = 1; i < this.length; i++){ if(this[i][0] == this[i-1][0]){ this.splice(i,1); } } }; };
if (!Array.prototype.empty) { Array.prototype.empty = function () { for(i = 0; i <= this.length; i++){ this.shift(); }};};

var events = {

    _registry : new Array(),

	/* register the event manager */
    init: function()
    {
        if (this._registry == null)
        {
            this._registry = [];
            events.add(window, "unload", this.dispose);
        }
    },

    /* register an event and handler */
    add: function(obj, type, fn, useCapture)
    {
        this.init();

		obj = (typeof obj == "string") ? document.getElementById(obj) : obj;

		if (obj!=null && fn!=null)
		{
			// reduce duplicates
			this.remove(obj, type, fn);
		
			if (obj.addEventListener)
			{
				obj.addEventListener(type, fn, useCapture);
				this._registry.push({obj: obj, type: type, fn: fn, useCapture: useCapture});
				return true;
			};

			if (obj.attachEvent && obj.attachEvent("on" + type, fn))
			{
				this._registry.push({obj: obj, type: type, fn: fn, useCapture: false});
				return true;
			};
		}
		else return false;
    },
    
	cancel : function(e)
	{
	    var e = (e) ? e:window.event;
		if (!e) return; 
	    e.returnValue = false; e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
		if (e.preventDefault) e.preventDefault();
	},

	/* remove a registered event from an object */
	remove: function(o, t, f)
	{
        for (var i = 0; i < events._registry.length; i++)
        {      
            with (events._registry[i])
            {
				if ((obj==o) && (type==t) && (fn==f))
				{			
					if (obj.detachEvent) {obj.detachEvent("on" + type, fn); }
					else if (obj.removeEventListener) obj.removeEventListener(type, fn, useCapture);

					events._registry[i]=null;
					events._registry.erase(i);
					
					return true;
				}       
            }
        }
        
        return false;
	},

    /* Cleans up all the registered event handlers. */
    dispose: function()
    {
        for (var i = 0; i < events._registry.length; i++)
        {
            with (events._registry[i])
            {
                if (obj.removeEventListener) obj.removeEventListener(type, fn, useCapture);
                else if (obj.detachEvent) obj.detachEvent("on" + type, fn);
            }
        };

        events._registry.erase();
        events._registry = null;
    }
};