/* Updated Thurs June 26 2007. See comment on line 110 */
/*
 * EventManager.js
 * by Keith Gaughan
 *
 * This allows event handlers to be registered unobtrusively, and cleans
 * them up on unload to prevent memory leaks.
 *
 * Copyright (c) Keith Gaughan, 2005.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * (CPL) which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/cpl.php
 *
 * This software is covered by a modified version of the Common Public License
 * (CPL), where Keith Gaughan is the Agreement Steward, and the licensing
 * agreement is covered by the laws of the Republic of Ireland.
 */

// For implementations that don't include the push() methods for arrays.
if (!Array.prototype.push)
{
    Array.prototype.push = function(elem)
    {
        this[this.length] = elem;
    }
}

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.
*/
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;
	}

	// 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;
	},

	/**
	* Cleans up all the registered event handlers.
	*/
	CleanUp: function()
	{
	
		for (var i = 0; i < EventManager._registry.length; i++)
		{
			if(typeof(EventManager._registry[i]) == 'undefined')
			{	// events removed from _registry with Remove() are undefined
				continue;
			}

			with (EventManager._registry[i])
			{
				// Mozilla/W3C listeners?

				if(type == 'unload')
				{ 
				
				/* added by paul June 21 2007. Call any onunload event triggered functions before
						they are removed by this method. 	
					*/
					if(fn.toString().indexOf('EventManager') == -1)
					{
						fn();					
					}
				}

				if ( obj.removeEventListener )
				{
					obj.removeEventListener(type, fn, useCapture);
			
				}
				else if ( obj.detachEvent )
				{
				// IE-style listeners?
					obj.detachEvent("on" + type, fn);
				}
			}
		}

	// Kill off the registry itself to get rid of the last remaining
	// references.
	
	EventManager._registry = null;
	},
	
	Remove: function(obj, type, fn, useCapture)
	{
		var i;

		for (i in this._registry)
		{
			if ( this._registry[i].obj == obj && 
			    this._registry[i].type == type && 
			    this._registry[i].fn == fn)
        		{
       			    if (obj.removeEventListener)
			    {
                		 obj.removeEventListener(type, fn, useCapture);
				//alert(" removed " + type + ' ' + fn);

			    }
        		// IE-style listeners?
        		else if (obj.detachEvent)
			{
        		    obj.detachEvent("on" + type, fn);
        		}

			delete this._registry[i];

			 }
			    
		}
	}
};

/*
var eventListeners = [];

function findEventListener(node, event, handler)
{
    var i;
    for (i in eventListeners)
    {
        if (eventListeners[i].node == node && eventListeners[i].event == event
         && eventListeners[i].handler == handler)
        {
            return i;
        }
    }
    return null;
}
function myAddEventListener(node, event, handler)
{
    if (findEventListener(node, event, handler) != null)
    {
        return;
    }

    if (!node.addEventListener)
    {
        node.attachEvent('on' + event, handler);
    }
    else
    {
        node.addEventListener(event, handler, false);
    }

    eventListeners.push({node: node, event: event, handler: handler});
}

function removeEventListenerIndex(index)
{
    var eventListener = eventListeners[index];
    delete eventListeners[index];
    
    if (!eventListener.node.removeEventListener)
    {
        eventListener.node.detachEvent('on' + eventListener.event,
                                       eventListener.handler);
    }
    else
    {
        eventListener.node.removeEventListener(eventListener.event,
                                               eventListener.handler, false);
    }
}

function myRemoveEventListener(node, event, handler)
{
    removeEventListenerIndex(findEventListener(node, event, handler));
}

function cleanupEventListeners()
{
    var i;
    for (i = eventListeners.length; i > 0; i--)
    {
        if (eventListeners[i] != undefined)
        {
            removeEventListenerIndex(i);
        }
    }
}
myAddEventListener(window, 'unload', cleanupEventListeners);

*/
