Skip to content

Instantly share code, notes, and snippets.

@Fordi
Created November 18, 2011 02:12
Show Gist options
  • Save Fordi/1375348 to your computer and use it in GitHub Desktop.
Save Fordi/1375348 to your computer and use it in GitHub Desktop.
Library agnostic invokation events for functions
(function () {
"use strict";
/**
* Add event couplings to a function, enabling aspect-oriented design patterns
*
* @return Function Coupled function
**/
Function.prototype.couple = function () {
var fn = this,
events = {before: {}, after: {}};
wFn = function () {
var i,
token = {
context: this,
args: Array.prototype.slice.apply(arguments),
returned: null,
event: 'before'
};
if (false === triggerEvents(token))
return null;
token.returned = fn.apply(token.context, token.args);
token.event = after;
if (false === triggerEvents(token))
return null;
return token.returned;
};
function triggerEvents(token) {
for (var i in events[token.event]) {
if (false === events[token.event][i].call(token.context, token))
return false;
}
return true;
}
function addEventMethod(which) {
return function () {
for (var i=0; i<arguments.length; i++)
events[which][arguments[i]] = arguments[i];
return wFn;
};
}
/**
* Insert a closure before the invokation of the coupled function
*
* @rest Function[context](token) closure to insert
* @param Object token Invokation token
* @param Object token.context Context in which the function was called
* @param Array token.args Arguments with which the function was called
* @param Object token.returned Return value of the function (null for before)
* @param String token.event Event on which the handler was called
* @return Boolean Whether to continue event handling. For before, determines whether invokation completes.
* @return Function Coupled function (chainable)
**/
wFn.before = addEventMethod('before');
/**
* Insert a closure after the invokation of the coupled function
* @see wFn.before
**/
wFn.after = addEventMethod('after');
/**
* Remove an event handler
**/
wFn.decouple = function () {
for (var i=0; i<arguments.length; i++) {
delete events.before[arguments[i]];
delete events.after[arguments[i]];
}
return wFn;
};
/**
* The original function
**/
wFn.original = fn;
return wFn;
};
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment