Version 3.18.1

APIs

  • Begin typing in the search box above to see results.
Show:

File: base/js/BaseBuild.js

 /**
 * 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;
 }
 });
 
 /**
 * <p>
 * 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.
 * </p>
 * <p>
 * The cfg object supports the following properties
 * </p>
 * <dl>
 * <dt>dynamic &#60;boolean&#62;</dt>
 * <dd>
 * <p>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.</p>
 * <p>If false, the extensions classes are augmented directly to
 * the main class, modifying the main class' prototype.</p>
 * </dd>
 * <dt>aggregates &#60;String[]&#62;</dt>
 * <dd>An array of static property names, which will get aggregated
 * on to the built class, in addition to the default properties build
 * will always aggregate as defined by the main class' static _buildCfg
 * property.
 * </dd>
 * </dl>
 *
 * @method build
 * @deprecated Use the more convenient Base.create and Base.mix methods instead
 * @static
 * @param {Function} name The name of the new class. Used to define the NAME property for the new class.
 * @param {Function} main The main class on which to base the built class
 * @param {Function[]} extensions The set of extension classes which will be
 * augmented/aggregated to the built class.
 * @param {Object} cfg Optional. Build configuration for the class (see description).
 * @return {Function} A custom class, created from the provided main and extension classes
 */
 Base.build = function(name, main, extensions, cfg) {
 return build(name, main, extensions, null, null, cfg);
 };
 
 /**
 * Creates a new class (constructor function) which extends the base class passed in as the second argument,
 * and mixes in the array of extensions provided.
 *
 * Prototype properties or methods can be added to the new class, using the px argument (similar to Y.extend).
 *
 * Static properties or methods can be added to the new class, using the sx argument (similar to Y.extend).
 *
 * **NOTE FOR COMPONENT DEVELOPERS**: Both the `base` class, and `extensions` can define static a `_buildCfg`
 * property, which acts as class creation meta-data, and drives how special static properties from the base
 * class, or extensions should be copied, aggregated or (custom) mixed into the newly created class.
 *
 * The `_buildCfg` property is a hash with 3 supported properties: `statics`, `aggregates` and `custom`, e.g:
 *
 * // If the Base/Main class is the thing introducing the property:
 *
 * MyBaseClass._buildCfg = {
 *
 * // Static properties/methods to copy (Alias) to the built class.
 * statics: ["CopyThisMethod", "CopyThisProperty"],
 *
 * // Static props to aggregate onto the built class.
 * aggregates: ["AggregateThisProperty"],
 *
 * // Static properties which need custom handling (e.g. deep merge etc.)
 * custom: {
 * "CustomProperty" : function(property, Receiver, Supplier) {
 * ...
 * var triggers = Receiver.CustomProperty.triggers;
 * Receiver.CustomProperty.triggers = triggers.concat(Supplier.CustomProperty.triggers);
 * ...
 * }
 * }
 * };
 *
 * MyBaseClass.CopyThisMethod = function() {...};
 * MyBaseClass.CopyThisProperty = "foo";
 * MyBaseClass.AggregateThisProperty = {...};
 * MyBaseClass.CustomProperty = {
 * triggers: [...]
 * }
 *
 * // Or, if the Extension is the thing introducing the property:
 *
 * MyExtension._buildCfg = {
 * statics : ...
 * aggregates : ...
 * custom : ...
 * }
 *
 * This way, when users pass your base or extension class to `Y.Base.create` or `Y.Base.mix`, they don't need to
 * know which properties need special handling. `Y.Base` has a buildCfg which defines `ATTRS` for custom mix handling
 * (to protect the static config objects), and `Y.Widget` has a buildCfg which specifies `HTML_PARSER` for
 * straight up aggregation.
 *
 * @method create
 * @static
 * @param {String} name The name of the newly created class. Used to define the NAME property for the new class.
 * @param {Function} main The base class which the new class should extend.
 * This class needs to be Base or a class derived from base (e.g. Widget).
 * @param {Function[]} extensions The list of extensions which will be mixed into the built class.
 * @param {Object} px The set of prototype properties/methods to add to the built class.
 * @param {Object} sx The set of static properties/methods to add to the built class.
 * @return {Function} The newly created class.
 */
 Base.create = function(name, base, extensions, px, sx) {
 return build(name, base, extensions, px, sx);
 };
 
 /**
 * <p>Mixes in a list of extensions to an existing class.</p>
 * @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
 * <a href="#method_Base.build">Base.build</a> 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
 }
 };
 
 

AltStyle によって変換されたページ (->オリジナル) /