Place to store the code and config used for the next-Iterations live event. https://iterations.space/live/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

288 lines
7.2 KiB

/*
* The same functionality as EventEmitter but with the inclusion of callbacks
*/
function PluginInterface () {
// Holder for all the bound listeners by this module
this._listeners = {};
// Event proxies
this._parent = null;
this._children = [];
}
PluginInterface.prototype.on = function (event_name, fn, scope) {
this._listeners[event_name] = this._listeners[event_name] || [];
this._listeners[event_name].push(['on', fn, scope]);
};
PluginInterface.prototype.once = function (event_name, fn, scope) {
this._listeners[event_name] = this._listeners[event_name] || [];
this._listeners[event_name].push(['once', fn, scope]);
};
PluginInterface.prototype.off = function (event_name, fn, scope) {
var idx;
if (typeof event_name === 'undefined') {
// Remove all listeners
this._listeners = {};
} else if (typeof fn === 'undefined') {
// Remove all of 1 event type
delete this._listeners[event_name];
} else if (typeof scope === 'undefined') {
// Remove a single event type + callback
for (idx=0; idx<(this._listeners[event_name] || []).length; idx++) {
if (this._listeners[event_name][idx][1] === fn) {
//delete this._listeners[event_name][idx];
this._listeners[event_name].splice(idx, 1);
idx--;
}
}
} else {
// Remove a single event type + callback + scope
for (idx=0; idx<(this._listeners[event_name] || []).length; idx++) {
if (this._listeners[event_name][idx][1] === fn && this._listeners[event_name][idx][2] === scope) {
//delete this._listeners[event_name][idx];
this._listeners[event_name].splice(idx, 1);
idx--;
}
}
}
};
PluginInterface.prototype.getListeners = function(event_name) {
return this._listeners[event_name] || [];
};
PluginInterface.prototype.createProxy = function() {
var proxy = new PluginInterface();
proxy._parent = this._parent || this;
proxy._parent._children.push(proxy);
return proxy;
};
PluginInterface.prototype.dispose = function() {
this.off();
if (this._parent) {
var idx = this._parent._children.indexOf(this);
if (idx > -1) {
this._parent._children.splice(idx, 1);
}
}
};
// Call all the listeners for a certain event, passing them some event data that may be changed
PluginInterface.prototype.emit = function (event_name, event_data) {
var emitter = new this.EmitCall(event_name, event_data),
listeners = [],
child_idx;
// Get each childs event listeners in order of last created
for(child_idx=this._children.length-1; child_idx>=0; child_idx--) {
listeners = listeners.concat(this._children[child_idx].getListeners(event_name));
}
// Now include any listeners directly on this instance
listeners = listeners.concat(this.getListeners(event_name));
// Once emitted, remove any 'once' bound listeners
emitter.then(function () {
var len = listeners.length,
idx;
for(idx = 0; idx < len; idx++) {
if (listeners[idx][0] === 'once') {
listeners[idx] = undefined;
}
}
});
// Emit the event to the listeners and return
emitter.callListeners(listeners);
return emitter;
};
// Promise style object to emit events to listeners
PluginInterface.prototype.EmitCall = function EmitCall (event_name, event_data) {
var that = this,
completed = false,
completed_fn = [],
// Has event.preventDefault() been called
prevented = false,
prevented_fn = [];
// Emit this event to an array of listeners
function callListeners(listeners) {
var current_event_idx = -1;
// Make sure we have some data to pass to the listeners
event_data = event_data || undefined;
// If no bound listeners for this event, leave now
if (listeners.length === 0) {
emitComplete();
return;
}
// Call the next listener in our array
function nextListener() {
var listener, event_obj;
// We want the next listener
current_event_idx++;
// If we've ran out of listeners end this emit call
if (!listeners[current_event_idx]) {
emitComplete();
return;
}
// Object the listener ammends to tell us what it's going to do
event_obj = {
// If changed to true, expect this listener is going to callback
wait: false,
// If wait is true, this callback must be called to continue running listeners
callback: function () {
// Invalidate this callback incase a listener decides to call it again
event_obj.callback = undefined;
nextListener.apply(that);
},
// Prevents the default 'done' functions from executing
preventDefault: function () {
prevented = true;
}
};
listener = listeners[current_event_idx];
listener[1].call(listener[2] || that, event_obj, event_data);
// If the listener hasn't signalled it's going to wait, proceed to next listener
if (!event_obj.wait) {
// Invalidate the callback just incase a listener decides to call it anyway
event_obj.callback = undefined;
nextListener();
}
}
nextListener();
}
function emitComplete() {
completed = true;
var funcs = prevented ? prevented_fn : completed_fn;
funcs = funcs || [];
// Call the completed/prevented functions
for (var idx = 0; idx < funcs.length; idx++) {
if (typeof funcs[idx] === 'function') funcs[idx]();
}
}
function addCompletedFunc(fn) {
// Only accept functions
if (typeof fn !== 'function') return false;
completed_fn.push(fn);
// If we have already completed the emits, call this now
if (completed && !prevented) fn();
return this;
}
function addPreventedFunc(fn) {
// Only accept functions
if (typeof fn !== 'function') return false;
prevented_fn.push(fn);
// If we have already completed the emits, call this now
if (completed && prevented) fn();
return this;
}
return {
callListeners: callListeners,
then: addCompletedFunc,
catch: addPreventedFunc
};
};
// If running a node module, set the exports
if (typeof module === 'object' && typeof module.exports !== 'undefined') {
module.exports = PluginInterface;
}
/*
* Example usage
*/
/*
var modules = new PluginInterface();
// A plugin
modules.on('irc message', function (event, data) {
//event.wait = true;
setTimeout(event.callback, 2000);
});
// Core code that is being extended by plugins
var data = {
nick: 'prawnsalald',
command: '/dothis'
};
modules.emit('irc message', data).done(function () {
console.log('Your command is: ' + data.command);
});
*/