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 * @module base
64953b0596d07dbee9a9b521ed61c434ce4709b5Satyen Desai * @submodule base-build
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai Base._build = function(name, main, extensions, px, sx, cfg) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai for (i = 0, l = extensions.length; i < l; i++) {
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai // Prototype, old non-displacing augment
9f74fe13660a0d9d411c97798c85863de1745bbfSatyen Desai // Custom Statics
9f74fe13660a0d9d411c97798c85863de1745bbfSatyen Desai Y.mix(builtClass, build._clean(sx, buildCfg), true);
52e73635546b2ee315b3d99cc7145a73ebc5b30eSatyen Desai for (i = 0, l = aggregates.length; i < l; i++) {
52e73635546b2ee315b3d99cc7145a73ebc5b30eSatyen Desai if (!r.hasOwnProperty(aggr) && s.hasOwnProperty(aggr)) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai BuiltClass.superclass.constructor.apply(this, arguments);
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai var classes = this._getClasses(), i, l, cls, exts, ll, j;
c938b255ef3c02ee132e52fbd15bb211c6f3f760Satyen Desai return true;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai return false;
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai var dynamic = (cfg && false === cfg.dynamic) ? false : true,
a091e633a8a28a2f787150f3b87e4e4ec8e717baSatyen Desai builtClass = (dynamic) ? build._tmpl(main) : main,
52e73635546b2ee315b3d99cc7145a73ebc5b30eSatyen Desai // Prototype Chain
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai while (c && c.prototype) {
1201815cf554ddd27ca4898d9623926cfe3c2ac9Satyen Desai c = c.superclass ? c.superclass.constructor : null;
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai for (i = 0, l = aggregates.length; i < l; i++) {
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * Builds a custom constructor function (class) from the
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * main function, and array of extension functions (classes)
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * provided. The NAME field for the constructor function is
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * defined by the first argument passed in.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * The cfg object supports the following properties
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <dt>dynamic <boolean></dt>
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <p>If true (default), a completely new class
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * is created which extends the main class, and acts as the
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * host on which the extension classes are augmented.</p>
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <p>If false, the extensions classes are augmented directly to
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * the main class, modifying the main class' prototype.</p>
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <dt>aggregates <String[]></dt>
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <dd>An array of static property names, which will get aggregated
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * on to the built class, in addition to the default properties build
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * will always aggregate as defined by the main class' static _buildCfg
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method build
af716e785a91e92d5cfa85d40fdd10a30f94751fSatyen Desai * @deprecated Use the more convenient Base.create and Base.mix methods instead
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function} name The name of the new class. Used to defined the NAME property for the new class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function} main The main class on which to base the built class
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function[]} extensions The set of extension classes which will be
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * augmented/aggregated to the built class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Object} cfg Optional. Build configuration for the class (see description).
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @return {Function} A custom class, created from the provided main and extension classes
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai Base.build = function(name, main, extensions, cfg) {
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai return build(name, main, extensions, null, null, cfg);
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * Creates a new class (constructor function) which extends the base class passed in as the second argument,
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * and mixes in the array of extensions provided.
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * Prototype properties or methods can be added to the new class, using the px argument (similar to Y.extend).
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * Static properties or methods can be added to the new class, using the sx argument (similar to Y.extend).
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * **NOTE FOR COMPONENT DEVELOPERS**: Both the `base` class, and `extensions` can define static a `_buildCfg`
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * property, which acts as class creation meta-data, and drives how special static properties from the base
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * class, or extensions should be copied, aggregated or (custom) mixed into the newly created class.
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * The `_buildCfg` property is a hash with 3 supported properties: `statics`, `aggregates` and `custom`, e.g:
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * // If the Base/Main class is the thing introducing the property:
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyBaseClass._buildCfg = {
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * // Static properties/methods to copy (Alias) to the built class.
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * statics: ["CopyThisMethod", "CopyThisProperty"],
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * // Static props to aggregate onto the built class.
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * aggregates: ["AggregateThisProperty"],
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * // Static properties which need custom handling (e.g. deep merge etc.)
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * "CustomProperty" : function(property, Receiver, Supplier) {
35ab18cdc8398064c2c60b0ed6bbe181ae9d05efSatyen Desai * var triggers = Receiver.CustomProperty.triggers;
35ab18cdc8398064c2c60b0ed6bbe181ae9d05efSatyen Desai Receiver.CustomProperty.triggers = triggers.concat(Supplier.CustomProperty.triggers);
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyBaseClass.CopyThisMethod = function() {...};
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyBaseClass.CopyThisProperty = "foo";
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyBaseClass.AggregateThisProperty = {...};
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyBaseClass.CustomProperty = {
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * triggers: [...]
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * // Or, if the Extension is the thing introducing the property:
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * MyExtension._buildCfg = {
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * statics : ...
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * aggregates : ...
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * custom : ...
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * This way, when users pass your base or extension class to `Y.Base.create` or `Y.Base.mix`, they don't need to
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * know which properties need special handling. `Y.Base` has a buildCfg which defines `ATTRS` for custom mix handling
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * (to protect the static config objects), and `Y.Widget` has a buildCfg which specifies `HTML_PARSER` for
6c65c3574a8e5039c6504276177d116d5c63efbdSatyen Desai * straight up aggregation.
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method create
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function} name The name of the newly created class. Used to defined the NAME property for the new class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @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).
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function[]} extensions The list of extensions which will be mixed into the built class.
af716e785a91e92d5cfa85d40fdd10a30f94751fSatyen Desai * @param {Object} px The set of prototype properties/methods to add to the built class.
af716e785a91e92d5cfa85d40fdd10a30f94751fSatyen Desai * @param {Object} sx The set of static properties/methods to add to the built class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @return {Function} The newly created class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai Base.create = function(name, base, extensions, px, sx) {
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * <p>Mixes in a list of extensions to an existing class.</p>
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method mix
0709cd166604645c5511b892413b44ad6bce6b64Satyen Desai * @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)
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @param {Function[]} extensions The set of extension classes which will mixed into the existing main class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @return {Function} The modified main class, with extensions mixed in.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai return build(null, main, extensions, null, null, {dynamic:false});
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * The build configuration for the Base class.
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * Defines the static fields which need to be aggregated
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * when the Base class is used as the main class passed to
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * the <a href="#method_Base.build">Base.build</a> method.
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @property _buildCfg
969d790cf689400dd37fcf1f11c1909a66c06de9Satyen Desai * @type Object