[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 <boolean></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 <String[]></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"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |