]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/app/bind/AbstractStub.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / app / bind / AbstractStub.js
CommitLineData
6527f429
DM
1/**\r
2 * This class manages bindings for a `Session` or `ViewModel`.\r
3 * @private\r
4 */\r
5Ext.define('Ext.app.bind.AbstractStub', {\r
6 extend: 'Ext.util.Schedulable',\r
7\r
8 requires: [\r
9 'Ext.app.bind.Binding'\r
10 ],\r
11\r
12 children: null,\r
13\r
14 depth: 0,\r
15\r
16 generation: 1,\r
17\r
18 kind: 10,\r
19\r
20 parent: null,\r
21\r
22 constructor: function (owner, name) {\r
23 var me = this;\r
24\r
25 /**\r
26 * @property {Ext.data.Session/Ext.app.ViewModel} owner\r
27 * This property is set at creation of ths stub and should not be changed.\r
28 * @readonly\r
29 */\r
30 me.owner = owner;\r
31 me.name = name;\r
32\r
33 me.callParent();\r
34 },\r
35\r
36 destroy: function () {\r
37 var me = this,\r
38 children = me.children,\r
39 bindings = me.bindings,\r
40 len, i, key;\r
41\r
42 if (bindings) {\r
43 for (i = 0, len = bindings.length; i < len; ++i) {\r
44 bindings[i].destroy(true);\r
45 }\r
46 }\r
47\r
48 for (key in children) {\r
49 children[key].destroy();\r
50 }\r
51 me.callParent();\r
52 me.bindings = me.children = me.owner = null;\r
53 },\r
54\r
55 add: function (child) {\r
56 var me = this;\r
57\r
58 (me.children || (me.children = {}))[child.name] = child;\r
59\r
60 child.depth = me.depth + 1;\r
61 child.parent = me;\r
62 },\r
63\r
64 getChild: function (path) {\r
65 var pathArray = Ext.isString(path) ? path.split('.') : path;\r
66\r
67 if (pathArray && pathArray.length) {\r
68 return this.descend(pathArray, 0);\r
69 }\r
70\r
71 return this;\r
72 },\r
73\r
74 getFullName: function () {\r
75 var me = this,\r
76 name = me.fullName,\r
77 parent = me.parent,\r
78 s;\r
79\r
80 if (!name) {\r
81 name = me.name || me.id;\r
82 if (parent && (s = parent.getFullName())) {\r
83 name = ((s.charAt(s.length-1) !== ':') ? s + '.' : s) + name;\r
84 }\r
85 me.fullName = name;\r
86 }\r
87\r
88 return name;\r
89 },\r
90\r
91 getSession: function () {\r
92 var owner = this.owner;\r
93\r
94 return owner.isSession ? owner : owner.getSession();\r
95 },\r
96\r
97 bind: function (callback, scope, options) {\r
98 var me = this,\r
99 binding = new Ext.app.bind.Binding(me, callback, scope, options),\r
100 bindings = (me.bindings || (me.bindings = []));\r
101\r
102 binding.depth = me.depth;\r
103 bindings.push(binding);\r
104\r
105 return binding;\r
106 },\r
107\r
108 getValue: function () {\r
109 return this.isLoading() ? null : this.getRawValue();\r
110 },\r
111\r
112 graft: function (replacement) {\r
113 var me = this,\r
114 bindings = me.bindings,\r
115 name = me.name,\r
116 i;\r
117\r
118 // Clear these so that when we call destroy we won't damage anything:\r
119 me.parent = me.bindings = null;\r
120 me.destroy(); // we may be scheduled\r
121\r
122 replacement.depth = me.depth;\r
123 replacement.bindings = bindings;\r
124 replacement.generation = me.generation + 1;\r
125 replacement.name = name;\r
126 replacement.id = me.id;\r
127 replacement.path = me.path;\r
128\r
129 // Now for the fun part...\r
130 if (bindings) {\r
131 for (i = bindings.length; i-- > 0; ) {\r
132 bindings[i].stub = replacement;\r
133 }\r
134 } \r
135\r
136 return replacement;\r
137 },\r
138\r
139 isDescendantOf: function (item) {\r
140 for (var parent = this; parent = parent.parent; ) {\r
141 if (parent === item) {\r
142 return true;\r
143 }\r
144 }\r
145 return false;\r
146 },\r
147\r
148 onSchedule: function() {\r
149 // When a stub changes, say "foo.bar.baz" we may need to notify bindings on our\r
150 // parents "foo.bar" and "foo", This is true especially when these are targets of\r
151 // links. To economize on this we require that bindings that want to be notified\r
152 // of changes to sub-properties of their target set the "deep" property to true.\r
153 for (var i, len, binding, bindings, p = this.parent; p; p = p.parent) {\r
154 bindings = p.bindings;\r
155 if (bindings) {\r
156 for (i = 0, len = bindings.length; i < len; ++i) {\r
157 binding = bindings[i];\r
158 if (binding.deep && !binding.scheduled) {\r
159 binding.schedule();\r
160 }\r
161 }\r
162 }\r
163 }\r
164 },\r
165\r
166 react: function () {\r
167 var bindings = this.bindings,\r
168 binding, i, len;\r
169 \r
170 if (bindings) {\r
171 for (i = 0, len = bindings.length; i < len; ++i) {\r
172 binding = bindings[i];\r
173 if (!binding.scheduled) {\r
174 binding.schedule();\r
175 }\r
176 }\r
177 }\r
178 },\r
179\r
180 unbind: function (binding) {\r
181 var bindings = this.bindings;\r
182\r
183 if (bindings && bindings.length) {\r
184 Ext.Array.remove(bindings, binding);\r
185 }\r
186 },\r
187\r
188 privates: {\r
189 collect: function() {\r
190 var children = this.children,\r
191 bindings = this.bindings,\r
192 totalCount = 0,\r
193 count = 0,\r
194 child,\r
195 key;\r
196 \r
197 if (children) {\r
198 for (key in children) {\r
199 child = children[key];\r
200 count = child.collect();\r
201 if (count === 0) {\r
202 // The child (and any deep children) have no bindings,\r
203 // so we can consider it a dead node.\r
204 child.destroy();\r
205 delete children[key];\r
206 }\r
207 totalCount += count;\r
208 }\r
209 }\r
210 \r
211 if (bindings) {\r
212 totalCount += bindings.length;\r
213 }\r
214 \r
215 return totalCount;\r
216 },\r
217 \r
218 getScheduler: function () {\r
219 var owner = this.owner;\r
220 return owner && owner.getScheduler();\r
221 },\r
222 \r
223 sort: function () {\r
224 var parent = this.parent;\r
225\r
226 if (parent) {\r
227 // We sort our parent first because if it is something like a link we need\r
228 // it to determine the value of the root-level property before we can dot\r
229 // our way into it. This is especially important for formulas that might\r
230 // throw errors if the links have not published results before they run.\r
231 this.scheduler.sortItem(parent);\r
232 }\r
233\r
234 // Schedulable#sort === emptyFn\r
235 //me.callParent();\r
236 }\r
237 }\r
238});\r