[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/base-build/ -> base-build-debug.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('base-build', function (Y, NAME) {
   9  
  10      /**
  11       * The base-build submodule provides Base.build functionality, which
  12       * can be used to create custom classes, by aggregating extensions onto
  13       * a main class.
  14       *
  15       * @module base
  16       * @submodule base-build
  17       * @for Base
  18       */
  19      var BaseCore = Y.BaseCore,
  20          Base     = Y.Base,
  21          L        = Y.Lang,
  22  
  23          INITIALIZER = "initializer",
  24          DESTRUCTOR  = "destructor",
  25          AGGREGATES  = ["_PLUG", "_UNPLUG"],
  26  
  27          build;
  28  
  29      // Utility function used in `_buildCfg` to aggregate array values into a new
  30      // array from the sender constructor to the receiver constructor.
  31      function arrayAggregator(prop, r, s) {
  32          if (s[prop]) {
  33              r[prop] = (r[prop] || []).concat(s[prop]);
  34          }
  35      }
  36  
  37      // Utility function used in `_buildCfg` to aggregate `_ATTR_CFG` array
  38      // values from the sender constructor into a new array on receiver's
  39      // constructor, and clear the cached hash.
  40      function attrCfgAggregator(prop, r, s) {
  41          if (s._ATTR_CFG) {
  42              // Clear cached hash.
  43              r._ATTR_CFG_HASH = null;
  44  
  45              arrayAggregator.apply(null, arguments);
  46          }
  47      }
  48  
  49      // Utility function used in `_buildCfg` to aggregate ATTRS configs from one
  50      // the sender constructor to the receiver constructor.
  51      function attrsAggregator(prop, r, s) {
  52          BaseCore.modifyAttrs(r, s.ATTRS);
  53      }
  54  
  55      Base._build = function(name, main, extensions, px, sx, cfg) {
  56  
  57          var build = Base._build,
  58  
  59              builtClass = build._ctor(main, cfg),
  60              buildCfg = build._cfg(main, cfg, extensions),
  61  
  62              _mixCust = build._mixCust,
  63  
  64              dynamic = builtClass._yuibuild.dynamic,
  65  
  66              i, l, extClass, extProto,
  67              initializer,
  68              destructor;
  69  
  70          // Augment/Aggregate
  71          for (i = 0, l = extensions.length; i < l; i++) {
  72              extClass = extensions[i];
  73  
  74              extProto = extClass.prototype;
  75  
  76              initializer = extProto[INITIALIZER];
  77              destructor = extProto[DESTRUCTOR];
  78              delete extProto[INITIALIZER];
  79              delete extProto[DESTRUCTOR];
  80  
  81              // Prototype, old non-displacing augment
  82              Y.mix(builtClass, extClass, true, null, 1);
  83  
  84              // Custom Statics
  85              _mixCust(builtClass, extClass, buildCfg);
  86  
  87              if (initializer) {
  88                  extProto[INITIALIZER] = initializer;
  89              }
  90  
  91              if (destructor) {
  92                  extProto[DESTRUCTOR] = destructor;
  93              }
  94  
  95              builtClass._yuibuild.exts.push(extClass);
  96          }
  97  
  98          if (px) {
  99              Y.mix(builtClass.prototype, px, true);
 100          }
 101  
 102          if (sx) {
 103              Y.mix(builtClass, build._clean(sx, buildCfg), true);
 104              _mixCust(builtClass, sx, buildCfg);
 105          }
 106  
 107          builtClass.prototype.hasImpl = build._impl;
 108  
 109          if (dynamic) {
 110              builtClass.NAME = name;
 111              builtClass.prototype.constructor = builtClass;
 112  
 113              // Carry along the reference to `modifyAttrs()` from `main`.
 114              builtClass.modifyAttrs = main.modifyAttrs;
 115          }
 116  
 117          return builtClass;
 118      };
 119  
 120      build = Base._build;
 121  
 122      Y.mix(build, {
 123  
 124          _mixCust: function(r, s, cfg) {
 125  
 126              var aggregates,
 127                  custom,
 128                  statics,
 129                  aggr,
 130                  l,
 131                  i;
 132  
 133              if (cfg) {
 134                  aggregates = cfg.aggregates;
 135                  custom = cfg.custom;
 136                  statics = cfg.statics;
 137              }
 138  
 139              if (statics) {
 140                  Y.mix(r, s, true, statics);
 141              }
 142  
 143              if (aggregates) {
 144                  for (i = 0, l = aggregates.length; i < l; i++) {
 145                      aggr = aggregates[i];
 146                      if (!r.hasOwnProperty(aggr) && s.hasOwnProperty(aggr)) {
 147                          r[aggr] = L.isArray(s[aggr]) ? [] : {};
 148                      }
 149                      Y.aggregate(r, s, true, [aggr]);
 150                  }
 151              }
 152  
 153              if (custom) {
 154                  for (i in custom) {
 155                      if (custom.hasOwnProperty(i)) {
 156                          custom[i](i, r, s);
 157                      }
 158                  }
 159              }
 160  
 161          },
 162  
 163          _tmpl: function(main) {
 164  
 165              function BuiltClass() {
 166                  BuiltClass.superclass.constructor.apply(this, arguments);
 167              }
 168              Y.extend(BuiltClass, main);
 169  
 170              return BuiltClass;
 171          },
 172  
 173          _impl : function(extClass) {
 174              var classes = this._getClasses(), i, l, cls, exts, ll, j;
 175              for (i = 0, l = classes.length; i < l; i++) {
 176                  cls = classes[i];
 177                  if (cls._yuibuild) {
 178                      exts = cls._yuibuild.exts;
 179                      ll = exts.length;
 180  
 181                      for (j = 0; j < ll; j++) {
 182                          if (exts[j] === extClass) {
 183                              return true;
 184                          }
 185                      }
 186                  }
 187              }
 188              return false;
 189          },
 190  
 191          _ctor : function(main, cfg) {
 192  
 193             var dynamic = (cfg && false === cfg.dynamic) ? false : true,
 194                 builtClass = (dynamic) ? build._tmpl(main) : main,
 195                 buildCfg = builtClass._yuibuild;
 196  
 197              if (!buildCfg) {
 198                  buildCfg = builtClass._yuibuild = {};
 199              }
 200  
 201              buildCfg.id = buildCfg.id || null;
 202              buildCfg.exts = buildCfg.exts || [];
 203              buildCfg.dynamic = dynamic;
 204  
 205              return builtClass;
 206          },
 207  
 208          _cfg : function(main, cfg, exts) {
 209              var aggr = [],
 210                  cust = {},
 211                  statics = [],
 212                  buildCfg,
 213                  cfgAggr = (cfg && cfg.aggregates),
 214                  cfgCustBuild = (cfg && cfg.custom),
 215                  cfgStatics = (cfg && cfg.statics),
 216                  c = main,
 217                  i,
 218                  l;
 219  
 220              // Prototype Chain
 221              while (c && c.prototype) {
 222                  buildCfg = c._buildCfg;
 223                  if (buildCfg) {
 224                      if (buildCfg.aggregates) {
 225                          aggr = aggr.concat(buildCfg.aggregates);
 226                      }
 227                      if (buildCfg.custom) {
 228                          Y.mix(cust, buildCfg.custom, true);
 229                      }
 230                      if (buildCfg.statics) {
 231                          statics = statics.concat(buildCfg.statics);
 232                      }
 233                  }
 234                  c = c.superclass ? c.superclass.constructor : null;
 235              }
 236  
 237              // Exts
 238              if (exts) {
 239                  for (i = 0, l = exts.length; i < l; i++) {
 240                      c = exts[i];
 241                      buildCfg = c._buildCfg;
 242                      if (buildCfg) {
 243                          if (buildCfg.aggregates) {
 244                              aggr = aggr.concat(buildCfg.aggregates);
 245                          }
 246                          if (buildCfg.custom) {
 247                              Y.mix(cust, buildCfg.custom, true);
 248                          }
 249                          if (buildCfg.statics) {
 250                              statics = statics.concat(buildCfg.statics);
 251                          }
 252                      }
 253                  }
 254              }
 255  
 256              if (cfgAggr) {
 257                  aggr = aggr.concat(cfgAggr);
 258              }
 259  
 260              if (cfgCustBuild) {
 261                  Y.mix(cust, cfg.cfgBuild, true);
 262              }
 263  
 264              if (cfgStatics) {
 265                  statics = statics.concat(cfgStatics);
 266              }
 267  
 268              return {
 269                  aggregates: aggr,
 270                  custom: cust,
 271                  statics: statics
 272              };
 273          },
 274  
 275          _clean : function(sx, cfg) {
 276              var prop, i, l, sxclone = Y.merge(sx),
 277                  aggregates = cfg.aggregates,
 278                  custom = cfg.custom;
 279  
 280              for (prop in custom) {
 281                  if (sxclone.hasOwnProperty(prop)) {
 282                      delete sxclone[prop];
 283                  }
 284              }
 285  
 286              for (i = 0, l = aggregates.length; i < l; i++) {
 287                  prop = aggregates[i];
 288                  if (sxclone.hasOwnProperty(prop)) {
 289                      delete sxclone[prop];
 290                  }
 291              }
 292  
 293              return sxclone;
 294          }
 295      });
 296  
 297      /**
 298       * <p>
 299       * Builds a custom constructor function (class) from the
 300       * main function, and array of extension functions (classes)
 301       * provided. The NAME field for the constructor function is
 302       * defined by the first argument passed in.
 303       * </p>
 304       * <p>
 305       * The cfg object supports the following properties
 306       * </p>
 307       * <dl>
 308       *    <dt>dynamic &#60;boolean&#62;</dt>
 309       *    <dd>
 310       *    <p>If true (default), a completely new class
 311       *    is created which extends the main class, and acts as the
 312       *    host on which the extension classes are augmented.</p>
 313       *    <p>If false, the extensions classes are augmented directly to
 314       *    the main class, modifying the main class' prototype.</p>
 315       *    </dd>
 316       *    <dt>aggregates &#60;String[]&#62;</dt>
 317       *    <dd>An array of static property names, which will get aggregated
 318       *    on to the built class, in addition to the default properties build
 319       *    will always aggregate as defined by the main class' static _buildCfg
 320       *    property.
 321       *    </dd>
 322       * </dl>
 323       *
 324       * @method build
 325       * @deprecated Use the more convenient Base.create and Base.mix methods instead
 326       * @static
 327       * @param {Function} name The name of the new class. Used to define the NAME property for the new class.
 328       * @param {Function} main The main class on which to base the built class
 329       * @param {Function[]} extensions The set of extension classes which will be
 330       * augmented/aggregated to the built class.
 331       * @param {Object} cfg Optional. Build configuration for the class (see description).
 332       * @return {Function} A custom class, created from the provided main and extension classes
 333       */
 334      Base.build = function(name, main, extensions, cfg) {
 335          return build(name, main, extensions, null, null, cfg);
 336      };
 337  
 338      /**
 339       * Creates a new class (constructor function) which extends the base class passed in as the second argument,
 340       * and mixes in the array of extensions provided.
 341       *
 342       * Prototype properties or methods can be added to the new class, using the px argument (similar to Y.extend).
 343       *
 344       * Static properties or methods can be added to the new class, using the sx argument (similar to Y.extend).
 345       *
 346       * **NOTE FOR COMPONENT DEVELOPERS**: Both the `base` class, and `extensions` can define static a `_buildCfg`
 347       * property, which acts as class creation meta-data, and drives how special static properties from the base
 348       * class, or extensions should be copied, aggregated or (custom) mixed into the newly created class.
 349       *
 350       * The `_buildCfg` property is a hash with 3 supported properties: `statics`, `aggregates` and `custom`, e.g:
 351       *
 352       *     // If the Base/Main class is the thing introducing the property:
 353       *
 354       *     MyBaseClass._buildCfg = {
 355       *
 356       *        // Static properties/methods to copy (Alias) to the built class.
 357       *        statics: ["CopyThisMethod", "CopyThisProperty"],
 358       *
 359       *        // Static props to aggregate onto the built class.
 360       *        aggregates: ["AggregateThisProperty"],
 361       *
 362       *        // Static properties which need custom handling (e.g. deep merge etc.)
 363       *        custom: {
 364       *           "CustomProperty" : function(property, Receiver, Supplier) {
 365       *              ...
 366       *              var triggers = Receiver.CustomProperty.triggers;
 367       *              Receiver.CustomProperty.triggers = triggers.concat(Supplier.CustomProperty.triggers);
 368       *              ...
 369       *           }
 370       *        }
 371       *     };
 372       *
 373       *     MyBaseClass.CopyThisMethod = function() {...};
 374       *     MyBaseClass.CopyThisProperty = "foo";
 375       *     MyBaseClass.AggregateThisProperty = {...};
 376       *     MyBaseClass.CustomProperty = {
 377       *        triggers: [...]
 378       *     }
 379       *
 380       *     // Or, if the Extension is the thing introducing the property:
 381       *
 382       *     MyExtension._buildCfg = {
 383       *         statics : ...
 384       *         aggregates : ...
 385       *         custom : ...
 386       *     }
 387       *
 388       * This way, when users pass your base or extension class to `Y.Base.create` or `Y.Base.mix`, they don't need to
 389       * know which properties need special handling. `Y.Base` has a buildCfg which defines `ATTRS` for custom mix handling
 390       * (to protect the static config objects), and `Y.Widget` has a buildCfg which specifies `HTML_PARSER` for
 391       * straight up aggregation.
 392       *
 393       * @method create
 394       * @static
 395       * @param {String} name The name of the newly created class. Used to define the NAME property for the new class.
 396       * @param {Function} main The base class which the new class should extend.
 397       * This class needs to be Base or a class derived from base (e.g. Widget).
 398       * @param {Function[]} extensions The list of extensions which will be mixed into the built class.
 399       * @param {Object} px The set of prototype properties/methods to add to the built class.
 400       * @param {Object} sx The set of static properties/methods to add to the built class.
 401       * @return {Function} The newly created class.
 402       */
 403      Base.create = function(name, base, extensions, px, sx) {
 404          return build(name, base, extensions, px, sx);
 405      };
 406  
 407      /**
 408       * <p>Mixes in a list of extensions to an existing class.</p>
 409       * @method mix
 410       * @static
 411       * @param {Function} main The existing class into which the extensions should be mixed.
 412       * The class needs to be Base or a class derived from Base (e.g. Widget)
 413       * @param {Function[]} extensions The set of extension classes which will mixed into the existing main class.
 414       * @return {Function} The modified main class, with extensions mixed in.
 415       */
 416      Base.mix = function(main, extensions) {
 417  
 418          if (main._CACHED_CLASS_DATA) {
 419              main._CACHED_CLASS_DATA = null;
 420          }
 421  
 422          return build(null, main, extensions, null, null, {dynamic:false});
 423      };
 424  
 425      /**
 426       * The build configuration for the Base class.
 427       *
 428       * Defines the static fields which need to be aggregated when the Base class
 429       * is used as the main class passed to the
 430       * <a href="#method_Base.build">Base.build</a> method.
 431       *
 432       * @property _buildCfg
 433       * @type Object
 434       * @static
 435       * @final
 436       * @private
 437       */
 438      BaseCore._buildCfg = {
 439          aggregates: AGGREGATES.concat(),
 440  
 441          custom: {
 442              ATTRS         : attrsAggregator,
 443              _ATTR_CFG     : attrCfgAggregator,
 444              _NON_ATTRS_CFG: arrayAggregator
 445          }
 446      };
 447  
 448      // Makes sure Base and BaseCore use separate `_buildCfg` objects.
 449      Base._buildCfg = {
 450          aggregates: AGGREGATES.concat(),
 451  
 452          custom: {
 453              ATTRS         : attrsAggregator,
 454              _ATTR_CFG     : attrCfgAggregator,
 455              _NON_ATTRS_CFG: arrayAggregator
 456          }
 457      };
 458  
 459  
 460  }, '3.17.2', {"requires": ["base-base"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1