[Rails-spinoffs] EventPublisher (contribution)

Ryan Gahl Ryan.Gahl at camtronics.com
Tue Feb 28 15:32:04 GMT 2006


Skipped content of type multipart/alternative-------------- next part --------------
///// EventPublisher Class /////////////////////////////////////////////////////////
//
// The EventPublisher class allows objects to fire events (and other objects to
// subscribe handlers to those events). The events can be fired either 
// synchronously or asynchonously (depending on how the handlers register themselves),
// and may pass optional arguments to the handlers.

EventPublisher = Class.create();
EventPublisher.prototype = {
	initialize: function() {
	},
	
	// pass the asynch flag (true/false) as the 3rd argument, or omit it to default to false
	attachEventHandler: function(eventName, handler) {
		// using an event cache array to track all handlers for proper cleanup
		if (this.allEvents == null)
			this.allEvents = new Array();
		// loop through the event cache to prevent adding duplicates
		var len = this.allEvents.length;
		var foundEvent = false;
		for (var i = 0; i < len; i++) {
			if (this.allEvents[i] == eventName) {
				foundEvent = true;
				break;
			}
		}
		if (!foundEvent)
			this.allEvents.push(eventName);
			
		eventName = eventName + "_evt"; // appending _evt to event name to avoid collisions
		if (this[eventName] == null)
			this[eventName] = new Array();
			
		//create a custom object containing the handler method and the asynch flag
		var asynchVar = arguments.length > 2 ? arguments[1] : false;
		var handlerObj = {
			method: handler,
			asynch: asynchVar
		};
		
		this[eventName].push(handlerObj);
	},
	
	// Removes a single handler from a specific event
	removeEventHandler: function(eventName, handler) {
		eventName = eventName + "_evt"; // appending _evt to event name to avoid collisions
		if (this[eventName] != null)
			this[eventName] = this[eventName].reject(function(obj) { return obj.method == handler; });
	},
	
	// Removes all handlers from a single event
	clearEventHandlers: function(eventName) {
		eventName = eventName + "_evt"; // appending _evt to event name to avoid collisions
		this[eventName] = null;
	},
	
	// Removes all handlers from ALL events
	clearAllEventHandlers: function() {
		if (this.allEvents) {
			var len = this.allEvents.length;
			for (var i = 0; i < len; i++) {
				this.clearEventHandlers(this.allEvents[i]);
			}
		}
	},    
	
	//to pass arguments to the handlers, include a 2nd argument (anonymous object that can contain whatever you want)
	fireEvent: function(eventName) {
		var evtName = eventName + "_evt"; // appending _evt to event name to avoid collisions
		if (this[evtName] != null) {
			var len = this[evtName].length; //optimization
							
			for (var i = 0; i < len; i++)
			{
				try
				{
					if (arguments.length > 1)
					{
						if (this[evtName][i].asynch)
						{
							//using a double closure to maintain "this" scope and pass all arguments properly (not sure if this is overkill or not)
							var eventArgs = arguments[1];
							var eventHandler = function(evt, index, args) { this[evt][index].method(args); }.bind(this);
							var eventHandlerPointer = function() { eventHandler(evtName, i, eventArgs); }.bind(this);
							setTimeout(eventHandlerPointer, 1);
						}
						else
							this[evtName][i].method(arguments[1]);                        
					} else {
						if (this[evtName][i].asynch)
						{
							var eventHandler = this[evtName][i].method;
							setTimeout(eventHandler, 1);
						}
						else
							if (this && this[evtName] && this[evtName][i] && this[evtName][i].method)
								this[evtName][i].method();
							//this[evtName][i].method();
					}
				}
				catch (e) {
					if (this.id) {
						alert("ERROR: error in " + this.id + ".fireEvent():\n\n"  + e.message);
					} else {
						alert("ERROR: error in [unknown object].fireEvent():\n\n" + e.message);
					}
				}
			}
		}
	}
};


More information about the Rails-spinoffs mailing list