diff --git a/js/src/common/extend.js b/js/src/common/extend.js index 7c8694f87..5a29411c6 100644 --- a/js/src/common/extend.js +++ b/js/src/common/extend.js @@ -9,27 +9,36 @@ * Care should be taken to extend the correct object – in most cases, a class' * prototype will be the desired target of extension, not the class itself. * - * @example + * @example Example usage of extending one method. * extend(Discussion.prototype, 'badges', function(badges) { * // do something with `badges` * }); * - * @param {Object} object The object that owns the method - * @param {String} method The name of the method to extend + * @example Example usage of extending multiple methods. + * extend(IndexPage.prototype, ['oncreate', 'onupdate'], function(vnode) { + * // something that needs to be run on creation and update + * }); + * + * @param {object} object The object that owns the method + * @param {string|string[]} methods The name or names of the method(s) to extend * @param {function} callback A callback which mutates the method's output */ -export function extend(object, method, callback) { - const original = object[method]; +export function extend(object, methods, callback) { + const allMethods = Array.isArray(methods) ? methods : [methods]; - object[method] = function (...args) { - const value = original ? original.apply(this, args) : undefined; + allMethods.forEach((method) => { + const original = object[method]; - callback.apply(this, [value].concat(args)); + object[method] = function (...args) { + const value = original ? original.apply(this, args) : undefined; - return value; - }; + callback.apply(this, [value].concat(args)); - Object.assign(object[method], original); + return value; + }; + + Object.assign(object[method], original); + }); } /** @@ -37,29 +46,38 @@ export function extend(object, method, callback) { * new function will be run every time the object's method is called. * * The replacement function accepts the original method as its first argument, - * which is like a call to 'super'. Any arguments passed to the original method + * which is like a call to `super`. Any arguments passed to the original method * are also passed to the replacement. * * Care should be taken to extend the correct object – in most cases, a class' * prototype will be the desired target of extension, not the class itself. * - * @example + * @example Example usage of overriding one method. * override(Discussion.prototype, 'badges', function(original) { * const badges = original(); * // do something with badges * return badges; * }); * - * @param {Object} object The object that owns the method - * @param {String} method The name of the method to override + * @example Example usage of overriding multiple methods. + * extend(Discussion.prototype, ['oncreate', 'onupdate'], function(original, vnode) { + * // something that needs to be run on creation and update + * }); + * + * @param {object} object The object that owns the method + * @param {string|string[]} method The name or names of the method(s) to override * @param {function} newMethod The method to replace it with */ -export function override(object, method, newMethod) { - const original = object[method]; +export function override(object, methods, newMethod) { + const allMethods = Array.isArray(methods) ? methods : [methods]; - object[method] = function (...args) { - return newMethod.apply(this, [original.bind(this)].concat(args)); - }; + allMethods.forEach((method) => { + const original = object[method]; - Object.assign(object[method], original); + object[method] = function (...args) { + return newMethod.apply(this, [original.bind(this)].concat(args)); + }; + + Object.assign(object[method], original); + }); }