UNPKG

framework-factory

Version:

A wonderful factory framwork for creating modern object oriented javascript libraries.

273 lines (232 loc) 9.91 kB
(function (root, undefined) { "use strict"; function classes($f) { var fnTest = /xyz/.test(function (){xyz;}) ? /\bbase\b/ : /.*/, defaultBaseClass = $f.config('defaultBaseClass'), requireNew = $f.config('requireNew', false), _createClass; /** * Define a new class. * * @function $f.Class(prop, [parent]) * @param {Object} prop [description] * @param {[BaseClas} parent [description] * * @example * $f.Test = $f.Class({ * * // constructorFn for $f.Test class. * init: (name) { * this.name = name; * }, * * // Returns currently set name. * getName: function getName() { * return this.name; * } * * }); * * @returns {Function} Returns a constructor function. * * @memberof $f * @public */ _createClass = function (prop, parent) { var prototype, key, constructorFn, meta = {}, create = Object.create, hasProp = Object.prototype.hasOwnProperty; // Setup parent. if ($f[defaultBaseClass] !== undefined) { parent = parent || $f[defaultBaseClass]; } else { parent = parent || Object; } // Setup prop prop = prop || {}; // Setup constructorFn if (requireNew) { constructorFn = function Object() { if (this instanceof constructorFn === false) { throw new Error('constructorFn used as function.'); } //this.constructor = constructorFn; if (this.init !== undefined) { this.init.apply(this, arguments); } }; } else { constructorFn = function Object () { var inst = null; // constructorFn is called as function, // instanciate it and return instance object. if(this instanceof constructorFn === false) { inst = create(constructorFn.prototype); if (inst.init !== undefined) { inst.init.apply(inst, arguments); } return inst; } //this.constructor = constructorFn; if (this.init !== undefined) { this.init.apply(this, arguments); } }; } // Setup Inheritance prototype = _extendClass(constructorFn, parent); // Attaches the new member to the // constructorFn prototype. constructorFn.attach = function attach(prop) { var item, type, val, processed, key, typeHandler; for(key in prop) { if (hasProp.call(prop, key)) { item = prop[key]; type = typeof item; val = item; processed = false; if ($f.is.plainObject(item)) { typeHandler = FrameworkFactory.typeHandlers.get(item.typeHandler); if (typeHandler !== undefined && typeHandler.handler !== undefined) { item.name = key; item.tag = (item.tag === undefined) ? null : item.tag; typeHandler.handler(constructorFn, key, item); processed = true; } } else if (type === 'function' && typeof parent.prototype[key] === 'function' && fnTest.test(item)) { prototype[key] = (function (key, fn) { var parentFn = parent; return function () { this.base = parentFn.prototype[key]; var ret = fn.apply(this, arguments); this.base = undefined; return ret; } })(key, item); processed = true; } if (!processed) { prototype[key] = val; } } meta[key] = item; } }; // Returns the extended class. constructorFn.extend = function extend(o) { return _createClass(o, constructorFn); }; _setupTypeHandlers(constructorFn); constructorFn.attach(prop); // Setup Meta Framework function _gmn(ownMembersOnly) { var keys = Object.keys(meta); if (!ownMembersOnly && $f.is.func(parent.getMemberNames)) { keys = keys.concat(parent.getMemberNames()); } return keys.sort().filter(function(item, pos, ary) { return item !== undefined && (!pos || item != ary[pos - 1]); }); } function _gm (member) { if (member in meta) { return meta[member]; } else if ($f.is.func(parent.getMember)) { return parent.getMember(member); } } function _gms(ownMembersOnly) { var memberNames = _gmn(ownMembersOnly), i = 0, iLen = memberNames.length, member = null, typeHandler = null, members = { functions: [], others: [] }; for (i = 0; i < iLen; i += 1) { member = _gm(memberNames[i]); if (wd.is.func(member)) { members.functions.push(member); } else if (member.typeHandler !== undefined) { members[member.typeHandler] = members[member.typeHandler] || []; members[member.typeHandler].push(member); } else { members.others.push(member); } } return members; } /** * Returns the detail about registered member in the specified class * @function $f.getMemberInfo( member) * @param {string} member The name of the member * @returns {any} An object describing member detail. **/ constructorFn.getMember = function (member) { return _gm(member); }; /** * Returns an array of all the registered member keys including members of base class. If ownMemberOnly is * passed as true, * @function $f.getMembers( ownMembersOnly ) * @param {string} ownMembersOnly The name of the member * @returns {Array(string)} An array of string having all the registed member keys. **/ constructorFn.getMemberNames = function (ownMembersOnly) { return _gmn(ownMembersOnly); }; constructorFn.getMembers = function (ownMembersOnly) { return _gms(ownMembersOnly); }; //return return constructorFn; }; /** * Creates a new class for $f. * @function Class(o) * @param {object} o The class definition object. * @example * $f.Test = $f.Class() * * @public * @version 1.0 **/ $f.Class = function () { return _createClass.apply(null, arguments) }; // Extends subClass with superClass function _extendClass(subClass, superClass) { // Coopy static members from superClass to subClass for (var key in superClass) { if (Object.prototype.hasOwnProperty.call(superClass, key)) { subClass[key] = superClass[key]; } } // Inherit subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; return subClass.prototype; } // Initializes the type handlers for specified class. function _setupTypeHandlers(constructorFn) { var typeHandlers = FrameworkFactory.typeHandlers.getTypeHandlers(), typeHandler, i, iLen; for (i=0, iLen=typeHandlers.length; i < iLen; i += 1) { typeHandler = FrameworkFactory.typeHandlers.get(typeHandlers[i]); if (typeHandler.setup) { typeHandler.setup(constructorFn); } } } } FrameworkFactory.plugins.register({ name: 'classes', load: classes }); })(root);