|
1 /* |
|
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved. |
|
3 Code licensed under the BSD License: |
|
4 http://developer.yahoo.net/yui/license.txt |
|
5 version: 3.0.0b1 |
|
6 build: 1163 |
|
7 */ |
|
8 YUI.add('base-build', function(Y) { |
|
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 |
|
20 var Base = Y.Base, |
|
21 L = Y.Lang; |
|
22 |
|
23 /** |
|
24 * The build configuration for the Base class. |
|
25 * |
|
26 * Defines the static fields which need to be aggregated |
|
27 * when the Base class is used as the main class passed to |
|
28 * the <a href="#method_Base.build">Base.build</a> method. |
|
29 * |
|
30 * @property Base._buildCfg |
|
31 * @type Object |
|
32 * @static |
|
33 * @final |
|
34 * @private |
|
35 */ |
|
36 Base._buildCfg = { |
|
37 aggregates : ["ATTRS", "_PLUG", "_UNPLUG"] |
|
38 }; |
|
39 |
|
40 /** |
|
41 * <p> |
|
42 * Builds a custom constructor function (class) from the |
|
43 * main function, and array of extension functions (classes) |
|
44 * provided. The NAME field for the constructor function is |
|
45 * defined by the first argument passed in. |
|
46 * </p> |
|
47 * <p> |
|
48 * The cfg object supports the following properties |
|
49 * </p> |
|
50 * <dl> |
|
51 * <dt>dynamic <boolean></dt> |
|
52 * <dd> |
|
53 * <p>If true (default), a completely new class |
|
54 * is created which extends the main class, and acts as the |
|
55 * host on which the extension classes are augmented.</p> |
|
56 * <p>If false, the extensions classes are augmented directly to |
|
57 * the main class, modifying the main class' prototype.</p> |
|
58 * </dd> |
|
59 * <dt>aggregates <String[]></dt> |
|
60 * <dd>An array of static property names, which will get aggregated |
|
61 * on to the built class, in addition to the default properties build |
|
62 * will always aggregate as defined by the main class' static _buildCfg |
|
63 * property. |
|
64 * </dd> |
|
65 * </dl> |
|
66 * |
|
67 * @method Base.build |
|
68 * @static |
|
69 * @param {Function} name The name of the new class. Used to defined the NAME property for the new class. |
|
70 * @param {Function} main The main class on which to base the built class |
|
71 * @param {Function[]} extensions The set of extension classes which will be |
|
72 * augmented/aggregated to the built class. |
|
73 * @param {Object} cfg Optional. Build configuration for the class (see description). |
|
74 * @return {Function} A custom class, created from the provided main and extension classes |
|
75 */ |
|
76 Base.build = function(name, main, extensions, cfg) { |
|
77 |
|
78 var build = Base.build, |
|
79 builtClass = build._getClass(main, cfg), |
|
80 aggregates = build._getAggregates(main, cfg), |
|
81 dynamic = builtClass._yuibuild.dynamic, |
|
82 i, l, val, extClass; |
|
83 |
|
84 // Shallow isolate aggregates |
|
85 if (dynamic) { |
|
86 if (aggregates) { |
|
87 for (i = 0, l = aggregates.length; i < l; ++i) { |
|
88 val = aggregates[i]; |
|
89 if (main.hasOwnProperty(val)) { |
|
90 builtClass[val] = L.isArray(main[val]) ? [] : {}; |
|
91 } |
|
92 } |
|
93 Y.aggregate(builtClass, main, true, aggregates); |
|
94 } |
|
95 } |
|
96 |
|
97 // Augment/Aggregate |
|
98 for (i = 0, l = extensions.length; i < l; i++) { |
|
99 extClass = extensions[i]; |
|
100 |
|
101 if (aggregates) { |
|
102 Y.aggregate(builtClass, extClass, true, aggregates); |
|
103 } |
|
104 |
|
105 // Old augment |
|
106 Y.mix(builtClass, extClass, true, null, 1); |
|
107 |
|
108 builtClass._yuibuild.exts.push(extClass); |
|
109 } |
|
110 |
|
111 builtClass.prototype.hasImpl = build._hasImpl; |
|
112 |
|
113 if (dynamic) { |
|
114 builtClass.NAME = name; |
|
115 builtClass.prototype.constructor = builtClass; |
|
116 } |
|
117 |
|
118 return builtClass; |
|
119 }; |
|
120 |
|
121 Y.mix(Base.build, { |
|
122 |
|
123 _template: function(main) { |
|
124 |
|
125 function BuiltClass() { |
|
126 |
|
127 BuiltClass.superclass.constructor.apply(this, arguments); |
|
128 |
|
129 var f = BuiltClass._yuibuild.exts, |
|
130 l = f.length, |
|
131 i; |
|
132 |
|
133 for (i = 0; i < l; i++) { |
|
134 f[i].apply(this, arguments); |
|
135 } |
|
136 |
|
137 return this; |
|
138 } |
|
139 Y.extend(BuiltClass, main); |
|
140 |
|
141 return BuiltClass; |
|
142 }, |
|
143 |
|
144 _hasImpl : function(extClass) { |
|
145 if (this.constructor._yuibuild) { |
|
146 var f = this.constructor._yuibuild.exts, |
|
147 l = f.length, |
|
148 i; |
|
149 |
|
150 for (i = 0; i < l; i++) { |
|
151 if (f[i] === extClass) { |
|
152 return true; |
|
153 } |
|
154 } |
|
155 } |
|
156 return false; |
|
157 }, |
|
158 |
|
159 _getClass : function(main, cfg) { |
|
160 |
|
161 var dynamic = (cfg && false === cfg.dynamic) ? false : true, |
|
162 builtClass = (dynamic) ? Base.build._template(main) : main; |
|
163 |
|
164 builtClass._yuibuild = { |
|
165 id: null, |
|
166 exts : [], |
|
167 dynamic : dynamic |
|
168 }; |
|
169 |
|
170 return builtClass; |
|
171 }, |
|
172 |
|
173 _getAggregates : function(main, cfg) { |
|
174 var aggr = [], |
|
175 cfgAggr = (cfg && cfg.aggregates), |
|
176 c = main, |
|
177 classAggr; |
|
178 |
|
179 while (c && c.prototype) { |
|
180 classAggr = c._buildCfg && c._buildCfg.aggregates; |
|
181 if (classAggr) { |
|
182 aggr = aggr.concat(classAggr); |
|
183 } |
|
184 c = c.superclass ? c.superclass.constructor : null; |
|
185 } |
|
186 |
|
187 if (cfgAggr) { |
|
188 aggr = aggr.concat(cfgAggr); |
|
189 } |
|
190 |
|
191 return aggr; |
|
192 } |
|
193 }); |
|
194 |
|
195 |
|
196 |
|
197 }, '3.0.0b1' ,{requires:['base-base']}); |