/* YUI 3.17.2 (build 9c3c78e) Copyright 2014 Yahoo! Inc. All rights reserved. Licensed under the BSD License. http://yuilibrary.com/license/ */ YUI.add('base-build', function (Y, NAME) { /** * The base-build submodule provides Base.build functionality, which * can be used to create custom classes, by aggregating extensions onto * a main class. * * @module base * @submodule base-build * @for Base */ var BaseCore = Y.BaseCore, Base = Y.Base, L = Y.Lang, INITIALIZER = "initializer", DESTRUCTOR = "destructor", AGGREGATES = ["_PLUG", "_UNPLUG"], build; // Utility function used in `_buildCfg` to aggregate array values into a new // array from the sender constructor to the receiver constructor. function arrayAggregator(prop, r, s) { if (s[prop]) { r[prop] = (r[prop] || []).concat(s[prop]); } } // Utility function used in `_buildCfg` to aggregate `_ATTR_CFG` array // values from the sender constructor into a new array on receiver's // constructor, and clear the cached hash. function attrCfgAggregator(prop, r, s) { if (s._ATTR_CFG) { // Clear cached hash. r._ATTR_CFG_HASH = null; arrayAggregator.apply(null, arguments); } } // Utility function used in `_buildCfg` to aggregate ATTRS configs from one // the sender constructor to the receiver constructor. function attrsAggregator(prop, r, s) { BaseCore.modifyAttrs(r, s.ATTRS); } Base._build = function(name, main, extensions, px, sx, cfg) { var build = Base._build, builtClass = build._ctor(main, cfg), buildCfg = build._cfg(main, cfg, extensions), _mixCust = build._mixCust, dynamic = builtClass._yuibuild.dynamic, i, l, extClass, extProto, initializer, destructor; // Augment/Aggregate for (i = 0, l = extensions.length; i < l; i++) { extClass = extensions[i]; extProto = extClass.prototype; initializer = extProto[INITIALIZER]; destructor = extProto[DESTRUCTOR]; delete extProto[INITIALIZER]; delete extProto[DESTRUCTOR]; // Prototype, old non-displacing augment Y.mix(builtClass, extClass, true, null, 1); // Custom Statics _mixCust(builtClass, extClass, buildCfg); if (initializer) { extProto[INITIALIZER] = initializer; } if (destructor) { extProto[DESTRUCTOR] = destructor; } builtClass._yuibuild.exts.push(extClass); } if (px) { Y.mix(builtClass.prototype, px, true); } if (sx) { Y.mix(builtClass, build._clean(sx, buildCfg), true); _mixCust(builtClass, sx, buildCfg); } builtClass.prototype.hasImpl = build._impl; if (dynamic) { builtClass.NAME = name; builtClass.prototype.constructor = builtClass; // Carry along the reference to `modifyAttrs()` from `main`. builtClass.modifyAttrs = main.modifyAttrs; } return builtClass; }; build = Base._build; Y.mix(build, { _mixCust: function(r, s, cfg) { var aggregates, custom, statics, aggr, l, i; if (cfg) { aggregates = cfg.aggregates; custom = cfg.custom; statics = cfg.statics; } if (statics) { Y.mix(r, s, true, statics); } if (aggregates) { for (i = 0, l = aggregates.length; i < l; i++) { aggr = aggregates[i]; if (!r.hasOwnProperty(aggr) && s.hasOwnProperty(aggr)) { r[aggr] = L.isArray(s[aggr]) ? [] : {}; } Y.aggregate(r, s, true, [aggr]); } } if (custom) { for (i in custom) { if (custom.hasOwnProperty(i)) { custom[i](i, r, s); } } } }, _tmpl: function(main) { function BuiltClass() { BuiltClass.superclass.constructor.apply(this, arguments); } Y.extend(BuiltClass, main); return BuiltClass; }, _impl : function(extClass) { var classes = this._getClasses(), i, l, cls, exts, ll, j; for (i = 0, l = classes.length; i < l; i++) { cls = classes[i]; if (cls._yuibuild) { exts = cls._yuibuild.exts; ll = exts.length; for (j = 0; j < ll; j++) { if (exts[j] === extClass) { return true; } } } } return false; }, _ctor : function(main, cfg) { var dynamic = (cfg && false === cfg.dynamic) ? false : true, builtClass = (dynamic) ? build._tmpl(main) : main, buildCfg = builtClass._yuibuild; if (!buildCfg) { buildCfg = builtClass._yuibuild = {}; } buildCfg.id = buildCfg.id || null; buildCfg.exts = buildCfg.exts || []; buildCfg.dynamic = dynamic; return builtClass; }, _cfg : function(main, cfg, exts) { var aggr = [], cust = {}, statics = [], buildCfg, cfgAggr = (cfg && cfg.aggregates), cfgCustBuild = (cfg && cfg.custom), cfgStatics = (cfg && cfg.statics), c = main, i, l; // Prototype Chain while (c && c.prototype) { buildCfg = c._buildCfg; if (buildCfg) { if (buildCfg.aggregates) { aggr = aggr.concat(buildCfg.aggregates); } if (buildCfg.custom) { Y.mix(cust, buildCfg.custom, true); } if (buildCfg.statics) { statics = statics.concat(buildCfg.statics); } } c = c.superclass ? c.superclass.constructor : null; } // Exts if (exts) { for (i = 0, l = exts.length; i < l; i++) { c = exts[i]; buildCfg = c._buildCfg; if (buildCfg) { if (buildCfg.aggregates) { aggr = aggr.concat(buildCfg.aggregates); } if (buildCfg.custom) { Y.mix(cust, buildCfg.custom, true); } if (buildCfg.statics) { statics = statics.concat(buildCfg.statics); } } } } if (cfgAggr) { aggr = aggr.concat(cfgAggr); } if (cfgCustBuild) { Y.mix(cust, cfg.cfgBuild, true); } if (cfgStatics) { statics = statics.concat(cfgStatics); } return { aggregates: aggr, custom: cust, statics: statics }; }, _clean : function(sx, cfg) { var prop, i, l, sxclone = Y.merge(sx), aggregates = cfg.aggregates, custom = cfg.custom; for (prop in custom) { if (sxclone.hasOwnProperty(prop)) { delete sxclone[prop]; } } for (i = 0, l = aggregates.length; i < l; i++) { prop = aggregates[i]; if (sxclone.hasOwnProperty(prop)) { delete sxclone[prop]; } } return sxclone; } }); /** *
* Builds a custom constructor function (class) from the * main function, and array of extension functions (classes) * provided. The NAME field for the constructor function is * defined by the first argument passed in. *
** The cfg object supports the following properties *
*If true (default), a completely new class * is created which extends the main class, and acts as the * host on which the extension classes are augmented.
*If false, the extensions classes are augmented directly to * the main class, modifying the main class' prototype.
*Mixes in a list of extensions to an existing class.
* @method mix * @static * @param {Function} main The existing class into which the extensions should be mixed. * The class needs to be Base or a class derived from Base (e.g. Widget) * @param {Function[]} extensions The set of extension classes which will mixed into the existing main class. * @return {Function} The modified main class, with extensions mixed in. */ Base.mix = function(main, extensions) { if (main._CACHED_CLASS_DATA) { main._CACHED_CLASS_DATA = null; } return build(null, main, extensions, null, null, {dynamic:false}); }; /** * The build configuration for the Base class. * * Defines the static fields which need to be aggregated when the Base class * is used as the main class passed to the * Base.build method. * * @property _buildCfg * @type Object * @static * @final * @private */ BaseCore._buildCfg = { aggregates: AGGREGATES.concat(), custom: { ATTRS : attrsAggregator, _ATTR_CFG : attrCfgAggregator, _NON_ATTRS_CFG: arrayAggregator } }; // Makes sure Base and BaseCore use separate `_buildCfg` objects. Base._buildCfg = { aggregates: AGGREGATES.concat(), custom: { ATTRS : attrsAggregator, _ATTR_CFG : attrCfgAggregator, _NON_ATTRS_CFG: arrayAggregator } }; }, '3.17.2', {"requires": ["base-base"]});