mediator-js
Advanced tools
Comparing version 0.9.8 to 0.9.9
@@ -19,3 +19,3 @@ /*jslint bitwise: true, nomen: true, plusplus: true, white: true */ | ||
if(typeof define === 'function' && define.amd) { | ||
if (typeof define === 'function' && define.amd) { | ||
// AMD | ||
@@ -53,4 +53,4 @@ define('mediator-js', [], function() { | ||
function Subscriber(fn, options, context){ | ||
if(!(this instanceof Subscriber)) { | ||
function Subscriber(fn, options, context) { | ||
if (!(this instanceof Subscriber)) { | ||
return new Subscriber(fn, options, context); | ||
@@ -66,22 +66,19 @@ } | ||
Subscriber.prototype = { | ||
// Mediator.update on a subscriber instance can update its function,context, | ||
// or options object. It takes in an object and looks for fn, context, or | ||
// options keys. | ||
update: function(options){ | ||
if(options){ | ||
this.fn = options.fn || this.fn; | ||
this.context = options.context || this.context; | ||
this.options = options.options || this.options; | ||
if(this.channel && this.options && this.options.priority !== undefined) { | ||
this.channel.setPriority(this.id, this.options.priority); | ||
} | ||
// Mediator.update on a subscriber instance can update its function,context, | ||
// or options object. It takes in an object and looks for fn, context, or | ||
// options keys. | ||
Subscriber.prototype.update = function(options) { | ||
if (options) { | ||
this.fn = options.fn || this.fn; | ||
this.context = options.context || this.context; | ||
this.options = options.options || this.options; | ||
if (this.channel && this.options && this.options.priority !== undefined) { | ||
this.channel.setPriority(this.id, this.options.priority); | ||
} | ||
} | ||
}; | ||
} | ||
function Channel(namespace, parent){ | ||
if(!(this instanceof Channel)) { | ||
function Channel(namespace, parent) { | ||
if (!(this instanceof Channel)) { | ||
return new Channel(namespace); | ||
@@ -102,97 +99,95 @@ } | ||
// through the Mediator instance. | ||
Channel.prototype.addSubscriber = function(fn, options, context) { | ||
var subscriber = new Subscriber(fn, options, context); | ||
Channel.prototype = { | ||
addSubscriber: function(fn, options, context){ | ||
var subscriber = new Subscriber(fn, options, context); | ||
if (options && options.priority !== undefined) { | ||
// Cheap hack to either parse as an int or turn it into 0. Runs faster | ||
// in many browsers than parseInt with the benefit that it won't | ||
// return a NaN. | ||
options.priority = options.priority >> 0; | ||
if(options && options.priority !== undefined){ | ||
// Cheap hack to either parse as an int or turn it into 0. Runs faster | ||
// in many browsers than parseInt with the benefit that it won't | ||
// return a NaN. | ||
options.priority = options.priority >> 0; | ||
if (options.priority < 0) { options.priority = 0; } | ||
if (options.priority >= this._subscribers.length) { options.priority = this._subscribers.length-1; } | ||
if(options.priority < 0){ options.priority = 0; } | ||
if(options.priority >= this._subscribers.length){ options.priority = this._subscribers.length-1; } | ||
this._subscribers.splice(options.priority, 0, subscriber); | ||
}else{ | ||
this._subscribers.push(subscriber); | ||
} | ||
this._subscribers.splice(options.priority, 0, subscriber); | ||
}else{ | ||
this._subscribers.push(subscriber); | ||
} | ||
subscriber.channel = this; | ||
subscriber.channel = this; | ||
return subscriber; | ||
} | ||
return subscriber; | ||
}, | ||
// The channel instance is passed as an argument to the mediator subscriber, | ||
// and further subscriber propagation can be called with | ||
// channel.StopPropagation(). | ||
Channel.prototype.stopPropagation = function() { | ||
this.stopped = true; | ||
} | ||
// The channel instance is passed as an argument to the mediator subscriber, | ||
// and further subscriber propagation can be called with | ||
// channel.StopPropagation(). | ||
stopPropagation: function(){ | ||
this.stopped = true; | ||
}, | ||
Channel.prototype.getSubscriber = function(identifier) { | ||
var x = 0, | ||
y = this._subscribers.length; | ||
getSubscriber: function(identifier){ | ||
var x = 0, | ||
y = this._subscribers.length; | ||
for(x, y; x < y; x++){ | ||
if(this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier){ | ||
return this._subscribers[x]; | ||
} | ||
for(x, y; x < y; x++) { | ||
if (this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier) { | ||
return this._subscribers[x]; | ||
} | ||
}, | ||
} | ||
} | ||
// Channel.setPriority is useful in updating the order in which Subscribers | ||
// are called, and takes an identifier (subscriber id or named function) and | ||
// an array index. It will not search recursively through subchannels. | ||
// Channel.setPriority is useful in updating the order in which Subscribers | ||
// are called, and takes an identifier (subscriber id or named function) and | ||
// an array index. It will not search recursively through subchannels. | ||
setPriority: function(identifier, priority){ | ||
var oldIndex = 0, | ||
x = 0, | ||
sub, firstHalf, lastHalf, y; | ||
Channel.prototype.setPriority = function(identifier, priority) { | ||
var oldIndex = 0, | ||
x = 0, | ||
sub, firstHalf, lastHalf, y; | ||
for(x = 0, y = this._subscribers.length; x < y; x++){ | ||
if(this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier){ | ||
break; | ||
} | ||
oldIndex ++; | ||
for(x = 0, y = this._subscribers.length; x < y; x++) { | ||
if (this._subscribers[x].id === identifier || this._subscribers[x].fn === identifier) { | ||
break; | ||
} | ||
oldIndex ++; | ||
} | ||
sub = this._subscribers[oldIndex]; | ||
firstHalf = this._subscribers.slice(0, oldIndex); | ||
lastHalf = this._subscribers.slice(oldIndex+1); | ||
sub = this._subscribers[oldIndex]; | ||
firstHalf = this._subscribers.slice(0, oldIndex); | ||
lastHalf = this._subscribers.slice(oldIndex+1); | ||
this._subscribers = firstHalf.concat(lastHalf); | ||
this._subscribers.splice(priority, 0, sub); | ||
}, | ||
this._subscribers = firstHalf.concat(lastHalf); | ||
this._subscribers.splice(priority, 0, sub); | ||
} | ||
addChannel: function(channel){ | ||
this._channels[channel] = new Channel((this.namespace ? this.namespace + ':' : '') + channel, this); | ||
}, | ||
Channel.prototype.addChannel = function(channel) { | ||
this._channels[channel] = new Channel((this.namespace ? this.namespace + ':' : '') + channel, this); | ||
} | ||
hasChannel: function(channel){ | ||
return this._channels.hasOwnProperty(channel); | ||
}, | ||
Channel.prototype.hasChannel = function(channel) { | ||
return this._channels.hasOwnProperty(channel); | ||
} | ||
returnChannel: function(channel){ | ||
return this._channels[channel]; | ||
}, | ||
Channel.prototype.returnChannel = function(channel) { | ||
return this._channels[channel]; | ||
} | ||
removeSubscriber: function(identifier){ | ||
var x = this._subscribers.length - 1; | ||
Channel.prototype.removeSubscriber = function(identifier) { | ||
var x = this._subscribers.length - 1; | ||
// If we don't pass in an id, we're clearing all | ||
if(!identifier){ | ||
this._subscribers = []; | ||
return; | ||
} | ||
// If we don't pass in an id, we're clearing all | ||
if (!identifier) { | ||
this._subscribers = []; | ||
return; | ||
} | ||
// Going backwards makes splicing a whole lot easier. | ||
for(x; x >= 0; x--) { | ||
if(this._subscribers[x].fn === identifier || this._subscribers[x].id === identifier){ | ||
this._subscribers[x].channel = null; | ||
this._subscribers.splice(x,1); | ||
} | ||
// Going backwards makes splicing a whole lot easier. | ||
for(x; x >= 0; x--) { | ||
if (this._subscribers[x].fn === identifier || this._subscribers[x].id === identifier) { | ||
this._subscribers[x].channel = null; | ||
this._subscribers.splice(x,1); | ||
} | ||
}, | ||
} | ||
} | ||
@@ -202,61 +197,60 @@ // This will publish arbitrary arguments to a subscriber and then to parent | ||
publish: function(data){ | ||
var x = 0, | ||
y = this._subscribers.length, | ||
shouldCall = false, | ||
subscriber, l, | ||
subsBefore,subsAfter; | ||
Channel.prototype.publish = function(data) { | ||
var x = 0, | ||
y = this._subscribers.length, | ||
shouldCall = false, | ||
subscriber, l, | ||
subsBefore,subsAfter; | ||
// Priority is preserved in the _subscribers index. | ||
for(x, y; x < y; x++) { | ||
// By default set the flag to false | ||
shouldCall = false; | ||
subscriber = this._subscribers[x]; | ||
// Priority is preserved in the _subscribers index. | ||
for(x, y; x < y; x++) { | ||
// By default set the flag to false | ||
shouldCall = false; | ||
subscriber = this._subscribers[x]; | ||
if(!this.stopped){ | ||
subsBefore = this._subscribers.length; | ||
if(subscriber.options !== undefined && typeof subscriber.options.predicate === "function"){ | ||
if(subscriber.options.predicate.apply(subscriber.context, data)){ | ||
// The predicate matches, the callback function should be called | ||
shouldCall = true; | ||
} | ||
}else{ | ||
// There is no predicate to match, the callback should always be called | ||
if (!this.stopped) { | ||
subsBefore = this._subscribers.length; | ||
if (subscriber.options !== undefined && typeof subscriber.options.predicate === "function") { | ||
if (subscriber.options.predicate.apply(subscriber.context, data)) { | ||
// The predicate matches, the callback function should be called | ||
shouldCall = true; | ||
} | ||
}else{ | ||
// There is no predicate to match, the callback should always be called | ||
shouldCall = true; | ||
} | ||
} | ||
// Check if the callback should be called | ||
if(shouldCall) { | ||
// Check if the subscriber has options and if this include the calls options | ||
if (subscriber.options && subscriber.options.calls !== undefined){ | ||
// Decrease the number of calls left by one | ||
subscriber.options.calls--; | ||
// Once the number of calls left reaches zero or less we need to remove the subscriber | ||
if(subscriber.options.calls < 1){ | ||
this.removeSubscriber(subscriber.id); | ||
} | ||
// Check if the callback should be called | ||
if (shouldCall) { | ||
// Check if the subscriber has options and if this include the calls options | ||
if (subscriber.options && subscriber.options.calls !== undefined) { | ||
// Decrease the number of calls left by one | ||
subscriber.options.calls--; | ||
// Once the number of calls left reaches zero or less we need to remove the subscriber | ||
if (subscriber.options.calls < 1) { | ||
this.removeSubscriber(subscriber.id); | ||
} | ||
// Now we call the callback, if this in turns publishes to the same channel it will no longer | ||
// cause the callback to be called as we just removed it as a subscriber | ||
subscriber.fn.apply(subscriber.context, data); | ||
} | ||
// Now we call the callback, if this in turns publishes to the same channel it will no longer | ||
// cause the callback to be called as we just removed it as a subscriber | ||
subscriber.fn.apply(subscriber.context, data); | ||
subsAfter = this._subscribers.length; | ||
y = subsAfter; | ||
if (subsAfter === subsBefore - 1){ | ||
x--; | ||
} | ||
subsAfter = this._subscribers.length; | ||
y = subsAfter; | ||
if (subsAfter === subsBefore - 1) { | ||
x--; | ||
} | ||
} | ||
} | ||
if(this._parent){ | ||
this._parent.publish(data); | ||
} | ||
this.stopped = false; | ||
if (this._parent) { | ||
this._parent.publish(data); | ||
} | ||
}; | ||
this.stopped = false; | ||
} | ||
function Mediator() { | ||
if(!(this instanceof Mediator)) { | ||
if (!(this instanceof Mediator)) { | ||
return new Mediator(); | ||
@@ -271,108 +265,104 @@ } | ||
Mediator.prototype = { | ||
// Returns a channel instance based on namespace, for example | ||
// application:chat:message:received. If readOnly is true we | ||
// will refrain from creating non existing channels. | ||
Mediator.prototype.getChannel = function(namespace, readOnly) { | ||
var channel = this._channels, | ||
namespaceHierarchy = namespace.split(':'), | ||
x = 0, | ||
y = namespaceHierarchy.length; | ||
// Returns a channel instance based on namespace, for example | ||
// application:chat:message:received. If readOnly is true we | ||
// will refrain from creating non existing channels. | ||
if (namespace === '') { | ||
return channel; | ||
} | ||
getChannel: function(namespace, readOnly){ | ||
var channel = this._channels, | ||
namespaceHierarchy = namespace.split(':'), | ||
x = 0, | ||
y = namespaceHierarchy.length; | ||
if (namespaceHierarchy.length > 0) { | ||
for(x, y; x < y; x++) { | ||
if(namespace === ''){ | ||
return channel; | ||
} | ||
if(namespaceHierarchy.length > 0){ | ||
for(x, y; x < y; x++){ | ||
if(!channel.hasChannel(namespaceHierarchy[x])){ | ||
if (readOnly) { | ||
break; | ||
} else { | ||
channel.addChannel(namespaceHierarchy[x]); | ||
} | ||
if (!channel.hasChannel(namespaceHierarchy[x])) { | ||
if (readOnly) { | ||
break; | ||
} else { | ||
channel.addChannel(namespaceHierarchy[x]); | ||
} | ||
} | ||
channel = channel.returnChannel(namespaceHierarchy[x]); | ||
} | ||
channel = channel.returnChannel(namespaceHierarchy[x]); | ||
} | ||
} | ||
return channel; | ||
}, | ||
return channel; | ||
} | ||
// Pass in a channel namespace, function to be called, options, and context | ||
// to call the function in to Subscribe. It will create a channel if one | ||
// does not exist. Options can include a predicate to determine if it | ||
// should be called (based on the data published to it) and a priority | ||
// index. | ||
// Pass in a channel namespace, function to be called, options, and context | ||
// to call the function in to Subscribe. It will create a channel if one | ||
// does not exist. Options can include a predicate to determine if it | ||
// should be called (based on the data published to it) and a priority | ||
// index. | ||
subscribe: function(channelName, fn, options, context){ | ||
var channel = this.getChannel(channelName || "", false); | ||
Mediator.prototype.subscribe = function(channelName, fn, options, context) { | ||
var channel = this.getChannel(channelName || "", false); | ||
options = options || {}; | ||
context = context || {}; | ||
options = options || {}; | ||
context = context || {}; | ||
return channel.addSubscriber(fn, options, context); | ||
}, | ||
return channel.addSubscriber(fn, options, context); | ||
} | ||
// Pass in a channel namespace, function to be called, options, and context | ||
// to call the function in to Subscribe. It will create a channel if one | ||
// does not exist. Options can include a predicate to determine if it | ||
// should be called (based on the data published to it) and a priority | ||
// index. | ||
// Pass in a channel namespace, function to be called, options, and context | ||
// to call the function in to Subscribe. It will create a channel if one | ||
// does not exist. Options can include a predicate to determine if it | ||
// should be called (based on the data published to it) and a priority | ||
// index. | ||
once: function(channelName, fn, options, context){ | ||
options = options || {}; | ||
options.calls = 1; | ||
Mediator.prototype.once = function(channelName, fn, options, context) { | ||
options = options || {}; | ||
options.calls = 1; | ||
return this.subscribe(channelName, fn, options, context); | ||
}, | ||
return this.subscribe(channelName, fn, options, context); | ||
} | ||
// Returns a subscriber for a given subscriber id / named function and | ||
// channel namespace | ||
// Returns a subscriber for a given subscriber id / named function and | ||
// channel namespace | ||
getSubscriber: function(identifier, channelName){ | ||
var channel = this.getChannel(channelName || "", true); | ||
// We have to check if channel within the hierarchy exists and if it is | ||
// an exact match for the requested channel | ||
if (channel.namespace !== channelName) { | ||
return null; | ||
} | ||
Mediator.prototype.getSubscriber = function(identifier, channelName) { | ||
var channel = this.getChannel(channelName || "", true); | ||
// We have to check if channel within the hierarchy exists and if it is | ||
// an exact match for the requested channel | ||
if (channel.namespace !== channelName) { | ||
return null; | ||
} | ||
return channel.getSubscriber(identifier); | ||
}, | ||
return channel.getSubscriber(identifier); | ||
} | ||
// Remove a subscriber from a given channel namespace recursively based on | ||
// a passed-in subscriber id or named function. | ||
// Remove a subscriber from a given channel namespace recursively based on | ||
// a passed-in subscriber id or named function. | ||
remove: function(channelName, identifier){ | ||
var channel = this.getChannel(channelName || "", true); | ||
if (channel.namespace !== channelName) { | ||
return false; | ||
} | ||
Mediator.prototype.remove = function(channelName, identifier) { | ||
var channel = this.getChannel(channelName || "", true); | ||
if (channel.namespace !== channelName) { | ||
return false; | ||
} | ||
channel.removeSubscriber(identifier); | ||
}, | ||
channel.removeSubscriber(identifier); | ||
} | ||
// Publishes arbitrary data to a given channel namespace. Channels are | ||
// called recursively downwards; a post to application:chat will post to | ||
// application:chat:receive and application:chat:derp:test:beta:bananas. | ||
// Called using Mediator.publish("application:chat", [ args ]); | ||
// Publishes arbitrary data to a given channel namespace. Channels are | ||
// called recursively downwards; a post to application:chat will post to | ||
// application:chat:receive and application:chat:derp:test:beta:bananas. | ||
// Called using Mediator.publish("application:chat", [ args ]); | ||
publish: function(channelName){ | ||
var channel = this.getChannel(channelName || "", true); | ||
if (channel.namespace !== channelName) { | ||
return null; | ||
} | ||
Mediator.prototype.publish = function(channelName) { | ||
var channel = this.getChannel(channelName || "", true); | ||
if (channel.namespace !== channelName) { | ||
return null; | ||
} | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
args.push(channel); | ||
args.push(channel); | ||
channel.publish(args); | ||
} | ||
}; | ||
channel.publish(args); | ||
} | ||
@@ -379,0 +369,0 @@ // Alias some common names for easy interop |
{ | ||
"name": "mediator-js", | ||
"version": "0.9.8", | ||
"version": "0.9.9", | ||
"description": "Flexible event management. Implementation of the mediator pattern.", | ||
@@ -5,0 +5,0 @@ "author": "Jack Lawson <jlawson@olivinelabs.com>", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
128359
2894