Container.html 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  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-layout-container-Container'>/**
  19. </span> * This class is intended to be extended or created via the {@link Ext.container.Container#layout layout}
  20. * configuration property. See {@link Ext.container.Container#layout} for additional details.
  21. */
  22. Ext.define('Ext.layout.container.Container', {
  23. /* Begin Definitions */
  24. extend: 'Ext.layout.Layout',
  25. alternateClassName: 'Ext.layout.ContainerLayout',
  26. mixins: {
  27. elementCt: 'Ext.util.ElementContainer'
  28. },
  29. requires: [
  30. 'Ext.XTemplate'
  31. ],
  32. type: 'container',
  33. /* End Definitions */
  34. <span id='Ext-layout-container-Container-cfg-itemCls'> /**
  35. </span> * @cfg {String} itemCls
  36. * An optional extra CSS class that will be added to the container. This can be useful for
  37. * adding customized styles to the container or any of its children using standard CSS
  38. * rules. See {@link Ext.Component}.{@link Ext.Component#componentCls componentCls} also.
  39. */
  40. <span id='Ext-layout-container-Container-cfg-manageOverflow'> /**
  41. </span> * @cfg {Number} [manageOverflow=0]
  42. * One of the following values:
  43. *
  44. * - 0 if the layout should ignore overflow.
  45. * - 1 if the layout should be rerun if scrollbars are needed.
  46. * - 2 if the layout should also correct padding when overflowed.
  47. */
  48. manageOverflow: 0,
  49. <span id='Ext-layout-container-Container-method-beginCollapse'> /**
  50. </span> * @private
  51. * Called by an owning Panel before the Panel begins its collapse process.
  52. * Most layouts will not need to override the default Ext.emptyFn implementation.
  53. */
  54. beginCollapse: Ext.emptyFn,
  55. <span id='Ext-layout-container-Container-method-beginExpand'> /**
  56. </span> * @private
  57. * Called by an owning Panel before the Panel begins its expand process.
  58. * Most layouts will not need to override the default Ext.emptyFn implementation.
  59. */
  60. beginExpand: Ext.emptyFn,
  61. <span id='Ext-layout-container-Container-property-animatePolicy'> /**
  62. </span> * An object which contains boolean properties specifying which properties are to be
  63. * animated upon flush of child Component ContextItems. For example, Accordion would
  64. * have:
  65. *
  66. * {
  67. * y: true,
  68. * height: true
  69. * }
  70. *
  71. * @private
  72. */
  73. animatePolicy: null,
  74. childEls: [
  75. <span id='Ext-layout-container-Container-property-overflowPadderEl'> /**
  76. </span> * @property {Ext.Element} overflowPadderEl
  77. * The element used to correct body padding during overflow.
  78. */
  79. 'overflowPadderEl'
  80. ],
  81. renderTpl: [
  82. '{%this.renderBody(out,values)%}'
  83. ],
  84. usesContainerHeight: true,
  85. usesContainerWidth: true,
  86. usesHeight: true,
  87. usesWidth: true,
  88. <span id='Ext-layout-container-Container-cfg-reserveScrollbar'> /**
  89. </span> * @cfg {Boolean} [reserveScrollbar=false]
  90. * Set to `true` to leave space for a vertical scrollbar (if the OS shows space-consuming scrollbars) regardless
  91. * of whether a scrollbar is needed.
  92. *
  93. * This is useful if content height changes during application usage, but you do not want the calculated width
  94. * of child items to change when a scrollbar appears or disappears. The scrollbar will appear in the reserved space,
  95. * and the calculated width of child Components will not change.
  96. *
  97. * @example
  98. * Ext.define('Employee', {
  99. * extend: 'Ext.data.Model',
  100. * fields: [
  101. * {name: 'rating', type: 'int'},
  102. * {name: 'salary', type: 'float'},
  103. * {name: 'name'}
  104. * ]
  105. * });
  106. *
  107. * function createFakeData(count) {
  108. * var firstNames = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay', 'Nicolas', 'Nige'],
  109. * lastNames = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson', 'Ferrero', 'White'],
  110. * ratings = [1, 2, 3, 4, 5],
  111. * salaries = [100, 400, 900, 1500, 1000000];
  112. *
  113. * var data = [];
  114. * for (var i = 0; i &lt; (count || 25); i++) {
  115. * var ratingId = Math.floor(Math.random() * ratings.length),
  116. * salaryId = Math.floor(Math.random() * salaries.length),
  117. * firstNameId = Math.floor(Math.random() * firstNames.length),
  118. * lastNameId = Math.floor(Math.random() * lastNames.length),
  119. *
  120. * rating = ratings[ratingId],
  121. * salary = salaries[salaryId],
  122. * name = Ext.String.format(&quot;{0} {1}&quot;, firstNames[firstNameId], lastNames[lastNameId]);
  123. *
  124. * data.push({
  125. * rating: rating,
  126. * salary: salary,
  127. * name: name
  128. * });
  129. * }
  130. * store.loadData(data);
  131. * }
  132. *
  133. * // create the Data Store
  134. * var store = Ext.create('Ext.data.Store', {
  135. * id: 'store',
  136. * model: 'Employee',
  137. * proxy: {
  138. * type: 'memory'
  139. * }
  140. * });
  141. * createFakeData(10);
  142. *
  143. * var grid = Ext.create('Ext.grid.Panel', {
  144. * title: 'Grid loaded with varying number of records',
  145. * anchor: '100%',
  146. * store: store,
  147. * columns: [{
  148. * xtype: 'rownumberer',
  149. * width: 40,
  150. * sortable: false
  151. * },{
  152. * text: 'Name',
  153. * flex: 1,
  154. * sortable: true,
  155. * dataIndex: 'name'
  156. * },{
  157. * text: 'Rating',
  158. * width: 125,
  159. * sortable: true,
  160. * dataIndex: 'rating'
  161. * },{
  162. * text: 'Salary',
  163. * width: 125,
  164. * sortable: true,
  165. * dataIndex: 'salary',
  166. * align: 'right',
  167. * renderer: Ext.util.Format.usMoney
  168. * }]
  169. * });
  170. *
  171. * Ext.create('Ext.panel.Panel', {
  172. * renderTo: document.body,
  173. * width: 800,
  174. * height: 600,
  175. * layout: {
  176. * type: 'anchor',
  177. * reserveScrollbar: true // There will be a gap even when there's no scrollbar
  178. * },
  179. * autoScroll: true,
  180. * items: grid,
  181. * tbar: {
  182. * defaults: {
  183. * handler: function(b) {
  184. * createFakeData(b.count);
  185. * }
  186. * },
  187. * items: [{
  188. * text: '10 Items',
  189. * count: 10
  190. * },{
  191. * text: '100 Items',
  192. * count: 100
  193. * },{
  194. * text: '300 Items',
  195. * count: 300
  196. * },{
  197. * text: '1000 Items',
  198. * count: 1000
  199. * },{
  200. * text: '5000 Items',
  201. * count: 5000
  202. * }]
  203. * }
  204. * });
  205. *
  206. */
  207. reserveScrollbar: false,
  208. // Begin with no previous adjustments
  209. lastOverflowAdjust: {
  210. width: 0,
  211. height: 0
  212. },
  213. constructor: function () {
  214. this.callParent(arguments);
  215. this.mixins.elementCt.constructor.call(this);
  216. },
  217. destroy : function() {
  218. this.callParent();
  219. this.mixins.elementCt.destroy.call(this);
  220. },
  221. initLayout: function() {
  222. var me = this,
  223. scrollbarWidth = Ext.getScrollbarSize().width;
  224. me.callParent();
  225. // Create a default lastOverflowAdjust based upon scrolling configuration.
  226. // If the Container is to overflow, or we *always* reserve space for a scrollbar
  227. // then reserve space for a vertical scrollbar
  228. if (scrollbarWidth &amp;&amp; me.manageOverflow &amp;&amp; !me.hasOwnProperty('lastOverflowAdjust')) {
  229. if (me.owner.autoScroll || me.reserveScrollbar) {
  230. me.lastOverflowAdjust = {
  231. width: scrollbarWidth,
  232. height: 0
  233. };
  234. }
  235. }
  236. },
  237. <span id='Ext-layout-container-Container-method-beginLayout'> /**
  238. </span> * In addition to work done by our base classes, containers benefit from some extra
  239. * cached data. The following properties are added to the ownerContext:
  240. *
  241. * - visibleItems: the result of {@link #getVisibleItems}
  242. * - childItems: the ContextItem[] for each visible item
  243. * - targetContext: the ContextItem for the {@link #getTarget} element
  244. */
  245. beginLayout: function (ownerContext) {
  246. this.callParent(arguments);
  247. ownerContext.targetContext = ownerContext.getEl('getTarget', this);
  248. this.cacheChildItems(ownerContext);
  249. },
  250. beginLayoutCycle: function (ownerContext, firstCycle) {
  251. var me = this,
  252. padEl = me.overflowPadderEl;
  253. me.callParent(arguments);
  254. // Begin with the scrollbar adjustment that we used last time - this is more likely to be correct
  255. // than beginning with no adjustment at all
  256. if (!ownerContext.state.overflowAdjust) {
  257. ownerContext.state.overflowAdjust = me.lastOverflowAdjust;
  258. }
  259. if (firstCycle) {
  260. if (me.usesContainerHeight) {
  261. ++ownerContext.consumersContainerHeight;
  262. }
  263. if (me.usesContainerWidth) {
  264. ++ownerContext.consumersContainerWidth;
  265. }
  266. }
  267. if (padEl) {
  268. padEl.setStyle('display', 'none');
  269. }
  270. },
  271. completeLayout: function (ownerContext) {
  272. // Cache the scrollbar adjustment
  273. this.lastOverflowAdjust = ownerContext.state.overflowAdjust;
  274. },
  275. cacheChildItems: function (ownerContext) {
  276. var context = ownerContext.context,
  277. childItems = [],
  278. items = this.getVisibleItems(),
  279. length = items.length,
  280. i;
  281. ownerContext.childItems = childItems;
  282. ownerContext.visibleItems = items;
  283. for (i = 0; i &lt; length; ++i) {
  284. childItems.push(context.getCmp(items[i]));
  285. }
  286. },
  287. cacheElements: function () {
  288. var owner = this.owner;
  289. this.applyChildEls(owner.el, owner.id); // from ElementContainer mixin
  290. },
  291. calculateContentSize: function (ownerContext, dimensions) {
  292. var me = this,
  293. containerDimensions = (dimensions || 0) | me.manageOverflow |
  294. ((ownerContext.widthModel.shrinkWrap ? 1 : 0) |
  295. (ownerContext.heightModel.shrinkWrap ? 2 : 0)),
  296. calcWidth = (containerDimensions &amp; 1) || undefined,
  297. calcHeight = (containerDimensions &amp; 2) || undefined,
  298. childItems = ownerContext.childItems,
  299. length = childItems.length,
  300. contentHeight = 0,
  301. contentWidth = 0,
  302. needed = 0,
  303. props = ownerContext.props,
  304. targetXY, targetX, targetY, targetPadding,
  305. borders, child, childContext, childX, childY, height, i, margins, width, xy;
  306. if (calcWidth) {
  307. if (isNaN(props.contentWidth)) {
  308. ++needed;
  309. } else {
  310. calcWidth = undefined;
  311. }
  312. }
  313. if (calcHeight) {
  314. if (isNaN(props.contentHeight)) {
  315. ++needed;
  316. } else {
  317. calcHeight = undefined;
  318. }
  319. }
  320. if (needed) {
  321. // TODO - this is rather brute force... maybe a wrapping el or clientHeight/Width
  322. // trick might help. Whatever we do, it must either work for Absolute layout or
  323. // at least be correctable by an overridden method in that derived class.
  324. for (i = 0; i &lt; length; ++i) {
  325. childContext = childItems[i];
  326. child = childContext.target;
  327. height = calcHeight &amp;&amp; childContext.getProp('height');
  328. width = calcWidth &amp;&amp; childContext.getProp('width');
  329. margins = childContext.getMarginInfo();
  330. // getXY is the root method here (meaning that we cannot avoid getting both
  331. // even if we need only one), so dip into the DOM if something is needed
  332. if ((calcWidth &amp;&amp; isNaN(child.x)) || (calcHeight &amp;&amp; isNaN(child.y))) {
  333. xy = child.el.getXY();
  334. if (!targetXY) {
  335. targetXY = ownerContext.targetContext.el.getXY();
  336. borders = ownerContext.targetContext.getBorderInfo();
  337. targetX = targetXY[0] + borders.left;
  338. targetY = targetXY[1] + borders.top;
  339. }
  340. // not worth avoiding the possibly useless calculation here:
  341. childX = xy[0] - targetX;
  342. childY = xy[1] - targetY;
  343. } else {
  344. // not worth avoiding these either:
  345. childX = child.x;
  346. childY = child.y;
  347. }
  348. // XY includes the top/left margin
  349. height += margins.bottom;
  350. width += margins.right;
  351. contentHeight = Math.max(contentHeight, childY + height);
  352. contentWidth = Math.max(contentWidth, childX + width);
  353. if (isNaN(contentHeight) &amp;&amp; isNaN(contentWidth)) {
  354. me.done = false;
  355. return;
  356. }
  357. }
  358. if (calcWidth || calcHeight) {
  359. targetPadding = ownerContext.targetContext.getPaddingInfo();
  360. }
  361. if (calcWidth &amp;&amp; !ownerContext.setContentWidth(contentWidth + targetPadding.right)) {
  362. me.done = false;
  363. }
  364. if (calcHeight &amp;&amp; !ownerContext.setContentHeight(contentHeight + targetPadding.bottom)) {
  365. me.done = false;
  366. }
  367. /* add a '/' to turn on this log ('//* enables, '/*' disables)
  368. if (me.done) {
  369. var el = ownerContext.targetContext.el.dom;
  370. Ext.log(this.owner.id, '.contentSize: ', contentWidth, 'x', contentHeight,
  371. ' =&gt; scrollSize: ', el.scrollWidth, 'x', el.scrollHeight);
  372. }/**/
  373. }
  374. },
  375. <span id='Ext-layout-container-Container-method-calculateOverflow'> /**
  376. </span> * Handles overflow processing for a container. This should be called once the layout
  377. * has determined contentWidth/Height. In addition to the ownerContext passed to the
  378. * {@link #calculate} method, this method also needs the containerSize (the object
  379. * returned by {@link #getContainerSize}).
  380. *
  381. * @param {Ext.layout.ContextItem} ownerContext
  382. * @param {Object} containerSize
  383. * @param {Number} dimensions A bit mask for the overflow managed dimensions. The 0-bit
  384. * is for `width` and the 1-bit is for `height`. In other words, a value of 1 would be
  385. * only `width`, 2 would be only `height` and 3 would be both.
  386. */
  387. calculateOverflow: function (ownerContext, containerSize, dimensions) {
  388. var me = this,
  389. owner = me.owner,
  390. manageOverflow = me.manageOverflow,
  391. state = ownerContext.state,
  392. overflowAdjust = state.overflowAdjust,
  393. padWidth, padHeight, padElContext, padding, scrollRangeFlags,
  394. overflow, scrollbarSize, contentW, contentH, ownerW, ownerH, scrollbars,
  395. xauto, yauto;
  396. if (manageOverflow &amp;&amp; !state.secondPass &amp;&amp; !me.reserveScrollbar) {
  397. // Determine the dimensions that have overflow:auto applied. If these come by
  398. // way of component config, this does not require a DOM read:
  399. if (owner.autoScroll) {
  400. xauto = yauto = true;
  401. } else {
  402. if (owner.overflowX) {
  403. xauto = owner.overflowX == 'auto';
  404. } else {
  405. overflow = ownerContext.targetContext.getStyle('overflow-x');
  406. xauto = overflow &amp;&amp; overflow != 'hidden' &amp;&amp; overflow != 'scroll';
  407. }
  408. if (owner.overflowY) {
  409. yauto = owner.overflowY == 'auto';
  410. } else {
  411. overflow = ownerContext.targetContext.getStyle('overflow-y');
  412. yauto = overflow &amp;&amp; overflow != 'hidden' &amp;&amp; overflow != 'scroll';
  413. }
  414. }
  415. // If the container layout is not using width, we don't need to adjust for the
  416. // vscroll (likewise for height). Perhaps we don't even need to run the layout
  417. // again if the adjustments won't have any effect on the result!
  418. if (!containerSize.gotWidth) {
  419. xauto = false;
  420. }
  421. if (!containerSize.gotHeight) {
  422. yauto = false;
  423. }
  424. if (xauto || yauto) {
  425. scrollbarSize = Ext.getScrollbarSize();
  426. // as a container we calculate contentWidth/Height, so we don't want
  427. // to use getProp and make it look like we are triggered by them...
  428. contentW = ownerContext.peek('contentWidth');
  429. contentH = ownerContext.peek('contentHeight');
  430. ownerW = containerSize.width;
  431. ownerH = containerSize.height;
  432. scrollbars = me.getScrollbarsNeeded(ownerW, ownerH, contentW, contentH);
  433. state.overflowState = scrollbars;
  434. if (typeof dimensions == 'number') {
  435. scrollbars &amp;= ~dimensions; // ignore dimensions that have no effect
  436. }
  437. overflowAdjust = {
  438. width: (xauto &amp;&amp; (scrollbars &amp; 2)) ? scrollbarSize.width : 0,
  439. height: (yauto &amp;&amp; (scrollbars &amp; 1)) ? scrollbarSize.height : 0
  440. };
  441. // We can have 0-sized scrollbars (new Mac OS) and so don't invalidate
  442. // the layout unless this will change something...
  443. if (overflowAdjust.width !== me.lastOverflowAdjust.width || overflowAdjust.height !== me.lastOverflowAdjust.height) {
  444. me.done = false;
  445. // we pass overflowAdjust and overflowState in as state for the next
  446. // cycle (these are discarded if one of our ownerCt's invalidates):
  447. ownerContext.invalidate({
  448. state: {
  449. overflowAdjust: overflowAdjust,
  450. overflowState: state.overflowState,
  451. secondPass: true
  452. }
  453. });
  454. }
  455. }
  456. }
  457. if (!me.done) {
  458. return;
  459. }
  460. padElContext = ownerContext.padElContext ||
  461. (ownerContext.padElContext = ownerContext.getEl('overflowPadderEl', me));
  462. // Even if overflow does not effect the layout, we still do need the padEl to be
  463. // sized or hidden appropriately...
  464. if (padElContext) {
  465. scrollbars = state.overflowState; // the true overflow state
  466. padWidth = containerSize.width;
  467. padHeight = 0;// TODO me.padHeightAdj; // 0 or 1
  468. if (scrollbars) {
  469. padding = ownerContext.targetContext.getPaddingInfo();
  470. scrollRangeFlags = me.scrollRangeFlags;
  471. if ((scrollbars &amp; 2) &amp;&amp; (scrollRangeFlags &amp; 1)) { // if (vscroll and loses bottom)
  472. padHeight += padding.bottom;
  473. }
  474. if ((scrollbars &amp; 1) &amp;&amp; (scrollRangeFlags &amp; 4)) { // if (hscroll and loses right)
  475. padWidth += padding.right;
  476. }
  477. padElContext.setProp('display', '');
  478. padElContext.setSize(padWidth, padHeight);
  479. } else {
  480. padElContext.setProp('display', 'none');
  481. }
  482. }
  483. },
  484. <span id='Ext-layout-container-Container-method-configureItem'> /**
  485. </span> * Adds layout's itemCls and owning Container's itemCls
  486. * @protected
  487. */
  488. configureItem: function(item) {
  489. var me = this,
  490. ownerItemCls = me.owner.itemCls,
  491. addClasses = [].concat(me.itemCls || []);
  492. me.callParent(arguments);
  493. if (ownerItemCls) {
  494. addClasses = Ext.Array.push(addClasses, ownerItemCls);
  495. }
  496. item.addCls(addClasses);
  497. },
  498. doRenderBody: function (out, renderData) {
  499. // Careful! This method is bolted on to the renderTpl so all we get for context is
  500. // the renderData! The &quot;this&quot; pointer is the renderTpl instance!
  501. this.renderItems(out, renderData);
  502. this.renderContent(out, renderData);
  503. },
  504. doRenderContainer: function (out, renderData) {
  505. // Careful! This method is bolted on to the renderTpl so all we get for context is
  506. // the renderData! The &quot;this&quot; pointer is the renderTpl instance!
  507. var me = renderData.$comp.layout,
  508. tpl = me.getRenderTpl(),
  509. data = me.getRenderData();
  510. tpl.applyOut(data, out);
  511. },
  512. doRenderItems: function (out, renderData) {
  513. // Careful! This method is bolted on to the renderTpl so all we get for context is
  514. // the renderData! The &quot;this&quot; pointer is the renderTpl instance!
  515. var me = renderData.$layout,
  516. tree = me.getRenderTree();
  517. if (tree) {
  518. Ext.DomHelper.generateMarkup(tree, out);
  519. }
  520. },
  521. <span id='Ext-layout-container-Container-method-doRenderPadder'> /**
  522. </span> * Creates an element that makes bottom/right body padding consistent across browsers.
  523. * This element is sized based on the need for scrollbars in {@link #calculateOverflow}.
  524. * If the {@link #manageOverflow} option is false, this element is not created.
  525. *
  526. * See {@link #getScrollRangeFlags} for more details.
  527. */
  528. doRenderPadder: function (out, renderData) {
  529. // Careful! This method is bolted on to the renderTpl so all we get for context is
  530. // the renderData! The &quot;this&quot; pointer is the renderTpl instance!
  531. var me = renderData.$layout,
  532. owner = me.owner,
  533. scrollRangeFlags = me.getScrollRangeFlags();
  534. if (me.manageOverflow == 2) {
  535. if (scrollRangeFlags &amp; 5) { // if (loses parent bottom and/or right padding)
  536. out.push('&lt;div id=&quot;',owner.id,'-overflowPadderEl&quot; ',
  537. 'style=&quot;font-size: 1px; width:1px; height: 1px;');
  538. // We won't want the height of the padder to cause problems when we only
  539. // want to adjust for right padding, so we relatively position it up 1px so
  540. // its height of 1px will have no vertical effect. This trick does not work
  541. // on IE due to bugs (the effects are worse than the off-by-1px in scroll
  542. // height).
  543. //
  544. /* turns out this does not work on FF (5) either... TODO
  545. if (Ext.isIE || Ext.isGecko) {
  546. me.padHeightAdj = 0;
  547. } else {
  548. me.padHeightAdj = 1;
  549. out.push('position: relative; top: -1px;');
  550. }/**/
  551. out.push('&quot;&gt;&lt;/div&gt;');
  552. me.scrollRangeFlags = scrollRangeFlags; // remember for calculateOverflow
  553. }
  554. }
  555. },
  556. finishRender: function () {
  557. var me = this,
  558. target, items;
  559. me.callParent();
  560. me.cacheElements();
  561. target = me.getRenderTarget();
  562. items = me.getLayoutItems();
  563. if (me.targetCls) {
  564. me.getTarget().addCls(me.targetCls);
  565. }
  566. me.finishRenderItems(target, items);
  567. },
  568. <span id='Ext-layout-container-Container-method-notifyOwner'> /**
  569. </span> * @private
  570. * Called for every layout in the layout context after all the layouts have been finally flushed
  571. */
  572. notifyOwner: function() {
  573. this.owner.afterLayout(this);
  574. },
  575. <span id='Ext-layout-container-Container-method-getContainerSize'> /**
  576. </span> * Returns the container size (that of the target). Only the fixed-sized dimensions can
  577. * be returned because the shrinkWrap dimensions are based on the contentWidth/Height
  578. * as determined by the container layout.
  579. *
  580. * If the {@link #calculateOverflow} method is used and if {@link #manageOverflow} is
  581. * true, this may adjust the width/height by the size of scrollbars.
  582. *
  583. * @param {Ext.layout.ContextItem} ownerContext The owner's context item.
  584. * @param {Boolean} [inDom=false] True if the container size must be in the DOM.
  585. * @return {Object} The size
  586. * @return {Number} return.width The width
  587. * @return {Number} return.height The height
  588. * @protected
  589. */
  590. getContainerSize : function(ownerContext, inDom) {
  591. // Subtle But Important:
  592. //
  593. // We don't want to call getProp/hasProp et.al. unless we in fact need that value
  594. // for our results! If we call it and don't need it, the layout manager will think
  595. // we depend on it and will schedule us again should it change.
  596. var targetContext = ownerContext.targetContext,
  597. frameInfo = targetContext.getFrameInfo(),
  598. padding = targetContext.getPaddingInfo(),
  599. got = 0,
  600. needed = 0,
  601. overflowAdjust = ownerContext.state.overflowAdjust,
  602. gotWidth, gotHeight, width, height;
  603. // In an shrinkWrap width/height case, we must not ask for any of these dimensions
  604. // because they will be determined by contentWidth/Height which is calculated by
  605. // this layout...
  606. // Fit/Card layouts are able to set just the width of children, allowing child's
  607. // resulting height to autosize the Container.
  608. // See examples/tabs/tabs.html for an example of this.
  609. if (!ownerContext.widthModel.shrinkWrap) {
  610. ++needed;
  611. width = inDom ? targetContext.getDomProp('width') : targetContext.getProp('width');
  612. gotWidth = (typeof width == 'number');
  613. if (gotWidth) {
  614. ++got;
  615. width -= frameInfo.width + padding.width;
  616. if (overflowAdjust) {
  617. width -= overflowAdjust.width;
  618. }
  619. }
  620. }
  621. if (!ownerContext.heightModel.shrinkWrap) {
  622. ++needed;
  623. height = inDom ? targetContext.getDomProp('height') : targetContext.getProp('height');
  624. gotHeight = (typeof height == 'number');
  625. if (gotHeight) {
  626. ++got;
  627. height -= frameInfo.height + padding.height;
  628. if (overflowAdjust) {
  629. height -= overflowAdjust.height;
  630. }
  631. }
  632. }
  633. return {
  634. width: width,
  635. height: height,
  636. needed: needed,
  637. got: got,
  638. gotAll: got == needed,
  639. gotWidth: gotWidth,
  640. gotHeight: gotHeight
  641. };
  642. },
  643. <span id='Ext-layout-container-Container-method-getLayoutItems'> /**
  644. </span> * Returns an array of child components either for a render phase (Performed in the beforeLayout
  645. * method of the layout's base class), or the layout phase (onLayout).
  646. * @return {Ext.Component[]} of child components
  647. */
  648. getLayoutItems: function() {
  649. var owner = this.owner,
  650. items = owner &amp;&amp; owner.items;
  651. return (items &amp;&amp; items.items) || [];
  652. },
  653. getRenderData: function () {
  654. var comp = this.owner;
  655. return {
  656. $comp: comp,
  657. $layout: this,
  658. ownerId: comp.id
  659. };
  660. },
  661. <span id='Ext-layout-container-Container-method-getRenderedItems'> /**
  662. </span> * @protected
  663. * Returns all items that are rendered
  664. * @return {Array} All matching items
  665. */
  666. getRenderedItems: function() {
  667. var me = this,
  668. target = me.getRenderTarget(),
  669. items = me.getLayoutItems(),
  670. ln = items.length,
  671. renderedItems = [],
  672. i, item;
  673. for (i = 0; i &lt; ln; i++) {
  674. item = items[i];
  675. if (item.rendered &amp;&amp; me.isValidParent(item, target, i)) {
  676. renderedItems.push(item);
  677. }
  678. }
  679. return renderedItems;
  680. },
  681. <span id='Ext-layout-container-Container-method-getRenderTarget'> /**
  682. </span> * Returns the element into which rendering must take place. Defaults to the owner Container's
  683. * target element.
  684. *
  685. * May be overridden in layout managers which implement an inner element.
  686. *
  687. * @return {Ext.Element}
  688. */
  689. getRenderTarget: function() {
  690. return this.owner.getTargetEl();
  691. },
  692. <span id='Ext-layout-container-Container-method-getElementTarget'> /**
  693. </span> * Returns the element into which extra functional DOM elements can be inserted. Defaults to the owner Component's encapsulating element.
  694. *
  695. * May be overridden in Component layout managers which implement a {@link #getRenderTarget component render target} which must only
  696. * contain child components.
  697. * @return {Ext.Element}
  698. */
  699. getElementTarget: function() {
  700. return this.getRenderTarget();
  701. },
  702. getRenderTpl: function () {
  703. var me = this,
  704. renderTpl = Ext.XTemplate.getTpl(this, 'renderTpl');
  705. // Make sure all standard callout methods for the owner component are placed on the
  706. // XTemplate instance (but only once please):
  707. if (!renderTpl.renderContent) {
  708. me.owner.setupRenderTpl(renderTpl);
  709. }
  710. return renderTpl;
  711. },
  712. getRenderTree: function () {
  713. var result,
  714. items = this.owner.items,
  715. itemsGen,
  716. renderCfgs = {};
  717. do {
  718. itemsGen = items.generation;
  719. result = this.getItemsRenderTree(this.getLayoutItems(), renderCfgs);
  720. } while (items.generation !== itemsGen);
  721. return result;
  722. },
  723. getScrollbarsNeeded: function (width, height, contentWidth, contentHeight) {
  724. var scrollbarSize = Ext.getScrollbarSize(),
  725. hasWidth = typeof width == 'number',
  726. hasHeight = typeof height == 'number',
  727. needHorz = 0,
  728. needVert = 0;
  729. // No space-consuming scrollbars.
  730. if (!scrollbarSize.width) {
  731. return 0;
  732. }
  733. if (hasHeight &amp;&amp; height &lt; contentHeight) {
  734. needVert = 2;
  735. width -= scrollbarSize.width;
  736. }
  737. if (hasWidth &amp;&amp; width &lt; contentWidth) {
  738. needHorz = 1;
  739. if (!needVert &amp;&amp; hasHeight) {
  740. height -= scrollbarSize.height;
  741. if (height &lt; contentHeight) {
  742. needVert = 2;
  743. }
  744. }
  745. }
  746. return needVert + needHorz;
  747. },
  748. <span id='Ext-layout-container-Container-property-getScrollRangeFlags'> /**
  749. </span> * Returns flags indicating cross-browser handling of scrollHeight/Width. In particular,
  750. * IE has issues with padding-bottom in a scrolling element (it does not include that
  751. * padding in the scrollHeight). Also, margin-bottom on a child in a scrolling element
  752. * can be lost.
  753. *
  754. * All browsers seem to ignore margin-right on children and padding-right on the parent
  755. * element (the one with the overflow)
  756. *
  757. * This method returns a number with the follow bit positions set based on things not
  758. * accounted for in scrollHeight and scrollWidth:
  759. *
  760. * - 1: Scrolling element's padding-bottom is not included in scrollHeight.
  761. * - 2: Last child's margin-bottom is not included in scrollHeight.
  762. * - 4: Scrolling element's padding-right is not included in scrollWidth.
  763. * - 8: Child's margin-right is not included in scrollWidth.
  764. *
  765. * To work around the margin-bottom issue, it is sufficient to create a 0px tall last
  766. * child that will &quot;hide&quot; the margin. This can also be handled by wrapping the children
  767. * in an element, again &quot;hiding&quot; the margin. Wrapping the elements is about the only
  768. * way to preserve their right margins. This is the strategy used by Column layout.
  769. *
  770. * To work around the padding-bottom problem, since it is comes from a style on the
  771. * parent element, about the only simple fix is to create a last child with height
  772. * equal to padding-bottom. To preserve the right padding, the sizing element needs to
  773. * have a width that includes the right padding.
  774. */
  775. getScrollRangeFlags: (function () {
  776. var flags = -1;
  777. return function () {
  778. if (flags &lt; 0) {
  779. var div = Ext.getBody().createChild({
  780. //cls: 'x-border-box x-hide-offsets',
  781. cls: Ext.baseCSSPrefix + 'border-box',
  782. style: {
  783. width: '100px', height: '100px', padding: '10px',
  784. overflow: 'auto'
  785. },
  786. children: [{
  787. style: {
  788. border: '1px solid red',
  789. width: '150px', height: '150px',
  790. margin: '0 5px 5px 0' // TRBL
  791. }
  792. }]
  793. }),
  794. scrollHeight = div.dom.scrollHeight,
  795. scrollWidth = div.dom.scrollWidth,
  796. heightFlags = {
  797. // right answer, nothing missing:
  798. 175: 0,
  799. // missing parent padding-bottom:
  800. 165: 1,
  801. // missing child margin-bottom:
  802. 170: 2,
  803. // missing both
  804. 160: 3
  805. },
  806. widthFlags = {
  807. // right answer, nothing missing:
  808. 175: 0,
  809. // missing parent padding-right:
  810. 165: 4,
  811. // missing child margin-right:
  812. 170: 8,
  813. // missing both
  814. 160: 12
  815. };
  816. flags = (heightFlags[scrollHeight] || 0) | (widthFlags[scrollWidth] || 0);
  817. //Ext.log('flags=',flags.toString(2));
  818. div.remove();
  819. }
  820. return flags;
  821. };
  822. }()),
  823. <span id='Ext-layout-container-Container-method-getTarget'> /**
  824. </span> * Returns the owner component's resize element.
  825. * @return {Ext.Element}
  826. */
  827. getTarget: function() {
  828. return this.owner.getTargetEl();
  829. },
  830. <span id='Ext-layout-container-Container-method-getVisibleItems'> /**
  831. </span> * @protected
  832. * Returns all items that are both rendered and visible
  833. * @return {Array} All matching items
  834. */
  835. getVisibleItems: function() {
  836. var target = this.getRenderTarget(),
  837. items = this.getLayoutItems(),
  838. ln = items.length,
  839. visibleItems = [],
  840. i, item;
  841. for (i = 0; i &lt; ln; i++) {
  842. item = items[i];
  843. if (item.rendered &amp;&amp; this.isValidParent(item, target, i) &amp;&amp; item.hidden !== true) {
  844. visibleItems.push(item);
  845. }
  846. }
  847. return visibleItems;
  848. },
  849. setupRenderTpl: function (renderTpl) {
  850. var me = this;
  851. renderTpl.renderBody = me.doRenderBody;
  852. renderTpl.renderContainer = me.doRenderContainer;
  853. renderTpl.renderItems = me.doRenderItems;
  854. renderTpl.renderPadder = me.doRenderPadder;
  855. }
  856. });
  857. </pre>
  858. </body>
  859. </html>