]> git.proxmox.com Git - extjs.git/blob - extjs/packages/core/src/mixin/Container.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / mixin / Container.js
1 /**
2 * @private
3 * Common methods for both classic & modern containers
4 */
5 Ext.define('Ext.mixin.Container', {
6 extend: 'Ext.Mixin',
7
8 mixinConfig: {
9 id: 'container'
10 },
11
12 /**
13 * @property {Boolean} isContainer
14 * `true` in this class to identify an object as an instantiated Container, or subclass thereof.
15 */
16 isContainer: true,
17
18 config: {
19 /**
20 * @cfg {Boolean} referenceHolder
21 * If `true`, this container will be marked as being a point in the hierarchy where
22 * references to items with a specified `reference` config will be held. The container
23 * will automatically become a referenceHolder if a {@link #controller} is specified.
24 *
25 * See the introductory docs for {@link Ext.container.Container} for more information
26 * about references & reference holders.
27 */
28 referenceHolder: false
29 },
30
31 /**
32 * Returns an object holding the descendants of this view keyed by their
33 * `{@link Ext.Component#cfg-reference reference}`. This object should not be held
34 * past the scope of the function calling this method. It will not be valid if items
35 * are added or removed from this or any sub-container.
36 *
37 * The intended usage is shown here (assume there are 3 components with reference
38 * values of "foo", "bar" and "baz" at some level below this container):
39 *
40 * onClick: function () {
41 * var refs = this.getReferences();
42 *
43 * // using "refs" we can access any descendant by its "reference"
44 *
45 * refs.foo.getValue() + refs.bar.getValue() + refs.baz.getValue();
46 * }
47 *
48 * If `this` component has a `{@link Ext.Component#cfg-reference reference}` assigned
49 * to it, that is **not** included in this object. That reference is understood to
50 * belong to the ancestor container configured as the `referenceHolder`.
51 *
52 * @return {Object} An object with each child reference. This will be `null` if this
53 * container has no descendants with a `{@link Ext.Component#cfg-reference reference}`
54 * specified.
55 * @since 5.0.0
56 */
57 getReferences: function () {
58 Ext.ComponentManager.fixReferences();
59 return this.refs || null;
60 },
61
62 /**
63 * Gets a reference to the component with the specified {@link #reference} value.
64 *
65 * The method is a short-hand for the {@link #lookupReference} method.
66 *
67 * @param {String} key The name of the reference to lookup.
68 * @return {Ext.Component} The referenced component or `null` if it is not found.
69 * @since 6.0.1
70 */
71 lookup: function (key) {
72 var refs = this.getReferences();
73 return (refs && refs[key]) || null;
74 },
75
76 /**
77 * Gets a reference to the component with the specified {@link #reference} value.
78 *
79 * The {@link #lookup} method is a short-hand version of this method.
80 *
81 * @param {String} key The name of the reference to lookup.
82 * @return {Ext.Component} The referenced component or `null` if it is not found.
83 * @since 5.0
84 */
85 lookupReference: function (key) {
86 return this.lookup(key);
87 },
88
89 privates: {
90 /**
91 * Sets up a component reference.
92 * @param {Ext.Component} component The component to reference.
93 * @private
94 */
95 attachReference: function (component) {
96 var me = this,
97 key, refs;
98
99 // Cleaning all this up later anyway
100 if (me.destroying || me.destroyed) {
101 return;
102 }
103
104 refs = me.refs || (me.refs = {});
105 key = component.referenceKey;
106 //<debug>
107 if (refs[key] && refs[key] !== component) {
108 Ext.log.warn('Duplicate reference: "' + key + '" on ' + me.id);
109 }
110 //</debug>
111 refs[key] = component;
112 },
113
114 /**
115 * Clear a component reference.
116 * @param {Ext.Component} component The component to remove.
117 * @private
118 */
119 clearReference: function (component) {
120 var refs = this.refs,
121 key = component.referenceKey;
122
123 if (refs && key) {
124 // viewModelKey would be better placed in app.Container however
125 // it's not really worth introducing a second method call to clear
126 // a single property.
127 component.viewModelKey = component.referenceKey = refs[key] = null;
128 }
129 },
130
131 containerOnAdded: function(component, instanced) {
132 // We have been added to a container, we may have child references
133 // or be a reference ourself. At this point we have no way of knowing if
134 // our references are correct, so trigger a fix.
135 if (instanced) {
136 Ext.ComponentManager.markReferencesDirty();
137 }
138 },
139
140 containerOnRemoved: function(destroying) {
141 var refHolder;
142
143 // If we're destroying this will get cleaned up anyway
144 if (!destroying) {
145 refHolder = this.lookupReferenceHolder();
146 if (refHolder) {
147 // Clear any references here, they will be reset after the
148 // next call to lookupReference after being marked dirty.
149 // It's easier to wipe & re-establish them than attempt to
150 // track what changed and prune the collection
151
152 Ext.ComponentManager.markReferencesDirty();
153 refHolder.clearReferences();
154 }
155 }
156 },
157
158 /**
159 * Invalidates the references collection. Typically called when
160 * removing a container from this container, since it's difficult
161 * to know what references got removed.
162 *
163 * @private
164 */
165 clearReferences: function () {
166 this.refs = null;
167 },
168
169 initContainerInheritedState: function(inheritedState, inheritedStateInner) {
170 var me = this,
171 controller = me.getController(),
172 session = me.getSession(),
173 // Don't instantiate it here, we just want to know whether we
174 // were configured with a VM
175 viewModel = me.getConfig('viewModel', true),
176 reference = me.getReference(),
177 referenceHolder = me.getReferenceHolder();
178
179
180
181 if (controller) {
182 inheritedState.referenceHolder = controller;
183 referenceHolder = true;
184 } else if (referenceHolder) {
185 inheritedState.referenceHolder = me;
186 }
187
188 if (referenceHolder) {
189 inheritedState.referencePath = '';
190 } else if (reference && me.isParentReference) {
191 inheritedState.referencePath = me.referenceKey + '.';
192 }
193
194 if (session) {
195 inheritedState.session = session;
196 }
197
198 if (viewModel) {
199 inheritedState.viewModelPath = '';
200 } else if (reference && me.isParentReference) {
201 inheritedState.viewModelPath = me.viewModelKey + '.';
202 }
203 },
204
205 setupReference: function(reference) {
206 var len;
207
208 if (reference && reference.charAt(len = reference.length - 1) === '>') {
209 this.isParentReference = true;
210 reference = reference.substring(0, len);
211 }
212
213 //<debug>
214 if (reference && !Ext.validIdRe.test(reference)) {
215 Ext.Error.raise('Invalid reference "' + reference + '" for ' + this.getId() +
216 ' - not a valid identifier');
217 }
218 //</debug>
219
220 return reference;
221 }
222 }
223 });