BaseBuild.js revision c938b255ef3c02ee132e52fbd15bb211c6f3f760
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai /**
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * The base-build submodule provides Base.build functionality, which
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * can be used to create custom classes, by aggregating extensions onto
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * a main class.
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai *
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai * @module base
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * @submodule base-build
e0008d92cea7515616980ad13e1075346a3bca2eSatyen Desai * @for Base
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai */
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai var Base = Y.Base,
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai L = Y.Lang;
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai /**
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * The build configuration for the Base class.
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai *
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * Defines the static fields which need to be aggregated
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * when the Base class is used as the main class passed to
793e508bd277c48d6a09b91bb99064b4046eda7aSatyen Desai * the <a href="#method_Base.build">Base.build</a> method.
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai *
793e508bd277c48d6a09b91bb99064b4046eda7aSatyen Desai * @property Base._buildCfg
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @type Object
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @static
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @final
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @private
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai */
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai Base._buildCfg = {
b4e59b5d4777b2fc949d0b8da063b6ea1f2d43a1Satyen Desai aggregates : ["ATTRS", "_PLUG", "_UNPLUG"]
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai };
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai /**
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <p>
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * Builds a custom constructor function (class) from the
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * main function, and array of extension functions (classes)
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * provided. The NAME field for the constructor function is
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * defined by the first argument passed in.
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * </p>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <p>
eaa9719567e2ec55d96f9298077f5fc0effe1ed3Satyen Desai * The cfg object supports the following properties
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * </p>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <dl>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <dt>dynamic &#60;boolean&#62;</dt>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <dd>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <p>If true (default), a completely new class
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * is created which extends the main class, and acts as the
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * host on which the extension classes are augmented.</p>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <p>If false, the extensions classes are augmented directly to
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * the main class, modifying the main class' prototype.</p>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * </dd>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <dt>aggregates &#60;String[]&#62;</dt>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * <dd>An array of static property names, which will get aggregated
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * on to the built class, in addition to the default properties build
793e508bd277c48d6a09b91bb99064b4046eda7aSatyen Desai * will always aggregate as defined by the main class' static _buildCfg
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * property.
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * </dd>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * </dl>
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai *
793e508bd277c48d6a09b91bb99064b4046eda7aSatyen Desai * @method Base.build
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @static
04f6f082e2978c0be5c674a54883b28e50040c39Satyen Desai * @param {Function} name The name of the new class. Used to defined the NAME property for the new class.
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @param {Function} main The main class on which to base the built class
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @param {Function[]} extensions The set of extension classes which will be
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * augmented/aggregated to the built class.
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * @param {Object} cfg Optional. Build configuration for the class (see description).
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai * @return {Function} A custom class, created from the provided main and extension classes
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai */
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai Base.build = function(name, main, extensions, cfg) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai var build = Base.build,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass = build._getClass(main, cfg),
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai aggregates = build._getAggregates(main, cfg),
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai dynamic = builtClass._yuibuild.dynamic,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai i, l, val, extClass;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai // Shallow isolate aggregates
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (dynamic) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (aggregates) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai for (i = 0, l = aggregates.length; i < l; ++i) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai val = aggregates[i];
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (main.hasOwnProperty(val)) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass[val] = L.isArray(main[val]) ? [] : {};
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai Y.aggregate(builtClass, main, true, aggregates);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai // Augment/Aggregate
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai for (i = 0, l = extensions.length; i < l; i++) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai extClass = extensions[i];
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (aggregates) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai Y.aggregate(builtClass, extClass, true, aggregates);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai // Old augment
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai Y.mix(builtClass, extClass, true, null, 1);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass._yuibuild.exts.push(extClass);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass.prototype.hasImpl = build._hasImpl;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (dynamic) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass.NAME = name;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass.prototype.constructor = builtClass;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return builtClass;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai };
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai Y.mix(Base.build, {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai _template: function(main) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai function BuiltClass() {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai BuiltClass.superclass.constructor.apply(this, arguments);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai var f = BuiltClass._yuibuild.exts,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai l = f.length,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai i;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai for (i = 0; i < l; i++) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai f[i].apply(this, arguments);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return this;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai Y.extend(BuiltClass, main);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return BuiltClass;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai },
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai _hasImpl : function(extClass) {
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai var classes = this._getClasses();
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai for (var i = 0, l = classes.length; i < l; i++) {
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai var cls = classes[i];
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai if (cls._yuibuild) {
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai var exts = cls._yuibuild.exts,
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai ll = exts.length,
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai j;
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai for (j = 0; j < ll; j++) {
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai if (exts[j] === extClass) {
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai return true;
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return false;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai },
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai _getClass : function(main, cfg) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai var dynamic = (cfg && false === cfg.dynamic) ? false : true,
2b449ca06646ebb6603e35918a40bca8e0f43c8eSatyen Desai builtClass = (dynamic) ? Base.build._template(main) : main;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai builtClass._yuibuild = {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai id: null,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai exts : [],
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai dynamic : dynamic
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai };
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return builtClass;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai },
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai _getAggregates : function(main, cfg) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai var aggr = [],
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai cfgAggr = (cfg && cfg.aggregates),
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai c = main,
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai classAggr;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai while (c && c.prototype) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai classAggr = c._buildCfg && c._buildCfg.aggregates;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (classAggr) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai aggr = aggr.concat(classAggr);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai c = c.superclass ? c.superclass.constructor : null;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai if (cfgAggr) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai aggr = aggr.concat(cfgAggr);
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return aggr;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai }
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai });