]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/app/bind/Multi.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / app / bind / Multi.js
CommitLineData
6527f429
DM
1/**\r
2 * This class is created to manage a multi-bind against a `ViewModel`.\r
3 */\r
4Ext.define('Ext.app.bind.Multi', {\r
5 extend: 'Ext.app.bind.BaseBinding',\r
6\r
7 isMultiBinding: true,\r
8\r
9 missing: 1,\r
10\r
11 // Multi binds have to be deep. We construct a single object/array and we only\r
12 // ever fire by notifying with that value which will never change. As such, we\r
13 // need to notify any child bindings so they can check if their individual\r
14 // bindings have changed.\r
15 deep: true,\r
16\r
17 /**\r
18 * @cfg {Boolean} trackStatics\r
19 * This option tracks for static branches of the root object which can be pruned using\r
20 * {@link #pruneStaticKeys}. This can be useful to only get the dynamic parts of a multi bind:\r
21 *\r
22 * {\r
23 * a: 1,\r
24 * b: '{someBind}',\r
25 * c: ['a', 'b', 'c'],\r
26 * d: ['a', 'b', '{someBind}'],\r
27 * e: {\r
28 * y: 1,\r
29 * z: 2\r
30 * },\r
31 * f: {\r
32 * y: 1,\r
33 * z: '{someBind}'\r
34 * }\r
35 * }\r
36 *\r
37 * // Will produce\r
38 * {\r
39 * b: value,\r
40 * d: ['a', 'b', value],\r
41 * f: {\r
42 * y: 1,\r
43 * z: value\r
44 * }\r
45 * }\r
46 * @private\r
47 * @since 5.1.0\r
48 */\r
49\r
50 constructor: function (descriptor, owner, callback, scope, options) {\r
51 var me = this,\r
52 trackStatics = options && options.trackStatics;\r
53\r
54 me.callParent([ owner, callback, scope, options ]);\r
55\r
56 me.bindings = [];\r
57 me.literal = descriptor.$literal;\r
58\r
59 if (descriptor.constructor === Object) {\r
60 if (trackStatics) {\r
61 me.staticKeys = [];\r
62 }\r
63 me.addObject(descriptor, me.lastValue = {}, me.staticKeys);\r
64 } else {\r
65 me.addArray(descriptor, me.lastValue = []);\r
66 }\r
67\r
68 // We started at missing == 1 so that no immediate callbacks would hit 0 before\r
69 // adding all bindings... so now we decrement by 1 to balance things and see if\r
70 // we are at 0.\r
71 if (! --me.missing && !me.scheduled) {\r
72 me.schedule();\r
73 }\r
74 },\r
75\r
76 destroy: function () {\r
77 var me = this;\r
78\r
79 me.bindings = Ext.destroy(me.bindings);\r
80\r
81 me.callParent();\r
82 },\r
83\r
84 add: function (descriptor, data, property) {\r
85 var me = this,\r
86 owner = me.owner,\r
87 bindings = me.bindings,\r
88 method = me.literal ? (descriptor.reference ? 'bindEntity' : 'bindExpression')\r
89 : 'bind',\r
90 binding, depth;\r
91\r
92 ++me.missing;\r
93\r
94 binding = owner[method](descriptor,\r
95 function (value) {\r
96 data[property] = value;\r
97\r
98 if (binding.calls === 1) {\r
99 --me.missing;\r
100 }\r
101\r
102 if (!me.missing && !me.scheduled) {\r
103 me.schedule();\r
104 }\r
105 },\r
106 //TODO - split bind options between us and the sub-binds (pass null for now)\r
107 me, null);\r
108\r
109 depth = binding.depth;\r
110 if (!bindings.length || depth < me.depth) {\r
111 me.depth = depth;\r
112 }\r
113\r
114 bindings.push(binding);\r
115 return !this.isBindingStatic(binding);\r
116 },\r
117\r
118 addArray: function (multiBindDescr, array) {\r
119 var me = this,\r
120 n = multiBindDescr.length,\r
121 hasDynamic = false,\r
122 dynamic, b, i;\r
123\r
124 for (i = 0; i < n; ++i) {\r
125 b = multiBindDescr[i];\r
126\r
127 if (b && (b.reference || Ext.isString(b))) {\r
128 dynamic = me.add(b, array, i);\r
129 } else if (Ext.isArray(b)) {\r
130 dynamic = me.addArray(b, array[i] = []);\r
131 } else if (b && b.constructor === Object) {\r
132 dynamic = me.addObject(b, array[i] = {});\r
133 } else {\r
134 array[i] = b;\r
135 dynamic = false;\r
136 }\r
137 hasDynamic = hasDynamic || dynamic;\r
138 }\r
139 return hasDynamic;\r
140 },\r
141\r
142 addObject: function (multiBindDescr, object, staticKeys) {\r
143 var me = this,\r
144 hasDynamic = false,\r
145 dynamic, b, name;\r
146\r
147 for (name in multiBindDescr) {\r
148 b = multiBindDescr[name];\r
149\r
150 if (b && (b.reference || Ext.isString(b))) {\r
151 dynamic = me.add(b, object, name);\r
152 } else if (Ext.isArray(b)) {\r
153 dynamic = me.addArray(b, object[name] = []);\r
154 } else if (b && b.constructor === Object) {\r
155 dynamic = me.addObject(b, object[name] = {});\r
156 } else {\r
157 object[name] = b;\r
158 dynamic = false;\r
159 }\r
160 if (staticKeys && !dynamic) {\r
161 staticKeys.push(name);\r
162 }\r
163 hasDynamic = hasDynamic || dynamic;\r
164 }\r
165 return hasDynamic;\r
166 },\r
167\r
168 getFullName: function () {\r
169 var me = this,\r
170 fullName = me.fullName,\r
171 bindings = me.bindings,\r
172 length = bindings.length,\r
173 i;\r
174\r
175 if (!fullName) {\r
176 fullName = '@[';\r
177 for (i = 0; i < length; ++i) {\r
178 if (i) {\r
179 fullName += ',';\r
180 }\r
181 fullName += bindings[i].getFullName();\r
182 }\r
183 fullName += ']';\r
184\r
185 me.fullName = fullName;\r
186 }\r
187\r
188 return fullName;\r
189 },\r
190\r
191 getRawValue: function () {\r
192 return this.lastValue;\r
193 },\r
194\r
195 isDescendantOf: function () {\r
196 return false;\r
197 },\r
198\r
199 isLoading: function () {\r
200 for (var bindings = this.bindings, n = bindings.length; n-- > 0; ) {\r
201 if (bindings[n].isLoading()) {\r
202 return true;\r
203 }\r
204 }\r
205\r
206 return false;\r
207 },\r
208\r
209 isBindingStatic: function(binding) {\r
210 return binding.isTemplateBinding && binding.isStatic;\r
211 },\r
212\r
213 isStatic: function() {\r
214 var bindings = this.bindings,\r
215 len = bindings.length,\r
216 i, binding;\r
217\r
218 for (i = 0; i < len; ++i) {\r
219 binding = bindings[i];\r
220 if (!this.isBindingStatic(binding)) {\r
221 return false;\r
222 }\r
223 }\r
224 return true;\r
225 },\r
226\r
227 pruneStaticKeys: function() {\r
228 var value = Ext.apply({}, this.lastValue),\r
229 keys = this.staticKeys,\r
230 len = keys.length,\r
231 i;\r
232\r
233 for (i = 0; i < len; ++i) {\r
234 delete value[keys[i]];\r
235 }\r
236 return value;\r
237 },\r
238\r
239 react: function () {\r
240 this.notify(this.lastValue);\r
241 },\r
242\r
243 refresh: function () {\r
244 // @TODO\r
245 },\r
246 \r
247 privates: {\r
248 sort: function () {\r
249 this.scheduler.sortItems(this.bindings);\r
250\r
251 // Schedulable#sort === emptyFn\r
252 //me.callParent();\r
253 }\r
254 }\r
255});\r