Created
July 14, 2010 17:59
-
-
Save davejohnson/475767 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Creates an event object. | |
* @class ChannelChannel class is used for attaching | |
* event handlers to JavaScript objects. | |
* <pre class="code"> | |
* function handleEvent(eventArgs) { | |
* // Do something with the event arguments... | |
* } | |
* | |
* var onItemSelected = new Channel(); | |
* onItemSelected.subscribe(handleEvent); | |
* | |
* // When the item is selected, fire the event. | |
* onItemSelected.notify(eventArgs = {arg1: 'val1', arg2: 'val2'}); | |
* </pre> | |
* @constructor | |
* @param {String} [type] The type of event, e.g., "click", "mouseover" etc. Does not affect the behaviour of the | |
* event object. | |
*/ | |
var Channel = function(type) | |
{ | |
this.type = type; | |
this.handlers = {}; | |
this.guid = 0; | |
this.fired = false; | |
this.enabled = true; | |
} | |
/** | |
* Subscribes a method with a given context to the event. | |
* @example | |
* var onClick = new Channel(); | |
* onClick.subscribe(myClickHandlerFunction); | |
* @param {Function} method The event handler to be executed when the event is fired. | |
* @param {Object} [context] The JavaScript object in the context of which the event handler is to be executed. | |
* @param {String} [guid] A custom GUID. Must be unique. | |
* @return The unique ID of the subscription - it can be used for unsubscription. | |
* @type Number | |
*/ | |
Channel.prototype.subscribe = function(method, context, guid) | |
{ | |
if (method == null) | |
return; | |
var func = method; | |
if (typeof context == "object" && method instanceof Function) | |
func = Channel.close(context, method); | |
guid = guid || func.observer_guid || method.observer_guid || this.guid++; | |
func.observer_guid = method.observer_guid = guid; | |
this.handlers[guid] = func; | |
return guid; | |
} | |
/** | |
* Subscribes a method to the event so that it will fire only once. When method | |
* is executed (on an event notification) it is immediately unsubscribed. | |
* @param {Function} method The event handler to be executed when the event is fired. | |
* @param {Object} context The JavaScript object in the context of which the event handler is to be executed. Optional. | |
* @return The unique ID of the subscription - it can be used for unsubscription. | |
* @type Number | |
*/ | |
Channel.prototype.subscribeOnce = function(method, context) | |
{ | |
var guid = null; | |
var _this = this; | |
var func1 = function() { | |
method.apply(context || null, arguments); | |
_this.unSubscribe(guid); | |
} | |
guid = this.subscribe(func1); | |
return guid; | |
} | |
/** | |
* Unsubscribes a method from an event. | |
* @param {Number|Function} guid The ID of the subscription to remove or the function to unsubscribe. | |
*/ | |
Channel.prototype.unSubscribe = function(guid) { | |
if (guid instanceof Function) | |
guid = guid.observer_guid; | |
this.handlers[guid] = null; | |
delete this.handlers[guid]; | |
} | |
/** | |
* Executes all the event handlers that have been subscribed to this event. | |
* Event handlers should return boolean values. | |
* @param {Object} evtArgs Arbitrary event arguments that are passed to the event handler functions. | |
* @type Boolean | |
*/ | |
Channel.prototype.notify = function(evtArgs) { | |
if (this.enabled) { | |
if (arguments.length == 0) { | |
arguments = new Array(); | |
arguments[0] = {}; | |
arguments[0].event = this; | |
arguments[0].source = null; | |
} else if (typeof(arguments[0].event) != "undefined" && arguments[0].event == null) { | |
arguments[0].event = this; | |
} | |
var fail = false; | |
for (var item in this.handlers) { | |
var handler = this.handlers[item]; | |
if (handler instanceof Function) { | |
var rv = (handler.apply(this, arguments)==false); | |
fail = fail || rv; | |
} | |
} | |
this.fired = true; | |
return !fail; | |
} | |
return true; | |
} | |
Channel.merge = function(handler, events) { | |
var i = events.length; | |
var f = function() { | |
if (!(--i)) handler(); | |
} | |
for (var j=0; j<i; j++) { | |
var e = events[j]; | |
(!e.fired?e.subscribeOnce(f):i--); | |
} | |
if (!i) handler(); | |
} | |
Channel.close = function(context, func, params) { | |
if (null == params) | |
return function() { | |
return func.apply(context, arguments); | |
} | |
else | |
return function() { | |
return func.apply(context, params); | |
} | |
} | |
//==================== | |
// Example usage... | |
var foo = new Channel(); | |
var bar = new Channel(); | |
Channel.merge(function() {alert('foobar!');}, [foo, bar]); | |
foo.notify(); // noting happens | |
bar.notify(); // alert('foobar!'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment