X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..6746dc89c47ed01b165cc1152533605f97eb8e8d:/docs/source/AbstractComponent.html diff --git a/docs/source/AbstractComponent.html b/docs/source/AbstractComponent.html index a36fbdf3..8197a86e 100644 --- a/docs/source/AbstractComponent.html +++ b/docs/source/AbstractComponent.html @@ -1,8 +1,24 @@ -
+ +/** - * @class Ext.AbstractComponent + + + + +\ No newline at end of file +The source code + + + + + + +/** + * @class Ext.AbstractComponent * <p>An abstract base class which provides shared methods for Components across the Sencha product line.</p> * <p>Please refer to sub class's documentation</p> - * @constructor */ Ext.define('Ext.AbstractComponent', { @@ -47,6 +63,7 @@ Ext.define('Ext.AbstractComponent', { return ++Ext.AbstractComponent.AUTO_ID; }, + /** * @cfg {String} id * <p>The <b><u>unique id of this component instance</u></b> (defaults to an {@link #getId auto-assigned id}).</p> @@ -94,7 +111,8 @@ var c = new Ext.panel.Panel({ // p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()} p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling * </code></pre> - * <p>Also see <tt>{@link #id}</tt>, <code>{@link #query}</code>, <code>{@link #down}</code> and <code>{@link #child}</code>.</p> + * <p>Also see <tt>{@link #id}</tt>, <code>{@link Ext.container.Container#query}</code>, + * <code>{@link Ext.container.Container#down}</code> and <code>{@link Ext.container.Container#child}</code>.</p> * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p> */ @@ -106,6 +124,26 @@ p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponen * @property ownerCt */ + /** + * @private + * Flag set by the container layout to which this Component is added. + * If the layout manages this Component's width, it sets the value to 1. + * If it does NOT manage the width, it sets it to 2. + * If the layout MAY affect the width, but only if the owning Container has a fixed width, this is set to 0. + * @type boolean + * @property layoutManagedWidth + */ + + /** + * @private + * Flag set by the container layout to which this Component is added. + * If the layout manages this Component's height, it sets the value to 1. + * If it does NOT manage the height, it sets it to 2. + * If the layout MAY affect the height, but only if the owning Container has a fixed height, this is set to 0. + * @type boolean + * @property layoutManagedHeight + */ + /** * @cfg {Mixed} autoEl * <p>A tag name or {@link Ext.core.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will @@ -289,14 +327,14 @@ and a property `descEl` referencing the `div` Element which contains the descrip * A set style for a component. Can be a string or an Array of multiple strings (UIs) */ ui: 'default', - + /** * @cfg {Array} uiCls * An array of of classNames which are currently applied to this component * @private */ uiCls: [], - + /** * @cfg {String} style * A custom style specification to be applied to this component's Element. Should be a valid argument to @@ -425,7 +463,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip */ /** - * @cfg {String} styleHtmlContent + * @cfg {Boolean} styleHtmlContent * True to automatically style the html inside the content target of this component (body for panels). * Defaults to false. */ @@ -508,8 +546,8 @@ and a property `descEl` referencing the `div` Element which contains the descrip trimRe: /^\s+|\s+$/g, spacesRe: /\s+/, - - + + /** * This is an internal flag that you use when creating custom components. * By default this is set to true which means that every component gets a mask when its disabled. @@ -517,9 +555,13 @@ and a property `descEl` referencing the `div` Element which contains the descrip * since they want to implement custom disable logic. * @property maskOnDisable * @type {Boolean} - */ + */ maskOnDisable: true, + /** + * Creates new Component. + * @param {Object} config (optional) Config object. + */ constructor : function(config) { var me = this, i, len; @@ -675,7 +717,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip me.plugins[i] = me.constructPlugin(me.plugins[i]); } } - + me.initComponent(); // ititComponent gets a chance to change the id property before registering @@ -685,6 +727,9 @@ and a property `descEl` referencing the `div` Element which contains the descrip me.mixins.observable.constructor.call(me); me.mixins.state.constructor.call(me, config); + // Save state on resize. + this.addStateEvents('resize'); + // Move this into Observable? if (me.plugins) { me.plugins = [].concat(me.plugins); @@ -697,12 +742,15 @@ and a property `descEl` referencing the `div` Element which contains the descrip if (me.renderTo) { me.render(me.renderTo); + // EXTJSIV-1935 - should be a way to do afterShow or something, but that + // won't work. Likewise, rendering hidden and then showing (w/autoShow) has + // implications to afterRender so we cannot do that. } if (me.autoShow) { me.show(); } - + //<debug> if (Ext.isDefined(me.disabledClass)) { if (Ext.isDefined(Ext.global.console)) { @@ -716,6 +764,82 @@ and a property `descEl` referencing the `div` Element which contains the descrip initComponent: Ext.emptyFn, + /** + * </p>The supplied default state gathering method for the AbstractComponent class.</p> + * This method returns dimension setings such as <code>flex</code>, <code>anchor</code>, <code>width</code> + * and <code>height</code> along with <code>collapsed</code> state.</p> + * <p>Subclasses which implement more complex state should call the superclass's implementation, and apply their state + * to the result if this basic state is to be saved.</p> + * <p>Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider + * configured for the document.</p> + */ + getState: function() { + var me = this, + layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null, + state = { + collapsed: me.collapsed + }, + width = me.width, + height = me.height, + cm = me.collapseMemento, + anchors; + + // If a Panel-local collapse has taken place, use remembered values as the dimensions. + // TODO: remove this coupling with Panel's privates! All collapse/expand logic should be refactored into one place. + if (me.collapsed && cm) { + if (Ext.isDefined(cm.data.width)) { + width = cm.width; + } + if (Ext.isDefined(cm.data.height)) { + height = cm.height; + } + } + + // If we have flex, only store the perpendicular dimension. + if (layout && me.flex) { + state.flex = me.flex; + state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap](); + } + // If we have anchor, only store dimensions which are *not* being anchored + else if (layout && me.anchor) { + state.anchor = me.anchor; + anchors = me.anchor.split(' ').concat(null); + if (!anchors[0]) { + if (me.width) { + state.width = width; + } + } + if (!anchors[1]) { + if (me.height) { + state.height = height; + } + } + } + // Store dimensions. + else { + if (me.width) { + state.width = width; + } + if (me.height) { + state.height = height; + } + } + + // Don't save dimensions if they are unchanged from the original configuration. + if (state.width == me.initialConfig.width) { + delete state.width; + } + if (state.height == me.initialConfig.height) { + delete state.height; + } + + // If a Box layout was managing the perpendicular dimension, don't save that dimension + if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) { + delete state[layout.perpendicularPrefix]; + } + return state; + }, + show: Ext.emptyFn, animate: function(animObj) { @@ -803,7 +927,6 @@ and a property `descEl` referencing the `div` Element which contains the descrip return plugin; }, - // @private initPlugin : function(plugin) { plugin.init(this); @@ -881,7 +1004,6 @@ and a property `descEl` referencing the `div` Element which contains the descrip onRender : function(container, position) { var me = this, el = me.el, - cls = me.initCls(), styles = me.initStyles(), renderTpl, renderData, i; @@ -916,7 +1038,9 @@ and a property `descEl` referencing the `div` Element which contains the descrip } } - el.addCls(cls); + me.setUI(me.ui); + + el.addCls(me.initCls()); el.setStyle(styles); // Here we check if the component has a height set through style or css. @@ -931,14 +1055,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip // } me.el = el; - - me.rendered = true; - me.addUIToElement(true); - //loop through all exisiting uiCls and update the ui in them - for (i = 0; i < me.uiCls.length; i++) { - me.addUIClsToElement(me.uiCls[i], true); - } - me.rendered = false; + me.initFrame(); renderTpl = me.initRenderTpl(); @@ -948,10 +1065,8 @@ and a property `descEl` referencing the `div` Element which contains the descrip } me.applyRenderSelectors(); - + me.rendered = true; - - me.setUI(me.ui); }, // @private @@ -968,7 +1083,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip } // For floaters, calculate x and y if they aren't defined by aligning - // the sized element to the center of either the the container or the ownerCt + // the sized element to the center of either the container or the ownerCt if (me.floating && (me.x === undefined || me.y === undefined)) { if (me.floatParent) { xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c'); @@ -992,6 +1107,18 @@ and a property `descEl` referencing the `div` Element which contains the descrip frameCls: Ext.baseCSSPrefix + 'frame', + frameElementCls: { + tl: [], + tc: [], + tr: [], + ml: [], + mc: [], + mr: [], + bl: [], + bc: [], + br: [] + }, + frameTpl: [ '<tpl if="top">', '<tpl if="left"><div class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left: {frameWidth}px" role="presentation"></tpl>', @@ -1037,7 +1164,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip '</tpl>', '</tbody></table>' ], - + /** * @private */ @@ -1045,12 +1172,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip if (Ext.supports.CSS3BorderRadius) { return false; } - + var me = this, frameInfo = me.getFrameInfo(), frameWidth = frameInfo.width, frameTpl = me.getFrameTpl(frameInfo.table); - + if (me.frame) { // Here we render the frameTpl to this component. This inserts the 9point div or the table framing. frameTpl.insertFirst(me.el, Ext.apply({}, { @@ -1067,7 +1194,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip // The frameBody is returned in getTargetEl, so that layouts render items to the correct target.= me.frameBody = me.el.down('.' + me.frameCls + '-mc'); - + // Add the render selectors for each of the frame elements Ext.apply(me.renderSelectors, { frameTL: '.' + me.baseCls + '-tl', @@ -1082,12 +1209,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip }); } }, - + updateFrame: function() { if (Ext.supports.CSS3BorderRadius) { return false; } - + var me = this, wasTable = this.frameSize && this.frameSize.table, oldFrameTL = this.frameTL, @@ -1095,11 +1222,11 @@ and a property `descEl` referencing the `div` Element which contains the descrip oldFrameML = this.frameML, oldFrameMC = this.frameMC, newMCClassName; - + this.initFrame(); - + if (oldFrameMC) { - if (me.frame) { + if (me.frame) { // Reapply render selectors delete me.frameTL; delete me.frameTC; @@ -1109,26 +1236,26 @@ and a property `descEl` referencing the `div` Element which contains the descrip delete me.frameMR; delete me.frameBL; delete me.frameBC; - delete me.frameBR; + delete me.frameBR; this.applyRenderSelectors(); - + // Store the class names set on the new mc newMCClassName = this.frameMC.dom.className; - + // Replace the new mc with the old mc oldFrameMC.insertAfter(this.frameMC); this.frameMC.remove(); - + // Restore the reference to the old frame mc as the framebody this.frameBody = this.frameMC = oldFrameMC; - + // Apply the new mc classes to the old mc element oldFrameMC.dom.className = newMCClassName; - + // Remove the old framing if (wasTable) { me.el.query('> table')[1].remove(); - } + } else { if (oldFrameTL) { oldFrameTL.remove(); @@ -1141,19 +1268,19 @@ and a property `descEl` referencing the `div` Element which contains the descrip } else { // We were framed but not anymore. Move all content from the old frame to the body - + } } else if (me.frame) { this.applyRenderSelectors(); } }, - + getFrameInfo: function() { if (Ext.supports.CSS3BorderRadius) { return false; } - + var me = this, left = me.el.getStyle('background-position-x'), top = me.el.getStyle('background-position-y'), @@ -1166,33 +1293,33 @@ and a property `descEl` referencing the `div` Element which contains the descrip left = info[0]; top = info[1]; } - + // We actually pass a string in the form of '[type][tl][tr]px [type][br][bl]px' as // the background position of this.el from the css to indicate to IE that this component needs // framing. We parse it here and change the markup accordingly. if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) { max = Math.max; - + frameInfo = { // Table markup starts with 110, div markup with 100. table: left.substr(0, 3) == '110', - + // Determine if we are dealing with a horizontal or vertical component vertical: top.substr(0, 3) == '110', - + // Get and parse the different border radius sizes top: max(left.substr(3, 2), left.substr(5, 2)), right: max(left.substr(5, 2), top.substr(3, 2)), bottom: max(top.substr(3, 2), top.substr(5, 2)), left: max(top.substr(5, 2), left.substr(3, 2)) }; - + frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left); // Just to be sure we set the background image of the el to none. me.el.setStyle('background-image', 'none'); - } - + } + // This happens when you set frame: true explicitly without using the x-frame mixin in sass. // This way IE can't figure out what sizes to use and thus framing can't work. if (me.frame === true && !frameInfo) { @@ -1202,28 +1329,28 @@ and a property `descEl` referencing the `div` Element which contains the descrip "to use and thus framing on this component will be disabled."); //</debug> } - + me.frame = me.frame || !!frameInfo; me.frameSize = frameInfo || false; - + return frameInfo; }, - + getFramePositions: function(frameInfo) { var me = this, frameWidth = frameInfo.width, dock = me.dock, positions, tc, bc, ml, mr; - + if (frameInfo.vertical) { tc = '0 -' + (frameWidth * 0) + 'px'; bc = '0 -' + (frameWidth * 1) + 'px'; - + if (dock && dock == "right") { tc = 'right -' + (frameWidth * 0) + 'px'; bc = 'right -' + (frameWidth * 1) + 'px'; } - + positions = { tl: '0 -' + (frameWidth * 0) + 'px', tr: '0 -' + (frameWidth * 1) + 'px', @@ -1239,12 +1366,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip } else { ml = '-' + (frameWidth * 0) + 'px 0'; mr = 'right 0'; - + if (dock && dock == "bottom") { ml = 'left bottom'; mr = 'right bottom'; } - + positions = { tl: '0 -' + (frameWidth * 2) + 'px', tr: 'right -' + (frameWidth * 3) + 'px', @@ -1258,10 +1385,10 @@ and a property `descEl` referencing the `div` Element which contains the descrip bc: '0 -' + (frameWidth * 1) + 'px' }; } - + return positions; }, - + /** * @private */ @@ -1303,7 +1430,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip return cls.concat(me.additionalCls); }, - + /** * Sets the UI for the component. This will remove any existing UIs on the component. It will also * loop through any uiCls set on the component and rename them so they include the new UI @@ -1313,77 +1440,103 @@ and a property `descEl` referencing the `div` Element which contains the descrip var me = this, oldUICls = Ext.Array.clone(me.uiCls), newUICls = [], + classes = [], cls, i; - + //loop through all exisiting uiCls and update the ui in them for (i = 0; i < oldUICls.length; i++) { cls = oldUICls[i]; - - me.removeClsWithUI(cls); + + classes = classes.concat(me.removeClsWithUI(cls, true)); newUICls.push(cls); } - + + if (classes.length) { + me.removeCls(classes); + } + //remove the UI from the element me.removeUIFromElement(); - + //set the UI me.ui = ui; - + //add the new UI to the elemend me.addUIToElement(); - + //loop through all exisiting uiCls and update the ui in them + classes = []; for (i = 0; i < newUICls.length; i++) { cls = newUICls[i]; - - me.addClsWithUI(cls); + classes = classes.concat(me.addClsWithUI(cls, true)); + } + + if (classes.length) { + me.addCls(classes); } }, - + /** * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds * to all elements of this component. * @param {String/Array} cls A string or an array of strings to add to the uiCls + * @param (Boolean) skip True to skip adding it to the class and do it later (via the return) */ - addClsWithUI: function(cls) { + addClsWithUI: function(cls, skip) { var me = this, + classes = [], i; - + if (!Ext.isArray(cls)) { cls = [cls]; } - + for (i = 0; i < cls.length; i++) { if (cls[i] && !me.hasUICls(cls[i])) { me.uiCls = Ext.Array.clone(me.uiCls); me.uiCls.push(cls[i]); - me.addUIClsToElement(cls[i]); + + classes = classes.concat(me.addUIClsToElement(cls[i])); } } + + if (skip !== true) { + me.addCls(classes); + } + + return classes; }, - + /** - * Removes a cls to the uiCls array, which will also call {@link #removeUIClsToElement} and removes + * Removes a cls to the uiCls array, which will also call {@link #removeUIClsFromElement} and removes * it from all elements of this component. * @param {String/Array} cls A string or an array of strings to remove to the uiCls */ - removeClsWithUI: function(cls) { + removeClsWithUI: function(cls, skip) { var me = this, + classes = [], i; - + if (!Ext.isArray(cls)) { cls = [cls]; } - + for (i = 0; i < cls.length; i++) { if (cls[i] && me.hasUICls(cls[i])) { me.uiCls = Ext.Array.remove(me.uiCls, cls[i]); - me.removeUIClsFromElement(cls[i]); + + classes = classes.concat(me.removeUIClsFromElement(cls[i])); } } + + if (skip !== true) { + me.removeCls(classes); + } + + return classes; }, - + /** * Checks if there is currently a specified uiCls * @param {String} cls The cls to check @@ -1391,117 +1544,144 @@ and a property `descEl` referencing the `div` Element which contains the descrip hasUICls: function(cls) { var me = this, uiCls = me.uiCls || []; - + return Ext.Array.contains(uiCls, cls); }, - + /** * Method which adds a specified UI + uiCls to the components element. * Can be overridden to remove the UI from more than just the components element. * @param {String} ui The UI to remove from the element - * @private */ addUIClsToElement: function(cls, force) { - var me = this; + var me = this, + result = [], + frameElementCls = me.frameElementCls; - me.addCls(Ext.baseCSSPrefix + cls); - me.addCls(me.baseCls + '-' + cls); - me.addCls(me.baseCls + '-' + me.ui + '-' + cls); + result.push(Ext.baseCSSPrefix + cls); + result.push(me.baseCls + '-' + cls); + result.push(me.baseCls + '-' + me.ui + '-' + cls); - if (!force && me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { + if (!force && me.frame && !Ext.supports.CSS3BorderRadius) { // define each element of the frame var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'], - i, el; - + classes, i, j, el; + // loop through each of them, and if they are defined add the ui for (i = 0; i < els.length; i++) { el = me['frame' + els[i].toUpperCase()]; - + classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]]; if (el && el.dom) { - el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]); - el.addCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]); + el.addCls(classes); + } else { + for (j = 0; j < classes.length; j++) { + if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) { + frameElementCls[els[i]].push(classes[j]); + } + } } } } + + me.frameElementCls = frameElementCls; + + return result; }, - + /** * Method which removes a specified UI + uiCls from the components element. * The cls which is added to the element will be: `this.baseCls + '-' + ui` * @param {String} ui The UI to add to the element - * @private */ removeUIClsFromElement: function(cls, force) { - var me = this; + var me = this, + result = [], + frameElementCls = me.frameElementCls; - me.removeCls(Ext.baseCSSPrefix + cls); - me.removeCls(me.baseCls + '-' + cls); - me.removeCls(me.baseCls + '-' + me.ui + '-' + cls); + result.push(Ext.baseCSSPrefix + cls); + result.push(me.baseCls + '-' + cls); + result.push(me.baseCls + '-' + me.ui + '-' + cls); - if (!force &&me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { + if (!force && me.frame && !Ext.supports.CSS3BorderRadius) { // define each element of the frame var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'], i, el; - + cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]; // loop through each of them, and if they are defined add the ui for (i = 0; i < els.length; i++) { el = me['frame' + els[i].toUpperCase()]; if (el && el.dom) { - el.removeCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]); + el.removeCls(cls); + } else { + Ext.Array.remove(frameElementCls[els[i]], cls); } } } + + me.frameElementCls = frameElementCls; + + return result; }, - + /** * Method which adds a specified UI to the components element. * @private */ addUIToElement: function(force) { - var me = this; + var me = this, + frameElementCls = me.frameElementCls; me.addCls(me.baseCls + '-' + me.ui); - if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { + if (me.frame && !Ext.supports.CSS3BorderRadius) { // define each element of the frame var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'], - i, el; + i, el, cls; // loop through each of them, and if they are defined add the ui for (i = 0; i < els.length; i++) { el = me['frame' + els[i].toUpperCase()]; - + cls = me.baseCls + '-' + me.ui + '-' + els[i]; if (el) { - el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]); + el.addCls(cls); + } else { + if (!Ext.Array.contains(frameElementCls[els[i]], cls)) { + frameElementCls[els[i]].push(cls); + } } } } }, - + /** * Method which removes a specified UI from the components element. * @private */ removeUIFromElement: function() { - var me = this; + var me = this, + frameElementCls = me.frameElementCls; me.removeCls(me.baseCls + '-' + me.ui); - if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { + if (me.frame && !Ext.supports.CSS3BorderRadius) { // define each element of the frame var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'], - i, el; - + i, j, el, cls; + // loop through each of them, and if they are defined add the ui for (i = 0; i < els.length; i++) { el = me['frame' + els[i].toUpperCase()]; + cls = me.baseCls + '-' + me.ui + '-' + els[i]; + if (el) { - el.removeCls(me.baseCls + '-' + me.ui + '-' + els[i]); + el.removeCls(cls); + } else { + Ext.Array.remove(frameElementCls[els[i]], cls); } } } }, - + getElConfig : function() { var result = this.autoEl || {tag: 'div'}; result.id = this.id; @@ -1575,15 +1755,18 @@ and a property `descEl` referencing the `div` Element which contains the descrip * @private */ getTpl: function(name) { - var prototype = this.self.prototype, - ownerPrototype; - - if (this.hasOwnProperty(name)) { - if (!(this[name] instanceof Ext.XTemplate)) { - this[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', this[name]); + var me = this, + prototype = me.self.prototype, + ownerPrototype, + tpl; + + if (me.hasOwnProperty(name)) { + tpl = me[name]; + if (tpl && !(tpl instanceof Ext.XTemplate)) { + me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl); } - return this[name]; + return me[name]; } if (!(prototype[name] instanceof Ext.XTemplate)) { @@ -1591,8 +1774,11 @@ and a property `descEl` referencing the `div` Element which contains the descrip do { if (ownerPrototype.hasOwnProperty(name)) { - ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', ownerPrototype[name]); - break; + tpl = ownerPrototype[name]; + if (tpl && !(tpl instanceof Ext.XTemplate)) { + ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl); + break; + } } ownerPrototype = ownerPrototype.superclass; @@ -1681,13 +1867,17 @@ and a property `descEl` referencing the `div` Element which contains the descrip initEvents : function() { var me = this, afterRenderEvents = me.afterRenderEvents, - property, listeners; + el, + property, + fn = function(listeners){ + me.mon(el, listeners); + }; if (afterRenderEvents) { for (property in afterRenderEvents) { if (afterRenderEvents.hasOwnProperty(property)) { - listeners = afterRenderEvents[property]; - if (me[property] && me[property].on) { - me.mon(me[property], listeners); + el = me[property]; + if (el && el.on) { + Ext.each(afterRenderEvents[property], fn); } } } @@ -1839,7 +2029,7 @@ var owningTabPanel = grid.up('tabpanel'); /** * <p>Returns the next node in the Component tree in tree traversal order.</p> * <p>Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will - * walk the tree to attempt to find a match. Contrast with {@link #pnextSibling}.</p> + * walk the tree to attempt to find a match. Contrast with {@link #nextSibling}.</p> * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes. * @returns The next node (or the next node which matches the selector). Returns null if there is no matching node. */ @@ -2091,12 +2281,12 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' return me; }, - + // @private onEnable: function() { if (this.maskOnDisable) { this.el.unmask(); - } + } }, // @private @@ -2105,7 +2295,7 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' this.el.mask(); } }, - + /** * Method to determine whether this Component is currently disabled. * @return {Boolean} the disabled state of this Component. @@ -2153,7 +2343,7 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' }, /** - * @deprecated 4.0 Replaced by {link:#addCls} + * @deprecated 4.0 Replaced by {@link #addCls} * Adds a CSS class to the top level element representing this component. * @param {String} cls The CSS class name to add * @return {Ext.Component} Returns the Component to allow method chaining. @@ -2237,14 +2427,35 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' me.mon(me[element], listeners); } else { me.afterRenderEvents = me.afterRenderEvents || {}; - me.afterRenderEvents[element] = listeners; + if (!me.afterRenderEvents[element]) { + me.afterRenderEvents[element] = []; + } + me.afterRenderEvents[element].push(listeners); } } return me.mixins.observable.addListener.apply(me, arguments); }, - // @TODO: implement removelistener to support the dom event stuff + // inherit docs + removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){ + var me = this, + element = managedListener.options ? managedListener.options.element : null; + + if (element) { + element = me[element]; + if (element && element.un) { + if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) { + element.un(managedListener.ename, managedListener.fn, managedListener.scope); + if (!isClear) { + Ext.Array.remove(me.managedListeners, managedListener); + } + } + } + } else { + return me.mixins.observable.removeManagedListenerItem.apply(me, arguments); + } + }, /** * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy. @@ -2368,13 +2579,39 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' return me; }, - setCalculatedSize : function(width, height, ownerCt) { + isFixedWidth: function() { + var me = this, + layoutManagedWidth = me.layoutManagedWidth; + + if (Ext.isDefined(me.width) || layoutManagedWidth == 1) { + return true; + } + if (layoutManagedWidth == 2) { + return false; + } + return (me.ownerCt && me.ownerCt.isFixedWidth()); + }, + + isFixedHeight: function() { + var me = this, + layoutManagedHeight = me.layoutManagedHeight; + + if (Ext.isDefined(me.height) || layoutManagedHeight == 1) { + return true; + } + if (layoutManagedHeight == 2) { + return false; + } + return (me.ownerCt && me.ownerCt.isFixedHeight()); + }, + + setCalculatedSize : function(width, height, callingContainer) { var me = this, layoutCollection; // support for standard size objects if (Ext.isObject(width)) { - ownerCt = width.ownerCt; + callingContainer = width.ownerCt; height = width.height; width = width.width; } @@ -2398,11 +2635,11 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' width: width, height: height, isSetSize: false, - ownerCt: ownerCt + ownerCt: callingContainer }; return me; } - me.doComponentLayout(width, height, false, ownerCt); + me.doComponentLayout(width, height, false, callingContainer); return me; }, @@ -2412,26 +2649,51 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' * layout to be recalculated. * @return {Ext.container.Container} this */ - doComponentLayout : function(width, height, isSetSize, ownerCt) { + doComponentLayout : function(width, height, isSetSize, callingContainer) { var me = this, - componentLayout = me.getComponentLayout(); + componentLayout = me.getComponentLayout(), + lastComponentSize = componentLayout.lastComponentSize || { + width: undefined, + height: undefined + }; // collapsed state is not relevant here, so no testing done. // Only Panels have a collapse method, and that just sets the width/height such that only // a single docked Header parallel to the collapseTo side are visible, and the Panel body is hidden. if (me.rendered && componentLayout) { - width = (width !== undefined) ? width : me.width; - height = (height !== undefined) ? height : me.height; + + + // If no width passed, then only insert a value if the Component is NOT ALLOWED to autowidth itself. + if (!Ext.isDefined(width)) { + if (me.isFixedWidth()) { + width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width; + } + } + + // If no height passed, then only insert a value if the Component is NOT ALLOWED to autoheight itself. + if (!Ext.isDefined(height)) { + if (me.isFixedHeight()) { + height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height; + } + } + if (isSetSize) { me.width = width; me.height = height; } - componentLayout.layout(width, height, isSetSize, ownerCt); + componentLayout.layout(width, height, isSetSize, callingContainer); } return me; }, + /** + * Forces this component to redo its componentLayout. + */ + forceComponentLayout: function () { + this.doComponentLayout(); + }, + // @private setComponentLayout : function(layout) { var currentLayout = this.componentLayout; @@ -2455,9 +2717,9 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' * @param {Number} adjWidth The box-adjusted width that was set * @param {Number} adjHeight The box-adjusted height that was set * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently - * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false. + * @param {Ext.Component} callingContainer Container requesting the layout. Only used when isSetSize is false. */ - afterComponentLayout: function(width, height, isSetSize, layoutOwner) { + afterComponentLayout: function(width, height, isSetSize, callingContainer) { this.fireEvent('resize', this, width, height); }, @@ -2467,14 +2729,15 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' * @param {Number} adjWidth The box-adjusted width that was set * @param {Number} adjHeight The box-adjusted height that was set * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently - * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false. + * @param {Ext.Component} callingContainer Container requesting sent the layout. Only used when isSetSize is false. */ - beforeComponentLayout: function(width, height, isSetSize, layoutOwner) { + beforeComponentLayout: function(width, height, isSetSize, callingContainer) { return true; }, /** - * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}. + * Sets the left and top of the component. To set the page XY position instead, use + * {@link Ext.Component#setPagePosition setPagePosition}. * This method fires the {@link #move} event. * @param {Number} left The new left * @param {Number} top The new top @@ -2664,15 +2927,15 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' me.ownerCt.remove(me, false); } - if (me.rendered) { - me.el.remove(); - } - me.onDestroy(); // Attempt to destroy all plugins Ext.destroy(me.plugins); + if (me.rendered) { + me.el.remove(); + } + Ext.ComponentManager.unregister(me); me.fireEvent('destroy', me); @@ -2700,7 +2963,7 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' } } }, - + /** * Determines whether this component is the descendant of a particular container. * @param {Ext.Container} container @@ -2718,4 +2981,6 @@ alert(t.getXTypes()); // alerts 'component/field/textfield' next: 'nextSibling' }); }); -