<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-layout-container-Auto'>/**
|
</span> * @class Ext.layout.container.Auto
|
*
|
* The AutoLayout is the default layout manager delegated by {@link Ext.container.Container} to
|
* render any child Components when no `{@link Ext.container.Container#layout layout}` is configured into
|
* a `{@link Ext.container.Container Container}.` AutoLayout provides only a passthrough of any layout calls
|
* to any child containers.
|
*
|
* @example
|
* Ext.create('Ext.Panel', {
|
* width: 500,
|
* height: 280,
|
* title: "AutoLayout Panel",
|
* layout: 'auto',
|
* renderTo: document.body,
|
* items: [{
|
* xtype: 'panel',
|
* title: 'Top Inner Panel',
|
* width: '75%',
|
* height: 90
|
* },
|
* {
|
* xtype: 'panel',
|
* title: 'Bottom Inner Panel',
|
* width: '75%',
|
* height: 90
|
* }]
|
* });
|
*/
|
Ext.define('Ext.layout.container.Auto', {
|
|
/* Begin Definitions */
|
|
alias: ['layout.auto', 'layout.autocontainer'],
|
|
extend: 'Ext.layout.container.Container',
|
|
<span id='Ext-layout-container-Auto-property-type'> /* End Definitions */
|
</span>
|
type: 'autocontainer',
|
|
<span id='Ext-layout-container-Auto-property-childEls'> childEls: [
|
</span> 'outerCt',
|
'innerCt',
|
'clearEl'
|
],
|
|
<span id='Ext-layout-container-Auto-cfg-reserveScrollbar'> /**
|
</span> * @cfg {Boolean} [reserveScrollbar=false]
|
* Set to `true` to leave space for a vertical scrollbar (if the OS shows space-consuming scrollbars) regardless
|
* of whether a scrollbar is needed.
|
*
|
* This is useful if content height changes during application usage, but you do not want the calculated width
|
* of child items to change when a scrollbar appears or disappears. The scrollbar will appear in the reserved space,
|
* and the calculated width of child Components will not change.
|
*
|
* @example
|
* Ext.define('Employee', {
|
* extend: 'Ext.data.Model',
|
* fields: [
|
* {name: 'rating', type: 'int'},
|
* {name: 'salary', type: 'float'},
|
* {name: 'name'}
|
* ]
|
* });
|
*
|
* function createFakeData(count) {
|
* var firstNames = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay', 'Nicolas', 'Nige'],
|
* lastNames = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson', 'Ferrero', 'White'],
|
* ratings = [1, 2, 3, 4, 5],
|
* salaries = [100, 400, 900, 1500, 1000000];
|
*
|
* var data = [];
|
* for (var i = 0; i < (count || 25); i++) {
|
* var ratingId = Math.floor(Math.random() * ratings.length),
|
* salaryId = Math.floor(Math.random() * salaries.length),
|
* firstNameId = Math.floor(Math.random() * firstNames.length),
|
* lastNameId = Math.floor(Math.random() * lastNames.length),
|
*
|
* rating = ratings[ratingId],
|
* salary = salaries[salaryId],
|
* name = Ext.String.format("{0} {1}", firstNames[firstNameId], lastNames[lastNameId]);
|
*
|
* data.push({
|
* rating: rating,
|
* salary: salary,
|
* name: name
|
* });
|
* }
|
* store.loadData(data);
|
* }
|
*
|
* // create the Data Store
|
* var store = Ext.create('Ext.data.Store', {
|
* id: 'store',
|
* model: 'Employee',
|
* proxy: {
|
* type: 'memory'
|
* }
|
* });
|
* createFakeData(10);
|
*
|
* var grid = Ext.create('Ext.grid.Panel', {
|
* title: 'Grid loaded with varying number of records',
|
* anchor: '100%',
|
* store: store,
|
* columns: [{
|
* xtype: 'rownumberer',
|
* width: 40,
|
* sortable: false
|
* },{
|
* text: 'Name',
|
* flex: 1,
|
* sortable: true,
|
* dataIndex: 'name'
|
* },{
|
* text: 'Rating',
|
* width: 125,
|
* sortable: true,
|
* dataIndex: 'rating'
|
* },{
|
* text: 'Salary',
|
* width: 125,
|
* sortable: true,
|
* dataIndex: 'salary',
|
* align: 'right',
|
* renderer: Ext.util.Format.usMoney
|
* }]
|
* });
|
*
|
* Ext.create('Ext.panel.Panel', {
|
* renderTo: document.body,
|
* width: 800,
|
* height: 600,
|
* layout: {
|
* type: 'anchor',
|
* reserveScrollbar: true // There will be a gap even when there's no scrollbar
|
* },
|
* autoScroll: true,
|
* items: grid,
|
* tbar: {
|
* defaults: {
|
* handler: function(b) {
|
* createFakeData(b.count);
|
* }
|
* },
|
* items: [{
|
* text: '10 Items',
|
* count: 10
|
* },{
|
* text: '100 Items',
|
* count: 100
|
* },{
|
* text: '300 Items',
|
* count: 300
|
* },{
|
* text: '1000 Items',
|
* count: 1000
|
* },{
|
* text: '5000 Items',
|
* count: 5000
|
* }]
|
* }
|
* });
|
*
|
*/
|
reserveScrollbar: false,
|
|
<span id='Ext-layout-container-Auto-property-managePadding'> /**
|
</span> * @property {Boolean} [managePadding=true]
|
* indicates that this layout will correct cross browser padding differences when the
|
* container has overflow.
|
*
|
* In some browsers the right and/or bottom padding of a container is lost when
|
* the container has overflow. If managePadding is true the layout will apply the
|
* padding to an inner wrapping element instead of the container element that has the
|
* overflow so that paddding will be included in the scrollable area.
|
* Note: padding will not be managed if it is configured on the container using
|
* a style config or css class. In order to be managed, padding must be added to the
|
* container using the appropriate {@link Ext.AbstractComponent#contentPaddingProperty
|
* contentPaddingProperty}. For {@link Ext.panel.Panel Panels} use
|
* {@link Ext.panel.AbstractPanel#bodyPadding}, and for
|
* {@link Ext.container.Container Containers}, use
|
* {@link Ext.AbstractComponent#padding padding}
|
*/
|
managePadding: true,
|
|
<span id='Ext-layout-container-Auto-property-manageOverflow'> /**
|
</span> * @property {Boolean} [manageOverflow=false]
|
* true to rerun the layout if scrollbars are needed.
|
*/
|
manageOverflow: false,
|
|
<span id='Ext-layout-container-Auto-property-lastOverflowAdjust'> // Begin with no previous adjustments
|
</span> lastOverflowAdjust: {
|
width: 0,
|
height: 0
|
},
|
|
<span id='Ext-layout-container-Auto-property-renderTpl'> // Auto layout's renderTpl wraps the content in an outerCt which is used to accomplish
|
</span> // the following 3 goals:
|
//
|
// 1. When the container has a shrink wrapped width and/or height, the outerCt is used
|
// to measure the size of the content.
|
// 2. When the container has overflow some browsers lose the container's right and/or
|
// bottom padding. To fix this, the padding is rendered to the outerCt instead of
|
// the container target element. This ensures that the padding is included in the
|
// container's scrollWidth/scrollHeight. In Old IE when a table is used, the padding
|
// is rendered to the innerCt td element.
|
// 3. The outerCt contains the margins of its children, that is to say, it prevents
|
// them from collapsing.
|
renderTpl: [
|
'{% if (!(Ext.isIEQuirks || Ext.isIE7m)) { %}',
|
// All browsers that support display:table use this template.
|
// An outerCt with display:table shrink-wraps contents, and contains child
|
// margins. The table-cell innerCt is required in order to support percentage
|
// heights on child elements. Originally the outerCt started out as a div, but
|
// was changed to a span to work around an obscure firefox 3.6 bug where
|
// placing a Container inside of a fieldset's legend element causes the legend
|
// to blow up if the outerCt is a div.
|
'<span id="{ownerId}-outerCt" style="display:table;">',
|
// height:100% is required on the innerCt in order for percentage-height
|
// children to work in IE, firefox, and opera
|
'<div id="{ownerId}-innerCt" style="display:table-cell;height:100%;',
|
'vertical-align:top;{%this.renderPadding(out, values)%}" class="{innerCtCls}">',
|
'{%this.renderBody(out,values)%}',
|
'</div>',
|
'</span>',
|
'{% } else if (values.shrinkWrapWidth) { %}',
|
// If the containers width is shrink wrapped a table-based outerCt/innerCt
|
// is required in old IE. See getRenderData() for more details on the criteria
|
// used to determine if the container has shrink wrapped width.
|
'<table id="{ownerId}-outerCt" class="' + Ext.plainTableCls + '">',
|
'<tr>',
|
'<td id="{ownerId}-innerCt" style="vertical-align:top;padding:0;',
|
'{%this.renderPadding(out, values)%}" class="{innerCtCls}">',
|
'{%this.renderBody(out,values)%}',
|
// clear element to contain the bottom margin of floated last child item
|
'<div id="{ownerId}-clearEl" class="', Ext.baseCSSPrefix, 'clear"',
|
'role="presentation"></div>',
|
'</td>',
|
'</tr>',
|
'</table>',
|
'{% } else { %}',
|
// If the container's width is not shrink wrapped, old IE can get by with
|
// divs as the outerCt/innerCt. zoom:1 is required to contain the margins
|
// of children. The padding is placed on the outerCt instead of the innerCt.
|
// This is to because if the padding was placed on the innerCt, the top
|
// margin of the first child item would collapse into the top padding of
|
// the innerCt.
|
'<div id="{ownerId}-outerCt" style="zoom:1;{%this.renderPadding(out, values)%}">',
|
'<div id="{ownerId}-innerCt" style="zoom:1;height:100%;" class="{innerCtCls}">',
|
'{%this.renderBody(out,values)%}',
|
// clear element to contain the bottom margin of floated last child item
|
'<div id="{ownerId}-clearEl" class="', Ext.baseCSSPrefix, 'clear"',
|
'role="presentation"></div>',
|
'</div>',
|
'</div>',
|
// set a flag that indicates we are not using a "shrink wrap" template
|
'{% values.$layout.isShrinkWrapTpl = false %}',
|
'{% } %}'
|
],
|
|
<span id='Ext-layout-container-Auto-property-tableTpl'> // This template is used for dynamically inserting a table outerCt/innerCt when needed.
|
</span> // It should be identical to the table template defined in renderTpl except that it
|
// does not have renderBody or clearEl. It is an empty shell so that the contents
|
// of an already existing innerCt can be moved into it.
|
tableTpl: [
|
'<table id="{ownerId}-outerCt" class="' + Ext.plainTableCls + '">',
|
'<tr>',
|
'<td id="{ownerId}-innerCt" style="vertical-align:top;padding:0;',
|
'{%this.renderPadding(out, values)%}" class="{innerCtCls}">',
|
'</td>',
|
'</tr>',
|
'</table>'
|
],
|
|
<span id='Ext-layout-container-Auto-property-isShrinkWrapTpl'> isShrinkWrapTpl: true,
|
</span>
|
|
<span id='Ext-layout-container-Auto-method-beginLayout'> beginLayout: function(ownerContext) {
|
</span> var me = this,
|
bottomPadding, overflowYStyle, overflowXStyle, needsTable;
|
|
me.callParent(arguments);
|
|
me.initContextItems(ownerContext);
|
|
if (!me.isShrinkWrapTpl) {
|
// In most cases the determination to use a table based template is made at
|
// render time; however, if the initial determination was incorrect, we may
|
// need to dynamically replace the existing outerCt/innerCt with a table
|
// (see insertTableCt)
|
if (ownerContext.widthModel.shrinkWrap) {
|
needsTable = true;
|
}
|
|
// in IE7 strict right padding is lost when there is horizontal overflow
|
// unless the outerCt is a table.
|
if (Ext.isStrict && Ext.isIE7) {
|
overflowXStyle = me.getOverflowXStyle(ownerContext);
|
if ((overflowXStyle === 'auto' || overflowXStyle === 'scroll') &&
|
ownerContext.paddingContext.getPaddingInfo().right) {
|
needsTable = true;
|
}
|
}
|
|
if (needsTable) {
|
me.insertTableCt(ownerContext);
|
}
|
}
|
|
// When using the non-table renderTpl IE7 strict loses bottom padding if there
|
// is vertical overflow. To adjust for the loss of padding, we add the bottom
|
// padding to the height of the clearEl
|
if (!me.isShrinkWrapTpl && Ext.isIE7 && Ext.isStrict && !me.clearElHasPadding) {
|
bottomPadding = ownerContext.paddingContext.getPaddingInfo().bottom;
|
overflowYStyle = me.getOverflowYStyle(ownerContext);
|
if (bottomPadding && (overflowYStyle === 'auto' || overflowYStyle === 'scroll')) {
|
me.clearEl.setStyle('height', bottomPadding);
|
me.clearElHasPadding = true;
|
}
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-beforeLayoutCycle'> beforeLayoutCycle: function(ownerContext){
|
</span> var comp = this.owner,
|
hierarchyState = comp.hierarchyState,
|
hierarchyStateInner = comp.hierarchyStateInner;
|
|
if (!hierarchyState || hierarchyState.invalid) {
|
hierarchyState = comp.getHierarchyState(); // fixes both
|
hierarchyStateInner = comp.hierarchyStateInner;
|
}
|
if (ownerContext.widthModel.shrinkWrap && this.isShrinkWrapTpl) {
|
hierarchyStateInner.inShrinkWrapTable = true;
|
} else {
|
delete hierarchyStateInner.inShrinkWrapTable;
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-beginLayoutCycle'> beginLayoutCycle: function(ownerContext) {
|
</span> var me = this,
|
outerCt = me.outerCt,
|
lastOuterCtWidth = me.lastOuterCtWidth || '',
|
lastOuterCtHeight = me.lastOuterCtHeight || '',
|
lastOuterCtTableLayout = me.lastOuterCtTableLayout || '',
|
state = ownerContext.state,
|
overflowXStyle, overflowYStyle, outerCtWidth, outerCtHeight, outerCtTableLayout,
|
deferWidth, hierarchyStateInner;
|
|
me.callParent(arguments);
|
|
// Default to "shrink wrap styles".
|
outerCtWidth = outerCtHeight = outerCtTableLayout = '';
|
|
if (!ownerContext.widthModel.shrinkWrap && me.isShrinkWrapTpl) {
|
// if we're not shrink wrapping width, but we're using a shrink wrap template
|
// we need to get the innerCt out of the way to avoid any shrink wrapping
|
// effect on child items
|
if (Ext.isIE7m && Ext.isStrict) {
|
overflowYStyle = me.getOverflowYStyle(ownerContext);
|
if (overflowYStyle === 'auto' || overflowYStyle === 'scroll') {
|
// IE6/7 strict will have the outerCt's width set by setCtSizeIfNeeded()
|
// when the container has potential vertical overflow, so there is
|
// no need to set the outerCt's width to 100% here
|
deferWidth = true;
|
}
|
}
|
|
if (!deferWidth) {
|
// fill the available width within the container
|
outerCtWidth = '100%';
|
}
|
hierarchyStateInner = me.owner.hierarchyStateInner;
|
// expand no further than the available width, even if contents are wider
|
// unless there is a potential for horizontal overflow, then allow
|
// the outerCt to expand to the width of the contents
|
overflowXStyle = me.getOverflowXStyle(ownerContext);
|
outerCtTableLayout = (hierarchyStateInner.inShrinkWrapTable ||
|
overflowXStyle === 'auto' ||
|
overflowXStyle === 'scroll') ? '' : 'fixed';
|
}
|
|
if (!ownerContext.heightModel.shrinkWrap &&
|
!Ext.supports.PercentageHeightOverflowBug) {
|
// if we're not shrink wrapping height, we need to get the outerCt out of the
|
// way so that percentage height children will be sized correctly. We do this
|
// by giving the outerCt a height of '100%' unless the browser is affected by
|
// the "percentage height overflow bug", in which case the outerCt will get a
|
// pixel height set during the calculate phase after we know the targetEl size.
|
outerCtHeight = '100%';
|
}
|
|
// if the outerCt width changed since last time (becuase of a widthModel change)
|
// or if we set a pixel width on the outerCt last time to work around a browser-
|
// specific bug, we need to set the width of the outerCt
|
if ((outerCtWidth !== lastOuterCtWidth) || me.hasOuterCtPxWidth) {
|
outerCt.setStyle('width', outerCtWidth);
|
me.lastOuterCtWidth = outerCtWidth;
|
me.hasOuterCtPxWidth = false;
|
}
|
|
// Set the outerCt table-layout property if different from last time.
|
if (outerCtTableLayout !== lastOuterCtTableLayout) {
|
outerCt.setStyle('table-layout', outerCtTableLayout);
|
me.lastOuterCtTableLayout = outerCtTableLayout;
|
}
|
|
// if the outerCt height changed since last time (becuase of a heightModel change)
|
// or if we set a pixel height on the outerCt last time to work around a browser-
|
// specific bug, we need to set the height of the outerCt
|
if ((outerCtHeight !== lastOuterCtHeight) || me.hasOuterCtPxHeight) {
|
outerCt.setStyle('height', outerCtHeight);
|
me.lastOuterCtHeight = outerCtHeight;
|
me.hasOuterCtPxHeight = false;
|
}
|
|
if (me.hasInnerCtPxHeight) {
|
me.innerCt.setStyle('height', '');
|
me.hasInnerCtPxHeight = false;
|
}
|
|
// Begin with the scrollbar adjustment that we used last time - this is more likely
|
// to be correct than beginning with no adjustment at all, but only if it is not
|
// already defined - it may have already been set by invalidate()
|
state.overflowAdjust = state.overflowAdjust || me.lastOverflowAdjust;
|
},
|
|
<span id='Ext-layout-container-Auto-method-calculate'> calculate: function(ownerContext) {
|
</span> var me = this,
|
state = ownerContext.state,
|
containerSize = me.getContainerSize(ownerContext, true),
|
// If subclass has a calculateItems method, call it and cache the result
|
calculatedItems = state.calculatedItems ||
|
(state.calculatedItems = me.calculateItems ?
|
me.calculateItems(ownerContext, containerSize) : true);
|
|
me.setCtSizeIfNeeded(ownerContext, containerSize);
|
|
if (calculatedItems && ownerContext.hasDomProp('containerChildrenSizeDone')) {
|
|
me.calculateContentSize(ownerContext);
|
|
if (containerSize.gotAll) {
|
if (me.manageOverflow && !ownerContext.state.secondPass && !me.reserveScrollbar) {
|
me.calculateOverflow(ownerContext, containerSize);
|
}
|
return;
|
}
|
}
|
|
me.done = false;
|
},
|
|
<span id='Ext-layout-container-Auto-method-calculateContentSize'> calculateContentSize: function (ownerContext) {
|
</span> var me = this,
|
containerDimensions = ((ownerContext.widthModel.shrinkWrap ? 1 : 0) |
|
(ownerContext.heightModel.shrinkWrap ? 2 : 0)),
|
calcWidth = (containerDimensions & 1) || undefined,
|
calcHeight = (containerDimensions & 2) || undefined,
|
needed = 0,
|
props = ownerContext.props;
|
|
if (calcWidth) {
|
if (isNaN(props.contentWidth)) {
|
++needed;
|
} else {
|
calcWidth = undefined;
|
}
|
}
|
if (calcHeight) {
|
if (isNaN(props.contentHeight)) {
|
++needed;
|
} else {
|
calcHeight = undefined;
|
}
|
}
|
|
if (needed) {
|
if (calcWidth && !ownerContext.setContentWidth(me.measureContentWidth(ownerContext))) {
|
me.done = false;
|
}
|
if (calcHeight && !ownerContext.setContentHeight(me.measureContentHeight(ownerContext))) {
|
me.done = false;
|
}
|
|
//if (me.done) {
|
// var el = ownerContext.targetContext.el.dom;
|
// Ext.log(this.owner.id, '.contentSize: ', contentWidth, 'x', contentHeight,
|
// ' => scrollSize: ', el.scrollWidth, 'x', el.scrollHeight);
|
//}
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-calculateOverflow'> /**
|
</span> * Handles overflow processing for a container. In addition to the ownerContext
|
* passed to the {@link #calculate} method, this method also needs the containerSize
|
* (the object returned by {@link #getContainerSize}).
|
* @protected
|
*
|
* @param {Ext.layout.ContextItem} ownerContext
|
*/
|
calculateOverflow: function (ownerContext) {
|
var me = this,
|
width, height, scrollbarSize, scrollbars, xauto, yauto, targetEl;
|
|
// Determine the dimensions that have overflow:auto applied. If these come by
|
// way of component config, this does not require a DOM read:
|
xauto = (me.getOverflowXStyle(ownerContext) === 'auto');
|
yauto = (me.getOverflowYStyle(ownerContext) === 'auto');
|
|
if (xauto || yauto) {
|
scrollbarSize = Ext.getScrollbarSize();
|
targetEl = ownerContext.overflowContext.el.dom;
|
scrollbars = 0;
|
|
if (targetEl.scrollWidth > targetEl.clientWidth) {
|
// has horizontal scrollbar
|
scrollbars |= 1;
|
}
|
|
if (targetEl.scrollHeight > targetEl.clientHeight) {
|
// has vertical scrollbar
|
scrollbars |= 2;
|
}
|
|
width = (yauto && (scrollbars & 2)) ? scrollbarSize.width : 0;
|
height = (xauto && (scrollbars & 1)) ? scrollbarSize.height : 0;
|
|
if (width !== me.lastOverflowAdjust.width || height !== me.lastOverflowAdjust.height) {
|
me.done = false;
|
|
// we pass overflowAdjust and overflowState in as state for the next
|
// cycle (these are discarded if one of our ownerCt's invalidates):
|
ownerContext.invalidate({
|
state: {
|
overflowAdjust: {
|
width: width,
|
height: height
|
},
|
overflowState: scrollbars,
|
secondPass: true
|
}
|
});
|
}
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-completeLayout'> completeLayout: function(ownerContext) {
|
</span> this.lastOverflowAdjust = ownerContext.state.overflowAdjust;
|
},
|
|
<span id='Ext-layout-container-Auto-method-doRenderPadding'> doRenderPadding: function(out, renderData) {
|
</span> // Careful! This method is bolted on to the renderTpl so all we get for context is
|
// the renderData! The "this" pointer is the renderTpl instance!
|
|
var me = renderData.$layout,
|
owner = renderData.$layout.owner,
|
padding = owner[owner.contentPaddingProperty];
|
|
if (me.managePadding && padding) {
|
out.push('padding:', owner.unitizeBox(padding));
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-finishedLayout'> finishedLayout: function (ownerContext) {
|
</span> var innerCt = this.innerCt;
|
|
this.callParent(arguments);
|
|
if (Ext.isIEQuirks || Ext.isIE8m) {
|
// IE6/7/quirks need a repaint to fix various rendering issues. TODO: narrow
|
// down the specific issues that require a repaint.
|
// IE8 strict needs a repaint to render percentage sized child items.
|
innerCt.repaint();
|
}
|
|
if (Ext.isOpera) {
|
// Opera also needs a repaint to render percentage sized child items. but
|
// the normal repaint() method doesn't seem to do the trick, but tweaking
|
// the position property in combination with reading scrollWidth does.
|
innerCt.setStyle('position', 'relative');
|
innerCt.dom.scrollWidth;
|
innerCt.setStyle('position', '');
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-getContainerSize'> /**
|
</span> * Returns the container size (that of the target). Only the fixed-sized dimensions can
|
* be returned because the shrinkWrap dimensions are based on the contentWidth/Height
|
* as determined by the container layout.
|
*
|
* If the {@link #calculateOverflow} method is used and if {@link #manageOverflow} is
|
* true, this will adjust the width/height by the size of scrollbars.
|
*
|
* @param {Ext.layout.ContextItem} ownerContext The owner's context item.
|
* @param {Boolean} [inDom=false] True if the container size must be in the DOM.
|
* @return {Object} The size
|
* @return {Number} return.width The width
|
* @return {Number} return.height The height
|
* @protected
|
*/
|
getContainerSize : function(ownerContext, inDom) {
|
// Subtle But Important:
|
//
|
// We don't want to call getProp/hasProp et.al. unless we in fact need that value
|
// for our results! If we call it and don't need it, the layout manager will think
|
// we depend on it and will schedule us again should it change.
|
|
var size = this.callParent(arguments),
|
overflowAdjust = ownerContext.state.overflowAdjust;
|
|
if (overflowAdjust) {
|
size.width -= overflowAdjust.width;
|
size.height -= overflowAdjust.height;
|
}
|
|
return size;
|
},
|
|
<span id='Ext-layout-container-Auto-method-getRenderData'> getRenderData: function() {
|
</span> var owner = this.owner,
|
data = this.callParent();
|
|
// The shrinkWrapWidth data property is used by the renderTpl to determine if
|
// a table-based outerCt/innerCt is required in old IE. There are currently 2
|
// container configs that turn on the table at render time:
|
//
|
// 1. shrinkWrap:[1/3/true] on the container's initial config. There
|
// are two reasons one would want to use this config:
|
// a) If the container's width is initially shrink wrapped.
|
// b) If the container is not initially shrink wrapped and it is known
|
// at creation time that it will be shrink wrapped at some point
|
// after the initial layout cycle, then it is recommended to
|
// use the shrinkWrap config to initially configure the container
|
// with shrink wrapped width so that the layout does not have to
|
// dynamically insert a table after initial render.
|
//
|
// 2. If the container's "floating" config is set to true, and the container
|
// does not have a configured width, we can be relatively certain at render
|
// time that the container will be shrink wrapped at layout time, so
|
// we go ahead and initially render using a table.
|
if ((Ext.isIEQuirks || Ext.isIE7m) && // old IE
|
((owner.shrinkWrap & 1) || // shrink wrap width (handles value of 1, 3, or true)
|
(owner.floating && !owner.width))) { // floating container with no configured width
|
data.shrinkWrapWidth = true;
|
}
|
|
return data;
|
},
|
|
<span id='Ext-layout-container-Auto-method-getRenderTarget'> // Overridden method from Ext.layout.container.Container.
|
</span> // Used in the beforeLayout method to render all items into.
|
getRenderTarget: function() {
|
return this.innerCt;
|
},
|
|
<span id='Ext-layout-container-Auto-method-getElementTarget'> // Overridden method from Ext.layout.container.Container.
|
</span> // Used by Container classes to insert special DOM elements which must exist in addition to the child components
|
getElementTarget: function() {
|
return this.innerCt;
|
},
|
|
<span id='Ext-layout-container-Auto-method-getOverflowXStyle'> /**
|
</span> * Returns the overflow-x style of the render target.
|
* Note: If overflow is configured on a container using style or css class this method
|
* will read the dom the first time it is called. It is therefore preferable for
|
* performance reasons to use the autoScroll or overflowX config when horizontal
|
* overflow is desired.
|
* @protected
|
* @param {Ext.layout.ContextItem} ownerContext
|
* @return {String}
|
*/
|
getOverflowXStyle: function(ownerContext) {
|
return ownerContext.overflowXStyle ||
|
(ownerContext.overflowXStyle = this.owner.scrollFlags.overflowX || ownerContext.overflowContext.getStyle('overflow-x'));
|
},
|
|
<span id='Ext-layout-container-Auto-method-getOverflowYStyle'> /**
|
</span> * Returns the overflow-y style of the render target.
|
* Note: If overflow is configured on a container using style or css class this method
|
* will read the dom the first time it is called. It is therefore preferable for
|
* performance reasons to use the autoScroll or overflowY config when vertical
|
* overflow is desired.
|
* @protected
|
* @param {Ext.layout.ContextItem} ownerContext
|
* @return {String}
|
*/
|
getOverflowYStyle: function(ownerContext) {
|
return ownerContext.overflowYStyle ||
|
(ownerContext.overflowYStyle = this.owner.scrollFlags.overflowY || ownerContext.overflowContext.getStyle('overflow-y'));
|
},
|
|
<span id='Ext-layout-container-Auto-method-initContextItems'> initContextItems: function(ownerContext) {
|
</span> var me = this,
|
target = ownerContext.target,
|
customOverflowEl = me.owner.customOverflowEl;
|
|
ownerContext.outerCtContext = ownerContext.getEl('outerCt', me);
|
ownerContext.innerCtContext = ownerContext.getEl('innerCt', me);
|
|
if (customOverflowEl) {
|
ownerContext.overflowContext = ownerContext.getEl(customOverflowEl);
|
} else {
|
ownerContext.overflowContext = ownerContext.targetContext;
|
}
|
|
if (target[target.contentPaddingProperty] !== undefined) {
|
// If padding was defined using the contentPaddingProperty, we render the
|
// the padding to the innerCt or outerCt (depending on the template that is
|
// being used), so we need to set the paddingContext accordingly.
|
// Otherwise we leave paddingContext as set by Container layout (defaults to
|
// the targetContext)
|
ownerContext.paddingContext = me.isShrinkWrapTpl ?
|
ownerContext.innerCtContext : ownerContext.outerCtContext;
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-initLayout'> initLayout: function() {
|
</span> var me = this,
|
scrollbarWidth = Ext.getScrollbarSize().width,
|
owner = me.owner;
|
|
me.callParent();
|
|
// Create a default lastOverflowAdjust based upon scrolling configuration.
|
// If the Container is to overflow, or we *always* reserve space for a scrollbar
|
// then reserve space for a vertical scrollbar
|
if (scrollbarWidth && me.manageOverflow && !me.hasOwnProperty('lastOverflowAdjust')) {
|
if (owner.autoScroll || me.reserveScrollbar) {
|
me.lastOverflowAdjust = {
|
width: scrollbarWidth,
|
height: 0
|
};
|
}
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-insertTableCt'> /**
|
</span> * In some cases a table-based outerCt/innerCt is required in old IE (see renderTpl).
|
* Most of the time this is determined at render time, however its possible that
|
* we made the wrong determination at render time and now that the layout is in
|
* progress we need a table. If so, this method should be called to replace the
|
* existing outerCt with a new table outerCt, and move the child elements to the new
|
* innerCt.
|
* @private
|
*/
|
insertTableCt: function(ownerContext) {
|
var me = this,
|
owner = me.owner,
|
i = 0,
|
renderTpl, fragment, childNodes, childLength, targetEl;
|
|
// get the table-based renderTpl
|
renderTpl = Ext.XTemplate.getTpl(this, 'tableTpl');
|
renderTpl.renderPadding = me.doRenderPadding
|
|
// To avoid unnecessary reflows, remove the innerCt from the dom
|
// before operating on its children.
|
me.outerCt.dom.removeChild(me.innerCt.dom);
|
// create a document fragment to move all the childNodes to, so that
|
// they can be batch appended to the new innerCt
|
fragment = document.createDocumentFragment();
|
childNodes = me.innerCt.dom.childNodes;
|
childLength = childNodes.length;
|
// append all the children to the document fragment
|
for (; i < childLength; i++) {
|
fragment.appendChild(childNodes[0]);
|
}
|
// process the table template and insert it into the target el
|
targetEl = me.getTarget();
|
targetEl.dom.innerHTML = renderTpl.apply({
|
$layout: me,
|
ownerId: me.owner.id
|
});
|
|
// append the document fragment containing the childNodes to the new innerCt
|
targetEl.down('td').dom.appendChild(fragment);
|
// reconfigure childEls to point to the new template's elements
|
// we need to do this after the childNodes are appended to the new innerCt
|
// because the clearEl is one of the childNodes
|
me.applyChildEls(owner.el, owner.id)
|
// set the flag that indicates we are using a "shrink wrap" template.
|
// this needs to be done before reinitializeing the context items so that
|
// the paddingContext will be configured correctly.
|
me.isShrinkWrapTpl = true;
|
// since we have new childEls we need to reinitialize the context items
|
ownerContext.removeEl(me.outerCt);
|
ownerContext.removeEl(me.innerCt);
|
me.initContextItems(ownerContext);
|
},
|
|
<span id='Ext-layout-container-Auto-method-measureContentHeight'> measureContentHeight: function (ownerContext) {
|
</span> // contentHeight includes padding, but not border, framing or margins
|
var contentHeight = this.outerCt.getHeight(),
|
target = ownerContext.target;
|
|
if (this.managePadding && (target[target.contentPaddingProperty] === undefined)) {
|
// if padding was not configured using the appropriate contentPaddingProperty
|
// then the padding will not be on the paddingContext, and therfore not included
|
// in the outerCt measurement, so we need to read the padding from the
|
// targetContext
|
contentHeight += ownerContext.targetContext.getPaddingInfo().height;
|
}
|
return contentHeight;
|
},
|
|
<span id='Ext-layout-container-Auto-method-measureContentWidth'> measureContentWidth: function (ownerContext) {
|
</span> var dom, style, old, contentWidth, target;
|
|
// In the newer Chrome versions, it won't measure the
|
// width correctly without repainting the inner
|
// cell in some circumstances.
|
if (this.chromeCellMeasureBug) {
|
dom = this.innerCt.dom;
|
style = dom.style;
|
old = style.display;
|
|
if (old == 'table-cell') {
|
style.display = '';
|
dom.offsetWidth;
|
style.display = old;
|
}
|
}
|
|
// contentWidth includes padding, but not border, framing or margins
|
contentWidth = this.outerCt.getWidth();
|
target = ownerContext.target;
|
|
if (this.managePadding && (target[target.contentPaddingProperty] === undefined)) {
|
// if padding was not configured using the appropriate contentPaddingProperty
|
// then the padding will not be on the paddingContext, and therfore not included
|
// in the outerCt measurement, so we need to read the padding from the
|
// targetContext
|
contentWidth += ownerContext.targetContext.getPaddingInfo().width;
|
}
|
return contentWidth;
|
},
|
|
<span id='Ext-layout-container-Auto-method-setCtSizeIfNeeded'> /**
|
</span> * This method sets the height and/or width of the outerCt/innerCt to adjust for the
|
* following browser-specific issues:
|
*
|
* 1. In IE6 and 7 strict if we are using the shrink wrap template, and the outerCt
|
* has a 100% width (because the container is not shrink wrapping width currently),
|
* and the target element has a vertical scrollbar, the browser disregards the
|
* scrollbar when sizing the width of the outerCt. This can result in the target
|
* element gaining a horizontal scrollbar. We fix this issue by setting a pixel
|
* width on the outerCt
|
*
|
* 2. In IE quirks when using the "non shrink wrap" template, a long non-breaking word
|
* can cause the outerCt's width to expand beyond the width of its container. This
|
* behavior is desired if the container has the potential for horizontal overflow,
|
* but can cause text to be hidden if the container's overflow is hidden. To prevent
|
* this from happening we give the outerCt a fixed width in IE quirks when the
|
* container does not have horizontal overflow.
|
*
|
* 3. In some browsers a percentage-height element ignores the horizontal scrollbar
|
* of its parent (see Ext.supports.PercentageHeightOverflowBug). If the browser is
|
* affected by this bug the outerCt needs a pixel height in order to support
|
* percentage-height children when not shrink-wrapping height. If the browser is not
|
* affected by this bug, a height of 100% is assigned to the outerCt (see
|
* beginLayoutCycle).
|
*
|
* 4. In IE6/7 strict when using the "shrink wrap" template, percentage heights on
|
* children do not work unless the innerCt td has a height set. We can't use height
|
* 100% on the innerCt because conent-box sizing will cause any top/bottom padding to
|
* be added to the height. The solution is to set a pixel height on the innerCt.
|
|
* 5. IE8 strict mode has a bug with percentage height children. if the innerCt has
|
* a height of 100%, has padding, and has a child item with a percentage height, that
|
* child item will be sized as a percentage of the parent's height plus padding height.
|
* In other words, a child with height:50% would have its height caclulated thusly:
|
* (parentHeight + parentPaddingHeight) * 0.5
|
* To fix this, we have to give the innerCt a pixel height.
|
*
|
* 6. In IE7 strict if we're using the "non shrink wrap" template, and the target
|
* element has overflow-y:auto, the outerCt reserves space for the target element's
|
* vertical scrollbar even when there is no vertical scrollbar. This is fixed by
|
* setting the targetEl's overflow property to "hidden" and then back to "auto".
|
*
|
* @protected
|
* @param {Ext.layout.ContextItem} ownerContext
|
* @param {Object} containerSize
|
*/
|
setCtSizeIfNeeded: function(ownerContext, containerSize) {
|
var me = this,
|
width = containerSize.width,
|
height = containerSize.height,
|
padding = ownerContext.paddingContext.getPaddingInfo(),
|
targetEl = me.getTarget(),
|
overflowXStyle = me.getOverflowXStyle(ownerContext),
|
overflowYStyle = me.getOverflowYStyle(ownerContext),
|
canOverflowX = (overflowXStyle === 'auto' || overflowXStyle === 'scroll'),
|
canOverflowY = (overflowYStyle === 'auto' || overflowYStyle === 'scroll'),
|
scrollbarSize = Ext.getScrollbarSize(),
|
isShrinkWrapTpl = me.isShrinkWrapTpl,
|
manageOverflow = me.manageOverflow,
|
overflowStyleName, needsOuterHeight, needsInnerHeight, needsInnerCtPaddingHeight;
|
|
if (width && !ownerContext.widthModel.shrinkWrap &&
|
// shrink wrap outerCt needs pixel width in IE6/7 strict because 100% width
|
// on the outerCt causes it to overlap the vertical scrollbar
|
((Ext.isIE7m && Ext.isStrict && isShrinkWrapTpl && canOverflowY) ||
|
// non shrink wrap tpl outerCt in IE quirks needs pixel width to prevent
|
// non-breaking text from causing the outerCt to expand beyond the width
|
// of its container.
|
(Ext.isIEQuirks && !isShrinkWrapTpl && !canOverflowX))) {
|
|
if (!manageOverflow) {
|
// If we're not managing overflow, the containerSize will not account for
|
// vertical scrollbar width, so we need to see if there is a vertical
|
// scrollbar and subtract its width
|
if (canOverflowY && (targetEl.dom.scrollHeight > targetEl.dom.clientHeight)) {
|
// has vertical scrollbar
|
width -= scrollbarSize.width;
|
}
|
}
|
|
ownerContext.outerCtContext.setProp('width', width + padding.width);
|
me.hasOuterCtPxWidth = true;
|
}
|
|
if (height && !ownerContext.heightModel.shrinkWrap) {
|
if (Ext.supports.PercentageHeightOverflowBug) {
|
// set a pixel height on the outerCt if the browser ignores horizontal
|
// scrollbar when rendering percentage-height elements
|
needsOuterHeight = true;
|
}
|
if (((Ext.isIE8 && Ext.isStrict) ||
|
Ext.isIE7m && Ext.isStrict && isShrinkWrapTpl)) {
|
// When using a shrink wrap template and not shrink wrapping, we set a
|
// pixel height on the innerCt to support percentage height children in
|
// IE6/7/8 strict.
|
needsInnerHeight = true;
|
// Do not add padding to the innerCt height in IE8 to prevent percentage-
|
// height children from adding padding height in their height calculation.
|
needsInnerCtPaddingHeight = !Ext.isIE8;
|
}
|
|
if ((needsOuterHeight || needsInnerHeight) && canOverflowX &&
|
(targetEl.dom.scrollWidth > targetEl.dom.clientWidth)) {
|
// adjust the height for scrollbar size since it's not accounted for
|
// in the containerSize.
|
// IE8 in what passes for "standards" mode does not tolerate -ve sizes
|
height = Math.max(height - scrollbarSize.height, 0);
|
}
|
|
if (needsOuterHeight) {
|
ownerContext.outerCtContext.setProp('height', height + padding.height);
|
me.hasOuterCtPxHeight = true;
|
}
|
|
if (needsInnerHeight) {
|
if (needsInnerCtPaddingHeight) {
|
height += padding.height;
|
}
|
ownerContext.innerCtContext.setProp('height', height);
|
me.hasInnerCtPxHeight = true;
|
}
|
}
|
|
if (Ext.isIE7 && Ext.isStrict && !isShrinkWrapTpl && (overflowYStyle === 'auto')) {
|
// IE7 strict has an insane bug where an auto-width element reserves
|
// space for its parent's vertical scrollbar if the parent has
|
// overflow-y:auto; even when no scrollbar is present. To workaround
|
// this issue we can set overflow-y to 'hidden' and then back to 'auto'.
|
// If we have vertical overflow, however, tweaking overflow-y can cause an
|
// illegitimate horizontal scrollbar to appear. So we have to tweak overflow-x
|
// instead if the overflow-x style is "auto"
|
overflowStyleName = (overflowXStyle === 'auto') ? 'overflow-x' : 'overflow-y';
|
targetEl.setStyle(overflowStyleName, 'hidden');
|
targetEl.setStyle(overflowStyleName, 'auto');
|
}
|
},
|
|
<span id='Ext-layout-container-Auto-method-setupRenderTpl'> setupRenderTpl: function (renderTpl) {
|
</span> this.callParent(arguments);
|
|
renderTpl.renderPadding = this.doRenderPadding;
|
},
|
|
<span id='Ext-layout-container-Auto-method-getContentTarget'> getContentTarget: function(){
|
</span> return this.innerCt;
|
}
|
|
}, function(){
|
this.prototype.chromeCellMeasureBug = Ext.isChrome && Ext.chromeVersion >= 26;
|
});
|
</pre>
|
</body>
|
</html>
|