1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708 |
- <!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-ContextItem'>/**
- </span> * This class manages state information for a component or element during a layout.
- *
- * # Blocks
- *
- * A "block" is a required value that is preventing further calculation. When a layout has
- * encountered a situation where it cannot possibly calculate results, it can associate
- * itself with the context item and missing property so that it will not be rescheduled
- * until that property is set.
- *
- * Blocks are a one-shot registration. Once the property changes, the block is removed.
- *
- * Be careful with blocks. If *any* further calculations can be made, a block is not the
- * right choice.
- *
- * # Triggers
- *
- * Whenever any call to {@link #getProp}, {@link #getDomProp}, {@link #hasProp} or
- * {@link #hasDomProp} is made, the current layout is automatically registered as being
- * dependent on that property in the appropriate state. Any changes to the property will
- * trigger the layout and it will be queued in the {@link Ext.layout.Context}.
- *
- * Triggers, once added, remain for the entire layout. Any changes to the property will
- * reschedule all unfinished layouts in their trigger set.
- *
- * @private
- */
- Ext.define('Ext.layout.ContextItem', {
-
- requires: ['Ext.layout.ClassList'],
- heightModel: null,
- widthModel: null,
- sizeModel: null,
- boxChildren: null,
- boxParent: null,
- children: [],
- dirty: null,
- // The number of dirty properties
- dirtyCount: 0,
- hasRawContent: true,
- isContextItem: true,
- isTopLevel: false,
- consumersContentHeight: 0,
- consumersContentWidth: 0,
- consumersContainerHeight: 0,
- consumersContainerWidth: 0,
- consumersHeight: 0,
- consumersWidth: 0,
- ownerCtContext: null,
- remainingChildLayouts: 0,
- remainingComponentChildLayouts: 0,
- remainingContainerChildLayouts: 0,
- // the current set of property values:
- props: null,
- <span id='Ext-layout-ContextItem-property-state'> /**
- </span> * @property {Object} state
- * State variables that are cleared when invalidated. Only applies to component items.
- */
- state: null,
- <span id='Ext-layout-ContextItem-property-wrapsComponent'> /**
- </span> * @property {Boolean} wrapsComponent
- * True if this item wraps a Component (rather than an Element).
- * @readonly
- */
- wrapsComponent: false,
- constructor: function (config) {
- var me = this,
- el, ownerCt, ownerCtContext, sizeModel, target;
- Ext.apply(me, config);
- el = me.el;
- me.id = el.id;
- me.lastBox = el.lastBox;
- // These hold collections of layouts that are either blocked or triggered by sets
- // to our properties (either ASAP or after flushing to the DOM). All of them have
- // the same structure:
- //
- // me.blocks = {
- // width: {
- // 'layout-1001': layout1001
- // }
- // }
- //
- // The property name is the primary key which yields an object keyed by layout id
- // with the layout instance as the value. This prevents duplicate entries for one
- // layout and gives O(1) access to the layout instance when we need to iterate and
- // process them.
- //
- // me.blocks = {};
- // me.domBlocks = {};
- // me.domTriggers = {};
- // me.triggers = {};
- me.flushedProps = {};
- me.props = {};
- // the set of cached styles for the element:
- me.styles = {};
- target = me.target;
- if (target.isComponent) {
- me.wrapsComponent = true;
- // These items are created top-down, so the ContextItem of our ownerCt should
- // be available (if it is part of this layout run).
- ownerCt = target.ownerCt;
- if (ownerCt && (ownerCtContext = me.context.items[ownerCt.el.id])) {
- me.ownerCtContext = ownerCtContext;
- }
- // If our ownerCtContext is in the run, it will have a SizeModel that we use to
- // optimize the determination of our sizeModel.
- me.sizeModel = sizeModel = target.getSizeModel(ownerCtContext &&
- ownerCtContext.widthModel.pairsByHeightOrdinal[ownerCtContext.heightModel.ordinal]);
- me.widthModel = sizeModel.width;
- me.heightModel = sizeModel.height;
- // NOTE: The initial determination of sizeModel is valid (thankfully) and is
- // needed to cope with adding components to a layout run on-the-fly (e.g., in
- // the menu overflow handler of a box layout). Since this is the case, we do
- // not need to recompute the sizeModel in init unless it is a "full" init (as
- // our ownerCt's sizeModel could have changed in that case).
- }
- },
- <span id='Ext-layout-ContextItem-method-init'> /**
- </span> * Clears all properties on this object except (perhaps) those not calculated by this
- * component. This is more complex than it would seem because a layout can decide to
- * invalidate its results and run the component's layouts again, but since some of the
- * values may be calculated by the container, care must be taken to preserve those
- * values.
- *
- * @param {Boolean} full True if all properties are to be invalidated, false to keep
- * those calculated by the ownerCt.
- * @return {Mixed} A value to pass as the first argument to {@link #initContinue}.
- * @private
- */
- init: function (full, options) {
- var me = this,
- oldProps = me.props,
- oldDirty = me.dirty,
- ownerCtContext = me.ownerCtContext,
- ownerLayout = me.target.ownerLayout,
- firstTime = !me.state,
- ret = full || firstTime,
- children, i, n, ownerCt, sizeModel, target,
- oldHeightModel = me.heightModel,
- oldWidthModel = me.widthModel,
- newHeightModel, newWidthModel;
- me.dirty = me.invalid = false;
- me.props = {};
- if (me.boxChildren) {
- me.boxChildren.length = 0; // keep array (more GC friendly)
- }
- if (!firstTime) {
- me.clearAllBlocks('blocks');
- me.clearAllBlocks('domBlocks');
- }
- // For Element wrappers, we are done...
- if (!me.wrapsComponent) {
- return ret;
- }
- // From here on, we are only concerned with Component wrappers...
- target = me.target;
- me.state = {}; // only Component wrappers need a "state"
- if (firstTime) {
- // This must occur before we proceed since it can do many things (like add
- // child items perhaps):
- if (target.beforeLayout) {
- target.beforeLayout();
- }
- // Determine the ownerCtContext if we aren't given one. Normally the firstTime
- // we meet a component is before the context is run, but it is possible for
- // components to be added to a run that is already in progress. If so, we have
- // to lookup the ownerCtContext since the odds are very high that the new
- // component is a child of something already in the run. It is currently
- // unsupported to drag in the owner of a running component (needs testing).
- if (!ownerCtContext && (ownerCt = target.ownerCt)) {
- ownerCtContext = me.context.items[ownerCt.el.id];
- }
- if (ownerCtContext) {
- me.ownerCtContext = ownerCtContext;
- me.isBoxParent = target.ownerLayout.isItemBoxParent(me);
- } else {
- me.isTopLevel = true; // this is used by initAnimation...
- }
- me.frameBodyContext = me.getEl('frameBody');
- } else {
- ownerCtContext = me.ownerCtContext;
- // In theory (though untested), this flag can change on-the-fly...
- me.isTopLevel = !ownerCtContext;
- // Init the children element items since they may have dirty state (no need to
- // do this the firstTime).
- children = me.children;
- for (i = 0, n = children.length; i < n; ++i) {
- children[i].init(true);
- }
- }
- // We need to know how we will determine content size: containers can look at the
- // results of their items but non-containers or item-less containers with just raw
- // markup need to be measured in the DOM:
- me.hasRawContent = !(target.isContainer && target.items.items.length > 0);
- if (full) {
- // We must null these out or getSizeModel will assume they are the correct,
- // dynamic size model and return them (the previous dynamic sizeModel).
- me.widthModel = me.heightModel = null;
- sizeModel = target.getSizeModel(ownerCtContext &&
- ownerCtContext.widthModel.pairsByHeightOrdinal[ownerCtContext.heightModel.ordinal]);
- if (firstTime) {
- me.sizeModel = sizeModel;
- }
- me.widthModel = sizeModel.width;
- me.heightModel = sizeModel.height;
- } else if (oldProps) {
- // these are almost always calculated by the ownerCt (we might need to track
- // this at some point more carefully):
- me.recoverProp('x', oldProps, oldDirty);
- me.recoverProp('y', oldProps, oldDirty);
- // if these are calculated by the ownerCt, don't trash them:
- if (me.widthModel.calculated) {
- me.recoverProp('width', oldProps, oldDirty);
- }
- if (me.heightModel.calculated) {
- me.recoverProp('height', oldProps, oldDirty);
- }
- }
- if (oldProps && ownerLayout && ownerLayout.manageMargins) {
- me.recoverProp('margin-top', oldProps, oldDirty);
- me.recoverProp('margin-right', oldProps, oldDirty);
- me.recoverProp('margin-bottom', oldProps, oldDirty);
- me.recoverProp('margin-left', oldProps, oldDirty);
- }
- // Process any invalidate options present. These can only come from explicit calls
- // to the invalidate() method.
- if (options) {
- // Consider a container box with wrapping text. If the box is made wider, the
- // text will take up less height (until there is no more wrapping). Conversely,
- // if the box is made narrower, the height starts to increase due to wrapping.
- //
- // Imposing a minWidth constraint would increase the width. This may decrease
- // the height. If the box is shrinkWrap, however, the width will already be
- // such that there is no wrapping, so the height will not further decrease.
- // Since the height will also not increase if we widen the box, there is no
- // problem simultaneously imposing a minHeight or maxHeight constraint.
- //
- // When we impose as maxWidth constraint, however, we are shrinking the box
- // which may increase the height. If we are imposing a maxHeight constraint,
- // that is fine because a further increased height will still need to be
- // constrained. But if we are imposing a minHeight constraint, we cannot know
- // whether the increase in height due to wrapping will be greater than the
- // minHeight. If we impose a minHeight constraint at the same time, then, we
- // could easily be locking in the wrong height.
- //
- // It is important to note that this logic applies to simultaneously *adding*
- // both a maxWidth and a minHeight constraint. It is perfectly fine to have
- // a state with both constraints, but we cannot add them both at once.
- newHeightModel = options.heightModel;
- newWidthModel = options.widthModel;
- if (newWidthModel && newHeightModel && oldWidthModel && oldHeightModel) {
- if (oldWidthModel.shrinkWrap && oldHeightModel.shrinkWrap) {
- if (newWidthModel.constrainedMax && newHeightModel.constrainedMin) {
- newHeightModel = null;
- }
- }
- }
- // Apply size model updates (if any) and state updates (if any).
- if (newWidthModel) {
- me.widthModel = newWidthModel;
- }
- if (newHeightModel) {
- me.heightModel = newHeightModel;
- }
- if (options.state) {
- Ext.apply(me.state, options.state);
- }
- }
- return ret;
- },
- <span id='Ext-layout-ContextItem-method-initContinue'> /**
- </span> * @private
- */
- initContinue: function (full) {
- var me = this,
- ownerCtContext = me.ownerCtContext,
- widthModel = me.widthModel,
- boxParent;
- if (full) {
- if (ownerCtContext && widthModel.shrinkWrap) {
- boxParent = ownerCtContext.isBoxParent ? ownerCtContext : ownerCtContext.boxParent;
- if (boxParent) {
- boxParent.addBoxChild(me);
- }
- } else if (widthModel.natural) {
- me.boxParent = ownerCtContext;
- }
- }
- return full;
- },
- <span id='Ext-layout-ContextItem-method-initDone'> /**
- </span> * @private
- */
- initDone: function (full, componentChildrenDone, containerChildrenDone, containerLayoutDone) {
- var me = this,
- props = me.props,
- state = me.state;
- // These properties are only set when they are true:
- if (componentChildrenDone) {
- props.componentChildrenDone = true;
- }
- if (containerChildrenDone) {
- props.containerChildrenDone = true;
- }
- if (containerLayoutDone) {
- props.containerLayoutDone = true;
- }
- if (me.boxChildren && me.boxChildren.length && me.widthModel.shrinkWrap) {
- // set a very large width to allow the children to measure their natural
- // widths (this is cleared once all children have been measured):
- me.el.setWidth(10000);
- // don't run layouts for this component until we clear this width...
- state.blocks = (state.blocks || 0) + 1;
- }
- },
- <span id='Ext-layout-ContextItem-method-initAnimation'> /**
- </span> * @private
- */
- initAnimation: function() {
- var me = this,
- target = me.target,
- ownerCtContext = me.ownerCtContext;
- if (ownerCtContext && ownerCtContext.isTopLevel) {
- // See which properties we are supposed to animate to their new state.
- // If there are any, queue ourself to be animated by the owning Context
- me.animatePolicy = target.ownerLayout.getAnimatePolicy(me);
- } else if (!ownerCtContext && target.isCollapsingOrExpanding && target.animCollapse) {
- // Collapsing/expnding a top level Panel with animation. We need to fabricate
- // an animatePolicy depending on which dimension the collapse is using,
- // isCollapsingOrExpanding is set during the collapse/expand process.
- me.animatePolicy = target.componentLayout.getAnimatePolicy(me);
- }
- if (me.animatePolicy) {
- me.context.queueAnimation(me);
- }
- },
- noFraming: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 },
- <span id='Ext-layout-ContextItem-method-addCls'> /**
- </span> * Queue the addition of a class name (or array of class names) to this ContextItem's target when next flushed.
- */
- addCls: function(newCls) {
- this.getClassList().addMany(newCls);
- },
- <span id='Ext-layout-ContextItem-method-removeCls'> /**
- </span> * Queue the removal of a class name (or array of class names) from this ContextItem's target when next flushed.
- */
- removeCls: function(removeCls) {
- this.getClassList().removeMany(removeCls);
- },
- <span id='Ext-layout-ContextItem-method-addBlock'> /**
- </span> * Adds a block.
- *
- * @param {String} name The name of the block list ('blocks' or 'domBlocks').
- * @param {Ext.layout.Layout} layout The layout that is blocked.
- * @param {String} propName The property name that blocked the layout (e.g., 'width').
- * @private
- */
- addBlock: function (name, layout, propName) {
- var me = this,
- collection = me[name] || (me[name] = {}),
- blockedLayouts = collection[propName] || (collection[propName] = {});
- if (!blockedLayouts[layout.id]) {
- blockedLayouts[layout.id] = layout;
- ++layout.blockCount;
- ++me.context.blockCount;
- }
- },
- addBoxChild: function (boxChildItem) {
- var me = this,
- children,
- widthModel = boxChildItem.widthModel;
- boxChildItem.boxParent = this;
- // Children that are widthModel.auto (regardless of heightModel) that measure the
- // DOM (by virtue of hasRawContent), need to wait for their "box parent" to be sized.
- // If they measure too early, they will be wrong results. In the widthModel.shrinkWrap
- // case, the boxParent "crushes" the child. In the case of widthModel.natural, the
- // boxParent's width is likely a key part of the child's width (e.g., "50%" or just
- // normal block-level behavior of 100% width)
- boxChildItem.measuresBox = widthModel.shrinkWrap ? boxChildItem.hasRawContent : widthModel.natural;
- if (boxChildItem.measuresBox) {
- children = me.boxChildren;
- if (children) {
- children.push(boxChildItem);
- } else {
- me.boxChildren = [ boxChildItem ];
- }
- }
- },
- <span id='Ext-layout-ContextItem-method-addTrigger'> /**
- </span> * Adds a trigger.
- *
- * @param {String} propName The property name that triggers the layout (e.g., 'width').
- * @param {Boolean} inDom True if the trigger list is `domTriggers`, false if `triggers`.
- * @private
- */
- addTrigger: function (propName, inDom) {
- var me = this,
- name = inDom ? 'domTriggers' : 'triggers',
- collection = me[name] || (me[name] = {}),
- context = me.context,
- layout = context.currentLayout,
- triggers = collection[propName] || (collection[propName] = {});
- if (!triggers[layout.id]) {
- triggers[layout.id] = layout;
- ++layout.triggerCount;
- triggers = context.triggers[inDom ? 'dom' : 'data'];
- (triggers[layout.id] || (triggers[layout.id] = [])).push({
- item: this,
- prop: propName
- });
- if (me.props[propName] !== undefined) {
- if (!inDom || !(me.dirty && (propName in me.dirty))) {
- ++layout.firedTriggers;
- }
- }
- }
- },
- boxChildMeasured: function () {
- var me = this,
- state = me.state,
- count = (state.boxesMeasured = (state.boxesMeasured || 0) + 1);
- if (count == me.boxChildren.length) {
- // all of our children have measured themselves, so we can clear the width
- // and resume layouts for this component...
- state.clearBoxWidth = 1;
- ++me.context.progressCount;
- me.markDirty();
- }
- },
- borderNames: [ 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'],
- marginNames: [ 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' ],
- paddingNames: [ 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' ],
- trblNames: [ 'top', 'right', 'bottom', 'left' ],
- cacheMissHandlers: {
- borderInfo: function (me) {
- var info = me.getStyles(me.borderNames, me.trblNames);
- info.width = info.left + info.right;
- info.height = info.top + info.bottom;
- return info;
- },
- marginInfo: function (me) {
- var info = me.getStyles(me.marginNames, me.trblNames);
- info.width = info.left + info.right;
- info.height = info.top + info.bottom;
- return info;
- },
- paddingInfo: function (me) {
- // if this context item's target is a framed component the padding is on the frameBody, not on the main el
- var item = me.frameBodyContext || me,
- info = item.getStyles(me.paddingNames, me.trblNames);
- info.width = info.left + info.right;
- info.height = info.top + info.bottom;
- return info;
- }
- },
- checkCache: function (entry) {
- return this.cacheMissHandlers[entry](this);
- },
- clearAllBlocks: function (name) {
- var collection = this[name],
- propName;
- if (collection) {
- for (propName in collection) {
- this.clearBlocks(name, propName);
- }
- }
- },
- <span id='Ext-layout-ContextItem-method-clearBlocks'> /**
- </span> * Removes any blocks on a property in the specified set. Any layouts that were blocked
- * by this property and are not still blocked (by other properties) will be rescheduled.
- *
- * @param {String} name The name of the block list ('blocks' or 'domBlocks').
- * @param {String} propName The property name that blocked the layout (e.g., 'width').
- * @private
- */
- clearBlocks: function (name, propName) {
- var collection = this[name],
- blockedLayouts = collection && collection[propName],
- context, layout, layoutId;
- if (blockedLayouts) {
- delete collection[propName];
- context = this.context;
- for (layoutId in blockedLayouts) {
- layout = blockedLayouts[layoutId];
- --context.blockCount;
- if (! --layout.blockCount && !layout.pending && !layout.done) {
- context.queueLayout(layout);
- }
- }
- }
- },
- <span id='Ext-layout-ContextItem-method-block'> /**
- </span> * Registers a layout in the block list for the given property. Once the property is
- * set in the {@link Ext.layout.Context}, the layout is unblocked.
- *
- * @param {Ext.layout.Layout} layout
- * @param {String} propName The property name that blocked the layout (e.g., 'width').
- */
- block: function (layout, propName) {
- this.addBlock('blocks', layout, propName);
- },
- <span id='Ext-layout-ContextItem-method-domBlock'> /**
- </span> * Registers a layout in the DOM block list for the given property. Once the property
- * flushed to the DOM by the {@link Ext.layout.Context}, the layout is unblocked.
- *
- * @param {Ext.layout.Layout} layout
- * @param {String} propName The property name that blocked the layout (e.g., 'width').
- */
- domBlock: function (layout, propName) {
- this.addBlock('domBlocks', layout, propName);
- },
- <span id='Ext-layout-ContextItem-method-fireTriggers'> /**
- </span> * Reschedules any layouts associated with a given trigger.
- *
- * @param {String} name The name of the trigger list ('triggers' or 'domTriggers').
- * @param {String} propName The property name that triggers the layout (e.g., 'width').
- * @private
- */
- fireTriggers: function (name, propName) {
- var collection = this[name],
- triggers = collection && collection[propName],
- context = this.context,
- layout, layoutId;
- if (triggers) {
- for (layoutId in triggers) {
- layout = triggers[layoutId];
- ++layout.firedTriggers;
- if (!layout.done && !layout.blockCount && !layout.pending) {
- context.queueLayout(layout);
- }
- }
- }
- },
- <span id='Ext-layout-ContextItem-method-flush'> /**
- </span> * Flushes any updates in the dirty collection to the DOM. This is only called if there
- * are dirty entries because this object is only added to the flushQueue of the
- * {@link Ext.layout.Context} when entries become dirty.
- */
- flush: function () {
- var me = this,
- dirty = me.dirty,
- state = me.state,
- targetEl = me.el;
- me.dirtyCount = 0;
- // Flush added/removed classes
- if (me.classList && me.classList.dirty) {
- me.classList.flush();
- }
- // Set any queued DOM attributes
- if ('attributes' in me) {
- targetEl.set(me.attributes);
- delete me.attributes;
- }
- // Set any queued DOM HTML content
- if ('innerHTML' in me) {
- targetEl.innerHTML = me.innerHTML;
- delete me.innerHTML;
- }
- if (state && state.clearBoxWidth) {
- state.clearBoxWidth = 0;
- me.el.setStyle('width', null);
- if (! --state.blocks) {
- me.context.queueItemLayouts(me);
- }
- }
- if (dirty) {
- delete me.dirty;
- me.writeProps(dirty, true);
- }
- },
- <span id='Ext-layout-ContextItem-method-flushAnimations'> /**
- </span> * @private
- */
- flushAnimations: function() {
- var me = this,
- animateFrom = me.lastBox,
- target, targetAnim, duration, animateProps, anim,
- changeCount, j, propsLen, propName, oldValue, newValue;
- // Only animate if the Component has been previously layed out: first layout should not animate
- if (animateFrom) {
- target = me.target;
- targetAnim = target.layout && target.layout.animate;
- if (targetAnim) {
- duration = Ext.isNumber(targetAnim) ? targetAnim : targetAnim.duration;
- }
- animateProps = Ext.Object.getKeys(me.animatePolicy);
- // Create an animation block using the targetAnim configuration to provide defaults.
- // They may want custom duration, or easing, or listeners.
- anim = Ext.apply({}, {
- from: {},
- to: {},
- duration: duration || Ext.fx.Anim.prototype.duration
- }, targetAnim);
- for (changeCount = 0, j = 0, propsLen = animateProps.length; j < propsLen; j++) {
- propName = animateProps[j];
- oldValue = animateFrom[propName];
- newValue = me.peek(propName);
- if (oldValue != newValue) {
- propName = me.translateProps[propName]||propName;
- anim.from[propName] = oldValue;
- anim.to[propName] = newValue;
- ++changeCount;
- }
- }
- // If any values have changed, kick off animation from the cached old values to the new values
- if (changeCount) {
- // It'a Panel being collapsed. rollback, and then fix the class name string
- if (me.isCollapsingOrExpanding === 1) {
- target.componentLayout.undoLayout(me);
- }
- // Otherwise, undo just the animated properties so the animation can proceed from the old layout.
- else {
- me.writeProps(anim.from);
- }
- me.el.animate(anim);
-
- Ext.fx.Manager.getFxQueue(me.el.id)[0].on({
- afteranimate: function() {
- if (me.isCollapsingOrExpanding === 1) {
- target.componentLayout.redoLayout(me);
- target.afterCollapse(true);
- } else if (me.isCollapsingOrExpanding === 2) {
- target.afterExpand(true);
- }
- }
- });
- }
- }
- },
- <span id='Ext-layout-ContextItem-method-getBorderInfo'> /**
- </span> * Gets the border information for the element as an object with left, top, right and
- * bottom properties holding border size in pixels. This object is only read from the
- * DOM on first request and is cached.
- * @return {Object}
- */
- getBorderInfo: function () {
- var me = this,
- info = me.borderInfo;
- if (!info) {
- me.borderInfo = info = me.checkCache('borderInfo');
- }
- return info;
- },
- <span id='Ext-layout-ContextItem-method-getClassList'> /**
- </span> * Returns a ClassList-like object to buffer access to this item's element's classes.
- */
- getClassList: function () {
- return this.classList || (this.classList = new Ext.layout.ClassList(this));
- },
- <span id='Ext-layout-ContextItem-method-getEl'> /**
- </span> * Returns the context item for an owned element. This should only be called on a
- * component's item. The list of child items is used to manage invalidating calculated
- * results.
- */
- getEl: function (nameOrEl, owner) {
- var me = this,
- src, el, elContext;
- if (nameOrEl) {
- if (nameOrEl.dom) {
- el = nameOrEl;
- } else {
- src = me.target;
- if (owner) {
- src = owner;
- }
- el = src[nameOrEl];
- if (typeof el == 'function') { // ex 'getTarget'
- el = el.call(src);
- if (el === me.el) {
- return this; // comp.getTarget() often returns comp.el
- }
- }
- }
- if (el) {
- elContext = me.context.getEl(me, el);
- }
- }
- return elContext || null;
- },
- getFraming: function () {
- var me = this;
- if (!me.framingInfo) {
- me.framingInfo = me.target.frameSize || me.noFraming;
- }
- return me.framingInfo;
- },
- <span id='Ext-layout-ContextItem-method-getFrameInfo'> /**
- </span> * Gets the "frame" information for the element as an object with left, top, right and
- * bottom properties holding border+framing size in pixels. This object is calculated
- * on first request and is cached.
- * @return {Object}
- */
- getFrameInfo: function () {
- var me = this,
- info = me.frameInfo,
- frame, border;
- if (!info) {
- frame = me.getFraming();
- border = me.getBorderInfo();
-
- me.frameInfo = info = {
- top : frame.top + border.top,
- right : frame.right + border.right,
- bottom: frame.bottom + border.bottom,
- left : frame.left + border.left,
- width : frame.width + border.width,
- height: frame.height + border.height
- };
- }
- return info;
- },
- <span id='Ext-layout-ContextItem-method-getMarginInfo'> /**
- </span> * Gets the margin information for the element as an object with left, top, right and
- * bottom properties holding margin size in pixels. This object is only read from the
- * DOM on first request and is cached.
- * @return {Object}
- */
- getMarginInfo: function () {
- var me = this,
- info = me.marginInfo,
- comp, manageMargins, margins, ownerLayout, ownerLayoutId;
- if (!info) {
- if (!me.wrapsComponent) {
- info = me.checkCache('marginInfo');
- } else {
- comp = me.target;
- ownerLayout = comp.ownerLayout;
- ownerLayoutId = ownerLayout ? ownerLayout.id : null;
- manageMargins = ownerLayout && ownerLayout.manageMargins;
- // Option #1 for configuring margins on components is the "margin" config
- // property. When supplied, this config is written to the DOM during the
- // render process (see AbstractComponent#initStyles).
- //
- // Option #2 is available to some layouts (e.g., Box, Border, Fit) that
- // handle margin calculations themselves. These layouts support a "margins"
- // config property on their items and they have a "defaultMargins" config
- // property. These margin values are added to the "natural" margins read
- // from the DOM and 0's are written to the DOM after they are added.
- // To avoid having to do all this on every layout, we cache the results on
- // the component in the (private) "margin$" property. We identify the cache
- // results as belonging to the appropriate ownerLayout in case items are
- // moved around.
- info = comp.margin$;
- if (info && info.ownerId !== ownerLayoutId) {
- // got one but from the wrong owner
- info = null;
- // if (manageMargins) {
- // TODO: clear inline margins (the 0's we wrote last time)???
- // }
- }
- if (!info) { // if (no cache)
- // CSS margins are only checked if there isn't a margin property on the component
- info = me.parseMargins(comp.margin) || me.checkCache('marginInfo');
- // Some layouts also support margins and defaultMargins, e.g. Fit, Border, Box
- if (manageMargins) {
- margins = me.parseMargins(comp.margins, ownerLayout.defaultMargins);
- if (margins) { // if (using 'margins' and/or 'defaultMargins')
- // margin and margins can both be present at the same time and must be combined
- info = {
- top: info.top + margins.top,
- right: info.right + margins.right,
- bottom: info.bottom + margins.bottom,
- left: info.left + margins.left
- };
- }
- me.setProp('margin-top', 0);
- me.setProp('margin-right', 0);
- me.setProp('margin-bottom', 0);
- me.setProp('margin-left', 0);
- }
- // cache the layout margins and tag them with the layout id:
- info.ownerId = ownerLayoutId;
- comp.margin$ = info;
- }
- info.width = info.left + info.right;
- info.height = info.top + info.bottom;
- }
- me.marginInfo = info;
- }
- return info;
- },
- <span id='Ext-layout-ContextItem-method-clearMarginCache'> /**
- </span> * clears the margin cache so that marginInfo get re-read from the dom on the next call to getMarginInfo()
- * This is needed in some special cases where the margins have changed since the last layout, making the cached
- * values invalid. For example collapsed window headers have different margin than expanded ones.
- */
- clearMarginCache: function() {
- delete this.marginInfo;
- delete this.target.margin$;
- },
- <span id='Ext-layout-ContextItem-method-getPaddingInfo'> /**
- </span> * Gets the padding information for the element as an object with left, top, right and
- * bottom properties holding padding size in pixels. This object is only read from the
- * DOM on first request and is cached.
- * @return {Object}
- */
- getPaddingInfo: function () {
- var me = this,
- info = me.paddingInfo;
- if (!info) {
- me.paddingInfo = info = me.checkCache('paddingInfo');
- }
- return info;
- },
- <span id='Ext-layout-ContextItem-method-getProp'> /**
- </span> * Gets a property of this object. Also tracks the current layout as dependent on this
- * property so that changes to it will trigger the layout to be recalculated.
- * @param {String} propName The property name that blocked the layout (e.g., 'width').
- * @return {Object} The property value or undefined if not yet set.
- */
- getProp: function (propName) {
- var me = this,
- result = me.props[propName];
- me.addTrigger(propName);
- return result;
- },
- <span id='Ext-layout-ContextItem-method-getDomProp'> /**
- </span> * Gets a property of this object if it is correct in the DOM. Also tracks the current
- * layout as dependent on this property so that DOM writes of it will trigger the
- * layout to be recalculated.
- * @param {String} propName The property name (e.g., 'width').
- * @return {Object} The property value or undefined if not yet set or is dirty.
- */
- getDomProp: function (propName) {
- var me = this,
- result = (me.dirty && (propName in me.dirty)) ? undefined : me.props[propName];
- me.addTrigger(propName, true);
- return result;
- },
- <span id='Ext-layout-ContextItem-method-getStyle'> /**
- </span> * Returns a style for this item. Each style is read from the DOM only once on first
- * request and is then cached. If the value is an integer, it is parsed automatically
- * (so '5px' is not returned, but rather 5).
- *
- * @param {String} styleName The CSS style name.
- * @return {Object} The value of the DOM style (parsed as necessary).
- */
- getStyle: function (styleName) {
- var me = this,
- styles = me.styles,
- info, value;
- if (styleName in styles) {
- value = styles[styleName];
- } else {
- info = me.styleInfo[styleName];
- value = me.el.getStyle(styleName);
- if (info && info.parseInt) {
- value = parseInt(value, 10) || 0;
- }
- styles[styleName] = value;
- }
- return value;
- },
- <span id='Ext-layout-ContextItem-method-getStyles'> /**
- </span> * Returns styles for this item. Each style is read from the DOM only once on first
- * request and is then cached. If the value is an integer, it is parsed automatically
- * (so '5px' is not returned, but rather 5).
- *
- * @param {String[]} styleNames The CSS style names.
- * @param {String[]} [altNames] The alternate names for the returned styles. If given,
- * these names must correspond one-for-one to the `styleNames`.
- * @return {Object} The values of the DOM styles (parsed as necessary).
- */
- getStyles: function (styleNames, altNames) {
- var me = this,
- styleCache = me.styles,
- values = {},
- hits = 0,
- n = styleNames.length,
- i, missing, missingAltNames, name, info, styleInfo, styles, value;
- altNames = altNames || styleNames;
- // We are optimizing this for all hits or all misses. If we hit on all styles, we
- // don't create a missing[]. If we miss on all styles, we also don't create one.
- for (i = 0; i < n; ++i) {
- name = styleNames[i];
- if (name in styleCache) {
- values[altNames[i]] = styleCache[name];
- ++hits;
- if (i && hits==1) { // if (first hit was after some misses)
- missing = styleNames.slice(0, i);
- missingAltNames = altNames.slice(0, i);
- }
- } else if (hits) {
- (missing || (missing = [])).push(name);
- (missingAltNames || (missingAltNames = [])).push(altNames[i]);
- }
- }
- if (hits < n) {
- missing = missing || styleNames;
- missingAltNames = missingAltNames || altNames;
- styleInfo = me.styleInfo;
- styles = me.el.getStyle(missing);
- for (i = missing.length; i--; ) {
- name = missing[i];
- info = styleInfo[name];
- value = styles[name];
- if (info && info.parseInt) {
- value = parseInt(value, 10) || 0;
- }
- values[missingAltNames[i]] = value;
- styleCache[name] = value;
- }
- }
- return values;
- },
- <span id='Ext-layout-ContextItem-method-hasProp'> /**
- </span> * Returns true if the given property has been set. This is equivalent to calling
- * {@link #getProp} and not getting an undefined result. In particular, this call
- * registers the current layout to be triggered by changes to this property.
- *
- * @param {String} propName The property name (e.g., 'width').
- * @return {Boolean}
- */
- hasProp: function (propName) {
- var value = this.getProp(propName);
- return typeof value != 'undefined';
- },
- <span id='Ext-layout-ContextItem-method-hasDomProp'> /**
- </span> * Returns true if the given property is correct in the DOM. This is equivalent to
- * calling {@link #getDomProp} and not getting an undefined result. In particular,
- * this call registers the current layout to be triggered by flushes of this property.
- *
- * @param {String} propName The property name (e.g., 'width').
- * @return {Boolean}
- */
- hasDomProp: function (propName) {
- var value = this.getDomProp(propName);
- return typeof value != 'undefined';
- },
- <span id='Ext-layout-ContextItem-method-invalidate'> /**
- </span> * Invalidates the component associated with this item. The layouts for this component
- * and all of its contained items will be re-run after first clearing any computed
- * values.
- *
- * If state needs to be carried forward beyond the invalidation, the `options` parameter
- * can be used.
- *
- * @param {Object} options An object describing how to handle the invalidation.
- * @param {Object} options.state An object to {@link Ext#apply} to the {@link #state}
- * of this item after invalidation clears all other properties.
- * @param {Function} options.before A function to call after the context data is cleared
- * and before the {@link Ext.layout.Layout#beginLayoutCycle} methods are called.
- * @param {Ext.layout.ContextItem} options.before.item This ContextItem.
- * @param {Object} options.before.options The options object passed to {@link #invalidate}.
- * @param {Function} options.after A function to call after the context data is cleared
- * and after the {@link Ext.layout.Layout#beginLayoutCycle} methods are called.
- * @param {Ext.layout.ContextItem} options.after.item This ContextItem.
- * @param {Object} options.after.options The options object passed to {@link #invalidate}.
- * @param {Object} options.scope The scope to use when calling the callback functions.
- */
- invalidate: function (options) {
- this.context.queueInvalidate(this, options);
- },
- markDirty: function () {
- if (++this.dirtyCount == 1) {
- // our first dirty property... queue us for flush
- this.context.queueFlush(this);
- }
- },
- onBoxMeasured: function () {
- var boxParent = this.boxParent,
- state = this.state;
- if (boxParent && boxParent.widthModel.shrinkWrap && !state.boxMeasured && this.measuresBox) {
- // since an autoWidth boxParent is holding a width on itself to allow each
- // child to measure
- state.boxMeasured = 1; // best to only call once per child
- boxParent.boxChildMeasured();
- }
- },
- parseMargins: function (margins, defaultMargins) {
- if (margins === true) {
- margins = 5;
- }
- var type = typeof margins,
- ret;
- if (type == 'string' || type == 'number') {
- ret = Ext.util.Format.parseBox(margins);
- } else if (margins || defaultMargins) {
- ret = { top: 0, right: 0, bottom: 0, left: 0 }; // base defaults
- if (defaultMargins) {
- Ext.apply(ret, this.parseMargins(defaultMargins)); // + layout defaults
- }
- Ext.apply(ret, margins); // + config
- }
- return ret;
- },
- peek: function (propName) {
- return this.props[propName];
- },
- <span id='Ext-layout-ContextItem-method-recoverProp'> /**
- </span> * Recovers a property value from the last computation and restores its value and
- * dirty state.
- *
- * @param {String} propName The name of the property to recover.
- * @param {Object} oldProps The old "props" object from which to recover values.
- * @param {Object} oldDirty The old "dirty" object from which to recover state.
- */
- recoverProp: function (propName, oldProps, oldDirty) {
- var me = this,
- props = me.props,
- dirty;
- if (propName in oldProps) {
- props[propName] = oldProps[propName];
- if (oldDirty && propName in oldDirty) {
- dirty = me.dirty || (me.dirty = {});
- dirty[propName] = oldDirty[propName];
- }
- }
- },
- redo: function(deep) {
- var me = this,
- items, len, i;
- me.revertProps(me.props);
- if (deep && me.wrapsComponent) {
- // Rollback the state of child Components
- if (me.childItems) {
- for (i = 0, items = me.childItems, len = items.length; i < len; i++) {
- items[i].redo(deep);
- }
- }
- // Rollback the state of child Elements
- for (i = 0, items = me.children, len = items.length; i < len; i++) {
- items[i].redo();
- }
- }
- },
- revertProps: function (props) {
- var name,
- flushed = this.flushedProps,
- reverted = {};
- for (name in props) {
- if (flushed.hasOwnProperty(name)) {
- reverted[name] = props[name];
- }
- }
- this.writeProps(reverted);
- },
- <span id='Ext-layout-ContextItem-method-setAttribute'> /**
- </span> * Queue the setting of a DOM attribute on this ContextItem's target when next flushed.
- */
- setAttribute: function(name, value) {
- var me = this;
- if (!me.attributes) {
- me.attributes = {};
- }
- me.attributes[name] = value;
- me.markDirty();
- },
- setBox: function (box) {
- var me = this;
- if ('left' in box) {
- me.setProp('x', box.left);
- }
- if ('top' in box) {
- me.setProp('y', box.top);
- }
- // if sizeModel says we should not be setting these, the appropriate calls will be
- // null operations... otherwise, we must set these values, so what we have in box
- // is what we go with (undefined, NaN and no change are handled at a lower level):
- me.setSize(box.width, box.height);
- },
- <span id='Ext-layout-ContextItem-method-setContentHeight'> /**
- </span> * Sets the contentHeight property. If the component uses raw content, then only the
- * measured height is acceptable.
- *
- * Calculated values can sometimes be NaN or undefined, which generally mean the
- * calculation is not done. To indicate that such as value was passed, 0 is returned.
- * Otherwise, 1 is returned.
- *
- * If the caller is not measuring (i.e., they are calculating) and the component has raw
- * content, 1 is returned indicating that the caller is done.
- */
- setContentHeight: function (height, measured) {
- if (!measured && this.hasRawContent) {
- return 1;
- }
- return this.setProp('contentHeight', height);
- },
- <span id='Ext-layout-ContextItem-method-setContentWidth'> /**
- </span> * Sets the contentWidth property. If the component uses raw content, then only the
- * measured width is acceptable.
- *
- * Calculated values can sometimes be NaN or undefined, which generally means that the
- * calculation is not done. To indicate that such as value was passed, 0 is returned.
- * Otherwise, 1 is returned.
- *
- * If the caller is not measuring (i.e., they are calculating) and the component has raw
- * content, 1 is returned indicating that the caller is done.
- */
- setContentWidth: function (width, measured) {
- if (!measured && this.hasRawContent) {
- return 1;
- }
- return this.setProp('contentWidth', width);
- },
- <span id='Ext-layout-ContextItem-method-setContentSize'> /**
- </span> * Sets the contentWidth and contentHeight properties. If the component uses raw content,
- * then only the measured values are acceptable.
- *
- * Calculated values can sometimes be NaN or undefined, which generally means that the
- * calculation is not done. To indicate that either passed value was such a value, false
- * returned. Otherwise, true is returned.
- *
- * If the caller is not measuring (i.e., they are calculating) and the component has raw
- * content, true is returned indicating that the caller is done.
- */
- setContentSize: function (width, height, measured) {
- return this.setContentWidth(width, measured) +
- this.setContentHeight(height, measured) == 2;
- },
- <span id='Ext-layout-ContextItem-method-setProp'> /**
- </span> * Sets a property value. This will unblock and/or trigger dependent layouts if the
- * property value is being changed. Values of NaN and undefined are not accepted by
- * this method.
- *
- * @param {String} propName The property name (e.g., 'width').
- * @param {Object} value The new value of the property.
- * @param {Boolean} dirty Optionally specifies if the value is currently in the DOM
- * (default is `true` which indicates the value is not in the DOM and must be flushed
- * at some point).
- * @return {Number} 1 if this call specified the property value, 0 if not.
- */
- setProp: function (propName, value, dirty) {
- var me = this,
- valueType = typeof value,
- borderBox, info;
- if (valueType == 'undefined' || (valueType === 'number' && isNaN(value))) {
- return 0;
- }
- if (me.props[propName] === value) {
- return 1;
- }
- me.props[propName] = value;
- ++me.context.progressCount;
- if (dirty === false) {
- // if the prop is equivalent to what is in the DOM (we won't be writing it),
- // we need to clear hard blocks (domBlocks) on that property.
- me.fireTriggers('domTriggers', propName);
- me.clearBlocks('domBlocks', propName);
- } else {
- info = me.styleInfo[propName];
- if (info) {
- if (!me.dirty) {
- me.dirty = {};
- }
- if (propName == 'width' || propName == 'height') {
- borderBox = me.isBorderBoxValue;
- if (borderBox == null) {
- me.isBorderBoxValue = borderBox = !!me.el.isBorderBox();
- }
- if (!borderBox) {
- me.borderInfo || me.getBorderInfo();
- me.paddingInfo || me.getPaddingInfo();
- }
- }
- me.dirty[propName] = value;
- me.markDirty();
- }
- }
- // we always clear soft blocks on set
- me.fireTriggers('triggers', propName);
- me.clearBlocks('blocks', propName);
- return 1;
- },
- <span id='Ext-layout-ContextItem-method-setHeight'> /**
- </span> * Sets the height and constrains the height to min/maxHeight range.
- *
- * @param {Number} height The height.
- * @param {Boolean} [dirty=true] Specifies if the value is currently in the DOM. A
- * value of `false` indicates that the value is already in the DOM.
- * @return {Number} The actual height after constraining.
- */
- setHeight: function (height, dirty /*, private {Boolean} force */) {
- var me = this,
- comp = me.target,
- frameBody, frameInfo, padding;
- if (height < 0) {
- height = 0;
- }
- if (!me.wrapsComponent) {
- if (!me.setProp('height', height, dirty)) {
- return NaN;
- }
- } else {
- height = Ext.Number.constrain(height, comp.minHeight || 0, comp.maxHeight);
- if (!me.setProp('height', height, dirty)) {
- return NaN;
- }
- frameBody = me.frameBodyContext;
- if (frameBody){
- frameInfo = me.getFrameInfo();
- frameBody.setHeight(height - frameInfo.height, dirty);
- }
- }
- return height;
- },
- <span id='Ext-layout-ContextItem-method-setWidth'> /**
- </span> * Sets the height and constrains the width to min/maxWidth range.
- *
- * @param {Number} width The width.
- * @param {Boolean} [dirty=true] Specifies if the value is currently in the DOM. A
- * value of `false` indicates that the value is already in the DOM.
- * @return {Number} The actual width after constraining.
- */
- setWidth: function (width, dirty /*, private {Boolean} force */) {
- var me = this,
- comp = me.target,
- frameBody, frameInfo, padding;
- if (width < 0) {
- width = 0;
- }
- if (!me.wrapsComponent) {
- if (!me.setProp('width', width, dirty)) {
- return NaN;
- }
- } else {
- width = Ext.Number.constrain(width, comp.minWidth || 0, comp.maxWidth);
- if (!me.setProp('width', width, dirty)) {
- return NaN;
- }
- //if ((frameBody = me.target.frameBody) && (frameBody = me.getEl(frameBody))){
- frameBody = me.frameBodyContext;
- if (frameBody) {
- frameInfo = me.getFrameInfo();
- frameBody.setWidth(width - frameInfo.width, dirty);
- }
- /*if (owner.frameMC) {
- frameContext = ownerContext.frameContext ||
- (ownerContext.frameContext = ownerContext.getEl('frameMC'));
- width += (frameContext.paddingInfo || frameContext.getPaddingInfo()).width;
- }*/
- }
- return width;
- },
- setSize: function (width, height, dirty) {
- this.setWidth(width, dirty);
- this.setHeight(height, dirty);
- },
- translateProps: {
- x: 'left',
- y: 'top'
- },
- undo: function(deep) {
- var me = this,
- items, len, i;
- me.revertProps(me.lastBox);
- if (deep && me.wrapsComponent) {
- // Rollback the state of child Components
- if (me.childItems) {
- for (i = 0, items = me.childItems, len = items.length; i < len; i++) {
- items[i].undo(deep);
- }
- }
- // Rollback the state of child Elements
- for (i = 0, items = me.children, len = items.length; i < len; i++) {
- items[i].undo();
- }
- }
- },
- unsetProp: function (propName) {
- var dirty = this.dirty;
- delete this.props[propName];
- if (dirty) {
- delete dirty[propName];
- }
- },
- writeProps: function(dirtyProps, flushing) {
- if (!(dirtyProps && typeof dirtyProps == 'object')) {
- //<debug warn>
- Ext.Logger.warn('writeProps expected dirtyProps to be an object');
- //</debug>
- return;
- }
- var me = this,
- el = me.el,
- styles = {},
- styleCount = 0, // used as a boolean, the exact count doesn't matter
- styleInfo = me.styleInfo,
-
- info,
- propName,
- numericValue,
-
- dirtyX = 'x' in dirtyProps,
- dirtyY = 'y' in dirtyProps,
- x = dirtyProps.x,
- y = dirtyProps.y,
-
- width = dirtyProps.width,
- height = dirtyProps.height,
- isBorderBox = me.isBorderBoxValue,
- target = me.target,
- max = Math.max,
- paddingWidth = 0,
- paddingHeight = 0,
- hasWidth, hasHeight, isAbsolute, scrollbarSize, style, targetEl;
- // Process non-style properties:
- if ('displayed' in dirtyProps) {
- el.setDisplayed(dirtyProps.displayed);
- }
- // Unblock any hard blocks (domBlocks) and copy dom styles into 'styles'
- for (propName in dirtyProps) {
- if (flushing) {
- me.fireTriggers('domTriggers', propName);
- me.clearBlocks('domBlocks', propName);
- me.flushedProps[propName] = 1;
- }
- info = styleInfo[propName];
- if (info && info.dom) {
- // Numeric dirty values should have their associated suffix added
- if (info.suffix && (numericValue = parseInt(dirtyProps[propName], 10))) {
- styles[propName] = numericValue + info.suffix;
- }
- // Non-numeric (eg "auto") go in unchanged.
- else {
- styles[propName] = dirtyProps[propName];
- }
- ++styleCount;
- }
- }
- // convert x/y into setPosition (for a component) or left/top styles (for an el)
- if (dirtyX || dirtyY) {
- if (target.isComponent) {
- // Ensure we always pass the current coordinate in if one coordinate has not been dirtied by a calculation cycle.
- target.setPosition(x||me.props.x, y||me.props.y);
- } else {
- // we wrap an element, so convert x/y to styles:
- if (dirtyX) {
- styles.left = x + 'px';
- ++styleCount;
- }
- if (dirtyY) {
- styles.top = y + 'px';
- ++styleCount;
- }
- }
- }
- // Support for the content-box box model...
- if (!isBorderBox && (width > 0 || height > 0)) { // no need to subtract from 0
- // The width and height values assume the border-box box model,
- // so we must remove the padding & border to calculate the content-box.
- //<debug>
- if (!(me.borderInfo && me.paddingInfo)) {
- throw Error("Needed to have gotten the borderInfo and paddingInfo when the width or height was setProp'd");
- }
- //</debug>
- if(!me.frameBodyContext) {
- // Padding needs to be removed only if the element is not framed.
- paddingWidth = me.paddingInfo.width;
- paddingHeight = me.paddingInfo.height;
- }
- if (width) {
- width = max(parseInt(width, 10) - (me.borderInfo.width + paddingWidth), 0);
- styles.width = width + 'px';
- ++styleCount;
- }
- if (height) {
- height = max(parseInt(height, 10) - (me.borderInfo.height + paddingHeight), 0);
- styles.height = height + 'px';
- ++styleCount;
- }
- }
- // IE9 strict subtracts the scrollbar size from the element size when the element
- // is absolutely positioned and uses box-sizing: border-box. To workaround this
- // issue we have to add the the scrollbar size.
- //
- // See http://social.msdn.microsoft.com/Forums/da-DK/iewebdevelopment/thread/47c5148f-a142-4a99-9542-5f230c78cb3b
- //
- if (me.wrapsComponent && Ext.isIE9 && Ext.isStrict) {
- // when we set a width and we have a vertical scrollbar (overflowY), we need
- // to add the scrollbar width... conversely for the height and overflowX
- if ((hasWidth = width !== undefined && me.hasOverflowY) ||
- (hasHeight = height !== undefined && me.hasOverflowX)) {
- // check that the component is absolute positioned and border-box:
- isAbsolute = me.isAbsolute;
- if (isAbsolute === undefined) {
- isAbsolute = false;
- targetEl = me.target.getTargetEl();
- style = targetEl.getStyle('position');
- if (style == 'absolute') {
- style = targetEl.getStyle('box-sizing');
- isAbsolute = (style == 'border-box');
- }
- me.isAbsolute = isAbsolute; // cache it
- }
- if (isAbsolute) {
- scrollbarSize = Ext.getScrollbarSize();
- if (hasWidth) {
- width = parseInt(width, 10) + scrollbarSize.width;
- styles.width = width + 'px';
- ++styleCount;
- }
- if (hasHeight) {
- height = parseInt(height, 10) + scrollbarSize.height;
- styles.height = height + 'px';
- ++styleCount;
- }
- }
- }
- }
- // we make only one call to setStyle to allow it to optimize itself:
- if (styleCount) {
- el.setStyle(styles);
- }
- }
- }, function () {
-
- var px = { dom: true, parseInt: true, suffix: 'px' },
- isDom = { dom: true },
- faux = { dom: false };
- // If a property exists in styleInfo, it participates in some way with the DOM. It may
- // be virtualized (like 'x' and y') and be indirect, but still requires a flush cycle
- // to reach the DOM. Properties (like 'contentWidth' and 'contentHeight') have no real
- // presence in the DOM and hence have no flush intanglements.
- //
- // For simple styles, the object value on the right contains properties that help in
- // decoding values read by getStyle and preparing values to pass to setStyle.
- //
- this.prototype.styleInfo = {
- childrenDone: faux,
- componentChildrenDone: faux,
- containerChildrenDone: faux,
- containerLayoutDone: faux,
- displayed: faux,
- done: faux,
- x: faux,
- y: faux,
- // For Ext.grid.ColumnLayout
- columnWidthsDone: faux,
- left: px,
- top: px,
- right: px,
- bottom: px,
- width: px,
- height: px,
- 'border-top-width': px,
- 'border-right-width': px,
- 'border-bottom-width': px,
- 'border-left-width': px,
- 'margin-top': px,
- 'margin-right': px,
- 'margin-bottom': px,
- 'margin-left': px,
- 'padding-top': px,
- 'padding-right': px,
- 'padding-bottom': px,
- 'padding-left': px,
- 'line-height': isDom,
- display: isDom
- };
- });
- </pre>
- </body>
- </html>
|