!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.stampit=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { throw new Error('Object.create implementation only accepts the first parameter.'); } function F() {} F.prototype = o; return new F(); }; if(!Array.isArray) { Array.isArray = function (vArg) { return Object.prototype.toString.call(vArg) === "[object Array]"; }; } var extractFunctions = function extractFunctions(arg) { var arr = [], args = [].slice.call(arguments); if (typeof arg === 'function') { arr = map(args, function (fn) { if (typeof fn === 'function') { return fn; } }); } else if (typeof arg === 'object') { forEach(args, function (obj) { forOwn(obj, function (fn) { arr.push(fn); }); }); } else if ( Array.isArray(arg) ) { forEach(arg, function (fn) { arr.push(fn); }); } return arr; }; /** * Return a factory function that will produce new objects using the * prototypes that are passed in or composed. * * @param {Object} [methods] A map of method names and bodies for delegation. * @param {Object} [state] A map of property names and values to clone for each new object. * @param {Function} [enclose] A closure (function) used to create private data and privileged methods. * @return {Function} factory A factory to produce objects using the given prototypes. * @return {Function} factory.create Just like calling the factory function. * @return {Object} factory.fixed An object map containing the fixed prototypes. * @return {Function} factory.methods Add methods to the methods prototype. Chainable. * @return {Function} factory.state Add properties to the state prototype. Chainable. * @return {Function} factory.enclose Add or replace the closure prototype. Not chainable. */ var stampit = function stampit(methods, state, enclose) { var fixed = { methods: methods || {}, state: state, enclose: extractFunctions(enclose) }, factory = function factory(properties) { var state = merge({}, fixed.state), instance = mixIn(create(fixed.methods || {}), state, properties), closures = fixed.enclose, args = slice.call(arguments, 1); forEach(closures, function (fn) { if (typeof fn === 'function') { instance = fn.apply(instance, args) || instance; } }); return instance; }; return mixIn(factory, { create: factory, fixed: fixed, /** * Take n objects and add them to the methods prototype. * @return {Object} stamp The factory in question (`this`). */ methods: function stampMethods() { var obj = fixed.methods || {}, args = [obj].concat([].slice.call(arguments)); fixed.methods = mixInChain.apply(this, args); return this; }, /** * Take n objects and add them to the state prototype. * @return {Object} stamp The factory in question (`this`). */ state: function stampState() { var obj = fixed.state || {}, args = [obj].concat([].slice.call(arguments)); fixed.state = mixIn.apply(this, args); return this; }, /** * Take n functions, an array of functions, or n objects and add * the functions to the enclose prototype. * @return {Object} stamp The factory in question (`this`). */ enclose: function stampEnclose() { fixed.enclose = fixed.enclose .concat( extractFunctions.apply(null, arguments) ); return this; } }); }; /** * Take two or more factories produced from stampit() and * combine them to produce a new factory. Combining overrides * properties with last-in priority. * * @param {...Function} factory A factory produced by stampit(). * @return {Function} A new stampit factory composed from arguments. */ var compose = function compose() { var args = [].slice.call(arguments), obj = stampit(); forEach(args, function (source) { if (source) { if (source.fixed.methods) { obj.fixed.methods = mixInChain({}, obj.fixed.methods, source.fixed.methods); } if (source.fixed.state) { obj.fixed.state = mixIn({}, obj.fixed.state, source.fixed.state); } if (source.fixed.enclose) { obj.fixed.enclose = obj.fixed.enclose .concat(source.fixed.enclose); } } }); return stampit(obj.fixed.methods, obj.fixed.state, obj.fixed.enclose); }; /** * Take an old-fashioned JS constructor and return a stampit stamp * that you can freely compose with other stamps. * @param {Function} Constructor * @return {Function} A composable stampit factory * (aka stamp). */ var convertConstructor = function convertConstructor(Constructor) { return stampit().methods(Constructor.prototype).enclose(Constructor); }; module.exports = mixIn(stampit, { compose: compose, /** * Alias for mixIn */ extend: mixIn, /** * Take a destination object followed by one or more source objects, * and copy the source object properties to the destination object, * with last in priority overrides. * @param {Object} destination An object to copy properties to. * @param {...Object} source An object to copy properties from. * @returns {Object} */ mixIn: mixIn, convertConstructor: convertConstructor }); },{"./mixinchain.js":1,"mout/array/forEach":2,"mout/array/map":3,"mout/object/forOwn":15,"mout/object/merge":17,"mout/object/mixIn":18}]},{},[19]) (19) });