/* * 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) { if (this._registry == null) 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; var func // Mozilla/W3C listeners? if (obj.addEventListener) { if (arguments[4]) { var args=arguments[4]; obj.addEventListener(type,func=function(e) { if (e.cancelBubble) e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); fn(this,args);return false;}, useCapture); } else { func=fn obj.addEventListener(type, fn, useCapture); } this._registry.push({obj: obj, type: type, fn: func, useCapture: useCapture}); return true; } // IE-style listeners? if (obj.attachEvent) { if (arguments[4]) { var args=arguments[4]; obj.attachEvent("on"+type,func=function(e) { if (e.cancelBubble) e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); fn(this,args);return false;}); } else { func=fn obj.attachEvent("on" + type, fn) } this._registry.push({obj: obj, type: type, fn: func, useCapture: false}); return true; } return false; }, Remove: function(obj) { // If a string was passed in, it's an id. if (typeof obj == "string") obj = document.getElementById(obj); if (obj == null) return false; for (var i = 0; i < this._registry.length; i++){ if (this._registry[i] && this._registry[i]['obj']==obj) { var e=this._registry[i]; // Mozilla/W3C listeners? if (obj.removeEventListener){obj.removeEventListener(e.type, e.fn, e.useCapture);} // IE-style listeners? else if (obj.detachEvent){ obj.detachEvent("on" + e.type, e.fn);} this._registry[i]=null; } } }, /** * Cleans up all the registered event handlers. */ CleanUp: function() { var e; for (var i = 0; i < EventManager._registry.length; i++) { if (e=EventManager._registry[i]) { // Mozilla/W3C listeners? if (e.obj.removeEventListener) e.obj.removeEventListener(e.type,e.fn,e.useCapture); // IE-style listeners? else if (e.obj.detachEvent) e.obj.detachEvent("on" + e.type, e.fn); } } // Kill off the registry itself to get rid of the last remaining // references. EventManager._registry = null; } };