AbstractContainer.html 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-container-AbstractContainer'>/**
  19. </span> * An abstract base class which provides shared methods for Containers across the Sencha product line.
  20. *
  21. * Please refer to sub class's documentation
  22. *
  23. * @private
  24. */
  25. Ext.define('Ext.container.AbstractContainer', {
  26. /* Begin Definitions */
  27. extend: 'Ext.Component',
  28. requires: [
  29. 'Ext.util.MixedCollection',
  30. 'Ext.layout.container.Auto',
  31. 'Ext.ZIndexManager'
  32. ],
  33. /* End Definitions */
  34. renderTpl: '{%this.renderContainer(out,values)%}',
  35. <span id='Ext-container-AbstractContainer-cfg-layout'> /**
  36. </span> * @cfg {String/Object} layout
  37. * **Important**: In order for child items to be correctly sized and
  38. * positioned, typically a layout manager **must** be specified through
  39. * the `layout` configuration option.
  40. *
  41. * The sizing and positioning of child {@link #cfg-items} is the responsibility of
  42. * the Container's layout manager which creates and manages the type of layout
  43. * you have in mind. For example:
  44. *
  45. * If the {@link #layout} configuration is not explicitly specified for
  46. * a general purpose container (e.g. Container or Panel) the
  47. * {@link Ext.layout.container.Auto default layout manager} will be used
  48. * which does nothing but render child components sequentially into the
  49. * Container (no sizing or positioning will be performed in this situation).
  50. *
  51. * **layout** may be specified as either as an Object or as a String:
  52. *
  53. * # Specify as an Object
  54. *
  55. * Example usage:
  56. *
  57. * layout: {
  58. * type: 'vbox',
  59. * align: 'left'
  60. * }
  61. *
  62. * - **type**
  63. *
  64. * The layout type to be used for this container. If not specified,
  65. * a default {@link Ext.layout.container.Auto} will be created and used.
  66. *
  67. * Valid layout &lt;code&gt;type&lt;/code&gt; values are:
  68. *
  69. * - {@link Ext.layout.container.Auto Auto} - **Default**
  70. * - {@link Ext.layout.container.Card card}
  71. * - {@link Ext.layout.container.Fit fit}
  72. * - {@link Ext.layout.container.HBox hbox}
  73. * - {@link Ext.layout.container.VBox vbox}
  74. * - {@link Ext.layout.container.Anchor anchor}
  75. * - {@link Ext.layout.container.Table table}
  76. *
  77. * - Layout specific configuration properties
  78. *
  79. * Additional layout specific configuration properties may also be
  80. * specified. For complete details regarding the valid config options for
  81. * each layout type, see the layout class corresponding to the `type`
  82. * specified.
  83. *
  84. * # Specify as a String
  85. *
  86. * Example usage:
  87. *
  88. * layout: 'vbox'
  89. *
  90. * - **layout**
  91. *
  92. * The layout `type` to be used for this container (see list
  93. * of valid layout type values above).
  94. *
  95. * Additional layout specific configuration properties. For complete
  96. * details regarding the valid config options for each layout type, see the
  97. * layout class corresponding to the `layout` specified.
  98. *
  99. * # Configuring the default layout type
  100. *
  101. * If a certain Container class has a default layout (For example a {@link Ext.toolbar.Toolbar Toolbar}
  102. * with a default `Box` layout), then to simply configure the default layout,
  103. * use an object, but without the `type` property:
  104. *
  105. *
  106. * xtype: 'toolbar',
  107. * layout: {
  108. * pack: 'center'
  109. * }
  110. */
  111. <span id='Ext-container-AbstractContainer-cfg-activeItem'> /**
  112. </span> * @cfg {String/Number} activeItem
  113. * A string component id or the numeric index of the component that should be
  114. * initially activated within the container's layout on render. For example,
  115. * activeItem: 'item-1' or activeItem: 0 (index 0 = the first item in the
  116. * container's collection). activeItem only applies to layout styles that can
  117. * display items one at a time (like {@link Ext.layout.container.Card} and
  118. * {@link Ext.layout.container.Fit}).
  119. */
  120. <span id='Ext-container-AbstractContainer-cfg-items'> /**
  121. </span> * @cfg {Object/Object[]} items
  122. * A single item, or an array of child Components to be added to this container
  123. *
  124. * **Unless configured with a {@link #layout}, a Container simply renders child
  125. * Components serially into its encapsulating element and performs no sizing or
  126. * positioning upon them.**
  127. *
  128. * Example:
  129. *
  130. * // specifying a single item
  131. * items: {...},
  132. * layout: 'fit', // The single items is sized to fit
  133. *
  134. * // specifying multiple items
  135. * items: [{...}, {...}],
  136. * layout: 'hbox', // The items are arranged horizontally
  137. *
  138. * Each item may be:
  139. *
  140. * - A {@link Ext.Component Component}
  141. * - A Component configuration object
  142. *
  143. * If a configuration object is specified, the actual type of Component to be
  144. * instantiated my be indicated by using the {@link Ext.Component#xtype xtype} option.
  145. *
  146. * Every Component class has its own {@link Ext.Component#xtype xtype}.
  147. *
  148. * If an {@link Ext.Component#xtype xtype} is not explicitly specified, the
  149. * {@link #defaultType} for the Container is used, which by default is usually `panel`.
  150. *
  151. * # Notes:
  152. *
  153. * Ext uses lazy rendering. Child Components will only be rendered
  154. * should it become necessary. Items are automatically laid out when they are first
  155. * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.
  156. *
  157. * Do not specify {@link Ext.panel.Panel#contentEl contentEl} or
  158. * {@link Ext.panel.Panel#html html} with `items`.
  159. */
  160. <span id='Ext-container-AbstractContainer-cfg-defaults'> /**
  161. </span> * @cfg {Object/Function} defaults
  162. * This option is a means of applying default settings to all added items whether added
  163. * through the {@link #cfg-items} config or via the {@link #method-add} or {@link #insert} methods.
  164. *
  165. * Defaults are applied to both config objects and instantiated components conditionally
  166. * so as not to override existing properties in the item (see {@link Ext#applyIf}).
  167. *
  168. * If the defaults option is specified as a function, then the function will be called
  169. * using this Container as the scope (`this` reference) and passing the added item as
  170. * the first parameter. Any resulting object from that call is then applied to the item
  171. * as default properties.
  172. *
  173. * For example, to automatically apply padding to the body of each of a set of
  174. * contained {@link Ext.panel.Panel} items, you could pass:
  175. * `defaults: {bodyStyle:'padding:15px'}`.
  176. *
  177. * Usage:
  178. *
  179. * defaults: { // defaults are applied to items, not the container
  180. * autoScroll: true
  181. * },
  182. * items: [
  183. * // default will not be applied here, panel1 will be autoScroll: false
  184. * {
  185. * xtype: 'panel',
  186. * id: 'panel1',
  187. * autoScroll: false
  188. * },
  189. * // this component will have autoScroll: true
  190. * new Ext.panel.Panel({
  191. * id: 'panel2'
  192. * })
  193. * ]
  194. */
  195. <span id='Ext-container-AbstractContainer-cfg-suspendLayout'> /**
  196. </span> * @cfg {Boolean} suspendLayout
  197. * If true, suspend calls to doLayout. Useful when batching multiple adds to a container
  198. * and not passing them as multiple arguments or an array.
  199. */
  200. suspendLayout : false,
  201. <span id='Ext-container-AbstractContainer-cfg-autoDestroy'> /**
  202. </span> * @cfg {Boolean} [autoDestroy=true]
  203. * If true the container will automatically destroy any contained component that is removed
  204. * from it, else destruction must be handled manually.
  205. */
  206. autoDestroy : true,
  207. <span id='Ext-container-AbstractContainer-cfg-defaultType'> /**
  208. </span> * @cfg {String} [defaultType=&quot;panel&quot;]
  209. * The default {@link Ext.Component xtype} of child Components to create in this Container when
  210. * a child item is specified as a raw configuration object, rather than as an instantiated Component.
  211. */
  212. defaultType: 'panel',
  213. <span id='Ext-container-AbstractContainer-cfg-detachOnRemove'> /**
  214. </span> * @cfg {Boolean} [detachOnRemove=true]
  215. * True to move any component to the {@link Ext#getDetachedBody detachedBody} when the component is
  216. * removed from this container. This option is only applicable when the component is not destroyed while
  217. * being removed, see {@link #autoDestroy} and {@link #method-remove}. If this option is set to false, the DOM
  218. * of the component will remain in the current place until it is explicitly moved.
  219. */
  220. detachOnRemove: true,
  221. /*
  222. * @property {Boolean} isContainer
  223. * `true` in this class to identify an object as an instantiated Container, or subclass thereof.
  224. */
  225. isContainer : true,
  226. <span id='Ext-container-AbstractContainer-property-layoutCounter'> /**
  227. </span> * @property {Number} layoutCounter
  228. * The number of container layout calls made on this object.
  229. * @private
  230. */
  231. layoutCounter : 0,
  232. baseCls: Ext.baseCSSPrefix + 'container',
  233. <span id='Ext-container-AbstractContainer-cfg-bubbleEvents'> /**
  234. </span> * @cfg {String[]} bubbleEvents
  235. * An array of events that, when fired, should be bubbled to any parent container.
  236. * See {@link Ext.util.Observable#enableBubble}.
  237. */
  238. bubbleEvents: ['add', 'remove'],
  239. // @private
  240. initComponent : function(){
  241. var me = this;
  242. me.addEvents(
  243. <span id='Ext-container-AbstractContainer-event-afterlayout'> /**
  244. </span> * @event afterlayout
  245. * Fires when the components in this container are arranged by the associated layout manager.
  246. * @param {Ext.container.Container} this
  247. * @param {Ext.layout.container.Container} layout The ContainerLayout implementation for this container
  248. */
  249. 'afterlayout',
  250. <span id='Ext-container-AbstractContainer-event-beforeadd'> /**
  251. </span> * @event beforeadd
  252. * Fires before any {@link Ext.Component} is added or inserted into the container.
  253. * A handler can return false to cancel the add.
  254. * @param {Ext.container.Container} this
  255. * @param {Ext.Component} component The component being added
  256. * @param {Number} index The index at which the component will be added to the container's items collection
  257. */
  258. 'beforeadd',
  259. <span id='Ext-container-AbstractContainer-event-beforeremove'> /**
  260. </span> * @event beforeremove
  261. * Fires before any {@link Ext.Component} is removed from the container. A handler can return
  262. * false to cancel the remove.
  263. * @param {Ext.container.Container} this
  264. * @param {Ext.Component} component The component being removed
  265. */
  266. 'beforeremove',
  267. <span id='Ext-container-AbstractContainer-event-add'> /**
  268. </span> * @event add
  269. * Fires after any {@link Ext.Component} is added or inserted into the container.
  270. *
  271. * **This event bubbles:** 'add' will also be fired when Component is added to any of
  272. * the child containers or their childern or ...
  273. * @param {Ext.container.Container} this
  274. * @param {Ext.Component} component The component that was added
  275. * @param {Number} index The index at which the component was added to the container's items collection
  276. */
  277. 'add',
  278. <span id='Ext-container-AbstractContainer-event-remove'> /**
  279. </span> * @event remove
  280. * Fires after any {@link Ext.Component} is removed from the container.
  281. *
  282. * **This event bubbles:** 'remove' will also be fired when Component is removed from any of
  283. * the child containers or their children or ...
  284. * @param {Ext.container.Container} this
  285. * @param {Ext.Component} component The component that was removed
  286. */
  287. 'remove'
  288. );
  289. me.callParent();
  290. me.getLayout();
  291. me.initItems();
  292. },
  293. // @private
  294. initItems : function() {
  295. var me = this,
  296. items = me.items;
  297. <span id='Ext-container-AbstractContainer-property-items'> /**
  298. </span> * The MixedCollection containing all the child items of this container.
  299. * @property items
  300. * @type Ext.util.AbstractMixedCollection
  301. */
  302. me.items = new Ext.util.AbstractMixedCollection(false, me.getComponentId);
  303. if (items) {
  304. if (!Ext.isArray(items)) {
  305. items = [items];
  306. }
  307. me.add(items);
  308. }
  309. },
  310. <span id='Ext-container-AbstractContainer-method-getFocusEl'> /**
  311. </span> * @private
  312. * Returns the focus holder element associated with this Container. By default, this is the Container's target
  313. * element. Subclasses which use embedded focusable elements (such as Window and Button) should override this for use
  314. * by the {@link #method-focus} method.
  315. * @returns {Ext.Element} the focus holding element.
  316. */
  317. getFocusEl: function() {
  318. return this.getTargetEl();
  319. },
  320. finishRenderChildren: function () {
  321. this.callParent();
  322. var layout = this.getLayout();
  323. if (layout) {
  324. layout.finishRender();
  325. }
  326. },
  327. beforeRender: function () {
  328. var me = this,
  329. layout = me.getLayout();
  330. me.callParent();
  331. if (!layout.initialized) {
  332. layout.initLayout();
  333. }
  334. },
  335. setupRenderTpl: function (renderTpl) {
  336. var layout = this.getLayout();
  337. this.callParent(arguments);
  338. layout.setupRenderTpl(renderTpl);
  339. },
  340. // @private
  341. setLayout : function(layout) {
  342. var currentLayout = this.layout;
  343. if (currentLayout &amp;&amp; currentLayout.isLayout &amp;&amp; currentLayout != layout) {
  344. currentLayout.setOwner(null);
  345. }
  346. this.layout = layout;
  347. layout.setOwner(this);
  348. },
  349. <span id='Ext-container-AbstractContainer-method-getLayout'> /**
  350. </span> * Returns the {@link Ext.layout.container.Container layout} instance currently associated with this Container.
  351. * If a layout has not been instantiated yet, that is done first
  352. * @return {Ext.layout.container.Container} The layout
  353. */
  354. getLayout : function() {
  355. var me = this;
  356. if (!me.layout || !me.layout.isLayout) {
  357. // Pass any configured in layout property, defaulting to the prototype's layout property, falling back to Auto.
  358. me.setLayout(Ext.layout.Layout.create(me.layout, me.self.prototype.layout || 'autocontainer'));
  359. }
  360. return me.layout;
  361. },
  362. <span id='Ext-container-AbstractContainer-method-doLayout'> /**
  363. </span> * Manually force this container's layout to be recalculated. The framework uses this internally to refresh layouts
  364. * form most cases.
  365. * @return {Ext.container.Container} this
  366. */
  367. doLayout : function() {
  368. this.updateLayout();
  369. return this;
  370. },
  371. <span id='Ext-container-AbstractContainer-method-afterLayout'> /**
  372. </span> * Invoked after the Container has laid out (and rendered if necessary)
  373. * its child Components.
  374. *
  375. * @param {Ext.layout.container.Container} layout
  376. *
  377. * @template
  378. * @protected
  379. */
  380. afterLayout : function(layout) {
  381. var me = this;
  382. ++me.layoutCounter;
  383. if (me.hasListeners.afterlayout) {
  384. me.fireEvent('afterlayout', me, layout);
  385. }
  386. },
  387. // @private
  388. prepareItems : function(items, applyDefaults) {
  389. // Create an Array which does not refer to the passed array.
  390. // The passed array is a reference to a user's config object and MUST NOT be mutated.
  391. if (Ext.isArray(items)) {
  392. items = items.slice();
  393. } else {
  394. items = [items];
  395. }
  396. // Make sure defaults are applied and item is initialized
  397. var me = this,
  398. i = 0,
  399. len = items.length,
  400. item;
  401. for (; i &lt; len; i++) {
  402. item = items[i];
  403. if (item == null) {
  404. Ext.Array.erase(items, i, 1);
  405. --i;
  406. --len;
  407. } else {
  408. if (applyDefaults) {
  409. item = this.applyDefaults(item);
  410. }
  411. // Tell the item we're in a container during construction
  412. item.isContained = me;
  413. items[i] = me.lookupComponent(item);
  414. delete item.isContained;
  415. }
  416. }
  417. return items;
  418. },
  419. // @private
  420. applyDefaults : function(config) {
  421. var defaults = this.defaults;
  422. if (defaults) {
  423. if (Ext.isFunction(defaults)) {
  424. defaults = defaults.call(this, config);
  425. }
  426. if (Ext.isString(config)) {
  427. config = Ext.ComponentManager.get(config);
  428. }
  429. Ext.applyIf(config, defaults);
  430. }
  431. return config;
  432. },
  433. // @private
  434. lookupComponent : function(comp) {
  435. return (typeof comp == 'string') ? Ext.ComponentManager.get(comp)
  436. : Ext.ComponentManager.create(comp, this.defaultType);
  437. },
  438. // @private - used as the key lookup function for the items collection
  439. getComponentId : function(comp) {
  440. return comp.getItemId();
  441. },
  442. <span id='Ext-container-AbstractContainer-method-add'> /**
  443. </span> * Adds {@link Ext.Component Component}(s) to this Container.
  444. *
  445. * ## Description:
  446. *
  447. * - Fires the {@link #beforeadd} event before adding.
  448. * - The Container's {@link #defaults default config values} will be applied
  449. * accordingly (see `{@link #defaults}` for details).
  450. * - Fires the `{@link #event-add}` event after the component has been added.
  451. *
  452. * ## Notes:
  453. *
  454. * If the Container is __already rendered__ when `add`
  455. * is called, it will render the newly added Component into its content area.
  456. *
  457. * **If** the Container was configured with a size-managing {@link #layout} manager,
  458. * the Container will recalculate its internal layout at this time too.
  459. *
  460. * Note that the default layout manager simply renders child Components sequentially
  461. * into the content area and thereafter performs no sizing.
  462. *
  463. * If adding multiple new child Components, pass them as an array to the `add` method,
  464. * so that only one layout recalculation is performed.
  465. *
  466. * tb = new {@link Ext.toolbar.Toolbar}({
  467. * renderTo: document.body
  468. * }); // toolbar is rendered
  469. * // add multiple items.
  470. * // ({@link #defaultType} for {@link Ext.toolbar.Toolbar Toolbar} is 'button')
  471. * tb.add([{text:'Button 1'}, {text:'Button 2'}]);
  472. *
  473. * To inject components between existing ones, use the {@link #insert} method.
  474. *
  475. * ## Warning:
  476. *
  477. * Components directly managed by the BorderLayout layout manager may not be removed
  478. * or added. See the Notes for {@link Ext.layout.container.Border BorderLayout} for
  479. * more details.
  480. *
  481. * @param {Ext.Component[]/Ext.Component...} component
  482. * Either one or more Components to add or an Array of Components to add.
  483. * See `{@link #cfg-items}` for additional information.
  484. *
  485. * @return {Ext.Component[]/Ext.Component} The Components that were added.
  486. */
  487. add : function() {
  488. var me = this,
  489. args = Ext.Array.slice(arguments),
  490. index = (typeof args[0] == 'number') ? args.shift() : -1,
  491. layout = me.getLayout(),
  492. addingArray, items, i, length, item, pos, ret;
  493. if (args.length == 1 &amp;&amp; Ext.isArray(args[0])) {
  494. items = args[0];
  495. addingArray = true;
  496. } else {
  497. items = args;
  498. }
  499. ret = items = me.prepareItems(items, true);
  500. length = items.length;
  501. if (me.rendered) {
  502. Ext.suspendLayouts(); // suspend layouts while adding items...
  503. }
  504. if (!addingArray &amp;&amp; length == 1) { // an array of 1 should still return an array...
  505. ret = items[0];
  506. }
  507. // loop
  508. for (i = 0; i &lt; length; i++) {
  509. item = items[i];
  510. //&lt;debug&gt;
  511. if (!item) {
  512. Ext.Error.raise(&quot;Cannot add null item to Container with itemId/id: &quot; + me.getItemId());
  513. }
  514. //&lt;/debug&gt;
  515. pos = (index &lt; 0) ? me.items.length : (index + i);
  516. // Floating Components are not added into the items collection, but to a separate floatingItems collection
  517. if (item.floating) {
  518. me.floatingItems = me.floatingItems || new Ext.util.MixedCollection();
  519. me.floatingItems.add(item);
  520. item.onAdded(me, pos);
  521. } else if ((!me.hasListeners.beforeadd || me.fireEvent('beforeadd', me, item, pos) !== false) &amp;&amp; me.onBeforeAdd(item) !== false) {
  522. me.items.insert(pos, item);
  523. item.onAdded(me, pos);
  524. me.onAdd(item, pos);
  525. layout.onAdd(item, pos);
  526. if (me.hasListeners.add) {
  527. me.fireEvent('add', me, item, pos);
  528. }
  529. }
  530. }
  531. // We need to update our layout after adding all passed items
  532. me.updateLayout();
  533. if (me.rendered) {
  534. Ext.resumeLayouts(true);
  535. }
  536. return ret;
  537. },
  538. <span id='Ext-container-AbstractContainer-method-onAdd'> /**
  539. </span> * This method is invoked after a new Component has been added. It
  540. * is passed the Component which has been added. This method may
  541. * be used to update any internal structure which may depend upon
  542. * the state of the child items.
  543. *
  544. * @param {Ext.Component} component
  545. * @param {Number} position
  546. *
  547. * @template
  548. * @protected
  549. */
  550. onAdd : Ext.emptyFn,
  551. <span id='Ext-container-AbstractContainer-method-onRemove'> /**
  552. </span> * This method is invoked after a new Component has been
  553. * removed. It is passed the Component which has been
  554. * removed. This method may be used to update any internal
  555. * structure which may depend upon the state of the child items.
  556. *
  557. * @param {Ext.Component} component
  558. * @param {Boolean} autoDestroy
  559. *
  560. * @template
  561. * @protected
  562. */
  563. onRemove : Ext.emptyFn,
  564. <span id='Ext-container-AbstractContainer-method-insert'> /**
  565. </span> * Inserts a Component into this Container at a specified index. Fires the
  566. * {@link #beforeadd} event before inserting, then fires the {@link #event-add}
  567. * event after the Component has been inserted.
  568. *
  569. * @param {Number} index The index at which the Component will be inserted
  570. * into the Container's items collection
  571. *
  572. * @param {Ext.Component} component The child Component to insert.
  573. *
  574. * Ext uses lazy rendering, and will only render the inserted Component should
  575. * it become necessary.
  576. *
  577. * A Component config object may be passed in order to avoid the overhead of
  578. * constructing a real Component object if lazy rendering might mean that the
  579. * inserted Component will not be rendered immediately. To take advantage of
  580. * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
  581. * property to the registered type of the Component wanted.
  582. *
  583. * For a list of all available xtypes, see {@link Ext.Component}.
  584. *
  585. * @return {Ext.Component} component The Component (or config object) that was
  586. * inserted with the Container's default config values applied.
  587. */
  588. insert : function(index, comp) {
  589. return this.add(index, comp);
  590. },
  591. <span id='Ext-container-AbstractContainer-method-move'> /**
  592. </span> * Moves a Component within the Container
  593. * @param {Number} fromIdx The index the Component you wish to move is currently at.
  594. * @param {Number} toIdx The new index for the Component.
  595. * @return {Ext.Component} component The Component (or config object) that was moved.
  596. */
  597. move : function(fromIdx, toIdx) {
  598. var items = this.items,
  599. item;
  600. item = items.removeAt(fromIdx);
  601. if (item === false) {
  602. return false;
  603. }
  604. items.insert(toIdx, item);
  605. this.doLayout();
  606. return item;
  607. },
  608. <span id='Ext-container-AbstractContainer-method-onBeforeAdd'> /**
  609. </span> * This method is invoked before adding a new child Component. It
  610. * is passed the new Component, and may be used to modify the
  611. * Component, or prepare the Container in some way. Returning
  612. * false aborts the add operation.
  613. *
  614. * @param {Ext.Component} item
  615. *
  616. * @template
  617. * @protected
  618. */
  619. onBeforeAdd : function(item) {
  620. var me = this,
  621. border = item.border;
  622. // Remove from current container if it's not us.
  623. if (item.ownerCt &amp;&amp; item.ownerCt !== me) {
  624. item.ownerCt.remove(item, false);
  625. }
  626. if (me.border === false || me.border === 0) {
  627. // If the parent has no border, only use an explicitly defined border
  628. item.border = Ext.isDefined(border) &amp;&amp; border !== false &amp;&amp; border !== 0;
  629. }
  630. },
  631. <span id='Ext-container-AbstractContainer-method-remove'> /**
  632. </span> * Removes a component from this container. Fires the {@link #beforeremove} event
  633. * before removing, then fires the {@link #event-remove} event after the component has
  634. * been removed.
  635. *
  636. * @param {Ext.Component/String} component The component reference or id to remove.
  637. *
  638. * @param {Boolean} [autoDestroy] True to automatically invoke the removed Component's
  639. * {@link Ext.Component#method-destroy} function.
  640. *
  641. * Defaults to the value of this Container's {@link #autoDestroy} config.
  642. *
  643. * @return {Ext.Component} component The Component that was removed.
  644. */
  645. remove : function(comp, autoDestroy) {
  646. var me = this,
  647. c = me.getComponent(comp);
  648. //&lt;debug&gt;
  649. if (Ext.isDefined(Ext.global.console) &amp;&amp; !c) {
  650. Ext.global.console.warn(&quot;Attempted to remove a component that does not exist. Ext.container.Container: remove takes an argument of the component to remove. cmp.remove() is incorrect usage.&quot;);
  651. }
  652. //&lt;/debug&gt;
  653. if (c &amp;&amp; (!me.hasListeners.beforeremove || me.fireEvent('beforeremove', me, c) !== false)) {
  654. me.doRemove(c, autoDestroy);
  655. if (me.hasListeners.remove) {
  656. me.fireEvent('remove', me, c);
  657. }
  658. if (!me.destroying) {
  659. me.doLayout();
  660. }
  661. }
  662. return c;
  663. },
  664. // @private
  665. doRemove : function(component, autoDestroy) {
  666. var me = this,
  667. layout = me.layout,
  668. hasLayout = layout &amp;&amp; me.rendered,
  669. destroying = autoDestroy === true || (autoDestroy !== false &amp;&amp; me.autoDestroy);
  670. autoDestroy = autoDestroy === true || (autoDestroy !== false &amp;&amp; me.autoDestroy);
  671. me.items.remove(component);
  672. // Inform ownerLayout of removal before deleting the ownerLayout &amp; ownerCt references in the onRemoved call
  673. if (hasLayout) {
  674. // Removing a component from a running layout has to cancel the layout
  675. if (layout.running) {
  676. Ext.AbstractComponent.cancelLayout(component, destroying);
  677. }
  678. layout.onRemove(component, destroying);
  679. }
  680. component.onRemoved(destroying);
  681. me.onRemove(component, destroying);
  682. // Destroy if we were explicitly told to, or we're defaulting to our autoDestroy configuration
  683. if (destroying) {
  684. component.destroy();
  685. }
  686. // Only have the layout perform remove postprocessing if the Component is not being destroyed
  687. else {
  688. if (hasLayout) {
  689. layout.afterRemove(component);
  690. }
  691. if (me.detachOnRemove &amp;&amp; component.rendered) {
  692. Ext.getDetachedBody().appendChild(component.getEl());
  693. }
  694. }
  695. },
  696. <span id='Ext-container-AbstractContainer-method-removeAll'> /**
  697. </span> * Removes all components from this container.
  698. * @param {Boolean} [autoDestroy] True to automatically invoke the removed
  699. * Component's {@link Ext.Component#method-destroy} function.
  700. * Defaults to the value of this Container's {@link #autoDestroy} config.
  701. * @return {Ext.Component[]} Array of the removed components
  702. */
  703. removeAll : function(autoDestroy) {
  704. var me = this,
  705. removeItems = me.items.items.slice(),
  706. items = [],
  707. i = 0,
  708. len = removeItems.length,
  709. item;
  710. // Suspend Layouts while we remove multiple items from the container
  711. me.suspendLayouts();
  712. for (; i &lt; len; i++) {
  713. item = removeItems[i];
  714. me.remove(item, autoDestroy);
  715. if (item.ownerCt !== me) {
  716. items.push(item);
  717. }
  718. }
  719. // Resume Layouts now that all items have been removed and do a single layout (if we removed anything!)
  720. me.resumeLayouts(!!len);
  721. return items;
  722. },
  723. // Used by ComponentQuery to retrieve all of the items
  724. // which can potentially be considered a child of this Container.
  725. // This should be overriden by components which have child items
  726. // that are not contained in items. For example dockedItems, menu, etc
  727. // IMPORTANT note for maintainers:
  728. // Items are returned in tree traversal order. Each item is appended to the result array
  729. // followed by the results of that child's getRefItems call.
  730. // Floating child items are appended after internal child items.
  731. getRefItems : function(deep) {
  732. var me = this,
  733. items = me.items.items,
  734. len = items.length,
  735. i = 0,
  736. item,
  737. result = [];
  738. for (; i &lt; len; i++) {
  739. item = items[i];
  740. result.push(item);
  741. if (deep &amp;&amp; item.getRefItems) {
  742. result.push.apply(result, item.getRefItems(true));
  743. }
  744. }
  745. // Append floating items to the list.
  746. if (me.floatingItems) {
  747. result.push.apply(result, me.floatingItems.items);
  748. }
  749. return result;
  750. },
  751. <span id='Ext-container-AbstractContainer-method-cascade'> /**
  752. </span> * Cascades down the component/container heirarchy from this component (passed in
  753. * the first call), calling the specified function with each component. The scope
  754. * (this reference) of the function call will be the scope provided or the current
  755. * component. The arguments to the function will be the args provided or the current
  756. * component. If the function returns false at any point, the cascade is stopped on
  757. * that branch.
  758. * @param {Function} fn The function to call
  759. * @param {Object} [scope] The scope of the function (defaults to current component)
  760. * @param {Array} [args] The args to call the function with. The current component
  761. * always passed as the last argument.
  762. * @return {Ext.Container} this
  763. */
  764. cascade : function(fn, scope, origArgs){
  765. var me = this,
  766. cs = me.items ? me.items.items : [],
  767. len = cs.length,
  768. i = 0,
  769. c,
  770. args = origArgs ? origArgs.concat(me) : [me],
  771. componentIndex = args.length - 1;
  772. if (fn.apply(scope || me, args) !== false) {
  773. for (; i &lt; len; i++){
  774. c = cs[i];
  775. if (c.cascade) {
  776. c.cascade(fn, scope, origArgs);
  777. } else {
  778. args[componentIndex] = c;
  779. fn.apply(scope || cs, args);
  780. }
  781. }
  782. }
  783. return this;
  784. },
  785. <span id='Ext-container-AbstractContainer-method-isAncestor'> /**
  786. </span> * Determines whether **this Container** is an ancestor of the passed Component.
  787. * This will return `true` if the passed Component is anywhere within the subtree
  788. * beneath this Container.
  789. * @param {Ext.Component} possibleDescendant The Component to test for presence
  790. * within this Container's subtree.
  791. */
  792. isAncestor: function(possibleDescendant) {
  793. while (possibleDescendant) {
  794. if (possibleDescendant.ownerCt === this) {
  795. return true;
  796. }
  797. possibleDescendant = possibleDescendant.ownerCt;
  798. }
  799. },
  800. <span id='Ext-container-AbstractContainer-method-getComponent'> /**
  801. </span> * Examines this container's {@link #property-items} **property** and gets a direct child
  802. * component of this container.
  803. *
  804. * @param {String/Number} comp This parameter may be any of the following:
  805. *
  806. * - a **String** : representing the {@link Ext.Component#itemId itemId}
  807. * or {@link Ext.Component#id id} of the child component.
  808. * - a **Number** : representing the position of the child component
  809. * within the {@link #property-items} **property**
  810. *
  811. * For additional information see {@link Ext.util.MixedCollection#get}.
  812. *
  813. * @return {Ext.Component} The component (if found).
  814. */
  815. getComponent : function(comp) {
  816. if (Ext.isObject(comp)) {
  817. comp = comp.getItemId();
  818. }
  819. return this.items.get(comp);
  820. },
  821. <span id='Ext-container-AbstractContainer-method-query'> /**
  822. </span> * Retrieves all descendant components which match the passed selector.
  823. * Executes an Ext.ComponentQuery.query using this container as its root.
  824. * @param {String} [selector] Selector complying to an Ext.ComponentQuery selector.
  825. * If no selector is specified all items will be returned.
  826. * @return {Ext.Component[]} Components which matched the selector
  827. */
  828. query : function(selector) {
  829. selector = selector || '*';
  830. return Ext.ComponentQuery.query(selector, this);
  831. },
  832. <span id='Ext-container-AbstractContainer-method-queryBy'> /**
  833. </span> * Retrieves all descendant components which match the passed function.
  834. * The function should return false for components that are to be
  835. * excluded from the selection.
  836. * @param {Function} fn The matcher function. It will be called with a single argument,
  837. * the component being tested.
  838. * @param {Object} [scope] The scope in which to run the function. If not specified,
  839. * it will default to the active component.
  840. * @return {Ext.Component[]} Components matched by the passed function
  841. */
  842. queryBy: function(fn, scope) {
  843. var out = [],
  844. items = this.getRefItems(true),
  845. i = 0,
  846. len = items.length,
  847. item;
  848. for (; i &lt; len; ++i) {
  849. item = items[i];
  850. if (fn.call(scope || item, item) !== false) {
  851. out.push(item);
  852. }
  853. }
  854. return out;
  855. },
  856. <span id='Ext-container-AbstractContainer-method-queryById'> /**
  857. </span> * Finds a component at any level under this container matching the id/itemId.
  858. * This is a shorthand for calling ct.down('#' + id);
  859. * @param {String} id The id to find
  860. * @return {Ext.Component} The matching id, null if not found
  861. */
  862. queryById: function(id){
  863. return this.down('#' + id);
  864. },
  865. <span id='Ext-container-AbstractContainer-method-child'> /**
  866. </span> * Retrieves the first direct child of this container which matches the passed selector.
  867. * The passed in selector must comply with an Ext.ComponentQuery selector.
  868. * @param {String} [selector] An Ext.ComponentQuery selector. If no selector is
  869. * specified, the first child will be returned.
  870. * @return Ext.Component
  871. */
  872. child : function(selector) {
  873. selector = selector || '';
  874. return this.query('&gt; ' + selector)[0] || null;
  875. },
  876. nextChild: function(child, selector) {
  877. var me = this,
  878. result,
  879. childIndex = me.items.indexOf(child);
  880. if (childIndex !== -1) {
  881. result = selector ? Ext.ComponentQuery(selector, me.items.items.slice(childIndex + 1)) : me.items.getAt(childIndex + 1);
  882. if (!result &amp;&amp; me.ownerCt) {
  883. result = me.ownerCt.nextChild(me, selector);
  884. }
  885. }
  886. return result;
  887. },
  888. prevChild: function(child, selector) {
  889. var me = this,
  890. result,
  891. childIndex = me.items.indexOf(child);
  892. if (childIndex !== -1) {
  893. result = selector ? Ext.ComponentQuery(selector, me.items.items.slice(childIndex + 1)) : me.items.getAt(childIndex + 1);
  894. if (!result &amp;&amp; me.ownerCt) {
  895. result = me.ownerCt.nextChild(me, selector);
  896. }
  897. }
  898. return result;
  899. },
  900. <span id='Ext-container-AbstractContainer-method-down'> /**
  901. </span> * Retrieves the first descendant of this container which matches the passed selector.
  902. * The passed in selector must comply with an Ext.ComponentQuery selector.
  903. * @param {String} [selector] An Ext.ComponentQuery selector. If no selector is
  904. * specified, the first child will be returned.
  905. * @return Ext.Component
  906. */
  907. down : function(selector) {
  908. return this.query(selector)[0] || null;
  909. },
  910. // @private
  911. // Enable all immediate children that was previously disabled
  912. // Override enable because onEnable only gets called when rendered
  913. enable: function() {
  914. this.callParent(arguments);
  915. var itemsToDisable = this.getChildItemsToDisable(),
  916. length = itemsToDisable.length,
  917. item, i;
  918. for (i = 0; i &lt; length; i++) {
  919. item = itemsToDisable[i];
  920. if (item.resetDisable) {
  921. item.enable();
  922. }
  923. }
  924. return this;
  925. },
  926. // Inherit docs
  927. // Disable all immediate children that was previously disabled
  928. // Override disable because onDisable only gets called when rendered
  929. disable: function() {
  930. this.callParent(arguments);
  931. var itemsToDisable = this.getChildItemsToDisable(),
  932. length = itemsToDisable.length,
  933. item, i;
  934. for (i = 0; i &lt; length; i++) {
  935. item = itemsToDisable[i];
  936. if (item.resetDisable !== false &amp;&amp; !item.disabled) {
  937. item.disable();
  938. item.resetDisable = true;
  939. }
  940. }
  941. return this;
  942. },
  943. <span id='Ext-container-AbstractContainer-method-getChildItemsToDisable'> /**
  944. </span> * Gets a list of child components to enable/disable when the container is
  945. * enabled/disabled
  946. * @private
  947. * @return {Ext.Component[]} Items to be enabled/disabled
  948. */
  949. getChildItemsToDisable: function(){
  950. return this.query('[isFormField],button');
  951. },
  952. <span id='Ext-container-AbstractContainer-method-beforeLayout'> /**
  953. </span> * Occurs before componentLayout is run. Returning false from this method
  954. * will prevent the containerLayout from being executed.
  955. *
  956. * @template
  957. * @protected
  958. */
  959. beforeLayout: function() {
  960. return true;
  961. },
  962. // @private
  963. beforeDestroy : function() {
  964. var me = this,
  965. items = me.items,
  966. c;
  967. if (items) {
  968. while ((c = items.first())) {
  969. me.doRemove(c, true);
  970. }
  971. }
  972. Ext.destroy(
  973. me.layout
  974. );
  975. me.callParent();
  976. }
  977. });
  978. </pre>
  979. </body>
  980. </html>