]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/src/Component.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / src / Component.js
CommitLineData
6527f429
DM
1/**\r
2 * Base class for all Ext components.\r
3 *\r
4 * The Component base class has built-in support for basic hide/show and enable/disable\r
5 * and size control behavior.\r
6 *\r
7 * ## xtypes\r
8 *\r
9 * Every component has a specific xtype, which is its Ext-specific type name, along with\r
10 * methods for checking the xtype like {@link #getXType} and {@link #isXType}. See the\r
11 * [Component Guide][../../../core_concepts/components.html] for more information on xtypes \r
12 * and the Component hierarchy.\r
13 *\r
14 * ## Finding components\r
15 *\r
16 * All Components are registered with the {@link Ext.ComponentManager} on construction so\r
17 * that they can be referenced at any time via {@link Ext#getCmp Ext.getCmp}, passing the\r
18 * {@link #id}.\r
19 *\r
20 * Additionally the {@link Ext.ComponentQuery} provides a CSS-selectors-like way to look\r
21 * up components by their xtype and many other attributes. For example the following code\r
22 * will find all textfield components inside component with `id: 'myform'`:\r
23 *\r
24 * Ext.ComponentQuery.query('#myform textfield');\r
25 *\r
26 * ## Extending Ext.Component\r
27 *\r
28 * All subclasses of Component may participate in the automated Ext component\r
29 * life cycle of creation, rendering and destruction which is provided by the\r
30 * {@link Ext.container.Container Container} class. Components may be added to a Container\r
31 * through the {@link Ext.container.Container#cfg-items items} config option at the time\r
32 * the Container is created, or they may be added dynamically via the\r
33 * {@link Ext.container.Container#method-add add} method.\r
34 *\r
35 * All user-developed visual widgets that are required to participate in automated\r
36 * life cycle and size management should subclass Component.\r
37 *\r
38 * See the Creating new UI controls chapter in [Component Guide][../../../core_concepts/components.html] \r
39 * for details on how and to either extend or augment Ext JS base classes to create custom Components.\r
40 *\r
41 * ## The Ext.Component class by itself\r
42 *\r
43 * Usually one doesn't need to instantiate the Ext.Component class. There are subclasses\r
44 * which implement specialized use cases, covering most application needs. However it is\r
45 * possible to instantiate a base Component, and it can be rendered to document, or handled\r
46 * by layouts as the child item of a Container:\r
47 *\r
48 * @example\r
49 * Ext.create('Ext.Component', {\r
50 * html: 'Hello world!',\r
51 * width: 300,\r
52 * height: 200,\r
53 * padding: 20,\r
54 * style: {\r
55 * color: '#FFFFFF',\r
56 * backgroundColor:'#000000'\r
57 * },\r
58 * renderTo: Ext.getBody()\r
59 * });\r
60 *\r
61 * The Component above creates its encapsulating `div` upon render, and use the configured\r
62 * HTML as content. More complex internal structure may be created using the\r
63 * {@link #renderTpl} configuration, although to display database-derived mass data, it is\r
64 * recommended that an ExtJS data-backed Component such as a {@link Ext.view.View View},\r
65 * {@link Ext.grid.Panel GridPanel}, or {@link Ext.tree.Panel TreePanel} be used.\r
66 */\r
67Ext.define('Ext.Component', {\r
68 alternateClassName: 'Ext.AbstractComponent',\r
69\r
70 xtype: [\r
71 'component',\r
72 'box'\r
73 ],\r
74\r
75 requires: [\r
76 'Ext.ComponentQuery',\r
77 'Ext.ComponentManager',\r
78 'Ext.util.ProtoElement',\r
79 'Ext.dom.CompositeElement',\r
80 'Ext.scroll.Scroller',\r
81 'Ext.scroll.TouchScroller',\r
82 'Ext.scroll.DomScroller'\r
83 ],\r
84\r
85 // Note that Floating must be mixed in before Positionable.\r
86 mixins: [\r
87 'Ext.mixin.Inheritable',\r
88 'Ext.util.Floating',\r
89 'Ext.util.Positionable',\r
90 'Ext.util.Observable',\r
91 'Ext.mixin.ComponentDelegation',\r
92 'Ext.mixin.Bindable',\r
93 'Ext.util.Animate',\r
94 'Ext.util.ElementContainer',\r
95 'Ext.util.Renderable',\r
96 'Ext.state.Stateful',\r
97 'Ext.util.Focusable',\r
98 'Ext.mixin.Accessible',\r
99 'Ext.util.KeyboardInteractive'\r
100 ],\r
101\r
102 uses: [\r
103 'Ext.overrides.*',\r
104 'Ext.Element',\r
105 'Ext.DomHelper',\r
106 'Ext.XTemplate',\r
107 'Ext.ComponentLoader',\r
108 'Ext.layout.Context',\r
109 'Ext.layout.Layout',\r
110 'Ext.layout.component.Auto',\r
111 'Ext.LoadMask',\r
112 'Ext.ZIndexManager',\r
113 'Ext.util.DelayedTask',\r
114 'Ext.resizer.Resizer',\r
115 'Ext.util.ComponentDragger'\r
116 ],\r
117\r
118 statics: {\r
119 AUTO_ID: 1000,\r
120\r
121 pendingLayouts: null,\r
122\r
123 layoutSuspendCount: 0,\r
124\r
125 // Collapse/expand directions\r
126 DIRECTION_TOP: 'top',\r
127 DIRECTION_RIGHT: 'right',\r
128 DIRECTION_BOTTOM: 'bottom',\r
129 DIRECTION_LEFT: 'left',\r
130\r
131 VERTICAL_DIRECTION_Re: /^(?:top|bottom)$/,\r
132\r
133 // RegExp whih specifies characters in an xtype which must be translated to '-' when generating auto IDs.\r
134 // This includes dot, comma and whitespace\r
135 INVALID_ID_CHARS_Re: /[\.,\s]/g,\r
136 \r
137 /**\r
138 * @property {String} ariaHighContrastModeCls CSS class to be applied\r
139 * to the document body when High Contrast mode is detected in Windows.\r
140 * @private\r
141 */\r
142 ariaHighContrastModeCls: Ext.baseCSSPrefix + 'aria-highcontrast',\r
143 \r
144 /**\r
145 * Cancels layout of a component.\r
146 * @param {Ext.Component} comp\r
147 */\r
148 cancelLayout: function(comp, isDestroying) {\r
149 var context = this.runningLayoutContext || this.pendingLayouts;\r
150\r
151 if (context) {\r
152 context.cancelComponent(comp, false, isDestroying);\r
153 }\r
154 },\r
155\r
156 /**\r
157 * Find the Widget or Component to which the given Element belongs.\r
158 *\r
159 * @param {Ext.dom.Element/HTMLElement} el The element from which to start to find an owning Component.\r
160 * @param {Ext.dom.Element/HTMLElement} [limit] The element at which to stop upward searching for an\r
161 * owning Component, or the number of Components to traverse before giving up.\r
162 * Defaults to the document's HTML element.\r
163 * @param {String} [selector] An optional {@link Ext.ComponentQuery} selector to filter the target.\r
164 * @return {Ext.Component/null} Component, or null\r
165 */\r
166 fromElement: function(node, limit, selector) {\r
167 return Ext.ComponentManager.fromElement(node, limit, selector);\r
168 },\r
169\r
170 /**\r
171 * Performs all pending layouts that were scheduled while\r
172 * {@link Ext.Component#suspendLayouts suspendLayouts} was in effect.\r
173 * @static\r
174 */\r
175 flushLayouts: function () {\r
176 var me = this,\r
177 context = me.pendingLayouts;\r
178\r
179 if (context && context.invalidQueue.length) {\r
180 me.pendingLayouts = null;\r
181 me.runningLayoutContext = context;\r
182\r
183 Ext.override(context, {\r
184 runComplete: function () {\r
185 // we need to release the layout queue before running any of the\r
186 // finishedLayout calls because they call afterComponentLayout\r
187 // which can re-enter by calling updateLayout/doComponentLayout.\r
188 me.runningLayoutContext = null;\r
189 \r
190 var result = this.callParent(); // not "me" here!\r
191 if (Ext.GlobalEvents.hasListeners.afterlayout) {\r
192 Ext.GlobalEvents.fireEvent('afterlayout');\r
193 }\r
194 return result;\r
195 }\r
196 });\r
197\r
198 context.run();\r
199 }\r
200 },\r
201\r
202 /**\r
203 * Resumes layout activity in the whole framework.\r
204 *\r
205 * {@link Ext#suspendLayouts} is alias of {@link Ext.Component#suspendLayouts}.\r
206 *\r
207 * @param {Boolean} [flush=false] `true` to perform all the pending layouts. This can also be\r
208 * achieved by calling {@link Ext.Component#flushLayouts flushLayouts} directly.\r
209 * @static\r
210 */\r
211 resumeLayouts: function (flush) {\r
212 if (this.layoutSuspendCount && ! --this.layoutSuspendCount) {\r
213 if (flush) {\r
214 this.flushLayouts();\r
215 }\r
216 if (Ext.GlobalEvents.hasListeners.resumelayouts) {\r
217 Ext.GlobalEvents.fireEvent('resumelayouts');\r
218 }\r
219 }\r
220 },\r
221\r
222 /**\r
223 * Stops layouts from happening in the whole framework.\r
224 *\r
225 * It's useful to suspend the layout activity while updating multiple components and\r
226 * containers:\r
227 *\r
228 * Ext.suspendLayouts();\r
229 * // batch of updates...\r
230 * Ext.resumeLayouts(true);\r
231 *\r
232 * {@link Ext#suspendLayouts} is alias of {@link Ext.Component#suspendLayouts}.\r
233 *\r
234 * See also {@link Ext#batchLayouts} for more abstract way of doing this.\r
235 *\r
236 * @static\r
237 */\r
238 suspendLayouts: function () {\r
239 ++this.layoutSuspendCount;\r
240 },\r
241\r
242 /**\r
243 * Updates layout of a component.\r
244 *\r
245 * @param {Ext.Component} comp The component to update.\r
246 * @param {Boolean} [defer=false] `true` to just queue the layout if this component.\r
247 * @static\r
248 */\r
249 updateLayout: function (comp, defer) {\r
250 var me = this,\r
251 running = me.runningLayoutContext,\r
252 pending;\r
253\r
254 if (running) {\r
255 running.queueInvalidate(comp);\r
256 } else {\r
257 pending = me.pendingLayouts || (me.pendingLayouts = new Ext.layout.Context());\r
258 pending.queueInvalidate(comp);\r
259\r
260 if (!defer && !me.layoutSuspendCount && !comp.isLayoutSuspended()) {\r
261 me.flushLayouts();\r
262 }\r
263 }\r
264 }\r
265 },\r
266\r
267 // <editor-fold desc="Config">\r
268 // ***********************************************************************************\r
269 // Begin Config\r
270 // ***********************************************************************************\r
271\r
272 // We do not want "_hidden" style backing properties.\r
273 $configPrefixed: false,\r
274 // We also want non-config system properties to go to the instance.\r
275 $configStrict: false,\r
276\r
277 config: {\r
278 /**\r
279 * @cfg {Object} data\r
280 * The initial set of data to apply to the `{@link #tpl}` to update the content\r
281 * area of the Component.\r
282 *\r
283 * @since 3.4.0\r
284 */\r
285 data: null,\r
286\r
287 /**\r
288 * @cfg {Boolean} modelValidation\r
289 * This config enables binding to your `{@link Ext.data.Model#validators}`. This\r
290 * is only processed by form fields (e.g., `Ext.form.field.Text`) at present, but\r
291 * this setting is inherited and so can be set on a parent container.\r
292 *\r
293 * When set to `true` by a component or not set by a component but inherited from\r
294 * an ancestor container, `Ext.data.Validation` records are used to automatically\r
295 * bind validation results for any form field to which a `value` is bound.\r
296 *\r
297 * While this config can be set arbitrarily high in the component hierarchy, doing\r
298 * so can create a lot overhead if most of your form fields do not actually rely on\r
299 * `validators` in your data model.\r
300 *\r
301 * Using this setting for a form that is bound to an `Ext.data.Model` might look\r
302 * like this:\r
303 *\r
304 * {\r
305 * xtype: 'panel',\r
306 * modelValidation: true,\r
307 * items: [{\r
308 * xtype: 'textfield',\r
309 * bind: '{theUser.firstName}'\r
310 * },{\r
311 * xtype: 'textfield',\r
312 * bind: '{theUser.lastName}'\r
313 * },{\r
314 * xtype: 'textfield',\r
315 * bind: '{theUser.phoneNumber}'\r
316 * },{\r
317 * xtype: 'textfield',\r
318 * bind: '{theUser.email}'\r
319 * }]\r
320 * }\r
321 *\r
322 * The above is equivalent to the following manual binding of validation:\r
323 *\r
324 * {\r
325 * xtype: 'panel',\r
326 * items: [{\r
327 * xtype: 'textfield',\r
328 * bind: {\r
329 * value: '{theUser.firstName}'\r
330 * validation: '{theUser.validation.firstName}'\r
331 * }\r
332 * },{\r
333 * xtype: 'textfield',\r
334 * bind: {\r
335 * value: '{theUser.lastName}'\r
336 * validation: '{theUser.validation.lastName}'\r
337 * }\r
338 * },{\r
339 * xtype: 'textfield',\r
340 * bind: {\r
341 * value: '{theUser.phoneNumber}'\r
342 * validation: '{theUser.validation.phoneNumber}'\r
343 * }\r
344 * },{\r
345 * xtype: 'textfield',\r
346 * bind: {\r
347 * value: '{theUser.email}'\r
348 * validation: '{theUser.validation.email}'\r
349 * }\r
350 * }]\r
351 * }\r
352 *\r
353 * Notice that "validation" is a pseudo-association defined for all entities. See\r
354 * `{@link Ext.data.Model#getValidation}` for further details.\r
355 */\r
356\r
357 /**\r
358 * @cfg {Number} maxHeight\r
359 * The maximum value in pixels which this Component will set its height to.\r
360 *\r
361 * **Warning:** This will override any size management applied by layout managers.\r
362 */\r
363 maxHeight: null,\r
364\r
365 /**\r
366 * @cfg {Number} maxWidth\r
367 * The maximum value in pixels which this Component will set its width to.\r
368 *\r
369 * **Warning:** This will override any size management applied by layout managers.\r
370 */\r
371 maxWidth: null,\r
372\r
373 /**\r
374 * @cfg {Number} minHeight\r
375 * The minimum value in pixels which this Component will set its height to.\r
376 *\r
377 * **Warning:** This will override any size management applied by layout managers.\r
378 */\r
379 minHeight: null,\r
380\r
381 /**\r
382 * @cfg {Number} minWidth\r
383 * The minimum value in pixels which this Component will set its width to.\r
384 *\r
385 * **Warning:** This will override any size management applied by layout managers.\r
386 */\r
387 minWidth: null,\r
388\r
389 /**\r
390 * @cfg {Boolean/String/Object} scrollable\r
391 * Configuration options to make this Component scrollable. Acceptable values are:\r
392 *\r
393 * - `true` to enable auto scrolling.\r
394 * - `false` (or `null`) to disable scrolling - this is the default.\r
395 * - `x` or `horizontal` to enable horizontal scrolling only\r
396 * - `y` or `vertical` to enable vertical scrolling only\r
397 *\r
398 * Also accepts a configuration object for a `{@link Ext.scroll.Scroller}` if\r
399 * if advanced configuration is needed.\r
400 *\r
401 * The getter for this config returns the {@link Ext.scroll.Scroller Scroller}\r
402 * instance. You can use the Scroller API to read or manipulate the scroll position:\r
403 *\r
404 * // scrolls the component to 5 on the x axis and 10 on the y axis\r
405 * component.getScrollable().scrollTo(5, 10);\r
406 */\r
407 scrollable: null\r
408 },\r
409\r
410 defaultBindProperty: 'html',\r
411\r
412 /**\r
413 * @cfg {String} [alignTarget]\r
414 * A Component or Element by which to position this component according to the {@link #defaultAlign}.\r
415 * Defaults to the owning Container.\r
416 *\r
417 * *Only applicable if this component is {@link #cfg-floating}*\r
418 *\r
419 * *Used upon first show*.\r
420 */\r
421 alignTarget: null,\r
422\r
423 /**\r
424 * @cfg {String} anchor\r
425 * @inheritDoc Ext.layout.container.Anchor\r
426 */\r
427\r
428 /**\r
429 * @cfg {String/Object} autoEl\r
430 * A tag name or {@link Ext.dom.Helper DomHelper} spec used to create the {@link #getEl Element} which will\r
431 * encapsulate this Component.\r
432 *\r
433 * You do not normally need to specify this. For the base classes {@link Ext.Component} and\r
434 * {@link Ext.container.Container}, this defaults to **'div'**. The more complex Sencha classes use a more\r
435 * complex DOM structure specified by their own {@link #renderTpl}s.\r
436 *\r
437 * This is intended to allow the developer to create application-specific utility Components encapsulated by\r
438 * different DOM elements. Example usage:\r
439 *\r
440 * {\r
441 * xtype: 'component',\r
442 * autoEl: {\r
443 * tag: 'img',\r
444 * src: 'http://www.example.com/example.jpg'\r
445 * }\r
446 * }, {\r
447 * xtype: 'component',\r
448 * autoEl: {\r
449 * tag: 'blockquote',\r
450 * html: 'autoEl is cool!'\r
451 * }\r
452 * }, {\r
453 * xtype: 'container',\r
454 * autoEl: 'ul',\r
455 * cls: 'ux-unordered-list',\r
456 * items: {\r
457 * xtype: 'component',\r
458 * autoEl: 'li',\r
459 * html: 'First list item'\r
460 * }\r
461 * }\r
462 *\r
463 * @since 2.3.0\r
464 */\r
465\r
466 /**\r
467 * @cfg {Boolean/String/HTMLElement/Ext.dom.Element} autoRender\r
468 * This config is intended mainly for non-{@link #cfg-floating} Components which may or may not be shown. Instead of using\r
469 * {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component to render itself\r
470 * upon first _{@link Ext.Component#method-show show}_. If {@link #cfg-floating} is `true`, the value of this config is omitted as if it is `true`.\r
471 *\r
472 * Specify as `true` to have this Component render to the document body upon first show.\r
473 *\r
474 * Specify as an element, or the ID of an element to have this Component render to a specific element upon first\r
475 * show.\r
476 */\r
477 autoRender: false,\r
478\r
479 /**\r
480 * @cfg {Boolean} [autoScroll=false]\r
481 * `true` to use overflow:'auto' on the components layout element and show scroll bars automatically when necessary,\r
482 * `false` to clip any overflowing content.\r
483 *\r
484 * This should not be combined with {@link #overflowX} or {@link #overflowY}.\r
485 * @deprecated 5.1.0 Use {@link #scrollable} instead\r
486 */\r
487\r
488 /**\r
489 * @cfg {Boolean} autoShow\r
490 * `true` to automatically show the component upon creation. This config option may only be used for\r
491 * {@link #cfg-floating} components or components that use {@link #autoRender}.\r
492 *\r
493 * @since 2.3.0\r
494 */\r
495 autoShow: false,\r
496\r
497 /**\r
498 * @cfg {String} [baseCls='x-component']\r
499 * The base CSS class to apply to this component's element. This will also be prepended to elements within this\r
500 * component like Panel's body will get a class `x-panel-body`. This means that if you create a subclass of Panel, and\r
501 * you want it to get all the Panels styling for the element and the body, you leave the `baseCls` `x-panel` and use\r
502 * `componentCls` to add specific styling for this component.\r
503 */\r
504 baseCls: Ext.baseCSSPrefix + 'component',\r
505\r
506 /**\r
507 * @cfg {Number/String/Boolean} border\r
508 * Specifies the border size for this component. The border can be a single numeric value to apply to all sides or it can\r
509 * be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).\r
510 *\r
511 * For components that have no border by default, setting this won't make the border appear by itself.\r
512 * You also need to specify border color and style:\r
513 *\r
514 * border: 5,\r
515 * style: {\r
516 * borderColor: 'red',\r
517 * borderStyle: 'solid'\r
518 * }\r
519 *\r
520 * To turn off the border, use `border: false`.\r
521 */\r
522\r
523 /**\r
524 * @cfg {Object/String[]/Object[]} childEls\r
525 * @inheritdoc Ext.util.ElementContainer#childEls\r
526 */\r
527 childEls: {\r
528 frameTable: { frame: true },\r
529 frameTL: { frame: 'tl' },\r
530 frameTC: { frame: 'tc' },\r
531 frameTR: { frame: 'tr' },\r
532 frameML: { frame: 'ml' },\r
533 frameBody: { frame: 'mc' },\r
534 frameMR: { frame: 'mr' },\r
535 frameBL: { frame: 'bl' },\r
536 frameBC: { frame: 'bc' },\r
537 frameBR: { frame: 'br' }\r
538 },\r
539\r
540 /**\r
541 * @cfg {String/String[]} [cls='']\r
542 * An optional extra CSS class that will be added to this component's Element. \r
543 * The value can be a string, a list of strings separated by spaces, or an array of strings. This can be useful \r
544 * for adding customized styles to the component or any of its children using standard CSS rules.\r
545 *\r
546 * @since 1.1.0\r
547 */\r
548\r
549 /**\r
550 * @cfg {Number} [columnWidth]\r
551 * Defines the column width inside {@link Ext.layout.container.Column column layout}.\r
552 *\r
553 * The columnWidth property is always evaluated as a percentage and must be a decimal value greater than 0 and \r
554 * less than 1 (e.g., .25). See the description at the top of {@link Ext.layout.container.Column column layout} for \r
555 * additional usage details when combining width and columnWidth configs within the layout.\r
556 */\r
557\r
558 /**\r
559 * @cfg {String} componentCls\r
560 * CSS Class to be added to a components root level element to give distinction to it via styling.\r
561 */\r
562\r
563 // @cmd-auto-dependency { aliasPrefix : "layout." }\r
564 /**\r
565 * @cfg {String/Object} componentLayout\r
566 * The sizing and positioning of a Component's internal Elements is the responsibility of the Component's layout\r
567 * manager which sizes a Component's internal structure in response to the Component being sized.\r
568 *\r
569 * Generally, developers will not use this configuration as all provided Components which need their internal\r
570 * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.\r
571 *\r
572 * The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component\r
573 * class which simply sizes the Component's encapsulating element to the height and width specified in the\r
574 * {@link #setSize} method.\r
575 * \r
576 */\r
577 componentLayout: 'autocomponent',\r
578\r
579 /**\r
580 * @cfg {Object/String} constraintInsets\r
581 * An object or a string (in TRBL order) specifying insets from the configured {@link #constrainTo constrain region}\r
582 * within which this component must be constrained when positioning or sizing.\r
583 * example:\r
584 *\r
585 * constraintInsets: '10 10 10 10' // Constrain with 10px insets from parent\r
586 */\r
587\r
588 /**\r
589 * @cfg {Ext.util.Region/Ext.dom.Element} constrainTo\r
590 * A {@link Ext.util.Region Region} (or an element from which a Region measurement will be read) which is used\r
591 * to constrain the component. Only applies when the component is floating.\r
592 */\r
593\r
594 /**\r
595 * @cfg {String} contentEl\r
596 * Specify an existing HTML element, or the `id` of an existing HTML element to use as the content for this component.\r
597 *\r
598 * This config option is used to take an existing HTML element and place it in the layout element of a new component\r
599 * (it simply moves the specified DOM element _after the Component is rendered_ to use as the content.\r
600 *\r
601 * **Notes:**\r
602 *\r
603 * The specified HTML element is appended to the layout element of the component _after any configured\r
604 * {@link #html HTML} has been inserted_, and so the document will not contain this element at the time\r
605 * the {@link #event-render} event is fired.\r
606 *\r
607 * The specified HTML element used will not participate in any **`{@link Ext.container.Container#layout layout}`**\r
608 * scheme that the Component may use. It is just HTML. Layouts operate on child\r
609 * **`{@link Ext.container.Container#cfg-items items}`**.\r
610 *\r
611 * Add either the `x-hidden` or the `x-hidden-display` CSS class to prevent a brief flicker of the content before it\r
612 * is rendered to the panel.\r
613 *\r
614 * @since 3.4.0\r
615 */\r
616\r
617 /**\r
618 * @cfg {String} [defaultAlign="c-c"]\r
619 * The default {@link Ext.util.Positionable#getAlignToXY Ext.dom.Element#getAlignToXY} anchor position value for this component\r
620 * relative to its {@link #alignTarget} (which defaults to its owning Container).\r
621 *\r
622 * _Only applicable if this component is {@link #cfg-floating}_\r
623 *\r
624 * *Used upon first show*.\r
625 */\r
626 defaultAlign: 'c-c',\r
627\r
628 /**\r
629 * @cfg {Boolean} disabled\r
630 * `true` to disable the component.\r
631 * @since 2.3.0\r
632 */\r
633 disabled: false,\r
634\r
635 // http://www.w3.org/TR/html5/disabled-elements.html\r
636 disabledRe: /^(?:button|input|select|textarea|optgroup|option|fieldset)$/i,\r
637\r
638 nonMaskableRe: (function () {\r
639 var re = ['input', 'select', 'textarea', 'optgroup', 'option', 'table'];\r
640\r
641 // All IE browsers 9 and below except for IE 9 standards.\r
642 if (Ext.isIE9m && !(Ext.isIE9 && !Ext.isIEQuirks)) {\r
643 // <p>.insertAdjacentHTML('BeforeEnd', '<div>...</div>') yields\r
644 // 'Invalid source HTML for this operation' in all IEs not IE 9 standards.\r
645 re.push('p');\r
646 }\r
647\r
648 return new RegExp('^(?:' + re.join('|') + ')$', 'i');\r
649 }()),\r
650\r
651 /**\r
652 * @cfg {String} [disabledCls='x-item-disabled']\r
653 * CSS class to add when the Component is disabled.\r
654 */\r
655 disabledCls: Ext.baseCSSPrefix + 'item-disabled',\r
656 \r
657 /**\r
658 * @cfg {'top'/'bottom'/'left'/'right'} dock\r
659 * The side of the {@link Ext.panel.Panel panel} where this component is to be \r
660 * docked when specified in the panel's \r
661 * {@link Ext.panel.Panel#dockedItems dockedItems} config.\r
662 * \r
663 * Possible values are:\r
664 * \r
665 * - top\r
666 * - bottom\r
667 * - left\r
668 * - right\r
669 */\r
670\r
671 /**\r
672 * @cfg {Boolean/Object} [draggable=false]\r
673 * Specify as true to make a {@link #cfg-floating} Component draggable using the Component's encapsulating element as\r
674 * the drag handle.\r
675 *\r
676 * This may also be specified as a config object for the {@link Ext.util.ComponentDragger ComponentDragger} which is\r
677 * instantiated to perform dragging.\r
678 *\r
679 * For example to create a Component which may only be dragged around using a certain internal element as the drag\r
680 * handle, use the delegate option:\r
681 *\r
682 * new Ext.Component({\r
683 * constrain: true,\r
684 * floating: true,\r
685 * style: {\r
686 * backgroundColor: '#fff',\r
687 * border: '1px solid black'\r
688 * },\r
689 * html: '<h1 style="cursor:move">The title</h1><p>The content</p>',\r
690 * draggable: {\r
691 * delegate: 'h1'\r
692 * }\r
693 * }).show();\r
694 */\r
695 draggable: false,\r
696\r
697 /**\r
698 * @cfg {Number} flex\r
699 * Flex may be applied to **child items** of a box layout ({@link Ext.layout.container.VBox vbox} or \r
700 * {@link Ext.layout.container.HBox hbox}). Each child item with a flex property will \r
701 * fill space (horizontally in `hbox`, vertically in `vbox`) according to that item's\r
702 * **relative** flex value compared to the sum of all items with a flex value specified. \r
703 * \r
704 * Any child items that have either a `flex` of `0` or `undefined` \r
705 * will not be 'flexed' (the initial size will not be changed).\r
706 */\r
707\r
708 /**\r
709 * @cfg {Boolean} floating\r
710 * Specify as true to float the Component outside of the document flow using CSS absolute positioning.\r
711 *\r
712 * Components such as {@link Ext.window.Window Window}s and {@link Ext.menu.Menu Menu}s are floating by default.\r
713 *\r
714 * Floating Components that are programmatically {@link Ext.Component#method-render rendered} will register\r
715 * themselves with the global {@link Ext.WindowManager ZIndexManager}\r
716 *\r
717 * ### Floating Components as child items of a Container\r
718 *\r
719 * A floating Component may be used as a child item of a Container. This just allows the floating Component to seek\r
720 * a ZIndexManager by examining the ownerCt chain.\r
721 *\r
722 * When configured as floating, Components acquire, at render time, a {@link Ext.ZIndexManager ZIndexManager} which\r
723 * manages a stack of related floating Components. The ZIndexManager sorts its stack according to\r
724 * an incrementing access counter and the {@link Ext.util.Floating#alwaysOnTop alwaysOnTop} config when the Component's {@link #toFront} method is called.\r
725 *\r
726 * The ZIndexManager is found by traversing up the {@link #ownerCt} chain to find an ancestor which itself is\r
727 * floating. This is so that descendant floating Components of floating _Containers_ (Such as a ComboBox dropdown\r
728 * within a Window) can have its zIndex managed relative to any siblings, but always **above** that floating\r
729 * ancestor Container.\r
730 *\r
731 * If no floating ancestor is found, a floating Component registers itself with the default {@link Ext.WindowManager\r
732 * ZIndexManager}.\r
733 *\r
734 * Floating components _do not participate in the Container's layout_. Because of this, they are not rendered until\r
735 * you explicitly {@link #method-show} them.\r
736 *\r
737 * After rendering, the ownerCt reference is deleted, and the {@link #floatParent} property is set to the found\r
738 * floating ancestor Container. If no floating ancestor Container was found the {@link #floatParent} property will\r
739 * not be set.\r
740 */\r
741 floating: false,\r
742\r
743 /**\r
744 * @cfg {Boolean} [formBind=false]\r
745 * When inside FormPanel, any component configured with `formBind: true` will\r
746 * be enabled/disabled depending on the validity state of the form.\r
747 * See {@link Ext.form.Panel} for more information and example.\r
748 */\r
749\r
750 /**\r
751 * @cfg {Boolean} frame\r
752 * Specify as `true` to have the Component inject framing elements within the Component at render time to provide a\r
753 * graphical rounded frame around the Component content.\r
754 *\r
755 * This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet\r
756 * Explorer prior to version 9 which do not support rounded corners natively.\r
757 *\r
758 * The extra space taken up by this framing is available from the read only property {@link #frameSize}.\r
759 */\r
760\r
761 /**\r
762 * @cfg {Number|String} height\r
763 * The height of this component. A numeric value will be interpreted as the number of\r
764 * pixels; a string value will be treated as a CSS value with units.\r
765 */\r
766\r
767 /**\r
768 * @cfg {Boolean} hidden\r
769 * `true` to hide the component.\r
770 * @since 2.3.0\r
771 */\r
772 hidden: false,\r
773\r
774 /**\r
775 * @cfg {String} hideMode\r
776 * A String which specifies how this Component's encapsulating DOM element will be hidden. Values may be:\r
777 *\r
778 * - `'display'` : The Component will be hidden using the `display: none` style.\r
779 * - `'visibility'` : The Component will be hidden using the `visibility: hidden` style.\r
780 * - `'offsets'` : The Component will be hidden by absolutely positioning it out of the visible area of the document.\r
781 * This is useful when a hidden Component must maintain measurable dimensions. Hiding using `display` results in a\r
782 * Component having zero dimensions.\r
783 *\r
784 * @since 1.1.0\r
785 */\r
786 hideMode: 'display',\r
787\r
788 /**\r
789 * @cfg {String/Object} [html='']\r
790 * An HTML fragment, or a {@link Ext.dom.Helper DomHelper} specification to use as the layout element content.\r
791 * The HTML content is added after the component is rendered, so the document will not contain this HTML at the time\r
792 * the {@link #event-render} event is fired. This content is inserted into the body _before_ any configured {@link #contentEl}\r
793 * is appended.\r
794 *\r
795 * @since 3.4.0\r
796 */\r
797\r
798 /**\r
799 * @cfg {String} id\r
800 * The **unique** id of this component instance.\r
801 *\r
802 * Use of this config should be considered carefully as this value must be unique across\r
803 * all existing components. Components created with an `id` may be accessed globally\r
804 * using {@link Ext#getCmp Ext.getCmp}.\r
805 *\r
806 * Instead of using assigned ids, consider a {@link #reference} config and a {@link #cfg-controller ViewController}\r
807 * to respond to events and perform processing upon this Component.\r
808 *\r
809 * Alternatively, {@link #itemId} and {@link Ext.ComponentQuery ComponentQuery} can be\r
810 * used to perform selector-based searching for Components analogous to DOM querying.\r
811 * The {@link Ext.container.Container Container} class contains several helpful\r
812 * {@link Ext.container.Container#down shortcut methods} to query its descendant\r
813 * Components by selector.\r
814 *\r
815 * Note that this `id` will also be used as the element id for the containing HTML\r
816 * element that is rendered to the page for this component. This allows you to write\r
817 * id-based CSS rules to style the specific instance of this component uniquely, and\r
818 * also to select sub-elements using this component's `id` as the parent.\r
819 *\r
820 * Defaults to an {@link #getId auto-assigned id}.\r
821 *\r
822 * **Note**: Valid identifiers start with a letter or underscore and are followed by\r
823 * (optional) additional letters, underscores, digits or hyphens.\r
824 *\r
825 * @since 1.1.0\r
826 */\r
827\r
828 /**\r
829 * @cfg {String} itemId\r
830 * The **unique** id of this component instance within its container. See also the\r
831 * {@link #reference} config.\r
832 *\r
833 * An `itemId` can be used as an alternative way to get a reference to a component when no object reference is\r
834 * available. Instead of using an `{@link #id}` with {@link Ext#getCmp getCmp}, use\r
835 * `itemId` with {@link Ext.container.Container#getComponent getComponent} which will\r
836 * retrieve `itemId`'s or {@link #id}'s. Since `itemId`'s are an index to the container's\r
837 * internal collection, the `itemId` is scoped locally to the container -- avoiding\r
838 * potential conflicts with {@link Ext.ComponentManager} which requires a **unique**\r
839 * `{@link #id}` values.\r
840 *\r
841 * var c = new Ext.panel.Panel({ //\r
842 * {@link Ext.Component#height height}: 300,\r
843 * {@link #renderTo}: document.body,\r
844 * {@link Ext.container.Container#layout layout}: 'auto',\r
845 * {@link Ext.container.Container#cfg-items items}: [\r
846 * {\r
847 * itemId: 'p1',\r
848 * {@link Ext.panel.Panel#title title}: 'Panel 1',\r
849 * {@link Ext.Component#height height}: 150\r
850 * },\r
851 * {\r
852 * itemId: 'p2',\r
853 * {@link Ext.panel.Panel#title title}: 'Panel 2',\r
854 * {@link Ext.Component#height height}: 150\r
855 * }\r
856 * ]\r
857 * })\r
858 * p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}\r
859 * p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling\r
860 *\r
861 * Also see {@link #id}, `{@link Ext.container.Container#query}`, `{@link Ext.container.Container#down}` and\r
862 * `{@link Ext.container.Container#child}`.\r
863 *\r
864 * **Note**: Valid identifiers start with a letter or underscore and are followed by\r
865 * (optional) additional letters, underscores, digits or hyphens.\r
866 *\r
867 * **Note**: to access the container of an item see {@link #ownerCt}.\r
868 *\r
869 * @since 3.4.0\r
870 */\r
871\r
872 /**\r
873 * @cfg {Ext.ComponentLoader/Object} loader\r
874 * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote content\r
875 * for this Component.\r
876 *\r
877 * Ext.create('Ext.Component', {\r
878 * loader: {\r
879 * url: 'content.html',\r
880 * autoLoad: true\r
881 * },\r
882 * renderTo: Ext.getBody()\r
883 * });\r
884 */\r
885\r
886 /**\r
887 * @cfg {Number/String} margin\r
888 * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or it can\r
889 * be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).\r
890 */\r
891\r
892 /**\r
893 * @cfg {String} [maskElement=null]\r
894 * Related to the {@link #cfg-childEls} configuration which specifies named properties which correspond to component sub-elements.\r
895 *\r
896 * The name of the element property in this component to mask when masked by a LoadMask.\r
897 *\r
898 * Defaults to `null` to indicate that Components cannot by default contain a LoadMask, and that any LoadMask should be rendered into the document body.\r
899 *\r
900 * For example, Panels use `"el"` to indicate that the whole panel should be masked. This could be configured to be\r
901 * `"body"` so that only the body is masked and toolbars and the header are still mouse-accessible.\r
902 */\r
903 maskElement: null,\r
904\r
905 /**\r
906 * @cfg {String} [overCls='']\r
907 * An optional extra CSS class that will be added to this component's Element when the mouse moves over the Element,\r
908 * and removed when the mouse moves out. This can be useful for adding customized 'active' or 'hover' styles to the\r
909 * component or any of its children using standard CSS rules.\r
910 *\r
911 * @since 2.3.0\r
912 */\r
913\r
914 /**\r
915 * @cfg {String} overflowX\r
916 * Possible values are:\r
917 *\r
918 * - `'auto'` to enable automatic horizontal scrollbar (Style overflow-x: 'auto').\r
919 * - `'scroll'` to always enable horizontal scrollbar (Style overflow-x: 'scroll').\r
920 *\r
921 * The default is overflow-x: 'hidden'. This should not be combined with {@link #autoScroll}.\r
922 * @deprecated 5.1.0 Use {@link #scrollable} instead\r
923 */\r
924\r
925 /**\r
926 * @cfg {String} overflowY\r
927 * Possible values are:\r
928 *\r
929 * - `'auto'` to enable automatic vertical scrollbar (Style overflow-y: 'auto').\r
930 * - `'scroll'` to always enable vertical scrollbar (Style overflow-y: 'scroll').\r
931 *\r
932 * The default is overflow-y: 'hidden'. This should not be combined with {@link #autoScroll}.\r
933 * @deprecated 5.1.0 Use {@link #scrollable} instead\r
934 */\r
935\r
936 /**\r
937 * @cfg {Number/String} padding\r
938 * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or it\r
939 * can be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).\r
940 */\r
941\r
942 /**\r
943 * @cfg {Ext.plugin.Abstract[]/Ext.plugin.Abstract/Object[]/Object/Ext.enums.Plugin[]/Ext.enums.Plugin} plugins\r
944 * An array of plugins to be added to this component. Can also be just a single plugin instead of array.\r
945 *\r
946 * Plugins provide custom functionality for a component. The only requirement for\r
947 * a valid plugin is that it contain an `init` method that accepts a reference of type Ext.Component. When a component\r
948 * is created, if any plugins are available, the component will call the init method on each plugin, passing a\r
949 * reference to itself. Each plugin can then call methods or respond to events on the component as needed to provide\r
950 * its functionality.\r
951 *\r
952 * Plugins can be added to component by either directly referencing the plugin instance:\r
953 *\r
954 * plugins: [Ext.create('Ext.grid.plugin.CellEditing', {clicksToEdit: 1})],\r
955 *\r
956 * By using config object with ptype:\r
957 *\r
958 * plugins: {ptype: 'cellediting', clicksToEdit: 1},\r
959 *\r
960 * Or with just a ptype:\r
961 *\r
962 * plugins: ['cellediting', 'gridviewdragdrop'],\r
963 *\r
964 * See {@link Ext.enums.Plugin} for list of all ptypes.\r
965 *\r
966 * @since 2.3.0\r
967 */\r
968\r
969 /**\r
970 * @cfg {"north"/"south"/"east"/"west"/"center"} [region=undefined]\r
971 * Defines the region inside {@link Ext.layout.container.Border border layout}.\r
972 *\r
973 * Possible values:\r
974 *\r
975 * - north - Positions component at top.\r
976 * - south - Positions component at bottom.\r
977 * - east - Positions component at right.\r
978 * - west - Positions component at left.\r
979 * - center - Positions component at the remaining space.\r
980 * There **must** be a component with `region: "center"` in every border layout.\r
981 */\r
982\r
983 /**\r
984 * @cfg {Object} renderData\r
985 *\r
986 * The data used by {@link #renderTpl} in addition to the following property values of the component:\r
987 *\r
988 * - id\r
989 * - ui\r
990 * - uiCls\r
991 * - baseCls\r
992 * - componentCls\r
993 * - frame\r
994 *\r
995 * See {@link #renderSelectors} and {@link #cfg-childEls} for usage examples.\r
996 */\r
997\r
998 /**\r
999 * @cfg {Object} renderSelectors\r
1000 * An object containing properties specifying CSS selectors which identify child elements\r
1001 * created by the render process.\r
1002 *\r
1003 * After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,\r
1004 * and the found Elements are added as properties to the Component using the `renderSelector` property name.\r
1005 *\r
1006 * For example, a Component which renders a title and description into its element:\r
1007 *\r
1008 * Ext.create('Ext.Component', {\r
1009 * renderTo: Ext.getBody(),\r
1010 * renderTpl: [\r
1011 * '<h1 class="title">{title}</h1>',\r
1012 * '<p>{desc}</p>'\r
1013 * ],\r
1014 * renderData: {\r
1015 * title: "Error",\r
1016 * desc: "Something went wrong"\r
1017 * },\r
1018 * renderSelectors: {\r
1019 * titleEl: 'h1.title',\r
1020 * descEl: 'p'\r
1021 * },\r
1022 * listeners: {\r
1023 * afterrender: function(cmp){\r
1024 * // After rendering the component will have a titleEl and descEl properties\r
1025 * cmp.titleEl.setStyle({color: "red"});\r
1026 * }\r
1027 * }\r
1028 * });\r
1029 *\r
1030 * The use of `renderSelectors` is deprecated (for performance reasons). The above\r
1031 * code should be refactored into something like this:\r
1032 *\r
1033 * Ext.create('Ext.Component', {\r
1034 * renderTo: Ext.getBody(),\r
1035 * renderTpl: [\r
1036 * '<h1 class="title" id="{id}-titleEl" data-ref="titleEl">{title}</h1>',\r
1037 * '<p id="{id}-descEl" data-ref="descEl">{desc}</p>'\r
1038 * ],\r
1039 * renderData: {\r
1040 * title: "Error",\r
1041 * desc: "Something went wrong"\r
1042 * },\r
1043 * childEls: [\r
1044 * 'titleEl',\r
1045 * 'descEl'\r
1046 * ]\r
1047 * });\r
1048 *\r
1049 * To use `childEls` yet retain the use of selectors (which remains as expensive as\r
1050 * `renderSelectors`):\r
1051 *\r
1052 * Ext.create('Ext.Component', {\r
1053 * renderTo: Ext.getBody(),\r
1054 * renderTpl: [\r
1055 * '<h1 class="title">{title}</h1>',\r
1056 * '<p>{desc}</p>'\r
1057 * ],\r
1058 * renderData: {\r
1059 * title: "Error",\r
1060 * desc: "Something went wrong"\r
1061 * },\r
1062 * childEls: {\r
1063 * titleEl: { selectNode: 'h1.title' },\r
1064 * descEl: { selectNode: 'p' }\r
1065 * }\r
1066 * });\r
1067 *\r
1068 * @deprecated 5.0 Use {@link #cfg-childEls} instead.\r
1069 */\r
1070\r
1071 /**\r
1072 * @cfg {String/HTMLElement/Ext.dom.Element} renderTo\r
1073 * Specify the `id` of the element, a DOM element or an existing Element that this component will be rendered into.\r
1074 *\r
1075 * **Notes:**\r
1076 *\r
1077 * Do *not* use this option if the Component is to be a child item of a {@link Ext.container.Container Container}.\r
1078 * It is the responsibility of the {@link Ext.container.Container Container}'s\r
1079 * {@link Ext.container.Container#layout layout manager} to render and manage its child items.\r
1080 *\r
1081 * When using this config, a call to `render()` is not required.\r
1082 *\r
1083 * See also: {@link #method-render}.\r
1084 *\r
1085 * @since 2.3.0\r
1086 */\r
1087\r
1088 /**\r
1089 * @cfg {Ext.XTemplate/String/String[]} renderTpl\r
1090 * An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's encapsulating\r
1091 * {@link #getEl Element}.\r
1092 *\r
1093 * You do not normally need to specify this. For the base classes {@link Ext.Component} and\r
1094 * {@link Ext.container.Container}, this defaults to **`null`** which means that they will be initially rendered\r
1095 * with no internal structure; they render their {@link #getEl Element} empty. The more specialized\r
1096 * classes with complex DOM structures provide their own template definitions.\r
1097 *\r
1098 * This is intended to allow the developer to create application-specific utility Components with customized\r
1099 * internal structure.\r
1100 *\r
1101 * Upon rendering, any created child elements may be automatically imported into object properties using the\r
1102 * {@link #renderSelectors} and {@link #cfg-childEls} options.\r
1103 * @protected\r
1104 */\r
1105 renderTpl: [\r
1106 '<tpl if="renderScroller">',\r
1107 '<div class="{scrollerCls}" style="{%this.renderPadding(out, values)%}">',\r
1108 '</tpl>',\r
1109 '{%this.renderContent(out,values)%}',\r
1110 '<tpl if="renderScroller"></div></tpl>'\r
1111 ],\r
1112\r
1113 /**\r
1114 * @cfg {Boolean/Object} resizable\r
1115 * Specify as `true` to apply a {@link Ext.resizer.Resizer Resizer} to this Component after rendering.\r
1116 *\r
1117 * May also be specified as a config object to be passed to the constructor of {@link Ext.resizer.Resizer Resizer}\r
1118 * to override any defaults. By default the Component passes its minimum and maximum size, and uses\r
1119 * `{@link Ext.resizer.Resizer#dynamic}: false`\r
1120 */\r
1121\r
1122 /**\r
1123 * @cfg {String} resizeHandles\r
1124 * A valid {@link Ext.resizer.Resizer} handles config string. Only applies when resizable = true.\r
1125 */\r
1126 resizeHandles: 'all',\r
1127\r
1128 /**\r
1129 * @cfg {Boolean/Number} [shrinkWrap=2]\r
1130 *\r
1131 * The possible values for shrinkWrap are:\r
1132 *\r
1133 * - 0 (or `false`): Neither width nor height depend on content.\r
1134 * - 1: Width depends on content (shrink wraps), but height does not.\r
1135 * - 2: Height depends on content (shrink wraps), but width does not.\r
1136 * - 3 (or `true`): Both width and height depend on content (shrink wrap).\r
1137 *\r
1138 * In CSS terms, shrink-wrap width is analogous to an inline-block element as opposed\r
1139 * to a block-level element.\r
1140 * \r
1141 * @localdoc ##Non-Panel Components\r
1142 * \r
1143 * The shrinkWrap config is a class-level config and should be used when defining a \r
1144 * subclass.\r
1145 * It is not intended to be set as a config on instances of a given component.\r
1146 * \r
1147 * For non-Panel components, shrinkWrap is a descriptive config only. It should be \r
1148 * set when defining your own custom class including the DOM elements used to \r
1149 * construct the component. The shrinkWrap property does not itself apply styling on \r
1150 * the component elements. Rather, it should describe the CSS styling you've applied \r
1151 * to your custom component (_refer to the numeric matrix above_).\r
1152 * \r
1153 * When a component is owned by a container the layout of that container will inspect \r
1154 * the component's shrinkWrap property during layout. The layout then uses the \r
1155 * content-wrapping policy described by shrinkWrap to correctly size and position the \r
1156 * container's child items.\r
1157 */\r
1158 shrinkWrap: 2,\r
1159\r
1160 /**\r
1161 * @cfg stateEvents\r
1162 * @inheritdoc Ext.state.Stateful#cfg-stateEvents\r
1163 * @localdoc By default the following stateEvents are added:\r
1164 * \r
1165 * - {@link #event-resize}\r
1166 */\r
1167\r
1168 /**\r
1169 * @cfg {String/Object} style\r
1170 * A custom style specification to be applied to this component's Element. Should be a valid argument to\r
1171 * {@link Ext.dom.Element#applyStyles}.\r
1172 *\r
1173 * new Ext.panel.Panel({\r
1174 * title: 'Some Title',\r
1175 * renderTo: Ext.getBody(),\r
1176 * width: 400, height: 300,\r
1177 * layout: 'form',\r
1178 * items: [{\r
1179 * xtype: 'textarea',\r
1180 * style: {\r
1181 * width: '95%',\r
1182 * marginBottom: '10px'\r
1183 * }\r
1184 * },\r
1185 * new Ext.button.Button({\r
1186 * text: 'Send',\r
1187 * minWidth: '100',\r
1188 * style: {\r
1189 * marginBottom: '10px'\r
1190 * }\r
1191 * })\r
1192 * ]\r
1193 * });\r
1194 *\r
1195 * @since 1.1.0\r
1196 */\r
1197\r
1198 /**\r
1199 * @cfg {Boolean} toFrontOnShow\r
1200 * True to automatically call {@link #toFront} when the {@link #method-show} method is called on an already visible,\r
1201 * floating component.\r
1202 */\r
1203 toFrontOnShow: true,\r
1204\r
1205 /**\r
1206 * @cfg {Ext.XTemplate/Ext.Template/String/String[]} tpl\r
1207 * An {@link Ext.Template}, {@link Ext.XTemplate} or an array of strings to form an Ext.XTemplate. Used in\r
1208 * conjunction with the `{@link #data}` and `{@link #tplWriteMode}` configurations.\r
1209 *\r
1210 * @since 3.4.0\r
1211 */\r
1212\r
1213 /**\r
1214 * @property {Boolean} [synthetic=false]\r
1215 * This property is `true` if the component was created internally by the framework\r
1216 * and is not explicitly user-defined. This is set for such things as `Splitter`\r
1217 * instances managed by `border` and `box` layouts.\r
1218 * @private\r
1219 */\r
1220 synthetic: false,\r
1221\r
1222 /**\r
1223 * @cfg {String} tplWriteMode\r
1224 * The Ext.(X)Template method to use when updating the content area of the Component.\r
1225 * See `{@link Ext.XTemplate#overwrite}` for information on default mode.\r
1226 *\r
1227 * @since 3.4.0\r
1228 */\r
1229 tplWriteMode: 'overwrite',\r
1230\r
1231 /**\r
1232 * @cfg {String} ui\r
1233 * A UI style for a component.\r
1234 */\r
1235 ui: 'default',\r
1236\r
1237 /**\r
1238 * @cfg {String[]} uiCls\r
1239 * An array of of `classNames` which are currently applied to this component.\r
1240 * @private\r
1241 */\r
1242 uiCls: [],\r
1243\r
1244 /**\r
1245 * @cfg {String/String[]} userCls\r
1246 * One or more CSS classes to add to the component's primary element. This config\r
1247 * is intended solely for use by the component instantiator (the "user"), not by\r
1248 * derived classes.\r
1249 *\r
1250 * For example:\r
1251 *\r
1252 * items: [{\r
1253 * xtype: 'button',\r
1254 * userCls: 'my-button'\r
1255 * ...\r
1256 * }]\r
1257 * @accessor\r
1258 */\r
1259 userCls: null,\r
1260\r
1261 /**\r
1262 * @cfg {Number} [weight]\r
1263 * A value to control how Components are laid out in a {@link Ext.layout.container.Border Border} layout or as docked items.\r
1264 *\r
1265 * In a Border layout, this can control how the regions (not the center) region lay out if the west or east take full height\r
1266 * or if the north or south region take full width. Also look at the {@link Ext.layout.container.Border#regionWeights} on the Border layout. An example to show how you can\r
1267 * take control of this is:\r
1268 *\r
1269 * Ext.create('Ext.container.Viewport', {\r
1270 * layout : 'border',\r
1271 * defaultType : 'panel',\r
1272 * items : [\r
1273 * {\r
1274 * region : 'north',\r
1275 * title : 'North',\r
1276 * height : 100\r
1277 * },\r
1278 * {\r
1279 * region : 'south',\r
1280 * title : 'South',\r
1281 * height : 100,\r
1282 * weight : -25\r
1283 * },\r
1284 * {\r
1285 * region : 'west',\r
1286 * title : 'West',\r
1287 * width : 200,\r
1288 * weight : 15\r
1289 * },\r
1290 * {\r
1291 * region : 'east',\r
1292 * title : 'East',\r
1293 * width : 200\r
1294 * },\r
1295 * {\r
1296 * region : 'center',\r
1297 * title : 'center'\r
1298 * }\r
1299 * ]\r
1300 * });\r
1301 *\r
1302 * If docked items, the weight will order how the items are laid out. Here is an example to put a {@link Ext.toolbar.Toolbar} above\r
1303 * a {@link Ext.panel.Panel}'s header:\r
1304 *\r
1305 * Ext.create('Ext.panel.Panel', {\r
1306 * renderTo : document.body,\r
1307 * width : 300,\r
1308 * height : 300,\r
1309 * title : 'Panel',\r
1310 * html : 'Panel Body',\r
1311 * dockedItems : [\r
1312 * {\r
1313 * xtype : 'toolbar',\r
1314 * items : [\r
1315 * {\r
1316 * text : 'Save'\r
1317 * }\r
1318 * ]\r
1319 * },\r
1320 * {\r
1321 * xtype : 'toolbar',\r
1322 * weight : -10,\r
1323 * items : [\r
1324 * {\r
1325 * text : 'Remove'\r
1326 * }\r
1327 * ]\r
1328 * }\r
1329 * ]\r
1330 * });\r
1331 */\r
1332 weight: null,\r
1333\r
1334 /**\r
1335 * @cfg {Number|String} width\r
1336 * The width of this component. A numeric value will be interpreted as the number of\r
1337 * pixels; a string value will be treated as a CSS value with units.\r
1338 */\r
1339\r
1340 /**\r
1341 * @cfg {Ext.enums.Widget} xtype\r
1342 * **Note:** Only applies to {@link Ext.Component} derived classes when used as \r
1343 * a config in {@link Ext#define Ext.define}.\r
1344 * \r
1345 * This property provides a shorter alternative to creating objects than using a full\r
1346 * class name. Using `xtype` is the most common way to define component instances,\r
1347 * especially in a container. For example, the items in a form containing text fields\r
1348 * could be created explicitly like so:\r
1349 *\r
1350 * items: [\r
1351 * Ext.create('Ext.form.field.Text', {\r
1352 * fieldLabel: 'Foo'\r
1353 * }),\r
1354 * Ext.create('Ext.form.field.Text', {\r
1355 * fieldLabel: 'Bar'\r
1356 * }),\r
1357 * Ext.create('Ext.form.field.Number', {\r
1358 * fieldLabel: 'Num'\r
1359 * })\r
1360 * ]\r
1361 *\r
1362 * But by using `xtype`, the above becomes:\r
1363 *\r
1364 * items: [\r
1365 * {\r
1366 * xtype: 'textfield',\r
1367 * fieldLabel: 'Foo'\r
1368 * },\r
1369 * {\r
1370 * xtype: 'textfield',\r
1371 * fieldLabel: 'Bar'\r
1372 * },\r
1373 * {\r
1374 * xtype: 'numberfield',\r
1375 * fieldLabel: 'Num'\r
1376 * }\r
1377 * ]\r
1378 *\r
1379 * When the `xtype` is common to many items, {@link Ext.container.Container#defaultType}\r
1380 * is another way to specify the `xtype` for all items that don't have an explicit `xtype`:\r
1381 *\r
1382 * defaultType: 'textfield',\r
1383 * items: [\r
1384 * { fieldLabel: 'Foo' },\r
1385 * { fieldLabel: 'Bar' },\r
1386 * { fieldLabel: 'Num', xtype: 'numberfield' }\r
1387 * ]\r
1388 *\r
1389 * Each member of the `items` array is now just a "configuration object". These objects\r
1390 * are used to create and configure component instances. A configuration object can be\r
1391 * manually used to instantiate a component using {@link Ext#widget}:\r
1392 *\r
1393 * var text1 = Ext.create('Ext.form.field.Text', {\r
1394 * fieldLabel: 'Foo'\r
1395 * });\r
1396 *\r
1397 * // or alternatively:\r
1398 *\r
1399 * var text1 = Ext.widget({\r
1400 * xtype: 'textfield',\r
1401 * fieldLabel: 'Foo'\r
1402 * });\r
1403 *\r
1404 * This conversion of configuration objects into instantiated components is done when\r
1405 * a container is created as part of its {Ext.container.AbstractContainer#initComponent}\r
1406 * process. As part of the same process, the `items` array is converted from its raw\r
1407 * array form into a {@link Ext.util.MixedCollection} instance.\r
1408 *\r
1409 * You can define your own `xtype` on a custom {@link Ext.Component component} by specifying\r
1410 * the `xtype` property in {@link Ext#define}. For example:\r
1411 *\r
1412 * Ext.define('MyApp.PressMeButton', {\r
1413 * extend: 'Ext.button.Button',\r
1414 * xtype: 'pressmebutton',\r
1415 * text: 'Press Me'\r
1416 * });\r
1417 *\r
1418 * Care should be taken when naming an `xtype` in a custom component because there is\r
1419 * a single, shared scope for all xtypes. Third part components should consider using\r
1420 * a prefix to avoid collisions.\r
1421 *\r
1422 * Ext.define('Foo.form.CoolButton', {\r
1423 * extend: 'Ext.button.Button',\r
1424 * xtype: 'ux-coolbutton',\r
1425 * text: 'Cool!'\r
1426 * });\r
1427 *\r
1428 * See {@link Ext.enums.Widget} for list of all available xtypes.\r
1429 *\r
1430 * @since 2.3.0\r
1431 */\r
1432\r
1433 // ***********************************************************************************\r
1434 // End Config\r
1435 // ***********************************************************************************\r
1436 // </editor-fold>\r
1437\r
1438 // <editor-fold desc="Properties">\r
1439 // ***********************************************************************************\r
1440 // Begin Properties\r
1441 // ***********************************************************************************\r
1442\r
1443 /**\r
1444 * @private\r
1445 */\r
1446 allowDomMove: true,\r
1447\r
1448 /**\r
1449 * @property {Boolean} autoGenId\r
1450 * `true` indicates an `id` was auto-generated rather than provided by configuration.\r
1451 * @private\r
1452 */\r
1453 autoGenId: false,\r
1454\r
1455 /**\r
1456 * @private\r
1457 */\r
1458 borderBoxCls: Ext.baseCSSPrefix + 'border-box',\r
1459\r
1460 /**\r
1461 * @property {Number} componentLayoutCounter\r
1462 * @private\r
1463 * The number of component layout calls made on this object.\r
1464 */\r
1465 componentLayoutCounter: 0,\r
1466\r
1467 /**\r
1468 * @property {String} [contentPaddingProperty='padding']\r
1469 * The name of the padding property that is used by the layout to manage\r
1470 * padding. See {@link Ext.layout.container.Auto#managePadding managePadding}\r
1471 */ \r
1472 contentPaddingProperty: 'padding',\r
1473\r
1474 /**\r
1475 * @private\r
1476 */\r
1477 deferLayouts: false,\r
1478\r
1479 /**\r
1480 * @property {Ext.Container} floatParent\r
1481 * **Only present for {@link #cfg-floating} Components which were inserted as child items of Containers.**\r
1482 *\r
1483 * There are other similar relationships such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the\r
1484 * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the\r
1485 * {@link Ext.grid.column.Column column header} which activated the column menu.\r
1486 *\r
1487 * These differences are abstracted away by the {@link #up} method.\r
1488 *\r
1489 * Floating Components that are programmatically {@link Ext.Component#method-render rendered} will not have a `floatParent`\r
1490 * property.\r
1491 *\r
1492 * See {@link #cfg-floating} and {@link #zIndexManager}\r
1493 * @readonly\r
1494 */\r
1495\r
1496 /**\r
1497 * @property {Object} frameSize\r
1498 * @readonly\r
1499 * Indicates the width of any framing elements which were added within the encapsulating\r
1500 * element to provide graphical, rounded borders. See the {@link #frame} config. This\r
1501 * property is `null` if the component is not framed.\r
1502 *\r
1503 * This is an object containing the frame width in pixels for all four sides of the\r
1504 * Component containing the following properties:\r
1505 *\r
1506 * @property {Number} [frameSize.top=0] The width of the top framing element in pixels.\r
1507 * @property {Number} [frameSize.right=0] The width of the right framing element in pixels.\r
1508 * @property {Number} [frameSize.bottom=0] The width of the bottom framing element in pixels.\r
1509 * @property {Number} [frameSize.left=0] The width of the left framing element in pixels.\r
1510 * @property {Number} [frameSize.width=0] The total width of the left and right framing elements in pixels.\r
1511 * @property {Number} [frameSize.height=0] The total height of the top and right bottom elements in pixels.\r
1512 */\r
1513 frameSize: null,\r
1514\r
1515 /**\r
1516 * @private\r
1517 */\r
1518 horizontalPosProp: 'left',\r
1519\r
1520 /**\r
1521 * @property {Boolean} isComponent\r
1522 * `true` in this class to identify an object as an instantiated Component, or subclass thereof.\r
1523 */\r
1524 isComponent: true,\r
1525 \r
1526 /**\r
1527 * @property {Boolean} [_isLayoutRoot=false]\r
1528 * Setting this property to `true` causes the {@link #isLayoutRoot} method to return\r
1529 * `true` and stop the search for the top-most component for a layout.\r
1530 * @protected\r
1531 */\r
1532 _isLayoutRoot: false,\r
1533\r
1534 /**\r
1535 * @private\r
1536 */\r
1537 layoutSuspendCount: 0,\r
1538\r
1539 /**\r
1540 * @cfg {Boolean}\r
1541 * Components that achieve their internal layout results using solely CSS with no JS\r
1542 * intervention must set this to true. This allows the component to opt out of the\r
1543 * layout run when used inside certain container layouts such as {@link \r
1544 * Ext.layout.container.Form Form} and {@link Ext.layout.container.Auto Auto}\r
1545 * resulting in a performance gain. The following components currently use liquid\r
1546 * layout (`liquidLayout: true`):\r
1547 * \r
1548 * - All Form Fields (subclasses of {@link Ext.form.field.Base})\r
1549 * - {@link Ext.button.Button}\r
1550 * \r
1551 * It is important to keep in mind that components using liquidLayout do not fire\r
1552 * the following events:\r
1553 * \r
1554 * - {@link #event-resize}\r
1555 * - {@link #event-boxready}\r
1556 * \r
1557 * In addition liquidLayout components do not call the following template methods:\r
1558 * \r
1559 * - {@link #afterComponentLayout}\r
1560 * - {@link #onBoxReady}\r
1561 * - {@link #onResize}\r
1562 * \r
1563 * Any component that needs to fire these events or to have these methods called during\r
1564 * its life cycle needs to set `liquidLayout` to `false`. The following example\r
1565 * demonstrates how to enable the resize event for a\r
1566 * {@link Ext.form.field.TextArea TextArea Field}:\r
1567 * \r
1568 * @example\r
1569 * var win = Ext.create({\r
1570 * xtype: 'window',\r
1571 * title: 'Resize This Window!',\r
1572 * height: 100,\r
1573 * width: 200,\r
1574 * layout: 'anchor',\r
1575 * items: [{\r
1576 * xtype: 'textarea',\r
1577 * anchor: '0 0',\r
1578 * liquidLayout: false // allows the textarea to fire "resize"\r
1579 * }]\r
1580 * }),\r
1581 * textfield = win.items.getAt(0);\r
1582 *\r
1583 * win.show();\r
1584 *\r
1585 * textfield.on('resize', function(textfield, width, height) {\r
1586 * Ext.Msg.alert('Text Field Resized', 'width: ' + width + ', height: ' + height);\r
1587 * });\r
1588 * \r
1589 * Use caution when setting `liquidLayout` to `false` as it carries a performance penalty\r
1590 * since it means the layout system must perform expensive DOM reads to determine the\r
1591 * Component's size.\r
1592 */\r
1593 liquidLayout: false,\r
1594\r
1595 /**\r
1596 * @property {Boolean} maskOnDisable\r
1597 * This is an internal flag that you use when creating custom components. By default this is set to `true` which means\r
1598 * that every component gets a mask when it's disabled. Components like FieldContainer, FieldSet, Field, Button, Tab\r
1599 * override this property to `false` since they want to implement custom disable logic.\r
1600 */\r
1601 maskOnDisable: true,\r
1602\r
1603 /**\r
1604 * @private\r
1605 */\r
1606 offsetsCls: Ext.baseCSSPrefix + 'hidden-offsets',\r
1607\r
1608 /**\r
1609 * @property {Ext.Container} ownerCt\r
1610 * This Component's owner {@link Ext.container.Container Container} (is set automatically\r
1611 * when this Component is added to a Container).\r
1612 *\r
1613 * *Important.* This is not a universal upwards navigation pointer. It indicates the Container which owns and manages\r
1614 * this Component if any. There are other similar relationships such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the\r
1615 * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the\r
1616 * {@link Ext.grid.column.Column column header} which activated the column menu.\r
1617 *\r
1618 * These differences are abstracted away by the {@link #up} method.\r
1619 *\r
1620 * **Note**: to access items within the Container see {@link #itemId}.\r
1621 * @readonly\r
1622 * @since 2.3.0\r
1623 */\r
1624\r
1625 /**\r
1626 * @property {Boolean} rendered\r
1627 * Indicates whether or not the component has been rendered.\r
1628 * @readonly\r
1629 * @since 1.1.0\r
1630 */\r
1631 rendered: false,\r
1632\r
1633 /**\r
1634 * @private\r
1635 */\r
1636 rootCls: Ext.baseCSSPrefix + 'body',\r
1637\r
1638 /**\r
1639 * @private\r
1640 */\r
1641 scrollerCls: Ext.baseCSSPrefix + 'scroll-scroller',\r
1642 scrollerSelector: '.' + Ext.baseCSSPrefix + 'scroll-scroller',\r
1643\r
1644 /**\r
1645 * @property {Object} scrollFlags\r
1646 * An object property which provides unified information as to which dimensions are\r
1647 * scrollable based upon the {@link #scrollable} settings (And for *views* of trees and\r
1648 * grids, the owning panel's {@link Ext.panel.Table#scroll scroll} setting).\r
1649 *\r
1650 * Note that if you set overflow styles using the {@link #style} config or\r
1651 * {@link Ext.panel.Panel#bodyStyle bodyStyle} config, this object does not include\r
1652 * that information. Use {@link #scrollable} if you need to access these flags.\r
1653 *\r
1654 * This object has the following properties:\r
1655 * @property {Boolean} scrollFlags.x `true` if this Component is scrollable\r
1656 * horizontally - style setting may be `'auto'` or `'scroll'`.\r
1657 * @property {Boolean} scrollFlags.y `true` if this Component is scrollable\r
1658 * vertically - style setting may be `'auto'` or `'scroll'`.\r
1659 * @property {Boolean} scrollFlags.both `true` if this Component is scrollable both\r
1660 * horizontally and vertically.\r
1661 * @property {String} scrollFlags.overflowX The `overflow-x` style setting, `'auto'`\r
1662 * or `'scroll'` or `''`.\r
1663 * @property {String} scrollFlags.overflowY The `overflow-y` style setting, `'auto'`\r
1664 * or `'scroll'` or `''`.\r
1665 * @readonly\r
1666 * @private\r
1667 */\r
1668 _scrollFlags: {\r
1669 auto: {\r
1670 // x:auto, y:auto\r
1671 auto: {\r
1672 overflowX: 'auto',\r
1673 overflowY: 'auto',\r
1674 x: true,\r
1675 y: true,\r
1676 both: true\r
1677 },\r
1678 // x:auto, y:false\r
1679 'false': {\r
1680 overflowX: 'auto',\r
1681 overflowY: 'hidden',\r
1682 x: true,\r
1683 y: false,\r
1684 both: false\r
1685 },\r
1686 // x:auto, y:scroll\r
1687 scroll: {\r
1688 overflowX: 'auto',\r
1689 overflowY: 'scroll',\r
1690 x: true,\r
1691 y: true,\r
1692 both: true\r
1693 }\r
1694 },\r
1695 'false': {\r
1696 // x:false, y:auto\r
1697 auto: {\r
1698 overflowX: 'hidden',\r
1699 overflowY: 'auto',\r
1700 x: false,\r
1701 y: true,\r
1702 both: false\r
1703 },\r
1704 // x:false, y:false\r
1705 'false': {\r
1706 overflowX: 'hidden',\r
1707 overflowY: 'hidden',\r
1708 x: false,\r
1709 y: false,\r
1710 both: false\r
1711 },\r
1712 // x:false, y:scroll\r
1713 scroll: {\r
1714 overflowX: 'hidden',\r
1715 overflowY: 'scroll',\r
1716 x: false,\r
1717 y: true,\r
1718 both: false\r
1719 }\r
1720 },\r
1721 scroll: {\r
1722 // x:scroll, y:auto\r
1723 auto: {\r
1724 overflowX: 'scroll',\r
1725 overflowY: 'auto',\r
1726 x: true,\r
1727 y: true,\r
1728 both: true\r
1729 },\r
1730 // x:scroll, y:false\r
1731 'false': {\r
1732 overflowX: 'scroll',\r
1733 overflowY: 'hidden',\r
1734 x: true,\r
1735 y: false,\r
1736 both: false\r
1737 },\r
1738 // x:scroll, y:scroll\r
1739 scroll: {\r
1740 overflowX: 'scroll',\r
1741 overflowY: 'scroll',\r
1742 x: true,\r
1743 y: true,\r
1744 both: true\r
1745 }\r
1746 },\r
1747 none: {\r
1748 overflowX: '',\r
1749 overflowY: '',\r
1750 x: false,\r
1751 y: false,\r
1752 both: false\r
1753 }\r
1754 },\r
1755\r
1756 _scrollableCfg: {\r
1757 x: {\r
1758 x: true,\r
1759 y: false\r
1760 },\r
1761 y: {\r
1762 x: false,\r
1763 y: true\r
1764 },\r
1765 horizontal: {\r
1766 x: true,\r
1767 y: false\r
1768 },\r
1769 vertical: {\r
1770 x: false,\r
1771 y: true\r
1772 },\r
1773 both: {\r
1774 x: true,\r
1775 y: true\r
1776 },\r
1777 'true': {\r
1778 x: true,\r
1779 y: true\r
1780 }\r
1781 },\r
1782\r
1783 validIdRe: Ext.validIdRe,\r
1784\r
1785 // ***********************************************************************************\r
1786 // End Properties\r
1787 // ***********************************************************************************\r
1788 // </editor-fold>\r
1789\r
1790 // <editor-fold desc="Events">\r
1791 // ***********************************************************************************\r
1792 // Begin Events\r
1793 // ***********************************************************************************\r
1794\r
1795 /**\r
1796 * @event afterlayoutanimation\r
1797 * This event first after a component's layout has been updated by a layout that\r
1798 * included animation (e.g., a {@link Ext.panel.Panel panel} in an\r
1799 * {@link Ext.layout.container.Accordion accordion} layout).\r
1800 * @param {Ext.Component} this\r
1801 * @since 6.0.0\r
1802 */\r
1803\r
1804 /**\r
1805 * @event beforeactivate\r
1806 * Fires before a Component has been visually activated. Returning `false` from an event listener can prevent\r
1807 * the activate from occurring.\r
1808 *\r
1809 * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}\r
1810 * that uses {@link Ext.layout.container.Card} as it's layout.\r
1811 * @param {Ext.Component} this\r
1812 */\r
1813\r
1814 /**\r
1815 * @event activate\r
1816 * Fires after a Component has been visually activated.\r
1817 *\r
1818 * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}\r
1819 * that uses {@link Ext.layout.container.Card} as it's layout or this Component is a floating Component.\r
1820 * @param {Ext.Component} this\r
1821 */\r
1822\r
1823 /**\r
1824 * @event beforedeactivate\r
1825 * Fires before a Component has been visually deactivated. Returning `false` from an event listener can\r
1826 * prevent the deactivate from occurring.\r
1827 *\r
1828 * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}\r
1829 * that uses {@link Ext.layout.container.Card} as it's layout.\r
1830 * @param {Ext.Component} this\r
1831 */\r
1832\r
1833 /**\r
1834 * @event deactivate\r
1835 * Fires after a Component has been visually deactivated.\r
1836 *\r
1837 * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}\r
1838 * that uses {@link Ext.layout.container.Card} as it's layout or this Component is a floating Component.\r
1839 * @param {Ext.Component} this\r
1840 */\r
1841\r
1842 /**\r
1843 * @event added\r
1844 * Fires after a Component had been added to a Container.\r
1845 * @param {Ext.Component} this\r
1846 * @param {Ext.container.Container} container Parent Container\r
1847 * @param {Number} pos position of Component\r
1848 * @since 3.4.0\r
1849 */\r
1850\r
1851 /**\r
1852 * @event disable\r
1853 * Fires after the component is disabled.\r
1854 * @param {Ext.Component} this\r
1855 * @since 1.1.0\r
1856 */\r
1857\r
1858 /**\r
1859 * @event enable\r
1860 * Fires after the component is enabled.\r
1861 * @param {Ext.Component} this\r
1862 * @since 1.1.0\r
1863 */\r
1864\r
1865 /**\r
1866 * @event beforeshow\r
1867 * Fires before the component is shown when calling the {@link Ext.Component#method-show show} method. Return `false` from an event\r
1868 * handler to stop the show.\r
1869 * @param {Ext.Component} this\r
1870 * @since 1.1.0\r
1871 */\r
1872\r
1873 /**\r
1874 * @event show\r
1875 * Fires after the component is shown when calling the {@link Ext.Component#method-show show} method.\r
1876 * @param {Ext.Component} this\r
1877 * @since 1.1.0\r
1878 */\r
1879\r
1880 /**\r
1881 * @event beforehide\r
1882 * Fires before the component is hidden when calling the {@link Ext.Component#method-hide hide} method. Return `false` from an event\r
1883 * handler to stop the hide.\r
1884 * @param {Ext.Component} this\r
1885 * @since 1.1.0\r
1886 */\r
1887\r
1888 /**\r
1889 * @event hide\r
1890 * Fires after the component is hidden. Fires after the component is hidden when calling the {@link Ext.Component#method-hide hide}\r
1891 * method.\r
1892 * @param {Ext.Component} this\r
1893 * @since 1.1.0\r
1894 */\r
1895\r
1896 /**\r
1897 * @event removed\r
1898 * Fires when a component is removed from an Ext.container.Container\r
1899 * @param {Ext.Component} this\r
1900 * @param {Ext.container.Container} ownerCt Container which holds the component\r
1901 * @since 3.4.0\r
1902 */\r
1903\r
1904 /**\r
1905 * @event beforerender\r
1906 * Fires before the component is {@link #rendered}. Return `false` from an event handler to stop the\r
1907 * {@link #method-render}.\r
1908 * @param {Ext.Component} this\r
1909 * @since 1.1.0\r
1910 */\r
1911\r
1912 /**\r
1913 * @event render\r
1914 * Fires after the component markup is {@link #rendered}.\r
1915 * @param {Ext.Component} this\r
1916 * @since 1.1.0\r
1917 */\r
1918\r
1919 /**\r
1920 * @event afterrender\r
1921 * Fires after the component rendering is finished.\r
1922 *\r
1923 * The `afterrender` event is fired after this Component has been {@link #rendered}, been post-processed by any\r
1924 * `afterRender` method defined for the Component.\r
1925 * @param {Ext.Component} this\r
1926 * @since 3.4.0\r
1927 */\r
1928\r
1929 /**\r
1930 * @event boxready\r
1931 * Fires *one time* - after the component has been laid out for the first time at its initial size.\r
1932 *\r
1933 * This event does not fire on components that use {@link #liquidLayout}, such as\r
1934 * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.\r
1935 * @param {Ext.Component} this\r
1936 * @param {Number} width The initial width.\r
1937 * @param {Number} height The initial height.\r
1938 */\r
1939\r
1940 /**\r
1941 * @event beforedestroy\r
1942 * Fires before the component is {@link #method-destroy}ed. Return `false` from an event handler to stop the\r
1943 * {@link #method-destroy}.\r
1944 * @param {Ext.Component} this\r
1945 * @since 1.1.0\r
1946 */\r
1947\r
1948 /**\r
1949 * @event destroy\r
1950 * Fires after the component is {@link #method-destroy}ed.\r
1951 * @param {Ext.Component} this\r
1952 * @since 1.1.0\r
1953 */\r
1954\r
1955 /**\r
1956 * @event resize\r
1957 * Fires after the component is resized. Note that this does *not* fire when the component is first laid out at its initial\r
1958 * size. To hook that point in the life cycle, use the {@link #boxready} event.\r
1959 * \r
1960 * This event does not fire on components that use {@link #liquidLayout}, such as\r
1961 * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.\r
1962 * @param {Ext.Component} this\r
1963 * @param {Number} width The new width that was set.\r
1964 * @param {Number} height The new height that was set.\r
1965 * @param {Number} oldWidth The previous width.\r
1966 * @param {Number} oldHeight The previous height.\r
1967 */\r
1968\r
1969 /**\r
1970 * @event move\r
1971 * Fires after the component is moved.\r
1972 * @param {Ext.Component} this\r
1973 * @param {Number} x The new x position.\r
1974 * @param {Number} y The new y position.\r
1975 */\r
1976\r
1977 // ***********************************************************************************\r
1978 // End Events\r
1979 // ***********************************************************************************\r
1980 // </editor-fold>\r
1981\r
1982 /**\r
1983 * Creates new Component.\r
1984 * @param {Ext.dom.Element/String/Object} config The configuration options may be specified as either:\r
1985 *\r
1986 * - **an element** : it is set as the internal element and its id used as the component id\r
1987 * - **a string** : it is assumed to be the id of an existing element and is used as the component id\r
1988 * - **anything else** : it is assumed to be a standard config object and is applied to the component\r
1989 */\r
1990 constructor: function(config) {\r
1991 var me = this,\r
1992 i, len, xhooks, controller, autoScroll, overflowX, overflowY, scrollable;\r
1993\r
1994 config = config || {};\r
1995 if (config.initialConfig) {\r
1996\r
1997 // Being initialized from an Ext.Action instance...\r
1998 if (config.isAction) {\r
1999 me.baseAction = config;\r
2000 }\r
2001 config = config.initialConfig;\r
2002 // component cloning / action set up\r
2003 }\r
2004 else if (config.tagName || config.dom || Ext.isString(config)) {\r
2005 // element object\r
2006 config = {\r
2007 applyTo: config,\r
2008 id: config.id || config\r
2009 };\r
2010 }\r
2011\r
2012 // Make initialConfig available early so that config getters may access it\r
2013 /**\r
2014 * @property {Object} initialConfig\r
2015 * @readonly\r
2016 * The config object passed to the constructor during Component creation.\r
2017 */\r
2018 me.initialConfig = config;\r
2019\r
2020 // Ensure that we have an id early so that config getters may access it\r
2021 me.getId();\r
2022 me.protoEl = new Ext.util.ProtoElement();\r
2023 //<debug>\r
2024 me.$calledInitConfig = true;\r
2025 //</debug>\r
2026 me.initConfig(config);\r
2027 //<debug>\r
2028 delete me.$calledInitConfig;\r
2029 //</debug>\r
2030\r
2031 if (me.scrollable == null) {\r
2032 autoScroll = me.autoScroll;\r
2033\r
2034 if (autoScroll) {\r
2035 scrollable = !!autoScroll;\r
2036 } else {\r
2037 overflowX = me.overflowX;\r
2038 overflowY = me.overflowY;\r
2039\r
2040 if (overflowX || overflowY) {\r
2041 scrollable = {\r
2042 x: (overflowX && overflowX !== 'hidden') ? overflowX : false,\r
2043 y: (overflowY && overflowY !== 'hidden') ? overflowY : false\r
2044 };\r
2045 }\r
2046 }\r
2047\r
2048 if (scrollable) {\r
2049 me.setScrollable(scrollable);\r
2050 }\r
2051 }\r
2052\r
2053 xhooks = me.xhooks;\r
2054 if (xhooks) {\r
2055 delete me.xhooks;\r
2056 Ext.override(me, xhooks);\r
2057 }\r
2058\r
2059 me.mixins.elementCt.constructor.call(me);\r
2060\r
2061 //<debug>\r
2062 if (!me.validIdRe.test(me.id)) {\r
2063 Ext.raise('Invalid component "id": "' + me.id + '"');\r
2064 }\r
2065 if (!me.validIdRe.test(me.itemId)) {\r
2066 Ext.raise('Invalid component "itemId": "' + me.itemId + '"');\r
2067 }\r
2068 //</debug>\r
2069\r
2070 me.setupProtoEl();\r
2071\r
2072 // initComponent, beforeRender, or event handlers may have set the style or `cls` property since the `protoEl` was set up\r
2073 // so we must apply styles and classes here too.\r
2074 if (me.cls) {\r
2075 me.initialCls = me.cls;\r
2076 me.protoEl.addCls(me.cls);\r
2077 }\r
2078 if (me.style) {\r
2079 me.initialStyle = me.style;\r
2080 me.protoEl.setStyle(me.style);\r
2081 }\r
2082\r
2083 me.renderData = me.renderData || {};\r
2084\r
2085 me.initComponent();\r
2086\r
2087 // initComponent gets a chance to change the id property before registering\r
2088 if (!me.preventRegister) {\r
2089 Ext.ComponentManager.register(me);\r
2090 }\r
2091\r
2092 me.mixins.state.constructor.call(me);\r
2093 me.addStateEvents('resize');\r
2094\r
2095 controller = me.getController();\r
2096 if (controller) {\r
2097 controller.init(me);\r
2098 }\r
2099\r
2100 // Move this into Observable?\r
2101 if (me.plugins) {\r
2102 for (i = 0, len = me.plugins.length; i < len; i++) {\r
2103 me.plugins[i] = me.initPlugin(me.plugins[i]);\r
2104 }\r
2105 }\r
2106\r
2107 me.loader = me.getLoader();\r
2108\r
2109 if (me.disabled) {\r
2110 me.disabled = false;\r
2111 me.disable(true);\r
2112 }\r
2113\r
2114 if (me.renderTo) {\r
2115 me.render(me.renderTo);\r
2116 // EXTJSIV-1935 - should be a way to do afterShow or something, but that\r
2117 // won't work. Likewise, rendering hidden and then showing (w/autoShow) has\r
2118 // implications to afterRender so we cannot do that.\r
2119 }\r
2120\r
2121 // Auto show only works unilaterally on *uncontained* Components.\r
2122 // If contained, then it is the Container's responsibility to do the showing at next layout time.\r
2123 if (me.autoShow && !me.$initParent) {\r
2124 me.show();\r
2125 }\r
2126\r
2127 //<debug>\r
2128 if (Ext.isDefined(me.disabledClass)) {\r
2129 if (Ext.isDefined(Ext.global.console)) {\r
2130 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');\r
2131 }\r
2132 me.disabledCls = me.disabledClass;\r
2133 delete me.disabledClass;\r
2134 }\r
2135 //</debug>\r
2136\r
2137 // If we were configured from an instance of Ext.Action, (or configured with a baseAction option),\r
2138 // register this Component as one of its items\r
2139 if (me.baseAction){\r
2140 me.baseAction.addComponent(me);\r
2141 }\r
2142 },\r
2143\r
2144 beforeInitConfig: function() {\r
2145 //<debug>\r
2146 if (!this.$calledInitConfig) {\r
2147 Ext.raise('initConfig should not be called by subclasses, it will be called by Ext.Component');\r
2148 }\r
2149 //</debug>\r
2150 this.mixins.observable.constructor.call(this);\r
2151 },\r
2152\r
2153 // <editor-fold desc="Component Methods">\r
2154 // ***********************************************************************************\r
2155 // Begin Component Methods\r
2156 // ***********************************************************************************\r
2157\r
2158 /**\r
2159 * Adds a CSS class to the top level element representing this component.\r
2160 * @param {String/String[]} cls The CSS class name to add.\r
2161 * @return {Ext.Component} Returns the Component to allow method chaining.\r
2162 */\r
2163 addCls: function(cls) {\r
2164 var me = this,\r
2165 el = me.rendered ? me.el : me.protoEl;\r
2166\r
2167 el.addCls.apply(el, arguments);\r
2168 return me;\r
2169 },\r
2170\r
2171 /**\r
2172 * Adds a `cls` to the `uiCls` array, which will also call {@link #addUIClsToElement} and adds to all elements of this\r
2173 * component.\r
2174 * @param {String/String[]} classes A string or an array of strings to add to the `uiCls`.\r
2175 * @param {Boolean} [skip] `true` to skip adding it to the class and do it later (via the return).\r
2176 */\r
2177 addClsWithUI: function(classes, skip) {\r
2178 var me = this,\r
2179 clsArray = [],\r
2180 i = 0,\r
2181 uiCls = me.uiCls = Ext.Array.clone(me.uiCls),\r
2182 activeUI = me.activeUI,\r
2183 length,\r
2184 cls;\r
2185\r
2186 if (typeof classes === "string") {\r
2187 classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);\r
2188 }\r
2189\r
2190 length = classes.length;\r
2191\r
2192 for (; i < length; i++) {\r
2193 cls = classes[i];\r
2194\r
2195 if (cls && !me.hasUICls(cls)) {\r
2196 uiCls.push(cls);\r
2197\r
2198 // We can skip this bit if there isn't an activeUI because we'll be called again from setUI\r
2199 if (activeUI) {\r
2200 clsArray = clsArray.concat(me.addUIClsToElement(cls));\r
2201 }\r
2202 }\r
2203 }\r
2204\r
2205 if (skip !== true && activeUI) {\r
2206 me.addCls(clsArray);\r
2207 }\r
2208\r
2209 return clsArray;\r
2210 },\r
2211\r
2212 /**\r
2213 * Called by the layout system after the Component has been laid out.\r
2214 *\r
2215 * This method is not called on components that use {@link #liquidLayout}, such as\r
2216 * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.\r
2217 *\r
2218 * @param {Number} width The width that was set\r
2219 * @param {Number} height The height that was set\r
2220 * @param {Number/undefined} oldWidth The old width, or `undefined` if this was the initial layout.\r
2221 * @param {Number/undefined} oldHeight The old height, or `undefined` if this was the initial layout.\r
2222 *\r
2223 * @template\r
2224 * @protected\r
2225 */\r
2226 afterComponentLayout: function(width, height, oldWidth, oldHeight) {\r
2227 var me = this,\r
2228 scroller;\r
2229\r
2230 if (++me.componentLayoutCounter === 1) {\r
2231\r
2232 // Update the scroller very early in first layout so that it has the overflow element\r
2233 // before any 'boxready', onResize, or 'resize' code gets to run.\r
2234 scroller = me.scrollable; // initConfig has already run by now\r
2235 if (scroller) {\r
2236 if (me.touchScroll && scroller.isTouchScroller) {\r
2237 scroller.setInnerElement(me.getScrollerEl());\r
2238 }\r
2239\r
2240 scroller.setElement(me.getOverflowEl());\r
2241\r
2242 // IE browsers don't restore scroll position if the component was scrolled and\r
2243 // then hidden and shown again, so we must do it manually.\r
2244 // See EXTJS-16233.\r
2245 if (Ext.isIE) {\r
2246 Ext.on('show', me.onGlobalShow, me);\r
2247 }\r
2248 }\r
2249 me.afterFirstLayout(width, height);\r
2250 }\r
2251\r
2252 if (width !== oldWidth || height !== oldHeight) {\r
2253 me.onResize(width, height, oldWidth, oldHeight);\r
2254 }\r
2255\r
2256 if (me.floating) {\r
2257 me.onAfterFloatLayout();\r
2258 }\r
2259 },\r
2260\r
2261 /**\r
2262 * @private\r
2263 * Adds a plugin. May be called at any time in the component's life cycle.\r
2264 */\r
2265 addPlugin: function(plugin) {\r
2266 var me = this;\r
2267\r
2268 plugin = me.constructPlugin(plugin);\r
2269 if (me.plugins) {\r
2270 me.plugins.push(plugin);\r
2271 } else {\r
2272 me.plugins = [ plugin ];\r
2273 }\r
2274 if (me.pluginsInitialized) {\r
2275 me.initPlugin(plugin);\r
2276 }\r
2277 return plugin;\r
2278 },\r
2279\r
2280 /**\r
2281 * Save a property to the given state object if it is not its default or configured\r
2282 * value.\r
2283 *\r
2284 * @param {Object} state The state object.\r
2285 * @param {String} propName The name of the property on this object to save.\r
2286 * @param {String} [value] The value of the state property (defaults to `this[propName]`).\r
2287 * @return {Object} The state object or a new object if state was `null` and the property\r
2288 * was saved.\r
2289 * @protected\r
2290 */\r
2291 addPropertyToState: function (state, propName, value) {\r
2292 var me = this,\r
2293 len = arguments.length;\r
2294\r
2295 // If the property is inherited, it is a default and we don't want to save it to\r
2296 // the state, however if we explicitly specify a value, always save it\r
2297 if (len === 3 || me.hasOwnProperty(propName)) {\r
2298 if (len < 3) {\r
2299 value = me[propName];\r
2300 }\r
2301\r
2302 // If the property has the same value as was initially configured, again, we\r
2303 // don't want to save it.\r
2304 if (value !== me.initialConfig[propName]) {\r
2305 (state || (state = {}))[propName] = value;\r
2306 }\r
2307 }\r
2308\r
2309 return state;\r
2310 },\r
2311\r
2312 /**\r
2313 * Method which adds a specified UI + `uiCls` to the components element. Can be overridden\r
2314 * to add the UI to more than just the component's element.\r
2315 * @param {String} uiCls The UI class to add to the element.\r
2316 * @protected\r
2317 */\r
2318 addUIClsToElement: function (uiCls) {\r
2319 var me = this,\r
2320 baseClsUI = me.baseCls + '-' + me.ui + '-' + uiCls,\r
2321 result = [ Ext.baseCSSPrefix + uiCls, me.baseCls + '-' + uiCls, baseClsUI ],\r
2322 childEls, childElName, el, suffix;\r
2323\r
2324 if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {\r
2325 // Loop through each frame element, and if they are defined add the ui:\r
2326 baseClsUI += '-';\r
2327 childEls = me.getChildEls();\r
2328\r
2329 for (childElName in childEls) {\r
2330 suffix = childEls[childElName].frame;\r
2331 if (suffix && suffix !== true) {\r
2332 el = me[childElName];\r
2333 if (el) {\r
2334 el.addCls(baseClsUI + suffix);\r
2335 }\r
2336 }\r
2337 }\r
2338 }\r
2339\r
2340 return result;\r
2341 },\r
2342\r
2343 /**\r
2344 * Method which removes a specified UI + `uiCls` from the components element. The `cls`\r
2345 * which is added to the element will be: `this.baseCls + '-' + ui + uiCls`.\r
2346 * @param {String} uiCls The UI class to remove from the element.\r
2347 * @protected\r
2348 */\r
2349 removeUIClsFromElement: function(uiCls) {\r
2350 var me = this,\r
2351 baseClsUI = me.baseCls + '-' + me.ui + '-' + uiCls,\r
2352 result = [ Ext.baseCSSPrefix + uiCls, me.baseCls + '-' + uiCls, baseClsUI ],\r
2353 childEls, childElName, el, suffix;\r
2354\r
2355 if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {\r
2356 // Loop through each frame element, and if they are defined remove the ui:\r
2357 baseClsUI += '-';\r
2358 childEls = me.getChildEls();\r
2359\r
2360 for (childElName in childEls) {\r
2361 suffix = childEls[childElName].frame;\r
2362 if (suffix && suffix !== true) {\r
2363 el = me[childElName];\r
2364 if (el) {\r
2365 el.removeCls(baseClsUI + suffix);\r
2366 }\r
2367 }\r
2368 }\r
2369 }\r
2370\r
2371 return result;\r
2372 },\r
2373\r
2374 /**\r
2375 * @private\r
2376 */\r
2377 adjustPosition: function(x, y) {\r
2378 var me = this,\r
2379 floatParentBox;\r
2380\r
2381 // Floating Components being positioned in their ownerCt have to be made absolute.\r
2382 if (me.isContainedFloater()) {\r
2383 floatParentBox = me.floatParent.getTargetEl().getViewRegion();\r
2384 x += floatParentBox.left;\r
2385 y += floatParentBox.top;\r
2386 }\r
2387\r
2388 return {\r
2389 x: x,\r
2390 y: y\r
2391 };\r
2392 },\r
2393\r
2394 /**\r
2395 * Invoked after the Component has been hidden.\r
2396 *\r
2397 * Gets passed the same `callback` and `scope` parameters that #onHide received.\r
2398 *\r
2399 * @param {Function} [callback]\r
2400 * @param {Object} [scope]\r
2401 *\r
2402 * @template\r
2403 * @protected\r
2404 */\r
2405 afterHide: function(cb, scope) {\r
2406 var me = this,\r
2407 container = me.focusableContainer;\r
2408\r
2409 me.hiddenByLayout = null;\r
2410\r
2411 // Only lay out if there is an owning layout which might be affected by the hide\r
2412 if (this.ownerLayout) {\r
2413 this.updateLayout({ isRoot: false });\r
2414 }\r
2415\r
2416 Ext.callback(cb, scope || me);\r
2417\r
2418 me.fireHierarchyEvent('hide');\r
2419 me.fireEvent('hide', me);\r
2420 \r
2421 if (container) {\r
2422 container.onFocusableChildHide(me);\r
2423 }\r
2424 },\r
2425\r
2426 /**\r
2427 * Template method called after a Component has been positioned.\r
2428 *\r
2429 * @param {Number} x\r
2430 * @param {Number} y\r
2431 *\r
2432 * @template\r
2433 * @protected\r
2434 */\r
2435 afterSetPosition: function(x, y) {\r
2436 var me = this;\r
2437 me.onPosition(x, y);\r
2438 if (me.hasListeners.move) {\r
2439 me.fireEvent('move', me, x, y);\r
2440 }\r
2441 },\r
2442\r
2443 /**\r
2444 * Invoked after the Component is shown (after #onShow is called).\r
2445 *\r
2446 * Gets passed the same parameters as #show.\r
2447 *\r
2448 * @param {String/Ext.dom.Element} [animateTarget]\r
2449 * @param {Function} [callback]\r
2450 * @param {Object} [scope]\r
2451 *\r
2452 * @template\r
2453 * @protected\r
2454 */\r
2455 afterShow: function(animateTarget, cb, scope) {\r
2456 var me = this,\r
2457 myEl = me.el,\r
2458 fromBox,\r
2459 toBox,\r
2460 ghostPanel;\r
2461\r
2462 // Default to configured animate target if none passed\r
2463 animateTarget = me.getAnimateTarget(animateTarget);\r
2464\r
2465 // Need to be able to ghost the Component\r
2466 if (!me.ghost) {\r
2467 animateTarget = null;\r
2468 }\r
2469 // If we're animating, kick of an animation of the ghost from the target to the *Element* current box\r
2470 if (animateTarget) {\r
2471 toBox = {\r
2472 x: myEl.getX(),\r
2473 y: myEl.getY(),\r
2474 width: myEl.dom.offsetWidth,\r
2475 height: myEl.dom.offsetHeight\r
2476 };\r
2477 fromBox = {\r
2478 x: animateTarget.getX(),\r
2479 y: animateTarget.getY(),\r
2480 width: animateTarget.dom.offsetWidth,\r
2481 height: animateTarget.dom.offsetHeight\r
2482 };\r
2483 myEl.addCls(me.offsetsCls);\r
2484 ghostPanel = me.ghost();\r
2485 ghostPanel.el.stopAnimation();\r
2486\r
2487 // Shunting it offscreen immediately, *before* the Animation class grabs it ensure no flicker.\r
2488 ghostPanel.setX(-10000);\r
2489\r
2490 me.ghostBox = toBox;\r
2491 ghostPanel.el.animate({\r
2492 from: fromBox,\r
2493 to: toBox,\r
2494 listeners: {\r
2495 afteranimate: function() {\r
2496 delete ghostPanel.componentLayout.lastComponentSize;\r
2497 me.unghost();\r
2498 delete me.ghostBox;\r
2499 myEl.removeCls(me.offsetsCls);\r
2500 me.onShowComplete(cb, scope);\r
2501 }\r
2502 }\r
2503 });\r
2504 }\r
2505 else {\r
2506 me.onShowComplete(cb, scope);\r
2507 }\r
2508 me.fireHierarchyEvent('show');\r
2509 },\r
2510\r
2511 animate: function(animObj) {\r
2512 var me = this,\r
2513 hasToWidth,\r
2514 hasToHeight,\r
2515 toHeight,\r
2516 toWidth,\r
2517 to,\r
2518 clearWidth,\r
2519 clearHeight,\r
2520 curWidth, w, curHeight, h, isExpanding,\r
2521 wasConstrained,\r
2522 wasConstrainedHeader,\r
2523 passedCallback,\r
2524 oldOverflow;\r
2525\r
2526 animObj = animObj || {};\r
2527 to = animObj.to || {};\r
2528\r
2529 if (Ext.fx.Manager.hasFxBlock(me.id)) {\r
2530 return me;\r
2531 }\r
2532\r
2533 hasToWidth = Ext.isDefined(to.width);\r
2534 if (hasToWidth) {\r
2535 toWidth = Ext.Number.constrain(to.width, me.minWidth, me.maxWidth);\r
2536 }\r
2537\r
2538 hasToHeight = Ext.isDefined(to.height);\r
2539 if (hasToHeight) {\r
2540 toHeight = Ext.Number.constrain(to.height, me.minHeight, me.maxHeight);\r
2541 }\r
2542\r
2543 // Special processing for animating Component dimensions.\r
2544 if (!animObj.dynamic && (hasToWidth || hasToHeight)) {\r
2545 curWidth = (animObj.from ? animObj.from.width : undefined) || me.getWidth();\r
2546 w = curWidth;\r
2547 curHeight = (animObj.from ? animObj.from.height : undefined) || me.getHeight();\r
2548 h = curHeight;\r
2549 isExpanding = false;\r
2550\r
2551 if (hasToHeight && toHeight > curHeight) {\r
2552 h = toHeight;\r
2553 isExpanding = true;\r
2554 }\r
2555 if (hasToWidth && toWidth > curWidth) {\r
2556 w = toWidth;\r
2557 isExpanding = true;\r
2558 }\r
2559\r
2560 // During animated sizing, overflow has to be hidden to clip expanded content\r
2561 if (hasToHeight || hasToWidth) {\r
2562 oldOverflow = me.el.getStyle('overflow');\r
2563 if (oldOverflow !== 'hidden') {\r
2564 me.el.setStyle('overflow', 'hidden');\r
2565 }\r
2566 }\r
2567\r
2568 // If any dimensions are being increased, we must resize the internal structure\r
2569 // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.\r
2570 // The animation will then progressively reveal the larger content.\r
2571 if (isExpanding) {\r
2572 clearWidth = !Ext.isNumber(me.width);\r
2573 clearHeight = !Ext.isNumber(me.height);\r
2574\r
2575 // Lay out this component at the new, larger size to get the internals correctly laid out.\r
2576 // Then size the encapsulating **Element** back down to size.\r
2577 // We will then just animate the element to reveal the correctly laid out content.\r
2578 me.setSize(w, h);\r
2579 me.el.setSize(curWidth, curHeight);\r
2580\r
2581 if (clearWidth) {\r
2582 delete me.width;\r
2583 }\r
2584 if (clearHeight) {\r
2585 delete me.height;\r
2586 }\r
2587 }\r
2588 if (hasToWidth) {\r
2589 to.width = toWidth;\r
2590 }\r
2591\r
2592 if (hasToHeight) {\r
2593 to.height = toHeight;\r
2594 }\r
2595 }\r
2596\r
2597 // No constraining during the animate - the "to" size has already been calculated with respect to all settings.\r
2598 // Arrange to reinstate any constraining after the animation has completed\r
2599 wasConstrained = me.constrain;\r
2600 wasConstrainedHeader = me.constrainHeader;\r
2601 if (wasConstrained || wasConstrainedHeader) {\r
2602 me.constrain = me.constrainHeader = false;\r
2603 passedCallback = animObj.callback;\r
2604 animObj.callback = function() {\r
2605 me.constrain = wasConstrained;\r
2606 me.constrainHeader = wasConstrainedHeader;\r
2607 // Call the original callback if any\r
2608 if (passedCallback) {\r
2609 passedCallback.call(animObj.scope||me, arguments);\r
2610 }\r
2611 if (oldOverflow !== 'hidden') {\r
2612 me.el.setStyle('overflow', oldOverflow);\r
2613 }\r
2614 };\r
2615 }\r
2616 return me.mixins.animate.animate.apply(me, arguments);\r
2617 },\r
2618\r
2619 applyScrollable: function(scrollable, oldScrollable) {\r
2620 var me = this,\r
2621 rendered = me.rendered,\r
2622 scrollableCfg,\r
2623 innerEl;\r
2624\r
2625 if (scrollable) {\r
2626 if (scrollable === true || typeof scrollable === 'string') {\r
2627 scrollableCfg = me._scrollableCfg[scrollable];\r
2628\r
2629 //<debug>\r
2630 if (!scrollableCfg) {\r
2631 Ext.raise("'" + scrollable + "' is not a valid value for 'scrollable'");\r
2632 }\r
2633 //</debug>\r
2634\r
2635 scrollable = scrollableCfg;\r
2636 }\r
2637\r
2638 if (oldScrollable) {\r
2639 oldScrollable.setConfig(scrollable);\r
2640 scrollable = oldScrollable;\r
2641 } else {\r
2642 scrollable = Ext.Object.chain(scrollable); // don't mutate the user's config\r
2643\r
2644 if (rendered) {\r
2645 // we create the scroller without an element by default (because the\r
2646 // element is not available at configuration time) and then assign\r
2647 // the element in onBoxReady. If we got here it means the scroller\r
2648 // is being configured after render, so we need to make sure the\r
2649 // element is in its config object\r
2650 scrollable.element = me.getOverflowEl();\r
2651 innerEl = me.getScrollerEl();\r
2652 if (innerEl) {\r
2653 scrollable.innerElement = innerEl;\r
2654 }\r
2655 }\r
2656\r
2657 // scroller gets refreshed by Component#onResize,\r
2658 // so there is no need to initialize a SizeMonitor\r
2659 scrollable.autoRefresh = false;\r
2660\r
2661 if (Ext.supports.touchScroll === 1) {\r
2662 // running in a browser that uses the touch scroller to control naturally\r
2663 // overflowing elements.\r
2664 scrollable.translatable = {\r
2665 translationMethod: 'scrollparent'\r
2666 };\r
2667 // We'll have native scrollbars, so no indicators are needed\r
2668 scrollable.indicators = false;\r
2669 }\r
2670 scrollable = Ext.scroll.Scroller.create(scrollable);\r
2671 scrollable.component = me;\r
2672 }\r
2673 } else if (oldScrollable) {\r
2674 oldScrollable.setConfig({\r
2675 x: false,\r
2676 y: false\r
2677 });\r
2678 oldScrollable.destroy();\r
2679 scrollable = null;\r
2680 }\r
2681\r
2682 if (me.rendered && !me.destroying && !me.destroyed) {\r
2683 if (scrollable) {\r
2684 me.getOverflowStyle(); // refresh the scrollFlags\r
2685 } else {\r
2686 me.scrollFlags = me._scrollFlags.none;\r
2687 }\r
2688 me.updateLayout();\r
2689 }\r
2690\r
2691 return scrollable;\r
2692 },\r
2693\r
2694 /**\r
2695 * Occurs before `componentLayout` is run. Returning `false` from this method will prevent the `componentLayout` from\r
2696 * being executed.\r
2697 *\r
2698 * @param {Number} adjWidth The box-adjusted width that was set.\r
2699 * @param {Number} adjHeight The box-adjusted height that was set.\r
2700 *\r
2701 * @template\r
2702 * @protected\r
2703 */\r
2704 beforeComponentLayout: function() {\r
2705 return true;\r
2706 },\r
2707\r
2708 /**\r
2709 * Invoked before the Component is destroyed.\r
2710 *\r
2711 * @method\r
2712 * @template\r
2713 * @protected\r
2714 */\r
2715 beforeDestroy : Ext.emptyFn,\r
2716\r
2717 /**\r
2718 * Occurs before componentLayout is run. In previous releases, this method could\r
2719 * return `false` to prevent its layout but that is not supported in Ext JS 4.1 or\r
2720 * higher. This method is simply a notification of the impending layout to give the\r
2721 * component a chance to adjust the DOM. Ideally, DOM reads should be avoided at this\r
2722 * time to reduce expensive document reflows.\r
2723 *\r
2724 * @template\r
2725 * @protected\r
2726 */\r
2727 beforeLayout: function(){\r
2728 if (this.floating) {\r
2729 this.onBeforeFloatLayout();\r
2730 }\r
2731 },\r
2732\r
2733 /**\r
2734 * @private\r
2735 * Template method called before a Component is positioned.\r
2736 *\r
2737 * Ensures that the position is adjusted so that the Component is constrained if so configured.\r
2738 */\r
2739 beforeSetPosition: function (x, y, animate) {\r
2740 var me = this,\r
2741 pos = null,\r
2742 x0, hasX, hasY, adj;\r
2743\r
2744 // Decode members of x if x is an array or an object.\r
2745 // If it is numeric (including zero), we need do nothing.\r
2746 if (x) {\r
2747 // Position in first argument as an array of [x, y]\r
2748 if (Ext.isNumber(x0 = x[0])) {\r
2749 animate = y;\r
2750 y = x[1];\r
2751 x = x0;\r
2752 }\r
2753 // Position in first argument as object w/ x & y properties\r
2754 else if ((x0 = x.x) !== undefined) {\r
2755 animate = y;\r
2756 y = x.y;\r
2757 x = x0;\r
2758 }\r
2759 }\r
2760\r
2761 if (me.constrain || me.constrainHeader) {\r
2762 pos = me.calculateConstrainedPosition(null, [x, y], true);\r
2763 if (pos) {\r
2764 x = pos[0];\r
2765 y = pos[1];\r
2766 }\r
2767 }\r
2768\r
2769 hasX = (x !== undefined);\r
2770 hasY = (y !== undefined);\r
2771\r
2772 if (hasX || hasY) {\r
2773 // The component's position is the position it was told to be at.\r
2774 // If it is contained, adjustPosition will add the floatParent's offsets.\r
2775 me.x = x;\r
2776 me.y = y;\r
2777\r
2778 adj = me.adjustPosition(x, y);\r
2779 // Set up the return info and store the position in this object\r
2780 pos = {\r
2781 x : adj.x,\r
2782 y : adj.y,\r
2783 anim: animate,\r
2784 hasX: hasX,\r
2785 hasY: hasY\r
2786 };\r
2787 }\r
2788\r
2789 return pos;\r
2790 },\r
2791\r
2792 /**\r
2793 * Invoked before the Component is shown.\r
2794 *\r
2795 * @method\r
2796 * @template\r
2797 * @protected\r
2798 */\r
2799 beforeShow: Ext.emptyFn,\r
2800\r
2801 /**\r
2802 * Bubbles up the component/container hierarchy, calling the specified function with each component. The scope\r
2803 * (*this*) of function call will be the scope provided or the current component. The arguments to the function will\r
2804 * be the args provided or the current component. If the function returns false at any point, the bubble is stopped.\r
2805 *\r
2806 * @param {Function} fn The function to call\r
2807 * @param {Object} [scope] The scope of the function. Defaults to current node.\r
2808 * @param {Array} [args] The args to call the function with. Defaults to passing the current component.\r
2809 * @return {Ext.Component} this\r
2810 */\r
2811 bubble: function(fn, scope, args) {\r
2812 var p = this;\r
2813 while (p) {\r
2814 if (fn.apply(scope || p, args || [p]) === false) {\r
2815 break;\r
2816 }\r
2817 p = p.getBubbleTarget();\r
2818 }\r
2819 return this;\r
2820 },\r
2821\r
2822 clearListeners: function() {\r
2823 var me = this;\r
2824 me.mixins.observable.clearListeners.call(me);\r
2825 me.mixins.componentDelegation.clearDelegatedListeners.call(me);\r
2826 },\r
2827\r
2828 /**\r
2829 * Clone the current component using the original config values passed into this instance by default.\r
2830 * @param {Object} overrides A new config containing any properties to override in the cloned version.\r
2831 * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.\r
2832 * @return {Ext.Component} clone The cloned copy of this component\r
2833 */\r
2834 cloneConfig: function(overrides) {\r
2835 overrides = overrides || {};\r
2836 var id = overrides.id || Ext.id(),\r
2837 cfg = Ext.applyIf(overrides, this.initialConfig),\r
2838 self;\r
2839\r
2840 cfg.id = id;\r
2841\r
2842 self = Ext.getClass(this);\r
2843\r
2844 // prevent dup id\r
2845 return new self(cfg);\r
2846 },\r
2847\r
2848 /**\r
2849 * Destroys the Component. This method must not be overridden.\r
2850 * To add extra functionality to destruction time in a subclass, implement the\r
2851 * template method {@link #beforeDestroy} or {@link #onDestroy}. And do not forget to\r
2852 * `callParent()` in your implementation.\r
2853 * @since 1.1.0\r
2854 */\r
2855 destroy: function() {\r
2856 var me = this,\r
2857 selectors = me.renderSelectors,\r
2858 viewModel = me.getConfig('viewModel', true),\r
2859 session = me.getConfig('session', true),\r
2860 selector, ownerCt, el;\r
2861\r
2862 if (!me.hasListeners.beforedestroy || me.fireEvent('beforedestroy', me) !== false) {\r
2863 // isDestroying added for compat reasons\r
2864 me.isDestroying = me.destroying = true;\r
2865\r
2866 ownerCt = me.floatParent || me.ownerCt;\r
2867 if (me.floating) {\r
2868 delete me.floatParent;\r
2869 // A zIndexManager is stamped into a *floating* Component when it is added to a Container.\r
2870 // If it has no zIndexManager at render time, it is assigned to the global Ext.WindowManager instance.\r
2871 if (me.zIndexManager) {\r
2872 me.zIndexManager.unregister(me);\r
2873 me.zIndexManager = null;\r
2874 }\r
2875 }\r
2876\r
2877 me.removeBindings();\r
2878\r
2879 // beforeDestroy destroys children, ensure they go before the viewModel/session/controller\r
2880 me.beforeDestroy();\r
2881\r
2882 me.destroyBindable();\r
2883\r
2884 if (ownerCt && ownerCt.remove) {\r
2885 ownerCt.remove(me, false);\r
2886 }\r
2887\r
2888 me.stopAnimation();\r
2889 me.onDestroy();\r
2890\r
2891 // Attempt to destroy all plugins\r
2892 Ext.destroy(me.plugins);\r
2893\r
2894 if (me.rendered) {\r
2895 Ext.Component.cancelLayout(me, true);\r
2896 }\r
2897\r
2898 me.componentLayout = null;\r
2899 if (me.hasListeners.destroy) {\r
2900 me.fireEvent('destroy', me);\r
2901 }\r
2902 if (!me.preventRegister) {\r
2903 Ext.ComponentManager.unregister(me);\r
2904 }\r
2905\r
2906 me.mixins.state.destroy.call(me);\r
2907\r
2908 if (me.floating) {\r
2909 me.onFloatDestroy();\r
2910 }\r
2911\r
2912 me.clearListeners();\r
2913 \r
2914 // make sure we clean up the element references after removing all events\r
2915 if (me.rendered) {\r
2916 if (!me.preserveElOnDestroy) {\r
2917 me.el.destroy();\r
2918 }\r
2919 me.el.component = null;\r
2920 me.mixins.elementCt.destroy.call(me); // removes childEls\r
2921 if (selectors) {\r
2922 for (selector in selectors) {\r
2923 if (selectors.hasOwnProperty(selector)) {\r
2924 el = me[selector];\r
2925 if (el) { // in case any other code may have already removed it\r
2926 delete me[selector];\r
2927 el.destroy();\r
2928 }\r
2929 }\r
2930 }\r
2931 }\r
2932 \r
2933 me.data = me.el = me.frameBody = me.rendered = me.afterRenderEvents = null;\r
2934 me.tpl = me.renderTpl = me.renderData = null;\r
2935 me.focusableContainer = me.container = me.scrollable = null;\r
2936 }\r
2937 \r
2938 // isDestroying added for compat reasons\r
2939 me.isDestroying = me.destroying = false;\r
2940 me.callParent();\r
2941 }\r
2942 },\r
2943\r
2944 /**\r
2945 * Disable the component.\r
2946 * @param {Boolean} [silent=false] Passing `true` will suppress the `disable` event from being fired.\r
2947 * @since 1.1.0\r
2948 */\r
2949 disable: function(silent, /* private */fromParent) {\r
2950 var me = this,\r
2951 container = me.focusableContainer,\r
2952 inherited = me.getInherited();\r
2953\r
2954 if (!fromParent) {\r
2955 inherited.disabled = true;\r
2956 me.savedDisabled = true;\r
2957 }\r
2958\r
2959 if (me.maskOnDisable) {\r
2960 inherited.disableMask = true;\r
2961 }\r
2962\r
2963 if (!me.disabled) {\r
2964 if (container) {\r
2965 container.beforeFocusableChildDisable(me);\r
2966 }\r
2967 \r
2968 me.addCls(me.disabledCls);\r
2969 \r
2970 if (me.rendered) {\r
2971 me.onDisable();\r
2972 }\r
2973 else {\r
2974 me.disableOnRender = true;\r
2975 }\r
2976\r
2977 me.disabled = true;\r
2978\r
2979 if (silent !== true) {\r
2980 me.fireEvent('disable', me);\r
2981 }\r
2982 \r
2983 if (container) {\r
2984 container.onFocusableChildDisable(me);\r
2985 }\r
2986 }\r
2987\r
2988 return me;\r
2989 },\r
2990\r
2991 doFireEvent: function(eventName, args, bubbles) {\r
2992 var me = this,\r
2993 ret = me.mixins.observable.doFireEvent.call(me, eventName, args, bubbles);\r
2994\r
2995 if (ret !== false) {\r
2996 ret = me.mixins.componentDelegation.doFireDelegatedEvent.call(me, eventName, args);\r
2997 }\r
2998\r
2999 return ret;\r
3000 },\r
3001\r
3002 /**\r
3003 * Enable the component\r
3004 * @param {Boolean} [silent=false] Passing `true` will suppress the `enable` event from being fired.\r
3005 * @since 1.1.0\r
3006 */\r
3007 enable: function(silent, /* private */fromParent) {\r
3008 var me = this,\r
3009 container = me.focusableContainer,\r
3010 inherited = me.getInherited();\r
3011\r
3012 if (!fromParent) {\r
3013 delete me.getInherited().disabled;\r
3014 me.savedDisabled = false;\r
3015 }\r
3016\r
3017 if (me.maskOnDisable) {\r
3018 delete inherited.disableMask;\r
3019 }\r
3020\r
3021 if (me.disabled) {\r
3022 // A parent is asking us to enable, but if we were disabled directly, keep\r
3023 // our current state\r
3024 if (!(fromParent && inherited.hasOwnProperty('disabled'))) {\r
3025 if (container) {\r
3026 container.beforeFocusableChildEnable(me);\r
3027 }\r
3028 \r
3029 me.disableOnRender = false;\r
3030 me.removeCls(me.disabledCls);\r
3031 \r
3032 if (me.rendered) {\r
3033 me.onEnable();\r
3034 }\r
3035\r
3036 me.disabled = false;\r
3037\r
3038 if (silent !== true) {\r
3039 me.fireEvent('enable', me);\r
3040 }\r
3041 \r
3042 if (container) {\r
3043 container.onFocusableChildEnable(me);\r
3044 }\r
3045 }\r
3046 }\r
3047\r
3048 return me;\r
3049 },\r
3050\r
3051 /**\r
3052 * Find a container above this component at any level by a custom function. If the passed function returns true, the\r
3053 * container will be returned.\r
3054 *\r
3055 * See also the {@link Ext.Component#up up} method.\r
3056 *\r
3057 * @param {Function} fn The custom function to call with the arguments (container, this component).\r
3058 * @return {Ext.container.Container} The first Container for which the custom function returns true\r
3059 */\r
3060 findParentBy: function(fn) {\r
3061 var p;\r
3062\r
3063 // Iterate up the owner chain until we don't have one, or we find an ancestor which matches using the selector function.\r
3064 for (p = this.getRefOwner(); p && !fn(p, this); p = p.getRefOwner()) {\r
3065 // do nothing\r
3066 }\r
3067 return p || null;\r
3068 },\r
3069\r
3070 /**\r
3071 * Find a container above this component at any level by xtype or class\r
3072 *\r
3073 * See also the {@link Ext.Component#up up} method.\r
3074 *\r
3075 * @param {String/Ext.Class} xtype The xtype string for a component, or the class of the component directly\r
3076 * @return {Ext.container.Container} The first Container which matches the given xtype or class\r
3077 */\r
3078 findParentByType: function(xtype) {\r
3079 return Ext.isFunction(xtype) ?\r
3080 this.findParentBy(function(p) {\r
3081 return p.constructor === xtype;\r
3082 })\r
3083 :\r
3084 this.up(xtype);\r
3085 },\r
3086\r
3087 /**\r
3088 * Retrieves plugin from this component's collection by its `ptype`.\r
3089 * \r
3090 * var grid = Ext.create('Ext.grid.Panel', {\r
3091 * store: {\r
3092 * fields: ['name'],\r
3093 * data: [{\r
3094 * name: 'Scott Pilgrim'\r
3095 * }]\r
3096 * },\r
3097 * columns: [{\r
3098 * header: 'Name',\r
3099 * dataIndex: 'name',\r
3100 * editor: 'textfield',\r
3101 * flex: 1\r
3102 * }],\r
3103 * selType: 'cellmodel',\r
3104 * plugins: {\r
3105 * ptype: 'cellediting',\r
3106 * clicksToEdit: 1,\r
3107 * pluginId: 'myplugin'\r
3108 * },\r
3109 * height: 200,\r
3110 * width: 400,\r
3111 * renderTo: Ext.getBody()\r
3112 * });\r
3113 * \r
3114 * grid.findPlugin('cellediting'); // the cellediting plugin\r
3115 * \r
3116 * **Note:** See also {@link #getPlugin}\r
3117 * \r
3118 * @param {String} ptype The Plugin's `ptype` as specified by the class's \r
3119 * {@link Ext.Class#cfg-alias alias} configuration.\r
3120 * @return {Ext.plugin.Abstract} plugin instance or `undefined` if not found\r
3121 */\r
3122 findPlugin: function(ptype) {\r
3123 var i,\r
3124 plugins = this.plugins,\r
3125 ln = plugins && plugins.length;\r
3126 for (i = 0; i < ln; i++) {\r
3127 if (plugins[i].ptype === ptype) {\r
3128 return plugins[i];\r
3129 }\r
3130 }\r
3131 },\r
3132 \r
3133 getAnimateTarget: function(target){\r
3134 target = target || this.animateTarget;\r
3135 if (target) {\r
3136 target = target.isComponent ? target.getEl() : Ext.get(target);\r
3137 }\r
3138 return target || null;\r
3139 },\r
3140\r
3141 /**\r
3142 * @protected\r
3143 * Implements an upward event bubbling policy. By default a Component bubbles events up to its {@link #getRefOwner reference owner}.\r
3144 *\r
3145 * Component subclasses may implement a different bubbling strategy by overriding this method.\r
3146 */\r
3147 getBubbleTarget: function() {\r
3148 return this.getRefOwner();\r
3149 },\r
3150\r
3151 getComponentLayout: function() {\r
3152 var me = this;\r
3153\r
3154 if (!me.componentLayout || !me.componentLayout.isLayout) {\r
3155 me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));\r
3156 }\r
3157 return me.componentLayout;\r
3158 },\r
3159\r
3160 /**\r
3161 * Retrieves the top level element representing this component.\r
3162 * @return {Ext.dom.Element}\r
3163 * @since 1.1.0\r
3164 */\r
3165 getEl: function() {\r
3166 return this.el;\r
3167 },\r
3168\r
3169 /**\r
3170 * Gets the current height of the component's underlying element.\r
3171 * @return {Number}\r
3172 */\r
3173 getHeight: function() {\r
3174 return this.el.getHeight();\r
3175 },\r
3176\r
3177 /**\r
3178 * Called by `getInherited` to initialize the inheritedState the first time it is\r
3179 * requested.\r
3180 * @protected\r
3181 */\r
3182 initInheritedState: function (inheritedState) {\r
3183 var me = this,\r
3184 layout = me.componentLayout;\r
3185\r
3186 if (me.hidden) {\r
3187 inheritedState.hidden = true;\r
3188 }\r
3189 if (me.collapseImmune) {\r
3190 inheritedState.collapseImmune = true;\r
3191 }\r
3192 if (me.modelValidation !== undefined) {\r
3193 inheritedState.modelValidation = me.modelValidation;\r
3194 }\r
3195\r
3196 if (me.savedDisabled) {\r
3197 inheritedState.disabled = true;\r
3198 }\r
3199\r
3200 me.mixins.bindable.initInheritedState.call(me, inheritedState);\r
3201\r
3202 if (layout && layout.initInheritedState) {\r
3203 layout.initInheritedState(inheritedState);\r
3204 }\r
3205 },\r
3206\r
3207 /**\r
3208 * Retrieves the `id` of this component. Will auto-generate an `id` if one has not already been set.\r
3209 * @return {String}\r
3210 */\r
3211 getId: function() {\r
3212 var me = this,\r
3213 xtype;\r
3214\r
3215 // If we have no id, attempt to gather it from our configuration.\r
3216 // Autogenerate it if none was configured.\r
3217 if (!(me.id || (me.id = me.initialConfig.id))) {\r
3218 xtype = me.getXType();\r
3219 if (xtype) {\r
3220 xtype = xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-');\r
3221 } else {\r
3222 xtype = Ext.name.toLowerCase() + '-comp';\r
3223 }\r
3224 me.id = xtype + '-' + me.getAutoId();\r
3225 }\r
3226 return me.id;\r
3227 },\r
3228\r
3229 /**\r
3230 * Returns the value of {@link #itemId} assigned to this component, or when that\r
3231 * is not set, returns the value of {@link #id}.\r
3232 * @return {String}\r
3233 */\r
3234 getItemId: function() {\r
3235 return this.itemId || this.id;\r
3236 },\r
3237\r
3238 /**\r
3239 * Gets the {@link Ext.ComponentLoader} for this Component.\r
3240 * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.\r
3241 */\r
3242 getLoader: function(){\r
3243 var me = this,\r
3244 loader = me.loader;\r
3245\r
3246 if (loader) {\r
3247 if (!loader.isLoader) {\r
3248 me.loader = new Ext.ComponentLoader(Ext.apply({\r
3249 target: me\r
3250 }, loader));\r
3251 } else {\r
3252 loader.setTarget(me);\r
3253 }\r
3254 return me.loader;\r
3255\r
3256 }\r
3257 return null;\r
3258 },\r
3259\r
3260 /**\r
3261 * @protected\r
3262 * Returns the element which is masked by the {@link #mask} method, or into which the {@link #setLoading LoadMask} is rendered into.\r
3263 *\r
3264 * The default implementation uses the {@link #maskElement} configuration to access the Component's child element by name. By default, {@link #maskElement}\r
3265 * is `null` which means that `null` is returned from this method indicating that the mask needs to be rendered into the document because\r
3266 * component structure should not be contaminated by mask elements.\r
3267 *\r
3268 * Some subclasses may override this method if they have knowledge about external structures where a mask could usefully be rendered.\r
3269 *\r
3270 * For example a {@link Ext.view.Table GridView} will request that its owning {@link Ext.panel.Table GridPanel} be masked. The\r
3271 * GridPanel will have its own implementation of `getMaskTarget` which will return the element dictated by its own {@link #maskElement}\r
3272 * Panels use `"el"` as their {@link #maskElement} by default, but that could be overridden to be `"body"` to leave toolbars and the header\r
3273 * mouse-accessible.\r
3274 * \r
3275 */\r
3276 getMaskTarget: function() {\r
3277 return this.maskElement ? this[this.maskElement] : null;\r
3278 },\r
3279\r
3280 /**\r
3281 * Retrieves a plugin from this component's collection by its `pluginId`.\r
3282 * \r
3283 * var grid = Ext.create('Ext.grid.Panel', {\r
3284 * store: {\r
3285 * fields: ['name'],\r
3286 * data: [{\r
3287 * name: 'Scott Pilgrim'\r
3288 * }]\r
3289 * },\r
3290 * columns: [{\r
3291 * header: 'Name',\r
3292 * dataIndex: 'name',\r
3293 * editor: 'textfield',\r
3294 * flex: 1\r
3295 * }],\r
3296 * selType: 'cellmodel',\r
3297 * plugins: {\r
3298 * ptype: 'cellediting',\r
3299 * clicksToEdit: 1,\r
3300 * pluginId: 'myplugin'\r
3301 * },\r
3302 * height: 200,\r
3303 * width: 400,\r
3304 * renderTo: Ext.getBody()\r
3305 * });\r
3306 * \r
3307 * grid.getPlugin('myplugin'); // the cellediting plugin\r
3308 * \r
3309 * **Note:** See also {@link #findPlugin}\r
3310 * \r
3311 * @param {String} pluginId The `pluginId` set on the plugin config object\r
3312 * @return {Ext.plugin.Abstract} plugin instance or `null` if not found\r
3313 */\r
3314 getPlugin: function(pluginId) {\r
3315 var i,\r
3316 plugins = this.plugins,\r
3317 ln = plugins && plugins.length;\r
3318\r
3319 for (i = 0; i < ln; i++) {\r
3320 if (plugins[i].pluginId === pluginId) {\r
3321 return plugins[i];\r
3322 }\r
3323 }\r
3324 return null;\r
3325 },\r
3326 \r
3327 /**\r
3328 * Gets the current XY position of the component's underlying element.\r
3329 * @param {Boolean} [local=false] If true the element's left and top are returned instead of page XY.\r
3330 * @return {Number[]} The XY position of the element (e.g., [100, 200])\r
3331 */\r
3332 getPosition: function(local) {\r
3333 var me = this,\r
3334 xy,\r
3335 isContainedFloater = me.isContainedFloater(),\r
3336 floatParentBox;\r
3337\r
3338 // Local position for non-floaters means element's local position\r
3339 if ((local === true) && !isContainedFloater) {\r
3340 return [me.getLocalX(), me.getLocalY()];\r
3341 }\r
3342\r
3343 xy = me.getXY();\r
3344\r
3345 // Local position for floaters means position relative to the container's target element\r
3346 if ((local === true) && isContainedFloater) {\r
3347 floatParentBox = me.floatParent.getTargetEl().getViewRegion();\r
3348 xy[0] -= floatParentBox.left;\r
3349 xy[1] -= floatParentBox.top;\r
3350 }\r
3351 return xy;\r
3352 },\r
3353\r
3354 /**\r
3355 * Returns the "x" scroll position for this component. Only applicable for\r
3356 * {@link #scrollable} components\r
3357 * @return {Number}\r
3358 */\r
3359 getScrollX: function() {\r
3360 var scroller = this.getScrollable();\r
3361 return scroller ? scroller.getPosition().x : 0;\r
3362 },\r
3363\r
3364 /**\r
3365 * Returns the "y" scroll position for this component. Only applicable for\r
3366 * {@link #scrollable} components\r
3367 * @return {Number}\r
3368 */\r
3369 getScrollY: function() {\r
3370 var scroller = this.getScrollable();\r
3371 return scroller ? scroller.getPosition().y : 0;\r
3372 },\r
3373\r
3374 /**\r
3375 * Gets the current size of the component's underlying element.\r
3376 * @param {Boolean} [contentSize] true to get the width/size minus borders and padding\r
3377 * @return {Object} An object containing the element's size:\r
3378 * @return {Number} return.width\r
3379 * @return {Number} return.height\r
3380 */\r
3381 getSize: function(contentSize) {\r
3382 return this.el.getSize(contentSize);\r
3383 },\r
3384\r
3385 /**\r
3386 * Returns an object that describes how this component's width and height are managed.\r
3387 * All of these objects are shared and should not be modified.\r
3388 *\r
3389 * @return {Object} The size model for this component.\r
3390 * @return {Ext.layout.SizeModel} return.width The {@link Ext.layout.SizeModel size model}\r
3391 * for the width.\r
3392 * @return {Ext.layout.SizeModel} return.height The {@link Ext.layout.SizeModel size model}\r
3393 * for the height.\r
3394 * @protected\r
3395 */\r
3396 getSizeModel: function (ownerCtSizeModel) {\r
3397 var me = this,\r
3398 models = Ext.layout.SizeModel,\r
3399 ownerContext = me.componentLayout.ownerContext,\r
3400 width = me.width,\r
3401 height = me.height,\r
3402 typeofWidth, typeofHeight,\r
3403 hasPixelWidth, hasPixelHeight,\r
3404 heightModel, ownerLayout, policy, shrinkWrap, topLevel, widthModel,\r
3405\r
3406 // floating === a floating Component, floated === a border layout's slideout view of a region.\r
3407 isFloating = me.floating || me.floated;\r
3408\r
3409 if (ownerContext) {\r
3410 // If we are in the middle of a running layout, always report the current,\r
3411 // dynamic size model rather than recompute it. This is not (only) a time\r
3412 // saving thing, but a correctness thing since we cannot get the right answer\r
3413 // otherwise.\r
3414 widthModel = ownerContext.widthModel;\r
3415 heightModel = ownerContext.heightModel;\r
3416 }\r
3417\r
3418 if (!widthModel || !heightModel) {\r
3419 hasPixelWidth = ((typeofWidth = typeof width) === 'number');\r
3420 hasPixelHeight = ((typeofHeight = typeof height) === 'number');\r
3421 topLevel = isFloating || !(ownerLayout = me.ownerLayout);\r
3422\r
3423 // Floating or no owner layout, e.g. rendered using renderTo\r
3424 if (topLevel) {\r
3425 policy = Ext.layout.Layout.prototype.autoSizePolicy;\r
3426 shrinkWrap = isFloating ? 3 : me.shrinkWrap;\r
3427\r
3428 if (hasPixelWidth) {\r
3429 widthModel = models.configured;\r
3430 }\r
3431\r
3432 if (hasPixelHeight) {\r
3433 heightModel = models.configured;\r
3434 }\r
3435 } else {\r
3436 policy = ownerLayout.getItemSizePolicy(me, ownerCtSizeModel);\r
3437 shrinkWrap = ownerLayout.isItemShrinkWrap(me);\r
3438 }\r
3439\r
3440 if (ownerContext) {\r
3441 ownerContext.ownerSizePolicy = policy;\r
3442 }\r
3443\r
3444 shrinkWrap = (shrinkWrap === true) ? 3 : (shrinkWrap || 0); // false->0, true->3\r
3445\r
3446 // Now that we have shrinkWrap as a 0-3 value, we need to turn off shrinkWrap\r
3447 // bits for any dimension that has a configured size not in pixels. These must\r
3448 // be read from the DOM.\r
3449 //\r
3450 if (topLevel && shrinkWrap) {\r
3451 if (width && typeofWidth === 'string') {\r
3452 shrinkWrap &= 2; // percentage, "30em" or whatever - not width shrinkWrap\r
3453 }\r
3454 if (height && typeofHeight === 'string') {\r
3455 shrinkWrap &= 1; // percentage, "30em" or whatever - not height shrinkWrap\r
3456 }\r
3457 }\r
3458\r
3459 if (shrinkWrap !== 3) {\r
3460 if (!ownerCtSizeModel) {\r
3461 ownerCtSizeModel = me.ownerCt && me.ownerCt.getSizeModel();\r
3462 }\r
3463\r
3464 if (ownerCtSizeModel) {\r
3465 shrinkWrap |= (ownerCtSizeModel.width.shrinkWrap ? 1 : 0) | (ownerCtSizeModel.height.shrinkWrap ? 2 : 0);\r
3466 }\r
3467 }\r
3468\r
3469 if (!widthModel) {\r
3470 if (!policy.setsWidth) {\r
3471 if (hasPixelWidth) {\r
3472 widthModel = models.configured;\r
3473 } else {\r
3474 widthModel = (shrinkWrap & 1) ? models.shrinkWrap : models.natural;\r
3475 }\r
3476 } else if (policy.readsWidth) {\r
3477 if (hasPixelWidth) {\r
3478 widthModel = models.calculatedFromConfigured;\r
3479 } else {\r
3480 widthModel = (shrinkWrap & 1) ? models.calculatedFromShrinkWrap :\r
3481 models.calculatedFromNatural;\r
3482 }\r
3483 } else {\r
3484 widthModel = models.calculated;\r
3485 }\r
3486 }\r
3487\r
3488 if (!heightModel) {\r
3489 if (!policy.setsHeight) {\r
3490 if (hasPixelHeight) {\r
3491 heightModel = models.configured;\r
3492 } else {\r
3493 heightModel = (shrinkWrap & 2) ? models.shrinkWrap : models.natural;\r
3494 }\r
3495 } else if (policy.readsHeight) {\r
3496 if (hasPixelHeight) {\r
3497 heightModel = models.calculatedFromConfigured;\r
3498 } else {\r
3499 heightModel = (shrinkWrap & 2) ? models.calculatedFromShrinkWrap :\r
3500 models.calculatedFromNatural;\r
3501 }\r
3502 } else {\r
3503 heightModel = models.calculated;\r
3504 }\r
3505 }\r
3506 }\r
3507\r
3508 // We return one of the cached objects with the proper "width" and "height" as the\r
3509 // sizeModels we have determined.\r
3510 return widthModel.pairsByHeightOrdinal[heightModel.ordinal];\r
3511 },\r
3512\r
3513 /**\r
3514 * The supplied default state gathering method for the Component class.\r
3515 *\r
3516 * This method returns dimension settings such as `flex`, `anchor`, `width` and `height` along with `collapsed`\r
3517 * state.\r
3518 *\r
3519 * Subclasses which implement more complex state should call the superclass's implementation, and apply their state\r
3520 * to the result if this basic state is to be saved.\r
3521 *\r
3522 * Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider\r
3523 * configured for the document.\r
3524 *\r
3525 * @return {Object}\r
3526 */\r
3527 getState: function() {\r
3528 var me = this,\r
3529 state = null,\r
3530 sizeModel = me.getSizeModel();\r
3531\r
3532 if (sizeModel.width.configured) {\r
3533 state = me.addPropertyToState(state, 'width');\r
3534 }\r
3535 if (sizeModel.height.configured) {\r
3536 state = me.addPropertyToState(state, 'height');\r
3537 }\r
3538\r
3539 return state;\r
3540 },\r
3541\r
3542 getUserCls: function () {\r
3543 return this.userCls;\r
3544 },\r
3545\r
3546 setUserCls: function (cls) {\r
3547 var me = this,\r
3548 was = me.userCls;\r
3549\r
3550 if (cls !== was) {\r
3551 me.userCls = cls;\r
3552\r
3553 if (me.rendered) {\r
3554 me.el.replaceCls(was, cls);\r
3555 }\r
3556 }\r
3557\r
3558 return was;\r
3559 },\r
3560\r
3561 /**\r
3562 * Gets the current width of the component's underlying element.\r
3563 * @return {Number}\r
3564 */\r
3565 getWidth: function() {\r
3566 return this.el.getWidth();\r
3567 },\r
3568\r
3569 /**\r
3570 * Gets the xtype for this component as registered with {@link Ext.ComponentManager}. For a list of all available\r
3571 * xtypes, see the {@link Ext.Component} header. Example usage:\r
3572 *\r
3573 * var t = new Ext.form.field.Text();\r
3574 * alert(t.getXType()); // alerts 'textfield'\r
3575 *\r
3576 * @return {String} The xtype\r
3577 */\r
3578 getXType: function() {\r
3579 return this.self.xtype;\r
3580 },\r
3581\r
3582 /**\r
3583 * Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all available xtypes, see the\r
3584 * {@link Ext.Component} header.\r
3585 *\r
3586 * **If using your own subclasses, be aware that a Component must register its own xtype to participate in\r
3587 * determination of inherited xtypes.**\r
3588 *\r
3589 * Example usage:\r
3590 *\r
3591 * @example\r
3592 * var t = new Ext.form.field.Text();\r
3593 * alert(t.getXTypes()); // alerts 'component/field/textfield'\r
3594 *\r
3595 * @return {String} The xtype hierarchy string\r
3596 *\r
3597 * @since 2.3.0\r
3598 */\r
3599 getXTypes: function() {\r
3600 var self = this.self,\r
3601 xtypes, parentPrototype, parentXtypes;\r
3602\r
3603 if (!self.xtypes) {\r
3604 xtypes = [];\r
3605 parentPrototype = this;\r
3606\r
3607 while (parentPrototype) {\r
3608 parentXtypes = parentPrototype.xtypes;\r
3609\r
3610 if (parentXtypes !== undefined) {\r
3611 xtypes.unshift.apply(xtypes, parentXtypes);\r
3612 }\r
3613\r
3614 parentPrototype = parentPrototype.superclass;\r
3615 }\r
3616\r
3617 self.xtypeChain = xtypes;\r
3618 self.xtypes = xtypes.join('/');\r
3619 }\r
3620\r
3621 return self.xtypes;\r
3622 },\r
3623\r
3624 /**\r
3625 * Checks if the specified CSS class exists on this element's DOM node.\r
3626 * @param {String} className The CSS class to check for.\r
3627 * @return {Boolean} `true` if the class exists, else `false`.\r
3628 * @method\r
3629 */\r
3630 hasCls: function (cls) {\r
3631 var el = this.rendered ? this.el : this.protoEl;\r
3632 return el.hasCls.apply(el, arguments);\r
3633 },\r
3634\r
3635 /**\r
3636 * Checks if there is currently a specified `uiCls`.\r
3637 * @param {String} cls The `cls` to check.\r
3638 */\r
3639 hasUICls: function(cls) {\r
3640 var me = this,\r
3641 uiCls = me.uiCls || [];\r
3642\r
3643 return Ext.Array.contains(uiCls, cls);\r
3644 },\r
3645\r
3646 /**\r
3647 * Hides this Component, setting it to invisible using the configured {@link #hideMode}.\r
3648 * @param {String/Ext.dom.Element/Ext.Component} [animateTarget=null] **only valid for {@link #cfg-floating} Components\r
3649 * such as {@link Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have\r
3650 * been configured with `floating: true`.**. The target to which the Component should animate while hiding.\r
3651 * @param {Function} [callback] A callback function to call after the Component is hidden.\r
3652 * @param {Object} [scope] The scope (`this` reference) in which the callback is executed.\r
3653 * Defaults to this Component.\r
3654 * @return {Ext.Component} this\r
3655 */\r
3656 hide: function(animateTarget, cb, scope) {\r
3657 var me = this;\r
3658\r
3659 if (me.pendingShow) {\r
3660 // If this is a hierarchically hidden floating component with a pending show\r
3661 // hide() simply cancels the pending show.\r
3662 me.pendingShow = false;\r
3663 }\r
3664\r
3665 if (!(me.rendered && !me.isVisible())) {\r
3666 if (!me.hasListeners.beforehide || me.fireEvent('beforehide', me) !== false || me.hierarchicallyHidden) {\r
3667 me.getInherited().hidden = me.hidden = true;\r
3668\r
3669 // Order of events is important here. Hierarchy event kicks off\r
3670 // ZIndexManager's collection sorting and floater activation;\r
3671 // The hidden flag must be set so that ZIndexManager takes it out of its stack.\r
3672 me.fireHierarchyEvent('beforehide');\r
3673\r
3674 if (me.rendered) {\r
3675 me.onHide.apply(me, arguments);\r
3676 }\r
3677 }\r
3678 }\r
3679 return me;\r
3680 },\r
3681\r
3682 /**\r
3683 * The initComponent template method is an important initialization step for a Component. It is intended to be\r
3684 * implemented by each subclass of Ext.Component to provide any needed constructor logic. The\r
3685 * initComponent method of the class being created is called first, with each initComponent method\r
3686 * up the hierarchy to Ext.Component being called thereafter. This makes it easy to implement and,\r
3687 * if needed, override the constructor logic of the Component at any step in the hierarchy.\r
3688 *\r
3689 * The initComponent method **must** contain a call to {@link Ext.Base#callParent callParent} in order\r
3690 * to ensure that the parent class' initComponent method is also called.\r
3691 *\r
3692 * All config options passed to the constructor are applied to `this` before initComponent is called,\r
3693 * so you can simply access them with `this.someOption`.\r
3694 *\r
3695 * The following example demonstrates using a dynamic string for the text of a button at the time of\r
3696 * instantiation of the class.\r
3697 *\r
3698 * Ext.define('DynamicButtonText', {\r
3699 * extend: 'Ext.button.Button',\r
3700 *\r
3701 * initComponent: function() {\r
3702 * this.text = new Date();\r
3703 * this.renderTo = Ext.getBody();\r
3704 * this.callParent();\r
3705 * }\r
3706 * });\r
3707 *\r
3708 * Ext.onReady(function() {\r
3709 * Ext.create('DynamicButtonText');\r
3710 * });\r
3711 *\r
3712 * @template\r
3713 * @protected\r
3714 * @since 1.1.0\r
3715 */\r
3716 initComponent: function () {\r
3717 var me = this,\r
3718 width = me.width,\r
3719 height = me.height;\r
3720\r
3721 // If plugins have been added by a subclass's initComponent before calling up to here (or any components\r
3722 // that don't have a table view), the processed flag will not have been set, and we must process them again.\r
3723 // We could just call getPlugins here however most components don't have them so prevent the extra function call.\r
3724 if (me.plugins && !me.plugins.processed) {\r
3725 me.plugins = me.constructPlugins();\r
3726 }\r
3727 me.pluginsInitialized = true;\r
3728\r
3729 // this will properly (ignore or) constrain the configured width/height to their\r
3730 // min/max values for consistency.\r
3731 if (width != null || height != null) {\r
3732 me.setSize(width, height);\r
3733 }\r
3734\r
3735 if (me.listeners) {\r
3736 me.on(me.listeners);\r
3737 me.listeners = null; //change the value to remove any on prototype\r
3738 }\r
3739 \r
3740 if (me.focusable) {\r
3741 me.initFocusable();\r
3742 }\r
3743 },\r
3744\r
3745 /**\r
3746 * Initialize any events on this component\r
3747 * @protected\r
3748 */\r
3749 initEvents: function() {\r
3750 var me = this,\r
3751 afterRenderEvents = me.afterRenderEvents,\r
3752 afterRenderEvent, el, property, index, len;\r
3753\r
3754 if (afterRenderEvents) {\r
3755 for (property in afterRenderEvents) {\r
3756 el = me[property];\r
3757\r
3758 if (el && el.on) {\r
3759 afterRenderEvent = afterRenderEvents[property];\r
3760\r
3761 for (index = 0, len = afterRenderEvent.length ; index < len ; ++index) {\r
3762 me.mon(el, afterRenderEvent[index]);\r
3763 }\r
3764 }\r
3765 }\r
3766 }\r
3767 \r
3768 if (me.focusable) {\r
3769 me.initFocusableEvents();\r
3770 }\r
3771 },\r
3772\r
3773 /**\r
3774 * Tests whether this Component matches a {@link Ext.ComponentQuery ComponentQuery}\r
3775 * selector string.\r
3776 * @param {String} selector The selector string to test against.\r
3777 * @return {Boolean} `true` if this Component matches the selector.\r
3778 */\r
3779 is: function(selector) {\r
3780 return Ext.ComponentQuery.is(this, selector);\r
3781 },\r
3782\r
3783 /**\r
3784 * Determines whether this component is the descendant of a passed component.\r
3785 * @param {Ext.Component} ancestor A Component which may contain this Component.\r
3786 * @return {Boolean} `true` if the component is the descendant of the passed component, otherwise `false`.\r
3787 */\r
3788 isDescendantOf: function(ancestor) {\r
3789 var p;\r
3790\r
3791 // Iterate up the owner chain until we don't have one, or we find the ancestor.\r
3792 for (p = this.getRefOwner(); p && p !== ancestor; p = p.getRefOwner()) {\r
3793 // do nothing\r
3794 }\r
3795 return p || null;\r
3796 },\r
3797\r
3798 /**\r
3799 * Determines whether **this Component** is an ancestor of the passed Component.\r
3800 * This will return `true` if the passed Component is anywhere within the subtree\r
3801 * beneath this Component.\r
3802 * @param {Ext.Component} possibleDescendant The Component to test for presence\r
3803 * within this Component's subtree.\r
3804 */\r
3805 isAncestor: function(possibleDescendant) {\r
3806 while (possibleDescendant) {\r
3807 if (possibleDescendant.getRefOwner() === this) {\r
3808 return true;\r
3809 }\r
3810 possibleDescendant = possibleDescendant.getRefOwner();\r
3811 }\r
3812 },\r
3813\r
3814 /**\r
3815 * Method to determine whether this Component is currently disabled.\r
3816 * @return {Boolean} the disabled state of this Component.\r
3817 */\r
3818 isDisabled: function() {\r
3819 return this.disabled;\r
3820 },\r
3821\r
3822 /**\r
3823 * Method to determine whether this Component is draggable.\r
3824 * @return {Boolean} the draggable state of this component.\r
3825 */\r
3826 isDraggable: function() {\r
3827 return !!this.draggable;\r
3828 },\r
3829\r
3830 /**\r
3831 * Method to determine whether this Component is droppable.\r
3832 * @return {Boolean} the droppable state of this component.\r
3833 */\r
3834 isDroppable: function() {\r
3835 return !!this.droppable;\r
3836 },\r
3837\r
3838 /**\r
3839 * Method to determine whether this Component is floating.\r
3840 * @return {Boolean} the floating state of this component.\r
3841 */\r
3842 isFloating: function() {\r
3843 return this.floating;\r
3844 },\r
3845\r
3846 /**\r
3847 * Method to determine whether this Component is currently set to hidden.\r
3848 * @return {Boolean} the hidden state of this Component.\r
3849 */\r
3850 isHidden: function() {\r
3851 return this.hidden;\r
3852 },\r
3853\r
3854 isHierarchicallyHidden: function() {\r
3855 var child = this,\r
3856 hidden = false,\r
3857 parent, parentInheritedState;\r
3858\r
3859 // It is possible for some components to be immune to collapse meaning the immune\r
3860 // component remains visible when its direct parent is collapsed, e.g. panel header.\r
3861 // Because of this, we must walk up the component hierarchy to determine the true\r
3862 // visible state of the component.\r
3863 for (; (parent = child.ownerCt || child.floatParent); child = parent) {\r
3864 parentInheritedState = parent.getInherited();\r
3865 if (parentInheritedState.hidden) {\r
3866 hidden = true;\r
3867 break;\r
3868 }\r
3869 if (child.getInherited().collapseImmune) {\r
3870 // The child or one of its ancestors is immune to collapse.\r
3871 if (parent.collapsed && !child.collapseImmune) {\r
3872 // If the child's direct parent is collapsed, and the child\r
3873 // itself does not have collapse immunity we know that\r
3874 // the child is not visible.\r
3875 hidden = true;\r
3876 break;\r
3877 }\r
3878 } else {\r
3879 // We have ascended the tree to a point where collapse immunity\r
3880 // is not in play. This means if any ancestor above this point\r
3881 // is collapsed, then the component is not visible.\r
3882 hidden = !!parentInheritedState.collapsed;\r
3883 break;\r
3884 }\r
3885 }\r
3886\r
3887 return hidden;\r
3888 },\r
3889\r
3890 /**\r
3891 * Checks if this component will be contained by the passed component as part of its\r
3892 * layout run. If `true`, then the layout on `this` can be skipped because it will be\r
3893 * encompassed when the layout for `comp` runs. Typical cases where this may be be `false`\r
3894 * is when asking about floaters nested in containers.\r
3895 * @param {Ext.Component} comp The potential owner.\r
3896 * @return {Boolean} `true` if this component is a layout child of `comp`.\r
3897 *\r
3898 * @private\r
3899 */\r
3900 isLayoutChild: function(ownerCandidate) {\r
3901 return !this.floating && !!this.up(ownerCandidate);\r
3902 },\r
3903\r
3904 /**\r
3905 * Determines whether this Component is the root of a layout. This returns `true` if\r
3906 * this component can run its layout without assistance from or impact on its owner.\r
3907 * If this component cannot run its layout given these restrictions, `false` is returned\r
3908 * and its owner will be considered as the next candidate for the layout root.\r
3909 *\r
3910 * Setting the {@link #_isLayoutRoot} property to `true` causes this method to always\r
3911 * return `true`. This may be useful when updating a layout of a Container which shrink\r
3912 * wraps content, and you know that it will not change size, and so can safely be the\r
3913 * topmost participant in the layout run.\r
3914 * @protected\r
3915 */\r
3916 isLayoutRoot: function() {\r
3917 var me = this,\r
3918 ownerLayout = me.ownerLayout;\r
3919\r
3920 // Return true if we have been explicitly flagged as the layout root, or if we are floating.\r
3921 // Sometimes floating Components get an ownerCt ref injected into them which is *not* a true ownerCt, merely\r
3922 // an upward link for reference purposes. For example a grid column menu is linked to the\r
3923 // owning header via an ownerCt reference.\r
3924 if (!ownerLayout || me._isLayoutRoot || me.floating) {\r
3925 return true;\r
3926 }\r
3927\r
3928 return ownerLayout.isItemLayoutRoot(me);\r
3929 },\r
3930\r
3931 /**\r
3932 * Returns `true` if layout is suspended for this component. This can come from direct\r
3933 * suspension of this component's layout activity ({@link Ext.Container#suspendLayout}) or if one\r
3934 * of this component's containers is suspended.\r
3935 *\r
3936 * @return {Boolean} `true` layout of this component is suspended.\r
3937 */\r
3938 isLayoutSuspended: function () {\r
3939 var comp = this,\r
3940 ownerLayout;\r
3941\r
3942 while (comp) {\r
3943 if (comp.layoutSuspendCount || comp.suspendLayout) {\r
3944 return true;\r
3945 }\r
3946\r
3947 ownerLayout = comp.ownerLayout;\r
3948 if (!ownerLayout) {\r
3949 break;\r
3950 }\r
3951\r
3952 // TODO - what about suspending a Layout instance?\r
3953\r
3954 // this works better than ownerCt since ownerLayout means "is managed by" in\r
3955 // the proper sense... some floating components have ownerCt but won't have an\r
3956 // ownerLayout\r
3957 comp = ownerLayout.owner;\r
3958 }\r
3959\r
3960 return false;\r
3961 },\r
3962\r
3963 /**\r
3964 * Returns `true` if this component is visible.\r
3965 *\r
3966 * @param {Boolean} [deep=false] Pass `true` to interrogate the visibility status of all parent Containers to\r
3967 * determine whether this Component is truly visible to the user.\r
3968 *\r
3969 * Generally, to determine whether a Component is hidden, the no argument form is needed. For example when creating\r
3970 * dynamically laid out UIs in a hidden Container before showing them.\r
3971 *\r
3972 * @return {Boolean} `true` if this component is visible, `false` otherwise.\r
3973 *\r
3974 * @since 1.1.0\r
3975 */\r
3976 isVisible: function(deep) {\r
3977 var me = this,\r
3978 hidden;\r
3979\r
3980 if (me.hidden || !me.rendered || me.destroyed) {\r
3981 hidden = true;\r
3982 } else if (deep) {\r
3983 hidden = me.isHierarchicallyHidden();\r
3984 }\r
3985\r
3986 return !hidden;\r
3987 },\r
3988\r
3989 /**\r
3990 * Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended\r
3991 * from the xtype (default) or whether it is directly of the xtype specified (`shallow = true`).\r
3992 *\r
3993 * **If using your own subclasses, be aware that a Component must register its own xtype to participate in\r
3994 * determination of inherited xtypes.**\r
3995 *\r
3996 * For a list of all available xtypes, see the {@link Ext.Component} header.\r
3997 *\r
3998 * Example usage:\r
3999 *\r
4000 * @example\r
4001 * var t = new Ext.form.field.Text();\r
4002 * var isText = t.isXType('textfield'); // true\r
4003 * var isBoxSubclass = t.isXType('field'); // true, descended from Ext.form.field.Base\r
4004 * var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance\r
4005 *\r
4006 * @param {String} xtype The xtype to check for this Component\r
4007 * @param {Boolean} [shallow=false] `true` to check whether this Component is directly of the specified xtype, `false` to\r
4008 * check whether this Component is descended from the xtype.\r
4009 * @return {Boolean} `true` if this component descends from the specified xtype, `false` otherwise.\r
4010 *\r
4011 * @since 2.3.0\r
4012 */\r
4013 isXType: function(xtype, shallow) {\r
4014 return shallow ? (Ext.Array.indexOf(this.xtypes, xtype) !== -1) :\r
4015 !!this.xtypesMap[xtype];\r
4016 },\r
4017 \r
4018 /**\r
4019 * Returns masked state for this Component.\r
4020 *\r
4021 * @param {Boolean} [deep=false] True to look up this Component's parent masked state.\r
4022 *\r
4023 * @return {Boolean} True if masked, false otherwise.\r
4024 */\r
4025 isMasked: function(deep) {\r
4026 var me = this;\r
4027 \r
4028 return !!(me.masked || (me.loadMask && me.loadMask.isVisible()) ||\r
4029 (deep && me.getInherited().masked));\r
4030 },\r
4031 \r
4032 /**\r
4033 * Set masked state for this Component.\r
4034 *\r
4035 * @param {Boolean} isMasked True if masked, false otherwise.\r
4036 * @private\r
4037 */\r
4038 setMasked: function(isMasked) {\r
4039 var me = this,\r
4040 container = me.focusableContainer;\r
4041 \r
4042 if (isMasked) {\r
4043 me.masked = true;\r
4044 me.getInherited().masked = isMasked;\r
4045 } else {\r
4046 me.masked = false;\r
4047 delete me.getInherited().masked;\r
4048 }\r
4049 \r
4050 if (container) {\r
4051 container.onFocusableChildMasked(me, isMasked);\r
4052 }\r
4053 \r
4054 return me;\r
4055 },\r
4056\r
4057 /**\r
4058 * Masks this component with a semi-opaque layer and makes the contents unavailable to clicks.\r
4059 *\r
4060 * See {@link #unmask}.\r
4061 *\r
4062 * @param {String} [msg] A message to show in the center of the mask layer.\r
4063 * @param {String} [msgCls] A CSS class name to use on the message element in the center of the layer.\r
4064 */\r
4065 mask: function (msg, msgCls, elHeight) {\r
4066 var box = this.lastBox,\r
4067 // getMaskTarget may be overridden in subclasses/\r
4068 // null means that a LoadMask has to be rendered to document.body\r
4069 // Element masking falls back to masking the local el\r
4070 target = this.getMaskTarget() || this.el;\r
4071\r
4072 // Pass it the height of our element if we know it.\r
4073 if (box) {\r
4074 elHeight = box.height;\r
4075 }\r
4076 target.mask(msg, msgCls, elHeight);\r
4077 \r
4078 this.setMasked(true);\r
4079 },\r
4080\r
4081 /**\r
4082 * Returns the next node in the Component tree in tree traversal order.\r
4083 *\r
4084 * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the\r
4085 * tree to attempt to find a match. Contrast with {@link #nextSibling}.\r
4086 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.\r
4087 * @return {Ext.Component} The next node (or the next node which matches the selector).\r
4088 * Returns `null` if there is no matching node.\r
4089 */\r
4090 nextNode: function(selector, /* private */ includeSelf) {\r
4091 var node = this,\r
4092 ownerCt = node.ownerCt,\r
4093 result,\r
4094 it, len, i, sib;\r
4095\r
4096 // If asked to include self, test me\r
4097 if (includeSelf && node.is(selector)) {\r
4098 return node;\r
4099 }\r
4100\r
4101 if (ownerCt) {\r
4102 for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) + 1, len = it.length; i < len; i++) {\r
4103 sib = it[i];\r
4104 if (sib.is(selector)) {\r
4105 return sib;\r
4106 }\r
4107 if (sib.down) {\r
4108 result = sib.down(selector);\r
4109 if (result) {\r
4110 return result;\r
4111 }\r
4112 }\r
4113 }\r
4114 return ownerCt.nextNode(selector);\r
4115 }\r
4116 return null;\r
4117 },\r
4118\r
4119 /**\r
4120 * Returns the next sibling of this Component.\r
4121 *\r
4122 * Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.\r
4123 *\r
4124 * May also be referred to as **`next()`**\r
4125 *\r
4126 * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with\r
4127 * {@link #nextNode}\r
4128 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.\r
4129 * @return {Ext.Component} The next sibling (or the next sibling which matches the selector).\r
4130 * Returns `null` if there is no matching sibling.\r
4131 */\r
4132 nextSibling: function(selector) {\r
4133 var o = this.ownerCt, it, last, idx, c;\r
4134 if (o) {\r
4135 it = o.items;\r
4136 idx = it.indexOf(this) + 1;\r
4137 if (idx) {\r
4138 if (selector) {\r
4139 for (last = it.getCount(); idx < last; idx++) {\r
4140 if ((c = it.getAt(idx)).is(selector)) {\r
4141 return c;\r
4142 }\r
4143 }\r
4144 } else {\r
4145 if (idx < it.getCount()) {\r
4146 return it.getAt(idx);\r
4147 }\r
4148 }\r
4149 }\r
4150 }\r
4151 return null;\r
4152 },\r
4153\r
4154 /**\r
4155 * Method to manage awareness of when components are added to their\r
4156 * respective Container, firing an #added event. References are\r
4157 * established at add time rather than at render time.\r
4158 *\r
4159 * Allows addition of behavior when a Component is added to a\r
4160 * Container. At this stage, the Component is in the parent\r
4161 * Container's collection of child items. After calling the\r
4162 * superclass's `onAdded`, the `ownerCt` reference will be present,\r
4163 * and if configured with a ref, the `refOwner` will be set.\r
4164 *\r
4165 * @param {Ext.container.Container} container Container which holds the component.\r
4166 * @param {Number} pos Position at which the component was added.\r
4167 * @param {Boolean} instanced `false` if this component was instanced by the parent\r
4168 * container. `true` if the instance already existed when it was passed to the container.\r
4169 *\r
4170 * @template\r
4171 * @protected\r
4172 * @since 3.4.0\r
4173 */\r
4174 onAdded: function (container, pos, instanced) {\r
4175 var me = this;\r
4176\r
4177 me.ownerCt = container;\r
4178\r
4179 me.onInheritedAdd(me, instanced);\r
4180\r
4181 if (me.hasListeners && me.hasListeners.added) {\r
4182 me.fireEvent('added', me, container, pos);\r
4183 }\r
4184\r
4185 if (Ext.GlobalEvents.hasListeners.added) {\r
4186 me.fireHierarchyEvent('added');\r
4187 }\r
4188 },\r
4189 \r
4190 /**\r
4191 * Method to manage awareness of when components are removed from their\r
4192 * respective Container, firing a #removed event. References are properly\r
4193 * cleaned up after removing a component from its owning container.\r
4194 *\r
4195 * Allows addition of behavior when a Component is removed from\r
4196 * its parent Container. At this stage, the Component has been\r
4197 * removed from its parent Container's collection of child items,\r
4198 * but has not been destroyed (It will be destroyed if the parent\r
4199 * Container's `autoDestroy` is `true`, or if the remove call was\r
4200 * passed a truthy second parameter). After calling the\r
4201 * superclass's `onRemoved`, the `ownerCt` and the `refOwner` will not\r
4202 * be present.\r
4203 * @param {Boolean} destroying Will be passed as `true` if the Container performing the remove operation will delete this\r
4204 * Component upon remove.\r
4205 *\r
4206 * @template\r
4207 * @protected\r
4208 * @since 3.4.0\r
4209 */\r
4210 onRemoved: function(destroying) {\r
4211 var me = this,\r
4212 refHolder;\r
4213\r
4214 if (Ext.GlobalEvents.hasListeners.removed) {\r
4215 me.fireHierarchyEvent('removed');\r
4216 }\r
4217\r
4218 if (me.hasListeners.removed) {\r
4219 me.fireEvent('removed', me, me.ownerCt);\r
4220 }\r
4221 \r
4222 if (!destroying) {\r
4223 me.removeBindings();\r
4224 }\r
4225\r
4226 me.onInheritedRemove(destroying);\r
4227\r
4228 me.ownerCt = me.ownerLayout = null;\r
4229 },\r
4230\r
4231 /**\r
4232 * Invoked when this component has first achieved size. Occurs after the\r
4233 * {@link #componentLayout} has completed its initial run.\r
4234 *\r
4235 * This method is not called on components that use {@link #liquidLayout}, such as\r
4236 * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.\r
4237 * \r
4238 * **Note:** If the Component has a {@link Ext.Component#controller ViewController} \r
4239 * and the controller has a {@link Ext.app.ViewController#boxReady boxReady} method \r
4240 * it will be called passing the Component as the single param.\r
4241 *\r
4242 * @param {Number} width The width of this component\r
4243 * @param {Number} height The height of this component\r
4244 *\r
4245 * @template\r
4246 * @protected\r
4247 */\r
4248 onBoxReady: function(width, height) {\r
4249 var me = this,\r
4250 label;\r
4251 \r
4252 // We have to do this lookup onBoxReady instead of afterRender\r
4253 // to ensure that the components that could be referenced in\r
4254 // me.ariaLabelledBy or me.ariaDescribedBy are already rendered\r
4255 if (me.ariaLabelledBy || me.ariaDescribedBy) {\r
4256 if (me.ariaLabelledBy) {\r
4257 label = me.getAriaLabelEl(me.ariaLabelledBy);\r
4258 \r
4259 if (label) {\r
4260 me.ariaEl.dom.setAttribute('aria-labelledby', label);\r
4261 }\r
4262 }\r
4263 \r
4264 if (me.ariaDescribedBy) {\r
4265 label = me.getAriaLabelEl(me.ariaDescribedBy);\r
4266 \r
4267 if (label) {\r
4268 me.ariaEl.dom.setAttribute('aria-describedby', label);\r
4269 }\r
4270 }\r
4271 }\r
4272 \r
4273 if (me.resizable) {\r
4274 me.initResizable(me.resizable);\r
4275 }\r
4276\r
4277 // Draggability must be initialized after resizability\r
4278 // Because if we have to be wrapped, the resizer wrapper must be dragged as a pseudo-Component\r
4279 if (me.draggable) {\r
4280 me.initDraggable();\r
4281 }\r
4282\r
4283 if (me.hasListeners.boxready) {\r
4284 me.fireEvent('boxready', me, width, height);\r
4285 }\r
4286 },\r
4287\r
4288 /**\r
4289 * Allows addition of behavior to the destroy operation.\r
4290 * After calling the superclass's onDestroy, the Component will be destroyed.\r
4291 *\r
4292 * @template\r
4293 * @protected\r
4294 */\r
4295 onDestroy: function() {\r
4296 var me = this,\r
4297 container = me.focusableContainer;\r
4298\r
4299 // Ensure that any ancillary components are destroyed.\r
4300 if (me.rendered) {\r
4301 Ext.destroy(\r
4302 me.dd,\r
4303 me.resizer,\r
4304 me.proxy,\r
4305 me.proxyWrap,\r
4306 me.resizerComponent,\r
4307 me.scrollable,\r
4308 me.contentEl\r
4309 );\r
4310 }\r
4311\r
4312 if (container) {\r
4313 container.onFocusableChildDestroy(me);\r
4314 }\r
4315\r
4316 if (me.focusable) {\r
4317 me.destroyFocusable();\r
4318 }\r
4319\r
4320 // Destroying the floatingItems ZIndexManager will also destroy descendant floating Components\r
4321 Ext.destroy(\r
4322 me.componentLayout,\r
4323 me.loadMask,\r
4324 me.floatingDescendants\r
4325 );\r
4326 },\r
4327\r
4328 /**\r
4329 * Allows addition of behavior to the disable operation.\r
4330 * After calling the superclass's `onDisable`, the Component will be disabled.\r
4331 *\r
4332 * @template\r
4333 * @protected\r
4334 */\r
4335 onDisable: function () {\r
4336 var me = this,\r
4337 dom, nodeName;\r
4338 \r
4339 if (me.focusable) {\r
4340 me.disableFocusable();\r
4341 }\r
4342 \r
4343 if (!me.ariaStaticRoles[me.ariaRole]) {\r
4344 me.ariaEl.dom.setAttribute('aria-disabled', true);\r
4345 }\r
4346 \r
4347 // Only mask if we're set to & nobody above us will do so\r
4348 if (me.maskOnDisable && !me.getInheritedConfig('disableMask', true)) {\r
4349 dom = me.el.dom;\r
4350 nodeName = dom.nodeName;\r
4351\r
4352 if (me.disabledRe.test(nodeName)) {\r
4353 dom.disabled = true;\r
4354 }\r
4355\r
4356 if (!me.nonMaskableRe.test(nodeName)) {\r
4357 me.mask();\r
4358 }\r
4359 }\r
4360 },\r
4361\r
4362 /**\r
4363 * Allows addition of behavior to the enable operation.\r
4364 * After calling the superclass's `onEnable`, the Component will be enabled.\r
4365 *\r
4366 * @template\r
4367 * @protected\r
4368 */\r
4369 onEnable: function () {\r
4370 var me = this,\r
4371 dom, nodeName;\r
4372 \r
4373 if (me.focusable) {\r
4374 me.enableFocusable();\r
4375 }\r
4376 \r
4377 if (!me.ariaStaticRoles[me.ariaRole]) {\r
4378 me.ariaEl.dom.setAttribute('aria-disabled', false);\r
4379 }\r
4380 \r
4381 if (me.maskOnDisable && me.getInherited().hasOwnProperty('masked')) {\r
4382 dom = me.el.dom;\r
4383 nodeName = dom.nodeName;\r
4384\r
4385 if (me.disabledRe.test(nodeName)) {\r
4386 dom.disabled = false;\r
4387 }\r
4388\r
4389 if (!me.nonMaskableRe.test(nodeName)) {\r
4390 me.unmask();\r
4391 }\r
4392 }\r
4393 },\r
4394\r
4395 onGlobalShow: function (c) {\r
4396 if (this.up(c)) {\r
4397 this.getScrollable().restoreState();\r
4398 }\r
4399 },\r
4400\r
4401 /**\r
4402 * Allows addition of behavior to the hide operation. After\r
4403 * calling the superclass's onHide, the Component will be hidden.\r
4404 *\r
4405 * Gets passed the same parameters as #hide.\r
4406 *\r
4407 * @param {String/Ext.dom.Element/Ext.Component} [animateTarget]\r
4408 * @param {Function} [callback]\r
4409 * @param {Object} [scope]\r
4410 *\r
4411 * @template\r
4412 * @protected\r
4413 */\r
4414 onHide: function(animateTarget, cb, scope) {\r
4415 var me = this,\r
4416 ghostPanel, fromSize, toBox;\r
4417 \r
4418 if (!me.ariaStaticRoles[me.ariaRole]) {\r
4419 me.ariaEl.dom.setAttribute('aria-hidden', true);\r
4420 }\r
4421 \r
4422 // Part of the Focusable mixin API.\r
4423 // If we have focus now, move focus back to whatever had it before.\r
4424 me.revertFocus();\r
4425\r
4426 // Default to configured animate target if none passed\r
4427 animateTarget = me.getAnimateTarget(animateTarget);\r
4428\r
4429 // Need to be able to ghost the Component\r
4430 if (!me.ghost) {\r
4431 animateTarget = null;\r
4432 }\r
4433 // If we're animating, kick off an animation of the ghost down to the target\r
4434 if (animateTarget) {\r
4435 toBox = {\r
4436 x: animateTarget.getX(),\r
4437 y: animateTarget.getY(),\r
4438 width: animateTarget.dom.offsetWidth,\r
4439 height: animateTarget.dom.offsetHeight\r
4440 };\r
4441 ghostPanel = me.ghost();\r
4442 ghostPanel.el.stopAnimation();\r
4443 fromSize = me.getSize();\r
4444 ghostPanel.el.animate({\r
4445 to: toBox,\r
4446 listeners: {\r
4447 afteranimate: function() {\r
4448 delete ghostPanel.componentLayout.lastComponentSize;\r
4449 ghostPanel.el.hide();\r
4450 ghostPanel.setHiddenState(true);\r
4451 ghostPanel.el.setSize(fromSize);\r
4452 me.afterHide(cb, scope);\r
4453 }\r
4454 }\r
4455 });\r
4456 }\r
4457 me.el.hide();\r
4458 if (!animateTarget) {\r
4459 me.afterHide(cb, scope);\r
4460 }\r
4461 },\r
4462\r
4463 /**\r
4464 * @method\r
4465 * Called after the component is moved, this method is empty by default but can be implemented by any\r
4466 * subclass that needs to perform custom logic after a move occurs.\r
4467 *\r
4468 * @param {Number} x The new x position.\r
4469 * @param {Number} y The new y position.\r
4470 *\r
4471 * @template\r
4472 * @protected\r
4473 */\r
4474 onPosition: Ext.emptyFn,\r
4475\r
4476 /**\r
4477 * Called when the component is resized.\r
4478 *\r
4479 * This method is not called on components that use {@link #liquidLayout}, such as\r
4480 * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.\r
4481 *\r
4482 * @method\r
4483 * @template\r
4484 * @protected\r
4485 */\r
4486 onResize: function(width, height, oldWidth, oldHeight) {\r
4487 var me = this;\r
4488\r
4489 // constrain is a config on Floating\r
4490 if (me.floating && me.constrain) {\r
4491 me.doConstrain();\r
4492 }\r
4493 \r
4494 me.refreshScroll();\r
4495\r
4496 if (me.hasListeners.resize) {\r
4497 me.fireEvent('resize', me, width, height, oldWidth, oldHeight);\r
4498 }\r
4499 },\r
4500\r
4501 /**\r
4502 * Invoked when a scroll is initiated on this component via its {@link #scrollable scroller}.\r
4503 * @method onScrollStart\r
4504 * @param {Number} x The current x position\r
4505 * @param {Number} y The current y position\r
4506 * @template\r
4507 * @protected\r
4508 */\r
4509\r
4510 /**\r
4511 * Invoked when this component is scrolled via its {@link #scrollable scroller}.\r
4512 * @method onScrollMove\r
4513 * @param {Number} x The current x position\r
4514 * @param {Number} y The current y position\r
4515 * @template\r
4516 * @protected\r
4517 */\r
4518\r
4519 /**\r
4520 * Invoked when a scroll operation is completed via this component's {@link #scrollable scroller}.\r
4521 * @method onScrollEnd\r
4522 * @param {Number} x The current x position\r
4523 * @param {Number} y The current y position\r
4524 * @template\r
4525 * @protected\r
4526 */\r
4527\r
4528 /**\r
4529 * Allows addition of behavior to the show operation. After\r
4530 * calling the superclass's onShow, the Component will be visible.\r
4531 *\r
4532 * Override in subclasses where more complex behaviour is needed.\r
4533 *\r
4534 * Gets passed the same parameters as #show.\r
4535 *\r
4536 * @param {String/Ext.dom.Element} [animateTarget]\r
4537 * @param {Function} [callback]\r
4538 * @param {Object} [scope]\r
4539 *\r
4540 * @template\r
4541 * @protected\r
4542 */\r
4543 onShow: function() {\r
4544 var me = this;\r
4545 \r
4546 if (!me.ariaStaticRoles[me.ariaRole]) {\r
4547 me.ariaEl.dom.setAttribute('aria-hidden', false);\r
4548 }\r
4549 \r
4550 me.el.show();\r
4551 \r
4552 me.updateLayout({ isRoot: false });\r
4553\r
4554 // Constraining/containing element may have changed size while this Component was hidden\r
4555 if (me.floating) {\r
4556 if (me.maximized) {\r
4557 me.fitContainer();\r
4558 }\r
4559 else if (me.constrain) {\r
4560 me.doConstrain();\r
4561 }\r
4562 }\r
4563 },\r
4564\r
4565 /**\r
4566 * Invoked after the #afterShow method is complete.\r
4567 *\r
4568 * Gets passed the same `callback` and `scope` parameters that #afterShow received.\r
4569 *\r
4570 * @param {Function} [callback]\r
4571 * @param {Object} [scope]\r
4572 *\r
4573 * @template\r
4574 * @protected\r
4575 */\r
4576 onShowComplete: function(cb, scope) {\r
4577 var me = this,\r
4578 container = me.focusableContainer;\r
4579 \r
4580 if (me.floating) {\r
4581 me.onFloatShow();\r
4582 }\r
4583 \r
4584 Ext.callback(cb, scope || me);\r
4585 me.fireEvent('show', me);\r
4586 \r
4587 if (container) {\r
4588 container.onFocusableChildShow(me);\r
4589 }\r
4590 \r
4591 delete me.hiddenByLayout;\r
4592 },\r
4593\r
4594 onShowVeto: Ext.emptyFn,\r
4595\r
4596 /**\r
4597 * Returns the previous node in the Component tree in tree traversal order.\r
4598 *\r
4599 * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the\r
4600 * tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.\r
4601 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.\r
4602 * @return {Ext.Component} The previous node (or the previous node which matches the selector).\r
4603 * Returns `null` if there is no matching node.\r
4604 */\r
4605 previousNode: function(selector, /* private */ includeSelf) {\r
4606 var node = this,\r
4607 ownerCt = node.ownerCt,\r
4608 result,\r
4609 it, i, sib;\r
4610\r
4611 // If asked to include self, test me\r
4612 if (includeSelf && node.is(selector)) {\r
4613 return node;\r
4614 }\r
4615\r
4616 if (ownerCt) {\r
4617 for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {\r
4618 sib = it[i];\r
4619 if (sib.query) {\r
4620 result = sib.query(selector);\r
4621 result = result[result.length - 1];\r
4622 if (result) {\r
4623 return result;\r
4624 }\r
4625 }\r
4626 if (sib.is(selector)) {\r
4627 return sib;\r
4628 }\r
4629 }\r
4630 return ownerCt.previousNode(selector, true);\r
4631 }\r
4632 return null;\r
4633 },\r
4634\r
4635 /**\r
4636 * Returns the previous sibling of this Component.\r
4637 *\r
4638 * Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery}\r
4639 * selector.\r
4640 *\r
4641 * May also be referred to as **`prev()`**\r
4642 *\r
4643 * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with\r
4644 * {@link #previousNode}\r
4645 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.\r
4646 * @return {Ext.Component} The previous sibling (or the previous sibling which matches the selector).\r
4647 * Returns `null` if there is no matching sibling.\r
4648 */\r
4649 previousSibling: function(selector) {\r
4650 var o = this.ownerCt, it, idx, c;\r
4651 if (o) {\r
4652 it = o.items;\r
4653 idx = it.indexOf(this);\r
4654 if (idx !== -1) {\r
4655 if (selector) {\r
4656 for (--idx; idx >= 0; idx--) {\r
4657 if ((c = it.getAt(idx)).is(selector)) {\r
4658 return c;\r
4659 }\r
4660 }\r
4661 } else {\r
4662 if (idx) {\r
4663 return it.getAt(--idx);\r
4664 }\r
4665 }\r
4666 }\r
4667 }\r
4668 return null;\r
4669 },\r
4670\r
4671 /**\r
4672 * Called by Component#doAutoRender\r
4673 *\r
4674 * Register a Container configured `floating: true` with this Component's {@link Ext.ZIndexManager ZIndexManager}.\r
4675 *\r
4676 * Components added in this way will not participate in any layout, but will be rendered\r
4677 * upon first show in the way that {@link Ext.window.Window Window}s are.\r
4678 */\r
4679 registerFloatingItem: function(cmp) {\r
4680 var me = this;\r
4681 if (!me.floatingDescendants) {\r
4682 me.floatingDescendants = new Ext.ZIndexManager(me);\r
4683 }\r
4684 me.floatingDescendants.register(cmp);\r
4685 },\r
4686\r
4687 /**\r
4688 * Removes a CSS class from the top level element representing this component.\r
4689 * @param {String/String[]} cls The CSS class name to remove.\r
4690 * @return {Ext.Component} Returns the Component to allow method chaining.\r
4691 */\r
4692 removeCls: function(cls) {\r
4693 var me = this,\r
4694 el = me.rendered ? me.el : me.protoEl;\r
4695\r
4696 el.removeCls.apply(el, arguments);\r
4697 return me;\r
4698 },\r
4699\r
4700 /**\r
4701 * Removes a `cls` to the `uiCls` array, which will also call {@link #removeUIClsFromElement} and removes it from all\r
4702 * elements of this component.\r
4703 * @param {String/String[]} cls A string or an array of strings to remove to the `uiCls`.\r
4704 */\r
4705 removeClsWithUI: function(classes, skip) {\r
4706 var me = this,\r
4707 clsArray = [],\r
4708 i = 0,\r
4709 extArray = Ext.Array,\r
4710 remove = extArray.remove,\r
4711 uiCls = me.uiCls = extArray.clone(me.uiCls),\r
4712 activeUI = me.activeUI,\r
4713 length, cls;\r
4714\r
4715 if (typeof classes === "string") {\r
4716 classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);\r
4717 }\r
4718\r
4719 length = classes.length;\r
4720\r
4721 for (i = 0; i < length; i++) {\r
4722 cls = classes[i];\r
4723\r
4724 if (cls && me.hasUICls(cls)) {\r
4725 remove(uiCls, cls);\r
4726\r
4727 //If there's no activeUI then there's nothing to remove\r
4728 if (activeUI) {\r
4729 clsArray = clsArray.concat(me.removeUIClsFromElement(cls));\r
4730 }\r
4731 }\r
4732 }\r
4733\r
4734 if (skip !== true && activeUI) {\r
4735 me.removeCls(clsArray);\r
4736 }\r
4737\r
4738 return clsArray;\r
4739 },\r
4740\r
4741 resumeLayouts: function (flushOptions) {\r
4742 var me = this;\r
4743 if (!me.rendered) {\r
4744 return;\r
4745 }\r
4746 //<debug>\r
4747 if (!me.layoutSuspendCount) {\r
4748 Ext.log.warn('Mismatched call to resumeLayouts - layouts are currently not suspended.');\r
4749 }\r
4750 //</debug>\r
4751 if (me.layoutSuspendCount && !--me.layoutSuspendCount) {\r
4752 me.suspendLayout = false;\r
4753 if (flushOptions && !me.isLayoutSuspended()) {\r
4754 me.updateLayout(flushOptions);\r
4755 }\r
4756 }\r
4757 },\r
4758\r
4759 /**\r
4760 * Scrolls this Component by the passed delta values, optionally animating.\r
4761 *\r
4762 * All of the following are equivalent:\r
4763 *\r
4764 * comp.scrollBy(10, 10, true);\r
4765 * comp.scrollBy([10, 10], true);\r
4766 * comp.scrollBy({ x: 10, y: 10 }, true);\r
4767 *\r
4768 * @param {Number/Number[]/Object} deltaX Either the x delta, an Array specifying x and y deltas or\r
4769 * an object with "x" and "y" properties.\r
4770 * @param {Number/Boolean/Object} deltaY Either the y delta, or an animate flag or config object.\r
4771 * @param {Boolean/Object} animate Animate flag/config object if the delta values were passed separately.\r
4772 */\r
4773 scrollBy: function(deltaX, deltaY, animate) {\r
4774 var scroller = this.getScrollable();\r
4775\r
4776 if (scroller) {\r
4777 scroller.scrollBy(deltaX, deltaY, animate);\r
4778 }\r
4779 },\r
4780\r
4781 /**\r
4782 * Scrolls this component to the specified `x` and `y` coordinates. Only applicable\r
4783 * for {@link #scrollable} components.\r
4784 * @param {Number} x\r
4785 * @param {Number} y\r
4786 * @param {Boolean/Object} [animate] true for the default animation or a standard Element\r
4787 * animation config object\r
4788 */\r
4789 scrollTo: function(x, y, animate) {\r
4790 var scroller = this.getScrollable();\r
4791\r
4792 if (scroller) {\r
4793 scroller.scrollTo(x, y, animate);\r
4794 }\r
4795 },\r
4796\r
4797 /**\r
4798 * Sets the overflow on the content element of the component.\r
4799 * @param {Boolean} scroll True to allow the Component to auto scroll.\r
4800 * @return {Ext.Component} this\r
4801 * @deprecated 5.0.0 Use {@link #setScrollable} instead\r
4802 */\r
4803 setAutoScroll: function(scroll) {\r
4804 this.setScrollable(!!scroll);\r
4805 return this;\r
4806 },\r
4807\r
4808 /**\r
4809 *\r
4810 * @param {String/Number} border The border, see {@link #border}. If a falsey value is passed\r
4811 * the border will be removed.\r
4812 */\r
4813 setBorder: function(border, /* private */ targetEl) {\r
4814 var me = this,\r
4815 initial = !!targetEl;\r
4816\r
4817 if (me.rendered || initial) {\r
4818 if (!initial) {\r
4819 targetEl = me.el;\r
4820 }\r
4821\r
4822 if (!border) {\r
4823 border = 0;\r
4824 } else if (border === true) {\r
4825 border = '1px';\r
4826 } else {\r
4827 border = this.unitizeBox(border);\r
4828 }\r
4829 targetEl.setStyle('border-width', border);\r
4830 if (!initial) {\r
4831 me.updateLayout();\r
4832 }\r
4833 }\r
4834 me.border = border;\r
4835 },\r
4836\r
4837 /**\r
4838 * Sets the dock position of this component in its parent panel. Note that this only has effect if this item is part\r
4839 * of the `dockedItems` collection of a parent that has a DockLayout (note that any Panel has a DockLayout by default)\r
4840 * @param {Object} dock The dock position.\r
4841 * @return {Ext.Component} this\r
4842 */\r
4843 setDock: function(dock) {\r
4844 var me = this,\r
4845 ownerCt = me.ownerCt;\r
4846\r
4847 if (dock !== me.dock) {\r
4848 if (ownerCt && ownerCt.moveDocked) {\r
4849 ownerCt.moveDocked(me, dock);\r
4850 } else {\r
4851 me.dock = dock;\r
4852 }\r
4853 }\r
4854\r
4855 return me;\r
4856 },\r
4857\r
4858 /**\r
4859 * Enable or disable the component.\r
4860 * @param {Boolean} disabled `true` to disable.\r
4861 */\r
4862 setDisabled: function(disabled) {\r
4863 return this[disabled ? 'disable': 'enable']();\r
4864 },\r
4865\r
4866 /**\r
4867 * Sets the flex property of this component. Only applicable when this component is\r
4868 * an item of a box layout\r
4869 * @private\r
4870 * @param {Number} flex\r
4871 */\r
4872 setFlex: function(flex) {\r
4873 this.flex = flex;\r
4874 },\r
4875\r
4876 /**\r
4877 * Sets the height of the component. This method fires the {@link #resize} event.\r
4878 *\r
4879 * @param {Number} height The new height to set. This may be one of:\r
4880 *\r
4881 * - A Number specifying the new height in pixels.\r
4882 * - A String used to set the CSS height style.\r
4883 * - `undefined` to leave the height unchanged.\r
4884 * - `null` to clear the height.\r
4885 *\r
4886 * @return {Ext.Component} this\r
4887 */\r
4888 setHeight: function(height) {\r
4889 return this.setSize(undefined, height);\r
4890 },\r
4891\r
4892 /**\r
4893 * This method allows you to show or hide a LoadMask on top of this component.\r
4894 *\r
4895 * The mask will be rendered into the element returned by {@link #getMaskTarget} which for most Components is the Component's\r
4896 * element. See {@link #getMaskTarget} and {@link #maskElement}.\r
4897 *\r
4898 * Most Components will return `null` indicating that their LoadMask cannot reside inside their element, but must\r
4899 * be rendered into the document body.\r
4900 *\r
4901 * {@link Ext.view.Table Grid Views} however will direct a LoadMask to be rendered into the owning {@link Ext.panel.Table GridPanel}.\r
4902 *\r
4903 * @param {Boolean/Object/String} load True to show the default LoadMask, a config object that will be passed to the\r
4904 * LoadMask constructor, or a message String to show. False to hide the current LoadMask.\r
4905 * @return {Ext.LoadMask} The LoadMask instance that has just been shown.\r
4906 */\r
4907 setLoading: function(load, /*deprecated */ targetEl) {\r
4908 var me = this,\r
4909 config = {\r
4910 target: me\r
4911 };\r
4912\r
4913 if (me.rendered) {\r
4914 // Shows mask for anything but false.\r
4915 if (load !== false) {\r
4916 if (Ext.isString(load)) {\r
4917 config.msg = load;\r
4918 } else {\r
4919 Ext.apply(config, load);\r
4920 }\r
4921 // We do not already have a LoadMask: create one\r
4922 if (!me.loadMask || !me.loadMask.isLoadMask) {\r
4923 // Deprecated second parameter.\r
4924 // maskElement config replaces this\r
4925 if (targetEl && config.useTargetEl == null) {\r
4926 config.useTargetEl = true;\r
4927 }\r
4928 me.loadMask = new Ext.LoadMask(config);\r
4929 }\r
4930 // Change any settings according to load config\r
4931 else {\r
4932 Ext.apply(me.loadMask, config);\r
4933 }\r
4934 // If already visible, just update display with passed configs.\r
4935 if (me.loadMask.isVisible()) {\r
4936 me.loadMask.syncMaskState();\r
4937 }\r
4938 // Otherwise show with new configs\r
4939 else {\r
4940 me.loadMask.show();\r
4941 }\r
4942 }\r
4943 // load == falsy: Hide the mask if it exists\r
4944 else {\r
4945 if (me.loadMask && me.loadMask.isLoadMask) {\r
4946 me.loadMask.hide();\r
4947 }\r
4948 }\r
4949 }\r
4950 return me.loadMask;\r
4951 },\r
4952\r
4953 /**\r
4954 * Sets the margin on the target element.\r
4955 * @param {Number/String} margin The margin to set. See the {@link #margin} config.\r
4956 */\r
4957 setMargin: function(margin, /* private */ preventLayout) {\r
4958 var me = this;\r
4959 \r
4960 if (me.rendered) {\r
4961 if (!margin && margin !== 0) {\r
4962 margin = '';\r
4963 } else {\r
4964 if (margin === true) {\r
4965 margin = 5;\r
4966 }\r
4967 margin = this.unitizeBox(margin);\r
4968 }\r
4969 me.margin = margin;\r
4970 // See: EXTJS-13359\r
4971 me.margin$ = null;\r
4972 me.getEl().setStyle('margin', margin);\r
4973 if (!preventLayout) {\r
4974 // Changing the margins can impact the position of this (and possibly) \r
4975 // other subsequent components in the layout.\r
4976 me.updateLayout(me._notAsLayoutRoot);\r
4977 }\r
4978 } else {\r
4979 me.margin = margin;\r
4980 }\r
4981 },\r
4982\r
4983 /**\r
4984 * Sets the overflow x/y on the content element of the component. The x/y overflow\r
4985 * values can be any valid CSS overflow (e.g., 'auto' or 'scroll'). By default, the\r
4986 * value is 'hidden'. Passing `undefined` will preserve the current value.\r
4987 *\r
4988 * @param {String} overflowX The overflow-x value.\r
4989 * @param {String} overflowY The overflow-y value.\r
4990 * @return {Ext.Component} this\r
4991 * @deprecated 5.0.0 Use {@link #setScrollable} instead\r
4992 */\r
4993 setOverflowXY: function(overflowX, overflowY) {\r
4994 this.setScrollable({\r
4995 x: (overflowX && overflowX !== 'hidden') ? overflowX : false,\r
4996 y: (overflowY && overflowY !== 'hidden') ? overflowY : false\r
4997 });\r
4998\r
4999 return this;\r
5000 },\r
5001\r
5002 /**\r
5003 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.\r
5004 * This method fires the {@link #event-move} event.\r
5005 * @param {Number/Number[]} x The new x position or an array of `[x,y]`.\r
5006 * @param {Number} [y] The new y position.\r
5007 * @param {Boolean/Object} [animate] True to animate the Component into its new position. You may also pass an\r
5008 * animation configuration.\r
5009 * @return {Ext.Component} this\r
5010 */\r
5011 setPagePosition: function(x, y, animate) {\r
5012 var me = this,\r
5013 p,\r
5014 floatParentBox;\r
5015\r
5016 if (Ext.isArray(x)) {\r
5017 y = x[1];\r
5018 x = x[0];\r
5019 }\r
5020 me.pageX = x;\r
5021 me.pageY = y;\r
5022\r
5023 if (me.floating) {\r
5024\r
5025 // Floating Components which are registered with a Container have to have their x and y properties made relative\r
5026 if (me.isContainedFloater()) {\r
5027 floatParentBox = me.floatParent.getTargetEl().getViewRegion();\r
5028 if (Ext.isNumber(x) && Ext.isNumber(floatParentBox.left)) {\r
5029 x -= floatParentBox.left;\r
5030 }\r
5031 if (Ext.isNumber(y) && Ext.isNumber(floatParentBox.top)) {\r
5032 y -= floatParentBox.top;\r
5033 }\r
5034 } else {\r
5035 p = me.el.translateXY(x, y);\r
5036 x = p.x;\r
5037 y = p.y;\r
5038 }\r
5039\r
5040 me.setPosition(x, y, animate);\r
5041 } else {\r
5042 p = me.el.translateXY(x, y);\r
5043 me.setPosition(p.x, p.y, animate);\r
5044 }\r
5045\r
5046 return me;\r
5047 },\r
5048\r
5049 /**\r
5050 * @member Ext.Component\r
5051 * Sets the left and top of the component. To set the page XY position instead, use {@link Ext.Component#setPagePosition setPagePosition}. This\r
5052 * method fires the {@link #event-move} event.\r
5053 * @param {Number/Number[]/Object} x The new left, an array of `[x,y]`, or animation config object containing `x` and `y` properties.\r
5054 * @param {Number} [y] The new top.\r
5055 * @param {Boolean/Object} [animate] If `true`, the Component is _animated_ into its new position. You may also pass an\r
5056 * animation configuration.\r
5057 * @return {Ext.Component} this\r
5058 */\r
5059 setPosition: function(x, y, animate) {\r
5060 var me = this,\r
5061 pos = me.beforeSetPosition.apply(me, arguments);\r
5062\r
5063 if (pos && me.rendered) {\r
5064 x = pos.x;\r
5065 y = pos.y;\r
5066\r
5067 if (animate) {\r
5068 // Proceed only if the new position is different from the current\r
5069 // one. We only do these DOM reads in the animate case as we don't\r
5070 // want to incur the penalty of read/write on every call to setPosition\r
5071 if (x !== me.getLocalX() || y !== me.getLocalY()) {\r
5072 me.stopAnimation();\r
5073 me.animate(Ext.apply({\r
5074 duration: 1000,\r
5075 listeners: {\r
5076 afteranimate: Ext.Function.bind(me.afterSetPosition, me, [x, y])\r
5077 },\r
5078 to: {\r
5079 // Use local coordinates for a component\r
5080 // We don't need to normalize this for RTL, the anim.target.Component\r
5081 // calls setPosition, which will normalize the x value to right when\r
5082 // it's necessary\r
5083 left: x,\r
5084 top: y\r
5085 }\r
5086 }, animate));\r
5087 }\r
5088 } else {\r
5089 me.setLocalXY(x, y);\r
5090 me.afterSetPosition(x, y);\r
5091 }\r
5092 }\r
5093 return me;\r
5094 },\r
5095\r
5096 /**\r
5097 * Sets the "x" scroll position for this component. Only applicable for\r
5098 * {@link #scrollable} components\r
5099 * @param {Number} x\r
5100 * @param {Boolean/Object} [animate] true for the default animation or a standard Element\r
5101 * animation config object\r
5102 */\r
5103 setScrollX: function(x, animate) {\r
5104 var scroller = this.getScrollable();\r
5105\r
5106 if (scroller) {\r
5107 scroller.scrollTo(x, null, animate);\r
5108 }\r
5109 },\r
5110\r
5111 /**\r
5112 * Sets the "y" scroll position for this component. Only applicable for\r
5113 * {@link #scrollable} components\r
5114 * @param {Number} y\r
5115 * @param {Boolean/Object} [animate] true for the default animation or a standard Element\r
5116 * animation config object\r
5117 */\r
5118 setScrollY: function(y, animate) {\r
5119 var scroller = this.getScrollable();\r
5120\r
5121 if (scroller) {\r
5122 scroller.scrollTo(null, y, animate);\r
5123 }\r
5124 },\r
5125\r
5126 /**\r
5127 * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept\r
5128 * either width and height as separate arguments, or you can pass a size object like `{width:10, height:20}`.\r
5129 *\r
5130 * @param {Number/String/Object} width The new width to set. This may be one of:\r
5131 *\r
5132 * - A Number specifying the new width in pixels.\r
5133 * - A String used to set the CSS width style.\r
5134 * - A size object in the format `{width: widthValue, height: heightValue}`.\r
5135 * - `undefined` to leave the width unchanged.\r
5136 *\r
5137 * @param {Number/String} height The new height to set (not required if a size object is passed as the first arg).\r
5138 * This may be one of:\r
5139 *\r
5140 * - A Number specifying the new height in pixels.\r
5141 * - A String used to set the CSS height style. Animation may **not** be used.\r
5142 * - `undefined` to leave the height unchanged.\r
5143 *\r
5144 * @return {Ext.Component} this\r
5145 */\r
5146 setSize: function(width, height) {\r
5147 var me = this,\r
5148 oldWidth = me.width,\r
5149 oldHeight = me.height,\r
5150 widthIsString, heightIsString;\r
5151\r
5152 // support for standard size objects\r
5153 if (width && typeof width === 'object') {\r
5154 height = width.height;\r
5155 width = width.width;\r
5156 }\r
5157\r
5158 // Constrain within configured maximum\r
5159 if (typeof width === 'number') {\r
5160 me.width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);\r
5161 } else if (width === null) {\r
5162 delete me.width;\r
5163 } else if(typeof width === 'string') {\r
5164 // handle width specified as a string css style\r
5165 widthIsString = true;\r
5166 me.width = width;\r
5167 }\r
5168 \r
5169 if (typeof height === 'number') {\r
5170 me.height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);\r
5171 } else if (height === null) {\r
5172 delete me.height;\r
5173 } else if(typeof height === 'string') {\r
5174 // handle width specified as a string css style\r
5175 heightIsString = true;\r
5176 me.height = height;\r
5177 }\r
5178\r
5179 // If not rendered, all we need to is set the properties.\r
5180 // The initial layout will set the size\r
5181 if (me.rendered && me.isVisible()) {\r
5182 if (oldWidth !== me.width || oldHeight !== me.height) {\r
5183 if (me.liquidLayout || widthIsString || heightIsString) {\r
5184 // if we have a liquid layout we must setSize now, since the following\r
5185 // updateLayout call will not set our size in the dom if we successfully\r
5186 // opt out of the layout run\r
5187 me.el.setSize(me.width, me.height);\r
5188 }\r
5189\r
5190 // If we are changing size, then we are not the root.\r
5191 me.updateLayout(me._notAsLayoutRoot);\r
5192 }\r
5193 }\r
5194\r
5195 return me;\r
5196 },\r
5197\r
5198 /**\r
5199 * Sets the style for this Component's primary element.\r
5200 * \r
5201 * Styles should be a valid DOM element style property. \r
5202 * [Valid style property names](http://www.w3schools.com/jsref/dom_obj_style.asp) \r
5203 * (_along with the supported CSS version for each_)\r
5204 * \r
5205 * var name = Ext.create({\r
5206 * xtype: 'component',\r
5207 * renderTo: Ext.getBody(),\r
5208 * html: 'Phineas Flynn'\r
5209 * });\r
5210 * \r
5211 * // two-param syntax\r
5212 * name.setStyle('color', 'white');\r
5213 * \r
5214 * // single-param syntax\r
5215 * name.setStyle({\r
5216 * fontWeight: 'bold',\r
5217 * backgroundColor: 'gray',\r
5218 * padding: '10px'\r
5219 * });\r
5220 * \r
5221 * @param {String/Object} property The style property to be set, or an object of\r
5222 * multiple styles.\r
5223 * @param {String} [value] The value to apply to the given property, or null if an\r
5224 * object was passed.\r
5225 * @return {Ext.Component} this\r
5226 */\r
5227 setStyle: function (prop, value) {\r
5228 var el = this.el || this.protoEl;\r
5229 el.setStyle(prop, value);\r
5230 return this;\r
5231 },\r
5232\r
5233 /**\r
5234 * Sets the UI for the component. This will remove any existing UIs on the component. It will also loop through any\r
5235 * `uiCls` set on the component and rename them so they include the new UI.\r
5236 * @param {String} ui The new UI for the component.\r
5237 */\r
5238 setUI: function(ui) {\r
5239 var me = this,\r
5240 uiCls = me.uiCls,\r
5241 activeUI = me.activeUI,\r
5242 classes;\r
5243\r
5244 if (ui === activeUI) {\r
5245 // The ui hasn't changed\r
5246 return;\r
5247 }\r
5248\r
5249 // activeUI will only be set if setUI has been called before. If it hasn't there's no need to remove anything\r
5250 if (activeUI) {\r
5251 classes = me.removeClsWithUI(uiCls, true);\r
5252\r
5253 if (classes.length) {\r
5254 me.removeCls(classes);\r
5255 }\r
5256\r
5257 // Remove the UI from the element\r
5258 me.removeUIFromElement();\r
5259 }\r
5260 else {\r
5261 // We need uiCls to be empty otherwise our call to addClsWithUI won't do anything\r
5262 me.uiCls = [];\r
5263 }\r
5264\r
5265 // Set the UI\r
5266 me.ui = ui;\r
5267\r
5268 // After the first call to setUI the values ui and activeUI should track each other but initially we need some\r
5269 // way to tell whether the ui has really been set.\r
5270 me.activeUI = ui;\r
5271\r
5272 // Add the new UI to the element\r
5273 me.addUIToElement();\r
5274\r
5275 classes = me.addClsWithUI(uiCls, true);\r
5276\r
5277 if (classes.length) {\r
5278 me.addCls(classes);\r
5279 }\r
5280\r
5281 // Changing the ui can lead to significant changes to a component's appearance, so the layout needs to be\r
5282 // updated. Internally most calls to setUI are pre-render. Buttons are a notable exception as setScale changes\r
5283 // the ui and often requires the layout to be updated.\r
5284 if (me.rendered) {\r
5285 me.updateLayout();\r
5286 }\r
5287 },\r
5288\r
5289 /**\r
5290 * Convenience function to hide or show this component by Boolean.\r
5291 * @param {Boolean} visible `true` to show, `false` to hide.\r
5292 * @return {Ext.Component} this\r
5293 * @since 1.1.0\r
5294 */\r
5295 setVisible: function(visible) {\r
5296 return this[visible ? 'show': 'hide']();\r
5297 },\r
5298\r
5299 /**\r
5300 * Sets the hidden state of this component. This is basically the same as\r
5301 * `{@link #setVisible}` but the boolean parameter has the opposite meaning.\r
5302 * @param {Boolean} hidden\r
5303 * @return {Ext.Component}\r
5304 */\r
5305 setHidden: function(hidden) {\r
5306 return this.setVisible(!hidden);\r
5307 },\r
5308\r
5309 /**\r
5310 * Sets the width of the component. This method fires the {@link #resize} event.\r
5311 *\r
5312 * @param {Number} width The new width to set. This may be one of:\r
5313 *\r
5314 * - A Number specifying the new width in pixels.\r
5315 * - A String used to set the CSS width style.\r
5316 * - `undefined` to leave the width unchanged.\r
5317 * - `null` to clear the width.\r
5318 *\r
5319 * @return {Ext.Component} this\r
5320 */\r
5321 setWidth: function(width) {\r
5322 return this.setSize(width);\r
5323 },\r
5324\r
5325 /**\r
5326 * Shows this Component, rendering it first if {@link #autoRender} or {@link #cfg-floating} are `true`.\r
5327 *\r
5328 * After being shown, a {@link #cfg-floating} Component (such as a {@link Ext.window.Window}), is activated it and\r
5329 * brought to the front of its {@link #zIndexManager z-index stack}.\r
5330 *\r
5331 * @param {String/Ext.dom.Element} [animateTarget=null] **only valid for {@link #cfg-floating} Components such as {@link\r
5332 * Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have been configured\r
5333 * with `floating: true`.** The target from which the Component should animate from while opening.\r
5334 * @param {Function} [callback] A callback function to call after the Component is displayed.\r
5335 * Only necessary if animation was specified.\r
5336 * @param {Object} [scope] The scope (`this` reference) in which the callback is executed.\r
5337 * Defaults to this Component.\r
5338 * @return {Ext.Component} this\r
5339 */\r
5340 show: function(animateTarget, cb, scope) {\r
5341 var me = this,\r
5342 rendered = me.rendered;\r
5343\r
5344 if (me.hierarchicallyHidden || (me.floating && !rendered && me.isHierarchicallyHidden())) {\r
5345 // If this is a hierarchically hidden floating component, we need to stash\r
5346 // the arguments to this call so that the call can be deferred until the next\r
5347 // time syncHidden() is called.\r
5348 if (!rendered) {\r
5349 // If the component has not yet been rendered it requires special treatment.\r
5350 // Normally, for rendered components we can just set the pendingShow property\r
5351 // and syncHidden() listens to events in the hierarchyEventSource and calls\r
5352 // show() when this component becomes hierarchically visible. However,\r
5353 // if the component has not yet been rendered the hierarchy event listeners\r
5354 // have not yet been attached (since Floating is initialized during the\r
5355 // render phase. This means we have to initialize the hierarchy event\r
5356 // listeners right now to ensure that the component will show itself when\r
5357 // it becomes hierarchically visible.\r
5358 me.initHierarchyEvents();\r
5359 }\r
5360 // defer the show call until next syncHidden(), but ignore animateTarget.\r
5361 if (arguments.length > 1) {\r
5362 arguments[0] = null; // jshint ignore:line\r
5363 me.pendingShow = arguments;\r
5364 } else {\r
5365 me.pendingShow = true;\r
5366 }\r
5367 } else if (rendered && me.isVisible()) {\r
5368 if (me.floating) {\r
5369 me.onFloatShow();\r
5370 }\r
5371 } else {\r
5372 if (me.fireEvent('beforeshow', me) !== false) {\r
5373 me.hidden = false;\r
5374 delete this.getInherited().hidden;\r
5375 // Render on first show if there is an autoRender config, or if this\r
5376 // is a floater (Window, Menu, BoundList etc).\r
5377\r
5378 // We suspend layouts here because floaters/autoRenders\r
5379 // will layout when onShow is called. If the render succeeded,\r
5380 // the layout will be trigger inside onShow, so we don't flush\r
5381 // in the first block. If, for some reason we couldn't render, then\r
5382 // we resume layouts and force a flush because we don't know if something\r
5383 // will force it.\r
5384 Ext.suspendLayouts();\r
5385 if (!rendered && (me.autoRender || me.floating)) {\r
5386 me.doAutoRender();\r
5387 rendered = me.rendered;\r
5388 }\r
5389\r
5390 if (rendered) {\r
5391 me.beforeShow();\r
5392 Ext.resumeLayouts();\r
5393 me.onShow.apply(me, arguments);\r
5394 me.afterShow.apply(me, arguments);\r
5395 } else {\r
5396 Ext.resumeLayouts(true);\r
5397 }\r
5398 } else {\r
5399 me.onShowVeto();\r
5400 }\r
5401 }\r
5402 return me;\r
5403 },\r
5404\r
5405 /**\r
5406 * Displays component at specific xy position.\r
5407 * A floating component (like a menu) is positioned relative to its ownerCt if any.\r
5408 * Useful for popping up a context menu:\r
5409 *\r
5410 * listeners: {\r
5411 * itemcontextmenu: function(view, record, item, index, event, options) {\r
5412 * Ext.create('Ext.menu.Menu', {\r
5413 * width: 100,\r
5414 * height: 100,\r
5415 * margin: '0 0 10 0',\r
5416 * items: [{\r
5417 * text: 'regular item 1'\r
5418 * },{\r
5419 * text: 'regular item 2'\r
5420 * },{\r
5421 * text: 'regular item 3'\r
5422 * }]\r
5423 * }).showAt(event.getXY());\r
5424 * }\r
5425 * }\r
5426 *\r
5427 * @param {Number/Number[]} x The new x position or array of `[x,y]`.\r
5428 * @param {Number} [y] The new y position\r
5429 * @param {Boolean/Object} [animate] True to animate the Component into its new position. You may also pass an\r
5430 * animation configuration.\r
5431 * @return {Ext.Component} this\r
5432 */\r
5433 showAt: function(x, y, animate) {\r
5434 var me = this;\r
5435\r
5436 // Not rendered, then animating to a position is meaningless,\r
5437 // just set the x,y position and allow show's processing to work.\r
5438 if (!me.rendered && (me.autoRender || me.floating)) {\r
5439 me.x = x;\r
5440 me.y = y;\r
5441 return me.show();\r
5442 }\r
5443 if (me.floating) {\r
5444 me.setPosition(x, y, animate);\r
5445 } else {\r
5446 me.setPagePosition(x, y, animate);\r
5447 }\r
5448 return me.show();\r
5449 },\r
5450\r
5451 /**\r
5452 * Shows this component by the specified {@link Ext.Component Component} or {@link Ext.dom.Element Element}.\r
5453 * Used when this component is {@link #cfg-floating}.\r
5454 * @param {Ext.Component/Ext.dom.Element} component The {@link Ext.Component} or {@link Ext.dom.Element} to show the component by.\r
5455 * @param {String} [position] Alignment position as used by {@link Ext.util.Positionable#getAlignToXY}.\r
5456 * Defaults to `{@link #defaultAlign}`. See {@link #alignTo} for possible values.\r
5457 * @param {Number[]} [offsets] Alignment offsets as used by {@link Ext.util.Positionable#getAlignToXY}. See {@link #alignTo} for possible values.\r
5458 * @return {Ext.Component} this\r
5459 */\r
5460 showBy: function(cmp, pos, off) {\r
5461 var me = this;\r
5462\r
5463 //<debug>\r
5464 if (!me.floating) {\r
5465 Ext.log.warn('Using showBy on a non-floating component');\r
5466 }\r
5467 //</debug>\r
5468\r
5469 if (me.floating && cmp) {\r
5470 me.alignTarget = cmp;\r
5471\r
5472 if (pos) {\r
5473 me.defaultAlign = pos;\r
5474 }\r
5475\r
5476 if (off) {\r
5477 me.alignOffset = off;\r
5478 }\r
5479\r
5480 me.show();\r
5481\r
5482 // Could have been vetoed.\r
5483 if (!me.hidden) {\r
5484 me.alignTo(cmp, pos || me.defaultAlign, off || me.alignOffset);\r
5485 }\r
5486 }\r
5487\r
5488 return me;\r
5489 },\r
5490\r
5491 suspendLayouts: function () {\r
5492 var me = this;\r
5493 if (!me.rendered) {\r
5494 return;\r
5495 }\r
5496 if (++me.layoutSuspendCount === 1) {\r
5497 me.suspendLayout = true;\r
5498 }\r
5499 },\r
5500\r
5501 unitizeBox: function(box) {\r
5502 return Ext.Element.unitizeBox(box); \r
5503 },\r
5504\r
5505 /**\r
5506 * Removes the mask applied by {@link #mask}\r
5507 */\r
5508 unmask: function() {\r
5509 (this.getMaskTarget() || this.el).unmask();\r
5510 \r
5511 this.setMasked(false);\r
5512 },\r
5513 \r
5514 unregisterFloatingItem: function(cmp) {\r
5515 var me = this;\r
5516 if (me.floatingDescendants) {\r
5517 me.floatingDescendants.unregister(cmp);\r
5518 }\r
5519 },\r
5520\r
5521 /**\r
5522 * Navigates up the ownership hierarchy searching for an ancestor Container which matches any passed selector or component.\r
5523 *\r
5524 * *Important.* There is not a universal upwards navigation pointer. There are several upwards relationships\r
5525 * such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the\r
5526 * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the\r
5527 * {@link Ext.grid.column.Column column header} which activated the column menu.\r
5528 *\r
5529 * These differences are abstracted away by this method.\r
5530 *\r
5531 * Example:\r
5532 *\r
5533 * var owningTabPanel = grid.up('tabpanel');\r
5534 *\r
5535 * @param {String/Ext.Component} [selector] The selector component or actual component to test. If not passed the immediate owner/activator is returned.\r
5536 * @param {String/Number/Ext.Component} [limit] This may be a selector upon which to stop the upward scan, or a limit of the number of steps, or Component reference to stop on.\r
5537 * @return {Ext.container.Container} The matching ancestor Container (or `undefined` if no match was found).\r
5538 */\r
5539 up: function (selector, limit) {\r
5540 var result = this.getRefOwner(),\r
5541 limitSelector = typeof limit === 'string',\r
5542 limitCount = typeof limit === 'number',\r
5543 limitComponent = limit && limit.isComponent,\r
5544 steps = 0;\r
5545\r
5546 if (selector) {\r
5547 for (; result; result = result.getRefOwner()) {\r
5548 steps++;\r
5549 if (selector.isComponent) {\r
5550 if (result === selector) {\r
5551 return result;\r
5552 }\r
5553 } else {\r
5554 if (Ext.ComponentQuery.is(result, selector)) {\r
5555 return result;\r
5556 }\r
5557 }\r
5558\r
5559 // Stop when we hit the limit selector\r
5560 if (limitSelector && result.is(limit)) {\r
5561 return;\r
5562 }\r
5563 if (limitCount && steps === limit) {\r
5564 return;\r
5565 }\r
5566 if (limitComponent && result === limit) {\r
5567 return;\r
5568 }\r
5569 }\r
5570 }\r
5571 return result;\r
5572 },\r
5573\r
5574 /**\r
5575 * Update the content area of a component.\r
5576 * @param {String/Object} htmlOrData If this component has been configured with a\r
5577 * template via the tpl config then it will use this argument as data to populate the\r
5578 * template. If this component was not configured with a template, the components\r
5579 * content area will be updated via Ext.Element update.\r
5580 * @param {Boolean} [loadScripts=false] Only legitimate when using the `html`\r
5581 * configuration. Causes embedded script tags to be executed. Inline source will be executed\r
5582 * with this Component as the scope (`this` reference).\r
5583 * @param {Function} [callback] Only legitimate when using the `html` configuration.\r
5584 * Callback to execute when scripts have finished loading.\r
5585 * @param {Object} [scriptScope=`this`] The scope (`this` reference) in which to\r
5586 * execute *inline* script elements content. Scripts with a `src` attribute cannot\r
5587 * be executed with this scope.\r
5588 *\r
5589 * @since 3.4.0\r
5590 */\r
5591 update: function(htmlOrData, loadScripts, callback, scriptScope) {\r
5592 var me = this,\r
5593 isData = (me.tpl && !Ext.isString(htmlOrData)),\r
5594 scroller = me.getScrollable(),\r
5595 container = me.focusableContainer,\r
5596 sizeModel, doLayout, el;\r
5597\r
5598\r
5599 if (isData) {\r
5600 me.data = (htmlOrData && htmlOrData.isEntity) ? htmlOrData.getData(true) : htmlOrData;\r
5601 } else {\r
5602 me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;\r
5603 }\r
5604\r
5605 if (me.rendered) {\r
5606 sizeModel = me.getSizeModel();\r
5607 doLayout = sizeModel.width.shrinkWrap || sizeModel.height.shrinkWrap;\r
5608\r
5609 if (me.isContainer) {\r
5610 el = me.layout.getRenderTarget();\r
5611\r
5612 // If we are a non-empty container being updated with raw content we have to lay out\r
5613 doLayout = doLayout || me.items.items.length > 0;\r
5614 } else {\r
5615 el = me.touchScroll ? me.getScrollerEl() : me.getTargetEl();\r
5616 }\r
5617 if (isData) {\r
5618 me.tpl[me.tplWriteMode](el, me.data || {});\r
5619 } else {\r
5620 el.setHtml(me.html, loadScripts, callback, scriptScope || me);\r
5621 }\r
5622\r
5623 if (doLayout) {\r
5624 me.updateLayout();\r
5625 }\r
5626 if (scroller) {\r
5627 scroller.refresh(true);\r
5628 }\r
5629 \r
5630 if (container) {\r
5631 container.onFocusableChildUpdate(me);\r
5632 }\r
5633 }\r
5634 },\r
5635\r
5636 setHtml: function (html, loadScripts, scriptScope) {\r
5637 this.update(html, loadScripts, null, scriptScope);\r
5638 },\r
5639\r
5640 applyData: function (data) {\r
5641 // Don't return data here, update will set this.data\r
5642 this.update(data);\r
5643 },\r
5644\r
5645 /**\r
5646 * Sets the current box measurements of the component's underlying element.\r
5647 * @param {Object} box An object in the format {x, y, width, height}\r
5648 * @return {Ext.Component} this\r
5649 */\r
5650 updateBox: function(box){\r
5651 this.setSize(box.width, box.height);\r
5652 this.setPagePosition(box.x, box.y);\r
5653 return this;\r
5654 },\r
5655\r
5656 _asLayoutRoot: { isRoot: true },\r
5657 _notAsLayoutRoot: { isRoot: false },\r
5658\r
5659 /**\r
5660 * Updates this component's layout. If this update affects this components {@link #ownerCt},\r
5661 * that component's `updateLayout` method will be called to perform the layout instead.\r
5662 * Otherwise, just this component (and its child items) will layout.\r
5663 *\r
5664 * @param {Object} [options] An object with layout options.\r
5665 * @param {Boolean} options.defer `true` if this layout should be deferred.\r
5666 * @param {Boolean} options.isRoot `true` if this layout should be the root of the layout.\r
5667 */\r
5668 updateLayout: function (options) {\r
5669 var me = this,\r
5670 defer,\r
5671 lastBox = me.lastBox,\r
5672 isRoot = options && options.isRoot;\r
5673\r
5674 if (lastBox) {\r
5675 // remember that this component's last layout result is invalid and must be\r
5676 // recalculated\r
5677 lastBox.invalid = true;\r
5678 }\r
5679\r
5680 if (!me.rendered || me.layoutSuspendCount || me.suspendLayout) {\r
5681 return;\r
5682 }\r
5683\r
5684 if (me.hidden) {\r
5685 Ext.Component.cancelLayout(me);\r
5686 } else if (typeof isRoot !== 'boolean') {\r
5687 isRoot = me.isLayoutRoot();\r
5688 }\r
5689\r
5690 // if we aren't the root, see if our ownerLayout will handle it...\r
5691 if (isRoot || !me.ownerLayout || !me.ownerLayout.onContentChange(me)) {\r
5692 // either we are the root or our ownerLayout doesn't care\r
5693 if (!me.isLayoutSuspended()) {\r
5694 // we aren't suspended (knew that), but neither is any of our ownerCt's...\r
5695 defer = (options && options.hasOwnProperty('defer')) ? options.defer : me.deferLayouts;\r
5696 Ext.Component.updateLayout(me, defer);\r
5697 }\r
5698 }\r
5699 },\r
5700\r
5701 updateMaxHeight: function(maxHeight, oldMaxHeight) {\r
5702 this.changeConstraint(maxHeight, oldMaxHeight, 'min', 'max-height', 'height');\r
5703 },\r
5704\r
5705 updateMaxWidth: function(maxWidth, oldMaxWidth) {\r
5706 this.changeConstraint(maxWidth, oldMaxWidth, 'min', 'max-width', 'width');\r
5707 },\r
5708\r
5709 updateMinHeight: function(minHeight, oldMinHeight) {\r
5710 this.changeConstraint(minHeight, oldMinHeight, 'max', 'min-height', 'height');\r
5711 },\r
5712\r
5713 updateMinWidth: function(minWidth, oldMinWidth) {\r
5714 this.changeConstraint(minWidth, oldMinWidth, 'max', 'min-width', 'width');\r
5715 },\r
5716\r
5717 // ***********************************************************************************\r
5718 // End Component methods\r
5719 // ***********************************************************************************\r
5720 // </editor-fold>\r
5721\r
5722 // <editor-fold desc="Positionable Methods">\r
5723 // ***********************************************************************************\r
5724 // Begin Positionable methods\r
5725 // ***********************************************************************************\r
5726 getAnchorToXY: function(el, anchor, local, mySize) {\r
5727 return el.getAnchorXY(anchor, local, mySize);\r
5728 },\r
5729\r
5730 getBorderPadding: function() {\r
5731 return this.el.getBorderPadding();\r
5732 },\r
5733\r
5734 getLocalX: function() {\r
5735 return this.el.getLocalX();\r
5736 },\r
5737\r
5738 getLocalXY: function() {\r
5739 return this.el.getLocalXY();\r
5740 },\r
5741\r
5742 getLocalY: function() {\r
5743 return this.el.getLocalY();\r
5744 },\r
5745\r
5746 getX: function() {\r
5747 return this.el.getX();\r
5748 },\r
5749\r
5750 getXY: function() {\r
5751 return this.el.getXY();\r
5752 },\r
5753\r
5754 getY: function() {\r
5755 return this.el.getY();\r
5756 },\r
5757\r
5758 setLocalX: function(x) {\r
5759 this.el.setLocalX(x);\r
5760 },\r
5761\r
5762 setLocalXY: function(x, y) {\r
5763 this.el.setLocalXY(x, y);\r
5764 },\r
5765\r
5766 setLocalY: function(y) {\r
5767 this.el.setLocalY(y);\r
5768 },\r
5769\r
5770 setX: function(x, animate) {\r
5771 this.el.setX(x, animate);\r
5772 },\r
5773\r
5774 setXY: function(xy, animate) {\r
5775 this.el.setXY(xy, animate);\r
5776 },\r
5777\r
5778 setY: function(y, animate) {\r
5779 this.el.setY(y, animate);\r
5780 },\r
5781\r
5782 // ***********************************************************************************\r
5783 // End Positionable methods\r
5784 // ***********************************************************************************\r
5785 // </editor-fold>\r
5786\r
5787 privates: {\r
5788 addOverCls: function() {\r
5789 var me = this;\r
5790 if (!me.disabled) {\r
5791 me.el.addCls(me.overCls);\r
5792 }\r
5793 },\r
5794\r
5795 /**\r
5796 * Method which adds a specified UI to the components element.\r
5797 * @private\r
5798 */\r
5799 addUIToElement: function() {\r
5800 var me = this,\r
5801 baseClsUI = me.baseCls + '-' + me.ui,\r
5802 childEls, childElName, el, suffix;\r
5803\r
5804 me.addCls(baseClsUI);\r
5805\r
5806 if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {\r
5807 // Loop through each frame element, and if they are defined add the ui:\r
5808 baseClsUI += '-';\r
5809 childEls = me.getChildEls();\r
5810\r
5811 for (childElName in childEls) {\r
5812 suffix = childEls[childElName].frame;\r
5813 if (suffix && suffix !== true) {\r
5814 el = me[childElName];\r
5815 if (el) {\r
5816 el.addCls(baseClsUI + suffix);\r
5817 }\r
5818 }\r
5819 }\r
5820 }\r
5821 },\r
5822\r
5823 /**\r
5824 * @private\r
5825 */\r
5826 changeConstraint: function(newValue, oldValue, constrainMethod, styleName, sizeName) {\r
5827 var me = this,\r
5828 size = me[sizeName];\r
5829\r
5830 if (newValue != null && typeof size === 'number') {\r
5831 me[sizeName] = Math[constrainMethod](size, newValue);\r
5832 }\r
5833\r
5834 if (me.liquidLayout) {\r
5835 // components that use liquidLayout need their size constraints set in the dom\r
5836 if (newValue != null) {\r
5837 me.setStyle(styleName, newValue + 'px');\r
5838 } else if (oldValue) {\r
5839 me.setStyle(styleName, '');\r
5840 }\r
5841 }\r
5842\r
5843 if (me.rendered) {\r
5844 me.updateLayout();\r
5845 }\r
5846 },\r
5847\r
5848 /**\r
5849 * @param {String/Object} ptype string or config object containing a ptype property.\r
5850 *\r
5851 * Constructs a plugin according to the passed config object/ptype string.\r
5852 *\r
5853 * Ensures that the constructed plugin always has a `cmp` reference back to this component.\r
5854 * The setting up of this is done in PluginManager. The PluginManager ensures that a reference to this\r
5855 * component is passed to the constructor. It also ensures that the plugin's `setCmp` method (if any) is called.\r
5856 * @private\r
5857 */\r
5858 constructPlugin: function(plugin) {\r
5859 var me = this;\r
5860\r
5861 // ptype only, pass as the defultType\r
5862 if (typeof plugin === 'string') {\r
5863 plugin = Ext.PluginManager.create({}, plugin, me);\r
5864 }\r
5865 // Object (either config with ptype or an instantiated plugin)\r
5866 else {\r
5867 plugin = Ext.PluginManager.create(plugin, null, me);\r
5868 }\r
5869 return plugin;\r
5870 },\r
5871\r
5872 /**\r
5873 * Returns an array of fully constructed plugin instances. This converts any configs into their\r
5874 * appropriate instances.\r
5875 *\r
5876 * It does not mutate the plugins array. It creates a new array.\r
5877 * @private\r
5878 */\r
5879 constructPlugins: function() {\r
5880 var me = this,\r
5881 plugins = me.plugins,\r
5882 result, i, len;\r
5883\r
5884 if (plugins) {\r
5885 result = [];\r
5886\r
5887 // The processed flag indicates that the plugins have been constructed. This is usually done\r
5888 // at construction time, so if at initComponent time, there is a non-zero array of plugins which\r
5889 // does NOT have the processed flag, it needs to be processed again.\r
5890 result.processed = true;\r
5891 if (!Ext.isArray(plugins)) {\r
5892 plugins = [ plugins ];\r
5893 }\r
5894 for (i = 0, len = plugins.length; i < len; i++) {\r
5895 // this just returns already-constructed plugin instances...\r
5896 result[i] = me.constructPlugin(plugins[i]);\r
5897 }\r
5898 }\r
5899\r
5900 me.pluginsInitialized = true;\r
5901 return result;\r
5902 },\r
5903\r
5904 detachFromBody: function() {\r
5905 // Currently this is called by column.Widget to store components\r
5906 // in the pool when they are not needed in the grid.\r
5907 // \r
5908 // Also see reattachToBody\r
5909 Ext.getDetachedBody().appendChild(this.el);\r
5910 Ext.Component.cancelLayout(this);\r
5911 this.isDetached = true;\r
5912 },\r
5913\r
5914 doAddListener: function(ename, fn, scope, options, order, caller, manager) {\r
5915 var me = this,\r
5916 listeners, option, eventOptions, elementName, element, delegate;\r
5917\r
5918 if (Ext.isObject(fn) || (options && options.element)) {\r
5919 if (options.element) {\r
5920 elementName = options.element;\r
5921 listeners = {};\r
5922 listeners[ename] = fn;\r
5923 if (scope) {\r
5924 listeners.scope = scope;\r
5925 }\r
5926\r
5927 eventOptions = me.$elementEventOptions;\r
5928 for (option in options) {\r
5929 if (eventOptions[option]) {\r
5930 listeners[option] = options[option];\r
5931 }\r
5932 }\r
5933 } else {\r
5934 listeners = fn;\r
5935 elementName = ename;\r
5936 }\r
5937\r
5938 element = me[elementName];\r
5939\r
5940 if (element && element.isObservable) { // can be any kind of observable, not just element\r
5941 me.mon(element, listeners);\r
5942 } else {\r
5943 me.afterRenderEvents = me.afterRenderEvents || {};\r
5944 if (!me.afterRenderEvents[elementName]) {\r
5945 me.afterRenderEvents[elementName] = [];\r
5946 }\r
5947 me.afterRenderEvents[elementName].push(listeners);\r
5948 }\r
5949 return;\r
5950 }\r
5951\r
5952 if (options) {\r
5953 delegate = options.delegate;\r
5954 if (delegate) {\r
5955 me.mixins.componentDelegation.addDelegatedListener.call(me, ename, fn, scope, options, order, caller, manager);\r
5956 return;\r
5957 }\r
5958 }\r
5959\r
5960 me.mixins.observable.doAddListener.call(me, ename, fn, scope, options, order, caller, manager);\r
5961 },\r
5962\r
5963 doRemoveListener: function(eventName, fn, scope) {\r
5964 var me = this;\r
5965 me.mixins.observable.doRemoveListener.call(me, eventName, fn, scope);\r
5966 me.mixins.componentDelegation.removeDelegatedListener.call(me, eventName, fn, scope);\r
5967 },\r
5968\r
5969 /**\r
5970 * This method fires an event on `Ext.GlobalEvents` allowing interested parties to know\r
5971 * of certain critical events for this component. This is done globally because the\r
5972 * (few) listeners can immediately receive the event rather than bubbling the event\r
5973 * only to reach the top and have no listeners.\r
5974 *\r
5975 * The main usage for these events is to do with floating components. For example, the\r
5976 * load mask is a floating component. The component it is masking may be inside several\r
5977 * containers. As such, they need to know when component is hidden, either directly, or\r
5978 * via a parent container being hidden. To do this they subscribe to these events and\r
5979 * filter out the appropriate container.\r
5980 *\r
5981 * This functionality is contained in Component (as opposed to Container) because a\r
5982 * Component can be the ownerCt for a floating component (loadmask), and the loadmask\r
5983 * needs to know when its owner is shown/hidden so that its hidden state can be\r
5984 * synchronized.\r
5985 *\r
5986 * @param {String} eventName The event name.\r
5987 * @since 4.2.0\r
5988 * @private\r
5989 */\r
5990 fireHierarchyEvent: function (eventName) {\r
5991 var globalEvents = Ext.GlobalEvents;\r
5992\r
5993 if (globalEvents.hasListeners[eventName]) {\r
5994 globalEvents.fireEvent(eventName, this);\r
5995 }\r
5996 },\r
5997\r
5998 getActionEl: function() {\r
5999 return this.el;\r
6000 },\r
6001\r
6002 /**\r
6003 * @private\r
6004 */\r
6005 getAutoId: function() {\r
6006 this.autoGenId = true;\r
6007 return ++Ext.Component.AUTO_ID;\r
6008 },\r
6009\r
6010 /**\r
6011 * @private\r
6012 */\r
6013 getContentTarget: function() {\r
6014 return this.el;\r
6015 },\r
6016\r
6017 getDragEl: function() {\r
6018 return this.el;\r
6019 },\r
6020\r
6021 /**\r
6022 * Get an el for overflowing, defaults to the target el\r
6023 * @private\r
6024 */\r
6025 getOverflowEl: function(){\r
6026 return this.getTargetEl();\r
6027 },\r
6028\r
6029 /**\r
6030 * @private\r
6031 * Returns the CSS style object which will set the Component's scroll styles.\r
6032 * This must be applied to the {@link #getTargetEl target element}.\r
6033 */\r
6034 getOverflowStyle: function() {\r
6035 var me = this,\r
6036 scroller = me.getScrollable(),\r
6037 flags = me._scrollFlags,\r
6038 x, y, scrollFlags;\r
6039\r
6040 if (scroller) {\r
6041 x = scroller.getX();\r
6042 if (x === true) {\r
6043 x = 'auto';\r
6044 }\r
6045 y = scroller.getY();\r
6046 if (y === true) {\r
6047 y = 'auto';\r
6048 }\r
6049 scrollFlags = flags[x][y];\r
6050 } else {\r
6051 scrollFlags = flags.none;\r
6052 }\r
6053\r
6054 me.scrollFlags = scrollFlags;\r
6055\r
6056 return {\r
6057 overflowX: scrollFlags.overflowX,\r
6058 overflowY: scrollFlags.overflowY\r
6059 };\r
6060 },\r
6061\r
6062 /**\r
6063 * Returns an array of current fully constructed plugin instances.\r
6064 * @private\r
6065 */\r
6066 getPlugins : function() {\r
6067 var plugins = this.plugins;\r
6068\r
6069 plugins = (plugins && plugins.processed) ? plugins : this.constructPlugins();\r
6070 return plugins || null;\r
6071 },\r
6072\r
6073 getProxy: function() {\r
6074 var me = this,\r
6075 target;\r
6076\r
6077 if (!me.proxy) {\r
6078 target = Ext.getBody();\r
6079 me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true);\r
6080 }\r
6081 return me.proxy;\r
6082 },\r
6083\r
6084 getScrollerEl: function() {\r
6085 var me = this;\r
6086\r
6087 return me.scrollerEl || (me.scrollerEl =\r
6088 me.componentLayout.getScrollerEl() || me.getOverflowEl().child(me.scrollerSelector));\r
6089 },\r
6090\r
6091 /**\r
6092 * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.\r
6093 * @private\r
6094 */\r
6095 getTargetEl: function() {\r
6096 return this.frameBody || this.el;\r
6097 },\r
6098\r
6099 /**\r
6100 * @private\r
6101 * Needed for when widget is rendered into a grid cell. The class to add to the cell element.\r
6102 */\r
6103 getTdCls: function() {\r
6104 return Ext.baseCSSPrefix + this.getTdType() + '-' + this.ui + '-cell';\r
6105 },\r
6106\r
6107 /**\r
6108 * @private\r
6109 * Partner method to {@link #getTdCls}.\r
6110 *\r
6111 * Returns the base type for the component. Defaults to return `this.xtype`, but\r
6112 * All derived classes of {@link Ext.form.field.Text TextField} can return the type 'textfield',\r
6113 * and all derived classes of {@link Ext.button.Button Button} can return the type 'button'\r
6114 */\r
6115 getTdType: function() {\r
6116 return this.xtype;\r
6117 },\r
6118\r
6119 /**\r
6120 * @private\r
6121 */\r
6122 getTpl: function(name) {\r
6123 return Ext.XTemplate.getTpl(this, name);\r
6124 },\r
6125\r
6126 initCls: function() {\r
6127 var me = this,\r
6128 cls = [me.baseCls],\r
6129 targetCls = me.getComponentLayout().targetCls;\r
6130\r
6131 if (targetCls) {\r
6132 cls.push(targetCls);\r
6133 }\r
6134\r
6135 //<deprecated since=0.99>\r
6136 if (Ext.isDefined(me.cmpCls)) {\r
6137 if (Ext.isDefined(Ext.global.console)) {\r
6138 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');\r
6139 }\r
6140 me.componentCls = me.cmpCls;\r
6141 delete me.cmpCls;\r
6142 }\r
6143 //</deprecated>\r
6144\r
6145 if (me.componentCls) {\r
6146 cls.push(me.componentCls);\r
6147 } else {\r
6148 me.componentCls = me.baseCls;\r
6149 }\r
6150\r
6151 return cls;\r
6152 },\r
6153\r
6154 initDraggable: function() {\r
6155 var me = this,\r
6156\r
6157 // If we are resizable, and the resizer had to wrap this Component's el (e.g. an Img)\r
6158 // Then we have to create a pseudo-Component out of the resizer to drag that,\r
6159 // otherwise, we just drag this Component\r
6160 dragTarget = (me.resizer && me.resizer.el !== me.el) ? me.resizerComponent = new Ext.Component({\r
6161 el: me.resizer.el,\r
6162 rendered: true,\r
6163 container: me.container\r
6164 }) : me,\r
6165 ddConfig = Ext.applyIf({\r
6166 el: dragTarget.getDragEl(),\r
6167 constrainTo: (me.constrain||me.draggable.constrain) ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.container)) : undefined\r
6168 }, me.draggable);\r
6169\r
6170 // Add extra configs if Component is specified to be constrained\r
6171 if (me.constrain || me.constrainDelegate) {\r
6172 ddConfig.constrain = me.constrain;\r
6173 ddConfig.constrainDelegate = me.constrainDelegate;\r
6174 }\r
6175\r
6176 me.dd = new Ext.util.ComponentDragger(dragTarget, ddConfig);\r
6177 },\r
6178\r
6179 /**\r
6180 * Initializes padding by applying it to the target element, or if the layout manages\r
6181 * padding ensures that the padding on the target element is "0".\r
6182 * @private\r
6183 */\r
6184 initPadding: function(targetEl) {\r
6185 var me = this,\r
6186 padding = me.padding;\r
6187\r
6188 if (padding != null) {\r
6189 if (me.touchScroll || (me.layout && me.layout.managePadding && me.contentPaddingProperty === 'padding')) {\r
6190 // If the container layout manages padding, or if a touch scroller is in\r
6191 // use, the padding will be applied to an inner layout element, or the\r
6192 // touch scroller element. This is done as a workaround for the browser bug\r
6193 // where right and/or bottom padding is lost when the element has overflow.\r
6194 // The assumed intent is for the configured padding to override any padding\r
6195 // that is applied to the target element via style sheet rules. It is\r
6196 // therefore necessary to set the target element's padding to "0".\r
6197 targetEl.setStyle('padding', 0);\r
6198 } else {\r
6199 // Convert the padding, margin and border properties from a space separated string\r
6200 // into a proper style string\r
6201 targetEl.setStyle('padding', this.unitizeBox((padding === true) ? 5 : padding));\r
6202 }\r
6203 }\r
6204 },\r
6205\r
6206 /**\r
6207 * @private\r
6208 */\r
6209 initPlugin: function(plugin) {\r
6210 plugin.init(this);\r
6211\r
6212 return plugin;\r
6213 },\r
6214\r
6215 initResizable: function(resizable) {\r
6216 var me = this;\r
6217\r
6218 resizable = Ext.apply({\r
6219 target: me,\r
6220 dynamic: false,\r
6221 constrainTo: (me.constrain||(resizable && resizable.constrain)) ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.container)) : undefined,\r
6222 handles: me.resizeHandles\r
6223 }, resizable);\r
6224 resizable.target = me;\r
6225 me.resizer = new Ext.resizer.Resizer(resizable);\r
6226 },\r
6227\r
6228 /**\r
6229 * Applies padding, margin, border, top, left, height, and width configs to the\r
6230 * appropriate elements.\r
6231 * @private\r
6232 */\r
6233 initStyles: function(targetEl) {\r
6234 var me = this,\r
6235 margin = me.margin,\r
6236 border = me.border,\r
6237 cls = me.cls,\r
6238 style = me.style,\r
6239 x = me.x,\r
6240 y = me.y,\r
6241 liquidLayout = me.liquidLayout,\r
6242 width, height;\r
6243\r
6244 me.initPadding(targetEl);\r
6245\r
6246 if (margin != null) {\r
6247 targetEl.setStyle('margin', this.unitizeBox((margin === true) ? 5 : margin));\r
6248 }\r
6249\r
6250 if (border != null) {\r
6251 me.setBorder(border, targetEl);\r
6252 }\r
6253\r
6254 // initComponent, beforeRender, or event handlers may have set the style or cls property since the protoEl was set up\r
6255 // so we must apply styles and classes here too.\r
6256 if (cls && cls !== me.initialCls) {\r
6257 targetEl.addCls(cls);\r
6258 me.cls = me.initialCls = null;\r
6259 }\r
6260 if (style && style !== me.initialStyle) {\r
6261 targetEl.setStyle(style);\r
6262 me.style = me.initialStyle = null;\r
6263 }\r
6264\r
6265 if (x != null) {\r
6266 targetEl.setStyle(me.horizontalPosProp, (typeof x === 'number') ? (x + 'px') : x);\r
6267 }\r
6268 if (y != null) {\r
6269 targetEl.setStyle('top', (typeof y === 'number') ? (y + 'px') : y);\r
6270 }\r
6271\r
6272 if (!me.ownerCt || me.floating) {\r
6273 if (Ext.scopeCss) {\r
6274 targetEl.addCls(me.rootCls);\r
6275 }\r
6276 targetEl.addCls(me.borderBoxCls);\r
6277 }\r
6278\r
6279 // Framed components need their width/height to apply to the frame, which is\r
6280 // best handled in layout at present. The exception to this rule is component\r
6281 // that use liquidLayout and so cannot rely on the layout to set their size.\r
6282 if (liquidLayout || !me.getFrameInfo()) {\r
6283 width = me.width;\r
6284 height = me.height;\r
6285\r
6286 // If we're using the content box model, we also cannot assign numeric initial sizes since we do not know the border widths to subtract\r
6287 if (width != null) {\r
6288 if (typeof width === 'number') {\r
6289 targetEl.setStyle('width', width + 'px');\r
6290 } else {\r
6291 targetEl.setStyle('width', width);\r
6292 }\r
6293 }\r
6294 if (height != null) {\r
6295 if (typeof height === 'number') {\r
6296 targetEl.setStyle('height', height + 'px');\r
6297 } else {\r
6298 targetEl.setStyle('height', height);\r
6299 }\r
6300 }\r
6301 }\r
6302 },\r
6303\r
6304 // Utility method to determine if a Component is floating, and has an owning Container whose coordinate system\r
6305 // it must be positioned in when using setPosition.\r
6306 isContainedFloater: function() {\r
6307 return (this.floating && this.floatParent);\r
6308 },\r
6309\r
6310 isDescendant: function(ancestor) {\r
6311 if (ancestor.isContainer) {\r
6312 for (var c = this.ownerCt; c; c = c.ownerCt) {\r
6313 if (c === ancestor) {\r
6314 return true;\r
6315 }\r
6316 }\r
6317 }\r
6318 return false;\r
6319 },\r
6320\r
6321 /**\r
6322 * @private\r
6323 * Returns `true` if the passed element is within the container tree of this component.\r
6324 *\r
6325 * For example if a menu's submenu contains an {@link Ext.form.field.Date}, that top level\r
6326 * menu owns the elements of the date picker. Using this method, you can tell if an event took place\r
6327 * within a certain component tree.\r
6328 */\r
6329 owns: function(element) {\r
6330 var result = false,\r
6331 cmp;\r
6332\r
6333 if (element.isEvent) {\r
6334 element = element.target;\r
6335 } else if (element.isElement) {\r
6336 element = element.dom;\r
6337 }\r
6338\r
6339 cmp = Ext.Component.fromElement(element);\r
6340\r
6341 if (cmp) {\r
6342 result = (cmp === this) || (!!cmp.up(this));\r
6343 }\r
6344\r
6345 return result;\r
6346 },\r
6347\r
6348 parseBox: function(box) {\r
6349 return Ext.Element.parseBox(box);\r
6350 },\r
6351\r
6352 reattachToBody: function() {\r
6353 // Also see detachFromBody\r
6354 this.isDetached = false;\r
6355 },\r
6356\r
6357 /**\r
6358 * @private\r
6359 * Implementation which updates the scroll range of a touch scroller.\r
6360 * Subclasses may change implementation.\r
6361 */\r
6362 refreshScroll: function() {\r
6363 var scroller = this.getScrollable();\r
6364\r
6365 if (scroller) {\r
6366 scroller.refresh();\r
6367 }\r
6368 },\r
6369\r
6370 removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){\r
6371 var me = this,\r
6372 element = managedListener.options ? managedListener.options.element : null;\r
6373\r
6374 if (element) {\r
6375 element = me[element];\r
6376 if (element && element.un) {\r
6377 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {\r
6378 element.un(managedListener.ename, managedListener.fn, managedListener.scope);\r
6379 if (!isClear) {\r
6380 Ext.Array.remove(me.managedListeners, managedListener);\r
6381 }\r
6382 }\r
6383 }\r
6384 } else {\r
6385 return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);\r
6386 }\r
6387 },\r
6388\r
6389 removeOverCls: function() {\r
6390 this.el.removeCls(this.overCls);\r
6391 },\r
6392\r
6393 removePlugin: function(plugin) {\r
6394 Ext.Array.remove(this.plugins, plugin);\r
6395 plugin.destroy();\r
6396 },\r
6397\r
6398 /**\r
6399 * Method which removes a specified UI from the components element.\r
6400 * @private\r
6401 */\r
6402 removeUIFromElement: function() {\r
6403 var me = this,\r
6404 baseClsUI = me.baseCls + '-' + me.ui,\r
6405 childEls, childElName, el, suffix;\r
6406\r
6407 me.removeCls(baseClsUI);\r
6408\r
6409 if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {\r
6410 // Loop through each frame element, and if they are defined remove the ui:\r
6411 baseClsUI += '-';\r
6412 childEls = me.getChildEls();\r
6413\r
6414 for (childElName in childEls) {\r
6415 suffix = childEls[childElName].frame;\r
6416 if (suffix && suffix !== true) {\r
6417 el = me[childElName];\r
6418 if (el) {\r
6419 el.removeCls(baseClsUI + suffix);\r
6420 }\r
6421 }\r
6422 }\r
6423 }\r
6424 },\r
6425\r
6426 /**\r
6427 * @private\r
6428 */\r
6429 setComponentLayout: function(layout) {\r
6430 var currentLayout = this.componentLayout;\r
6431 if (currentLayout && currentLayout.isLayout && currentLayout !== layout) {\r
6432 currentLayout.setOwner(null);\r
6433 }\r
6434 this.componentLayout = layout;\r
6435 layout.setOwner(this);\r
6436 },\r
6437\r
6438 setHiddenState: function (hidden) {\r
6439 var me = this,\r
6440 inheritedState = me.getInherited(),\r
6441 zIndexManager = me.zIndexManager;\r
6442\r
6443 me.hidden = hidden;\r
6444\r
6445 if (hidden) {\r
6446 inheritedState.hidden = true;\r
6447 } else {\r
6448 delete inheritedState.hidden;\r
6449 }\r
6450\r
6451 // Ensure any ZIndexManager knowns about visibility state change to keep its filtering correct\r
6452 if (zIndexManager) {\r
6453 zIndexManager.onComponentShowHide(me);\r
6454 }\r
6455 },\r
6456\r
6457 setupProtoEl: function() {\r
6458 var cls = this.initCls();\r
6459\r
6460 this.protoEl.addCls(cls);\r
6461 },\r
6462\r
6463 wrapPrimaryEl: function (dom) {\r
6464 var me = this,\r
6465 el = me.el;\r
6466\r
6467 if (!el || !el.isElement) { // allow subclass override to instantiate the element\r
6468 me.el = Ext.get(dom);\r
6469 }\r
6470\r
6471 if (me.floating) {\r
6472 this.mixins.floating.constructor.call(this);\r
6473 }\r
6474 }\r
6475 }, // private\r
6476\r
6477 deprecated: {\r
6478 5: {\r
6479 methods: {\r
6480 /**\r
6481 * @method addClass\r
6482 * @inheritdoc Ext.Component#addCls\r
6483 * @deprecated 4.1 Use {@link #addCls} instead.\r
6484 * @since 2.3.0\r
6485 */\r
6486 addClass: 'addCls',\r
6487\r
6488 /**\r
6489 * This method needs to be called whenever you change something on this component that\r
6490 * requires the Component's layout to be recalculated.\r
6491 * @return {Ext.Component} this\r
6492 * @deprecated 4.1 Use {@link #updateLayout} instead.\r
6493 */\r
6494 doComponentLayout: function() {\r
6495 this.updateLayout();\r
6496 return this;\r
6497 },\r
6498\r
6499 /**\r
6500 * @method removeClass\r
6501 * @inheritdoc Ext.Component#removeCls\r
6502 * @deprecated 4.1 Use {@link #addCls} instead.\r
6503 * @since 2.3.0\r
6504 */\r
6505 removeClass: 'removeCls',\r
6506\r
6507 /**\r
6508 * @method forceComponentLayout\r
6509 * @inheritdoc Ext.Component#updateLayout\r
6510 * @deprecated 4.1 Use {@link #updateLayout} instead.\r
6511 */\r
6512 forceComponentLayout: 'updateLayout',\r
6513\r
6514 /**\r
6515 * @method setDocked\r
6516 * @inheritdoc Ext.Component#setDock\r
6517 * @deprecated 5.0 Use {@link #setDock} instead.\r
6518 */\r
6519 setDocked: 'setDock'\r
6520 }\r
6521 }\r
6522 }\r
6523}, function(Component) {\r
6524 var prototype = Component.prototype;\r
6525\r
6526 // event options for listeners that use the "element" event options must also include\r
6527 // event options from Ext.Element\r
6528 (prototype.$elementEventOptions =\r
6529 Ext.Object.chain(Ext.Element.prototype.$eventOptions)).element = 1;\r
6530\r
6531 (prototype.$eventOptions = Ext.Object.chain(prototype.$eventOptions)).delegate = 1;\r
6532\r
6533 Component.createAlias({\r
6534 on: 'addListener',\r
6535 prev: 'previousSibling',\r
6536 next: 'nextSibling'\r
6537 });\r
6538\r
6539 /**\r
6540 * @method\r
6541 * @inheritdoc Ext.Component#static-resumeLayouts\r
6542 * @member Ext\r
6543 */\r
6544 Ext.resumeLayouts = function (flush) {\r
6545 Component.resumeLayouts(flush);\r
6546 };\r
6547\r
6548 /**\r
6549 * @method\r
6550 * @inheritdoc Ext.Component#static-suspendLayouts\r
6551 * @member Ext\r
6552 */\r
6553 Ext.suspendLayouts = function () {\r
6554 Component.suspendLayouts();\r
6555 };\r
6556\r
6557 /**\r
6558 * Utility wrapper that suspends layouts of all components for the duration of a given\r
6559 * function.\r
6560 * @param {Function} fn The function to execute.\r
6561 * @param {Object} [scope] The scope (`this` reference) in which the specified function\r
6562 * is executed.\r
6563 * @member Ext\r
6564 */\r
6565 Ext.batchLayouts = function(fn, scope) {\r
6566 Component.suspendLayouts();\r
6567 // Invoke the function\r
6568 fn.call(scope);\r
6569 Component.resumeLayouts(true);\r
6570 };\r
6571\r
6572 /**\r
6573 * Sets the default font-family to use for components that support a `glyph` config.\r
6574 * @param {String} fontFamily The name of the font-family\r
6575 * @member Ext\r
6576 */\r
6577 Ext.setGlyphFontFamily = function (fontFamily) {\r
6578 Ext._glyphFontFamily = fontFamily;\r
6579 };\r
6580\r
6581 // These are legacy names which are now subsumed by Ext.GlobalEvents\r
6582 Component.hierarchyEventSource = prototype.hierarchyEventSource =\r
6583 Ext.GlobalEvents;\r
6584\r
6585 // High Contrast mode in Windows disables background images and usually\r
6586 // causes much pain by this. We feature detect it early and add this class\r
6587 // to allow potential workarounds.\r
6588 Ext.onReady(function() {\r
6589 if (Ext.supports.HighContrastMode) {\r
6590 Ext.getBody().addCls(Component.ariaHighContrastModeCls);\r
6591 }\r
6592 });\r
6593\r
6594 //<debug>\r
6595 var metaTags = document.getElementsByTagName('head')[0].getElementsByTagName('meta'),\r
6596 len = metaTags.length,\r
6597 i, hasViewport;\r
6598\r
6599 for (i = 0; i < len; i++) {\r
6600 if (metaTags[i].name === 'viewport') {\r
6601 hasViewport = true;\r
6602 }\r
6603 }\r
6604\r
6605 if (!hasViewport) {\r
6606 Ext.log.warn('Ext JS requires a viewport meta tag in order to function correctly on mobile devices. Please add the following tag to the <head> of your html page: \n <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">');\r
6607 }\r
6608 //</debug>\r
6609});\r
6610\r
6611\r
6612\r
6613/* TODO\r
6614 *\r
6615 * ## Child Sessions\r
6616 *\r
6617 * By default, sessions created in child components are called "child sessions".\r
6618 * All data and edits are copied from the parent session in to the child session.\r
6619 * These changes can be written back to the parent session much like a session\r
6620 * can save its data to a server.\r
6621 *\r
6622 * Ext.create({\r
6623 * xtype: 'window',\r
6624 * modal: true,\r
6625 *\r
6626 * // Creates a new session for this Window but that session is linked\r
6627 * // to a parent session (probably from the application's Viewport).\r
6628 * //\r
6629 * session: true,\r
6630 *\r
6631 * items: [{\r
6632 * ...\r
6633 * },{\r
6634 * xtype: 'button',\r
6635 * text: 'OK',\r
6636 * listeners: {\r
6637 * click: function () {\r
6638 * // Get the Session this component has inherited (from\r
6639 * // the Window) and save it back to the parent session.\r
6640 * //\r
6641 * this.lookupSession().save();\r
6642 * }\r
6643 * }\r
6644 * }]\r
6645 * });\r
6646 *\r
6647 * ### Isolated Sessions\r
6648 *\r
6649 * This connection of a child session to its parent session is determined by the\r
6650 * `{@link Ext.data.Session#isolated isolated}` config. If `isolated` is\r
6651 * set to `true` then this session will not copy anything from a higher level\r
6652 * session and will instead do its own communication with the server.\r
6653 *\r
6654 * Ext.create({\r
6655 * xtype: 'window',\r
6656 * modal: true,\r
6657 *\r
6658 * // Creates a new session for this Window that is isolated from any\r
6659 * // other sessions. All data for this session will be fetched from\r
6660 * // the server and ultimately saved back to the server.\r
6661 * //\r
6662 * session: {\r
6663 * isolated: true\r
6664 * },\r
6665 *\r
6666 * items: [{\r
6667 * ...\r
6668 * },{\r
6669 * xtype: 'button',\r
6670 * text: 'OK',\r
6671 * listeners: {\r
6672 * click: function () {\r
6673 * // Get the Session this component has inherited (from\r
6674 * // the Window) and save it back to the server.\r
6675 * //\r
6676 * this.lookupSession().save();\r
6677 * }\r
6678 * }\r
6679 * }]\r
6680 * });\r
6681 */\r