source/intercom.js
// ##Intercom
// A standalone function for an event subscriber
// system to be used in other modules
Struck.Intercom = (function () {
// setup default subscription object
// used to clone and extend in `subscribe` function
var defaultSubscription = {
single: false,
name: 'all',
callback: _.noop,
context: root
};
// get keys from default subscription object
// useful for iteration and filtering
var subscriptionKeys = _.keys(defaultSubscription);
// #####Constructor
// set up default subscriptio object's context to the
// intercom instance and create subscription collection
var Intercom = Struck.BaseObject.extend();
Intercom.prototype.initializeObject = function () {
Struck.BaseObject.prototype.initializeObject.apply(this, arguments);
this.defaultSubscription = _.extend({}, defaultSubscription, { context: this });
this.subscriptions = [];
return this;
};
// #####Intercom.on
Intercom.prototype.on = function(names, callback, context, opts) {
subscriber(this, names, callback, {
single: firstDef(opts && opts.single, false),
context: context
});
return this;
};
// #####Intercom.once
Intercom.prototype.once = function(names, callback, context) {
return this.on(names, callback, context, { single: true });
};
// #####Intercom.off
Intercom.prototype.off = function(names, callback) {
unsubscriber(this, names, callback);
return this;
};
// #####Intercom.emit
Intercom.prototype.emit = function (names) {
var args = _.rest(arguments, 1);
var filteredSubs = _.reduce(splitName(names, this), function (subs, name) {
var matches = _.filter(this.subscriptions, function (subscriber) {
return subscriber.name === name;
}, this);
return subs.concat(matches);
}, [], this);
filteredSubs = _.unique(filteredSubs);
_.each(filteredSubs, function(sub) {
trigger(this, sub, args);
}, this);
return this;
};
// ###Private Functions
// #####subscriber
// splits and delegates subscriptions from on/once calls
function subscriber(com, names, func, opts) {
_.each(splitName(names, com), function (name) {
subscribe(com, name, func, {
single: opts.single,
context: opts.context
});
});
}
// #####subscribe
// build subscription object from
// name and function, additional
// options are optional...
function subscribe(com, name, func, opts) {
if (!name && !func) { return; }
var subOptions = {
name: name,
callback: func
};
// add useful options to subOptions
_.each(subscriptionKeys, function (key) {
if (opts[key]) {
subOptions[key] = opts[key];
}
});
// create a new subscription from the default object
// and overwrite properties with subOptions,
// then adds subscription to collection
var subscription = _.extend({}, defaultSubscription, subOptions);
com.subscriptions.push(subscription);
}
function unsubscriber(com, names, func) {
if (names === undefined) {
unsubscribe(com);
return;
}
_.each(splitName(names, com), function (name) {
unsubscribe(com, name, func);
});
}
// #####unsubscribe
//
function unsubscribe(com, name, func) {
var filter = function (sub) {
// com, name, func:
// .. remove specific subscriber function
if (func) {
return sub.name === name && sub.callback === func;
// com, name:
// .. remove all subscribers by name
} else if (name) {
return sub.name === name;
}
// remove all subscriptions if no arguments provided
return true;
};
com.subscriptions = _.reject(com.subscriptions, filter);
}
// #####trigger
//
function trigger(com, sub, args) {
sub.callback.apply(sub.context, args);
if (sub.single) {
unsubscribe(com, sub.name, sub.callback);
}
}
return Intercom;
})();