Skip to content

Instantly share code, notes, and snippets.

@szimek
Created July 21, 2011 13:44
Show Gist options
  • Save szimek/1097213 to your computer and use it in GitHub Desktop.
Save szimek/1097213 to your computer and use it in GitHub Desktop.
devmeetings.pl aspect js task implementation
var aspect = {};
aspect.add = function (obj, fnName, aspectFn, when, once) {
if ('object' !== typeof obj) throw new TypeError('Must pass an object as the first argument');
obj = obj || window;
if (Array.isArray(fnName)) {
fnName.forEach(function (name) {
aspect._add(obj, name, aspectFn, when, once);
});
} else if (fnName instanceof RegExp) {
for (var name in obj) {
if (fnName.test(name)) {
aspect._add(obj, name, aspectFn, when, once);
}
}
} else {
aspect._add(obj, fnName, aspectFn, when, once);
}
};
aspect._add = function (obj, fnName, aspectFn, when, once) {
if (!obj[fnName]) throw new TypeError('Object doesn\'t have function named: ' + fnName);
when = when || 'before';
aspectFn.once = once || false;
var currentFn = obj[fnName],
augmentedFn;
// Check if the function is already agumented
if (currentFn.originalFn) {
if (when === "before") {
currentFn.befores.unshift(aspectFn);
} else {
currentFn.afters.push(aspectFn);
}
} else {
augmentedFn = function () {
augmentedFn.befores.forEach(function (beforeFn) {
beforeFn.apply(this, arguments);
});
// Remove apsect functions that were supposed to run only once
augmentedFn.befores = augmentedFn.befores.filter(function (beforeFn) {
return !beforeFn.once;
});
var result = augmentedFn.originalFn.apply(this, arguments);
augmentedFn.afters.forEach(function (afterFn) {
afterFn.apply(this, arguments);
});
// Remove apsect functions that were supposed to run only once
augmentedFn.afters = augmentedFn.afters.filter(function (afterFn) {
return !afterFn.once;
});
return result;
};
augmentedFn.befores = [];
augmentedFn.afters = [];
augmentedFn.originalFn = currentFn;
if (when === "before") {
augmentedFn.befores.unshift(aspectFn);
} else {
augmentedFn.afters.push(aspectFn);
}
obj[fnName] = augmentedFn;
}
};
aspect.remove = function (obj, fnName, aspectFn, when) {
var augmentedFn = obj[fnName],
type, i;
obj = obj || window;
when = when || 'before';
type = when === 'before' ? 'befores' : 'afters';
// Remove aspect function
i = augmentedFn[type].indexOf(aspectFn);
if (i !== -1) {
augmentedFn[type].splice(i, 1);
}
// Revert function to the original one if there are no more aspect functions
if (!augmentedFn.befores.length && !augmentedFn.afters.length) {
obj[fnName] = augmentedFn.originalFn;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment