/*!
- * Ext JS Library 3.1.0
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.1.1
+ * Copyright(c) 2006-2010 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
*/
all : all,
+ /**
+ * The xtypes that have been registered with the component manager.
+ * @type {Object}
+ */
+ types : types,
+
+ /**
+ * The ptypes that have been registered with the component manager.
+ * @type {Object}
+ */
+ ptypes: ptypes,
+
/**
* Checks if a Component type is registered.
* @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
isRegistered : function(xtype){
return types[xtype] !== undefined;
},
+
+ /**
+ * Checks if a Plugin type is registered.
+ * @param {Ext.Component} ptype The mnemonic string by which the Plugin class may be looked up
+ * @return {Boolean} Whether the type is registered.
+ */
+ isPluginRegistered : function(ptype){
+ return ptypes[ptype] !== undefined;
+ },
/**
* <p>Registers a new Component constructor, keyed by a new
</code></pre>
*/
- // Configs below are used for all Components when rendered by AnchorLayout.
- /**
- * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
- * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
- * based layout manager, for example:<div class="mdetail-params"><ul>
- * <li>{@link Ext.form.FormPanel}</li>
- * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
- * </ul></div></p>
- * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
- */
-
/**
* @cfg {String} id
* <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
* @cfg {Mixed} tpl
* An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
* or an array of strings to form an Ext.XTemplate.
- * Used in conjunction with the <code>{@link #data}</code> and
+ * Used in conjunction with the <code>{@link #data}</code> and
* <code>{@link #tplWriteMode}</code> configurations.
*/
*/
if(this.ref && !this.refOwner){
var levels = this.ref.split('/'),
- last = levels.length,
+ last = levels.length,
i = 0,
t = this;
-
+
while(t && i < last){
t = t.ownerCt;
++i;
// private
getStateId : function(){
- return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
+ return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
},
// private
*/
Ext.BoxComponent = Ext.extend(Ext.Component, {
+ // Configs below are used for all Components when rendered by BoxLayout.
+ /**
+ * @cfg {Number} flex
+ * <p><b>Note</b>: this config is only used when this Component is rendered
+ * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
+ * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
+ * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
+ * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
+ * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
+ */
+ // Configs below are used for all Components when rendered by AnchorLayout.
+ /**
+ * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
+ * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
+ * based layout manager, for example:<div class="mdetail-params"><ul>
+ * <li>{@link Ext.form.FormPanel}</li>
+ * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
+ * </ul></div></p>
+ * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
+ */
// tabTip config is used when a BoxComponent is a child of a TabPanel
/**
* @cfg {String} tabTip
rz.setWidth(aw);
}
this.onResize(aw, ah, w, h);
+ this.fireEvent('resize', this, aw, ah, w, h);
}
return this;
},
this.positionEl = Ext.get(this.positionEl);
}
this.boxReady = true;
- this.setAutoScroll(this.autoScroll);
+ Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
this.setSize(this.width, this.height);
if(this.x || this.y){
this.setPosition(this.x, this.y);
* @param {Number} rawHeight The height that was originally specified
*/
onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
- this.fireEvent('resize', this, adjWidth, adjHeight, rawWidth, rawHeight);
},
/* // protected
* the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
* with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
*/
+ // Deprecated - will be removed in 3.2.x
bufferResize: 50,
/**
},
afterRender: function(){
- this.layoutDone = false;
+ // Render this Container, this should be done before setLayout is called which
+ // will hook onResize
+ Ext.Container.superclass.afterRender.call(this);
if(!this.layout){
this.layout = 'auto';
}
}
this.setLayout(this.layout);
- // BoxComponent's afterRender will set the size.
- // This will will trigger a layout if the layout is configured to monitor resize
- Ext.Container.superclass.afterRender.call(this);
-
- if(Ext.isDefined(this.activeItem)){
+ // If a CardLayout, the active item set
+ if(this.activeItem !== undefined){
var item = this.activeItem;
delete this.activeItem;
this.layout.setActiveItem(item);
}
- // If we have no ownerCt and the BoxComponent's sizing did not trigger a layout, force a layout
- if(!this.ownerCt && !this.layoutDone){
+ // If we have no ownerCt, render and size all children
+ if(!this.ownerCt){
this.doLayout(false, true);
}
+ // This is a manually configured flag set by users in conjunction with renderTo.
+ // Not to be confused with the flag by the same name used in Layouts.
if(this.monitorResize === true){
Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
}
onAdd : function(c){
// Empty template method
},
-
+
// private
onAdded : function(container, pos) {
//overridden here so we can cascade down, not worth creating a template method.
// private
doRemove: function(c, autoDestroy){
- if(this.layout && this.rendered){
- this.layout.onRemove(c);
+ var l = this.layout,
+ hasLayout = l && this.rendered;
+
+ if(hasLayout){
+ l.onRemove(c);
}
this.items.remove(c);
c.onRemoved();
if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
c.destroy();
}
+ if(hasLayout){
+ l.afterRemove(c);
+ }
},
/**
* We can only lay out if there is a view area in which to layout.
* display:none on the layout target, *or any of its parent elements* will mean it has no view area.
*/
- canLayout: function() {
- var el = this.getLayoutTarget(), vs;
- return !!(el && (vs = el.dom.offsetWidth || el.dom.offsetHeight));
+
+ // private
+ canLayout : function() {
+ var el = this.getVisibilityEl();
+ return el && el.dom && !el.isStyle("display", "none");
},
/**
* @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
* @return {Ext.Container} this
*/
- doLayout: function(shallow, force){
+
+ doLayout : function(shallow, force){
var rendered = this.rendered,
- forceLayout = force || this.forceLayout,
- cs, i, len, c;
+ forceLayout = force || this.forceLayout;
- this.layoutDone = true;
- if(!this.canLayout() || this.collapsed){
+ if(this.collapsed || !this.canLayout()){
this.deferLayout = this.deferLayout || !shallow;
if(!forceLayout){
return;
} else {
delete this.deferLayout;
}
-
- cs = (shallow !== true && this.items) ? this.items.items : [];
-
-// Inhibit child Containers from relaying on resize since we are about to to explicitly call doLayout on them all!
- for(i = 0, len = cs.length; i < len; i++){
- if ((c = cs[i]).layout) {
- c.suspendLayoutResize = true;
- }
- }
-
-// Tell the layout manager to ensure all child items are rendered, and sized according to their rules.
-// Will not cause the child items to relayout.
if(rendered && this.layout){
this.layout.layout();
}
-
-// Explicitly lay out all child items
- for(i = 0; i < len; i++){
- if((c = cs[i]).doLayout){
- c.doLayout(false, forceLayout);
+ if(shallow !== true && this.items){
+ var cs = this.items.items;
+ for(var i = 0, len = cs.length; i < len; i++){
+ var c = cs[i];
+ if(c.doLayout){
+ c.doLayout(false, forceLayout);
+ }
}
}
if(rendered){
// Initial layout completed
this.hasLayout = true;
delete this.forceLayout;
-
-// Re-enable child layouts relaying on resize.
- for(i = 0; i < len; i++){
- if ((c = cs[i]).layout) {
- delete c.suspendLayoutResize;
- }
- }
},
- //private
onLayout : Ext.emptyFn,
- onResize: function(adjWidth, adjHeight, rawWidth, rawHeight){
- Ext.Container.superclass.onResize.apply(this, arguments);
- if ((this.rendered && this.layout && this.layout.monitorResize) && !this.suspendLayoutResize) {
- this.layout.onResize();
+ // private
+ shouldBufferLayout: function(){
+ /*
+ * Returns true if the container should buffer a layout.
+ * This is true only if the container has previously been laid out
+ * and has a parent container that is pending a layout.
+ */
+ var hl = this.hasLayout;
+ if(this.ownerCt){
+ // Only ever buffer if we've laid out the first time and we have one pending.
+ return hl ? !this.hasLayoutPending() : false;
}
+ // Never buffer initial layout
+ return hl;
},
// private
hasLayoutPending: function(){
// Traverse hierarchy to see if any parent container has a pending layout.
- var pending = this.layoutPending;
+ var pending = false;
this.ownerCt.bubble(function(c){
- return !(pending = c.layoutPending);
+ if(c.layoutPending){
+ pending = true;
+ return false;
+ }
});
return pending;
-
},
onShow : function(){
+ // removes css classes that were added to hide
Ext.Container.superclass.onShow.call(this);
+ // If we were sized during the time we were hidden, layout.
if(Ext.isDefined(this.deferLayout)){
+ delete this.deferLayout;
this.doLayout(true);
}
},
Ext.reg('container', Ext.Container);
/**
* @class Ext.layout.ContainerLayout
- * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
- * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
- * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
- * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
- * positioning services. To utilize a layout that provides sizing and positioning of child Components,
- * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
* <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
* configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
*/
activeItem : null,
constructor : function(config){
+ this.id = Ext.id(null, 'ext-layout-');
Ext.apply(this, config);
},
+ type: 'container',
+
+ /* Workaround for how IE measures autoWidth elements. It prefers bottom-up measurements
+ whereas other browser prefer top-down. We will hide all target child elements before we measure and
+ put them back to get an accurate measurement.
+ */
+ IEMeasureHack : function(target, viewFlag) {
+ var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
+ for (i = 0 ; i < tLen ; i++) {
+ c = tChildren[i];
+ e = Ext.get(c);
+ if (e) {
+ d[i] = e.getStyle('display');
+ e.setStyle({display: 'none'});
+ }
+ }
+ ret = target ? target.getViewSize(viewFlag) : {};
+ for (i = 0 ; i < tLen ; i++) {
+ c = tChildren[i];
+ e = Ext.get(c);
+ if (e) {
+ e.setStyle({display: d[i]});
+ }
+ }
+ return ret;
+ },
+
+ // Placeholder for the derived layouts
+ getLayoutTargetSize : Ext.EmptyFn,
+
// private
layout : function(){
- var target = this.container.getLayoutTarget();
+ var ct = this.container, target = ct.getLayoutTarget();
if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
- target.addClass(this.targetCls)
+ target.addClass(this.targetCls);
}
- this.onLayout(this.container, target);
- this.container.fireEvent('afterlayout', this.container, this);
- this.hasLayout = true;
+ this.onLayout(ct, target);
+ ct.fireEvent('afterlayout', ct, this);
},
// private
// private
renderAll : function(ct, target){
- var items = ct.items.items;
- for(var i = 0, len = items.length; i < len; i++) {
- var c = items[i];
+ var items = ct.items.items, i, c, len = items.length;
+ for(i = 0; i < len; i++) {
+ c = items[i];
if(c && (!c.rendered || !this.isValidParent(c, target))){
this.renderItem(c, i, target);
}
// private
renderItem : function(c, position, target){
- if(c && !c.rendered){
- c.render(target, position);
- this.configureItem(c, position);
- }else if(c && !this.isValidParent(c, target)){
- if(Ext.isNumber(position)){
- position = target.dom.childNodes[position];
+ if(c){
+ if(!c.rendered){
+ c.render(target, position);
+ this.configureItem(c, position);
+ }else if(!this.isValidParent(c, target)){
+ if(Ext.isNumber(position)){
+ position = target.dom.childNodes[position];
+ }
+ target.dom.insertBefore(c.getPositionEl().dom, position || null);
+ c.container = target;
+ this.configureItem(c, position);
}
- target.dom.insertBefore(c.getPositionEl().dom, position || null);
- c.container = target;
- this.configureItem(c, position);
}
},
+ // private.
+ // Get all rendered items to lay out.
+ getRenderedItems: function(ct){
+ var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
+ for (i = 0; i < len; i++) {
+ if((c = cti[i]).rendered && this.isValidParent(c, t)){
+ items.push(c);
+ }
+ };
+ return items;
+ },
+
// private
configureItem: function(c, position){
if(this.extraCls){
}
// If we are forcing a layout, do so *before* we hide so elements have height/width
if(c.doLayout && this.forceLayout){
- c.doLayout(false, true);
+ c.doLayout();
}
if (this.renderHidden && c != this.activeItem) {
c.hide();
}
},
+ afterRemove: function(c){
+ if(c.removeRestore){
+ c.removeMode = 'container';
+ delete c.removeRestore;
+ }
+ },
+
// private
onResize: function(){
var ct = this.container,
- b = ct.bufferResize;
-
- if (ct.collapsed){
+ b;
+ if(ct.collapsed){
return;
}
-
- // Not having an ownerCt negates the buffering: floating and top level
- // Containers (Viewport, Window, ToolTip, Menu) need to lay out ASAP.
- if (b && ct.ownerCt) {
- // If we do NOT already have a layout pending from an ancestor, schedule one.
- // If there is a layout pending, we do nothing here.
- // buffering to be deprecated soon
- if (!ct.hasLayoutPending()){
+ if(b = ct.bufferResize){
+ // Only allow if we should buffer the layout
+ if(ct.shouldBufferLayout()){
if(!this.resizeTask){
this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
this.resizeBuffer = Ext.isNumber(b) ? b : 50;
this.resizeTask.delay(this.resizeBuffer);
}
}else{
- ct.doLayout(false, this.forceLayout);
+ this.runLayout();
}
},
- // private
runLayout: function(){
var ct = this.container;
+ // AutoLayout is known to require the recursive doLayout call, others need this currently (BorderLayout for example)
+ // but shouldn't. A more extensive review will take place for 3.2 which requires a ContainerMgr with hierarchy lookups.
+ //this.layout();
+ //ct.onLayout();
ct.doLayout();
delete ct.layoutPending;
},
// private
setContainer : function(ct){
- // No longer use events to handle resize. Instead this will be handled through a direct function call.
- /*
+ if (!Ext.LayoutManager) {
+ Ext.LayoutManager = {};
+ }
+
+ /* This monitorResize flag will be renamed soon as to avoid confusion
+ * with the Container version which hooks onWindowResize to doLayout
+ *
+ * monitorResize flag in this context attaches the resize event between
+ * a container and it's layout
+ */
+
if(this.monitorResize && ct != this.container){
var old = this.container;
if(old){
ct.on(ct.resizeEvent, this.onResize, this);
}
}
- */
this.container = ct;
},
var ms = v.split(' ');
var len = ms.length;
if(len == 1){
- ms[1] = ms[0];
- ms[2] = ms[0];
- ms[3] = ms[0];
- }
- if(len == 2){
+ ms[1] = ms[2] = ms[3] = ms[0];
+ } else if(len == 2){
ms[2] = ms[0];
ms[3] = ms[1];
- }
- if(len == 3){
+ } else if(len == 3){
ms[3] = ms[1];
}
return {
}
}
}
+});/**
+ * @class Ext.layout.AutoLayout
+ * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
+ * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
+ * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
+ * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
+ * positioning services. To utilize a layout that provides sizing and positioning of child Components,
+ * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
+ */
+Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ runLayout: function(){
+ var ct = this.container;
+ ct.doLayout();
+ delete ct.layoutPending;
+ }
});
-Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
+
+Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
/**\r
* @class Ext.layout.FitLayout\r
* @extends Ext.layout.ContainerLayout\r
// private\r
monitorResize:true,\r
\r
+ type: 'fit',\r
+\r
+ getLayoutTargetSize : function() {\r
+ var target = this.container.getLayoutTarget();\r
+ if (!target) {\r
+ return {};\r
+ }\r
+ // Style Sized (scrollbars not included)\r
+ return target.getStyleSize();\r
+ },\r
+\r
// private\r
onLayout : function(ct, target){\r
Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
- if(!this.container.collapsed){\r
- this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize(true));\r
+ if(!ct.collapsed){\r
+ this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());\r
}\r
},\r
\r
* true might improve performance.\r
*/\r
deferredRender : false,\r
- \r
+\r
/**\r
* @cfg {Boolean} layoutOnCardChange\r
* True to force a layout of the active item when the active card is changed. Defaults to false.\r
*/\r
// private\r
renderHidden : true,\r
- \r
+\r
+ type: 'card',\r
+\r
constructor: function(config){\r
Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
- // this.forceLayout = (this.deferredRender === false);\r
},\r
\r
/**\r
* @param {String/Number} item The string component id or numeric index of the item to activate\r
*/\r
setActiveItem : function(item){\r
- var ai = this.activeItem;\r
- item = this.container.getComponent(item);\r
- if(ai != item){\r
+ var ai = this.activeItem,\r
+ ct = this.container;\r
+ item = ct.getComponent(item);\r
+\r
+ // Is this a valid, different card?\r
+ if(item && ai != item){\r
+\r
+ // Changing cards, hide the current one\r
if(ai){\r
ai.hide();\r
+ if (ai.hidden !== true) {\r
+ return false;\r
+ }\r
ai.fireEvent('deactivate', ai);\r
}\r
- var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);\r
+ // Change activeItem reference\r
this.activeItem = item;\r
- if(item){\r
- item.show();\r
- }\r
+\r
+ // The container is about to get a recursive layout, remove any deferLayout reference\r
+ // because it will trigger a redundant layout.\r
+ delete item.deferLayout;\r
+\r
+ // Show the new component\r
+ item.show();\r
+\r
this.layout();\r
- if(item && layout){\r
+\r
+ if(item.doLayout){\r
item.doLayout();\r
}\r
item.fireEvent('activate', item);\r
// private
monitorResize:true,
+ type: 'anchor',
- // private
- // deprecate
- getAnchorViewSize : function(ct, target){
- return target.dom == document.body ?
- target.getViewSize(true) : target.getStyleSize();
+ getLayoutTargetSize : function() {
+ var target = this.container.getLayoutTarget();
+ if (!target) {
+ return {};
+ }
+ // Style Sized (scrollbars not included)
+ return target.getStyleSize();
},
// private
onLayout : function(ct, target){
Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
-
- var size = target.getViewSize(true);
+ var size = this.getLayoutTargetSize();
var w = size.width, h = size.height;
ah = ct.initialConfig.height;
}
- var cs = ct.items.items, len = cs.length, i, c, a, cw, ch, el, vs;
+ var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs;
for(i = 0; i < len; i++){
c = cs[i];
el = c.getPositionEl();
// private\r
monitorResize:true,\r
\r
+ type: 'column',\r
+\r
extraCls: 'x-column',\r
\r
scrollOffset : 0,\r
targetCls: 'x-column-layout-ct',\r
\r
isValidParent : function(c, target){\r
- return c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
+ return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
},\r
\r
- // private\r
- onLayout : function(ct, target){\r
- var cs = ct.items.items, len = cs.length, c, i;\r
+ getLayoutTargetSize : function() {\r
+ var target = this.container.getLayoutTarget(), ret;\r
+ if (target) {\r
+ ret = target.getViewSize();\r
+ ret.width -= target.getPadding('lr');\r
+ ret.height -= target.getPadding('tb');\r
+ }\r
+ return ret;\r
+ },\r
\r
+ renderAll : function(ct, target) {\r
if(!this.innerCt){\r
// the innerCt prevents wrapping and shuffling while\r
// the container is resizing\r
this.innerCt = target.createChild({cls:'x-column-inner'});\r
this.innerCt.createChild({cls:'x-clear'});\r
}\r
- this.renderAll(ct, this.innerCt);\r
+ Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);\r
+ },\r
+\r
+ // private\r
+ onLayout : function(ct, target){\r
+ var cs = ct.items.items, len = cs.length, c, i;\r
+\r
+ this.renderAll(ct, target);\r
\r
- var size = target.getViewSize(true);\r
+ var size = this.getLayoutTargetSize();\r
\r
if(size.width < 1 && size.height < 1){ // display none?\r
return;\r
for(i = 0; i < len; i++){\r
c = cs[i];\r
if(!c.columnWidth){\r
- pw -= (c.getSize().width + c.getPositionEl().getMargins('lr'));\r
+ pw -= (c.getWidth() + c.getPositionEl().getMargins('lr'));\r
}\r
}\r
\r
c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));\r
}\r
}\r
+\r
+ // Browsers differ as to when they account for scrollbars. We need to re-measure to see if the scrollbar\r
+ // spaces were accounted for properly. If not, re-layout.\r
+ if (Ext.isIE) {\r
+ if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {\r
+ var ts = this.getLayoutTargetSize();\r
+ if (ts.width != size.width){\r
+ this.adjustmentPass = true;\r
+ this.onLayout(ct, target);\r
+ }\r
+ }\r
+ }\r
+ delete this.adjustmentPass;\r
}\r
\r
/**\r
// private
rendered : false,
+ type: 'border',
+
targetCls: 'x-border-layout-ct',
+ getLayoutTargetSize : function() {
+ var target = this.container.getLayoutTarget();
+ return target ? target.getViewSize() : {};
+ },
+
// private
onLayout : function(ct, target){
- var collapsed;
+ var collapsed, i, c, pos, items = ct.items.items, len = items.length;
if(!this.rendered){
- var items = ct.items.items;
collapsed = [];
- for(var i = 0, len = items.length; i < len; i++) {
- var c = items[i];
- var pos = c.region;
+ for(i = 0; i < len; i++) {
+ c = items[i];
+ pos = c.region;
if(c.collapsed){
collapsed.push(c);
}
this.rendered = true;
}
- var size = target.getViewSize(false);
+ var size = this.getLayoutTargetSize();
if(size.width < 20 || size.height < 20){ // display none?
if(collapsed){
this.restoreCollapsed = collapsed;
delete this.restoreCollapsed;
}
- var w = size.width, h = size.height;
- var centerW = w, centerH = h, centerY = 0, centerX = 0;
-
- var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
+ var w = size.width, h = size.height,
+ centerW = w, centerH = h, centerY = 0, centerX = 0,
+ n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
+ b, m, totalWidth, totalHeight;
if(!c && Ext.layout.BorderLayout.WARN !== false){
throw 'No center region defined in BorderLayout ' + ct.id;
}
if(n && n.isVisible()){
- var b = n.getSize();
- var m = n.getMargins();
+ b = n.getSize();
+ m = n.getMargins();
b.width = w - (m.left+m.right);
b.x = m.left;
b.y = m.top;
n.applyLayout(b);
}
if(s && s.isVisible()){
- var b = s.getSize();
- var m = s.getMargins();
+ b = s.getSize();
+ m = s.getMargins();
b.width = w - (m.left+m.right);
b.x = m.left;
- var totalHeight = (b.height + m.top + m.bottom);
+ totalHeight = (b.height + m.top + m.bottom);
b.y = h - totalHeight + m.top;
centerH -= totalHeight;
s.applyLayout(b);
}
if(west && west.isVisible()){
- var b = west.getSize();
- var m = west.getMargins();
+ b = west.getSize();
+ m = west.getMargins();
b.height = centerH - (m.top+m.bottom);
b.x = m.left;
b.y = centerY + m.top;
- var totalWidth = (b.width + m.left + m.right);
+ totalWidth = (b.width + m.left + m.right);
centerX += totalWidth;
centerW -= totalWidth;
west.applyLayout(b);
}
if(e && e.isVisible()){
- var b = e.getSize();
- var m = e.getMargins();
+ b = e.getSize();
+ m = e.getMargins();
b.height = centerH - (m.top+m.bottom);
- var totalWidth = (b.width + m.left + m.right);
+ totalWidth = (b.width + m.left + m.right);
b.x = w - totalWidth + m.left;
b.y = centerY + m.top;
centerW -= totalWidth;
e.applyLayout(b);
}
if(c){
- var m = c.getMargins();
+ m = c.getMargins();
var centerBox = {
x: centerX + m.left,
y: centerY + m.top,
c.applyLayout(centerBox);
}
if(collapsed){
- for(var i = 0, len = collapsed.length; i < len; i++){
+ for(i = 0, len = collapsed.length; i < len; i++){
collapsed[i].collapse(false);
}
}
if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
target.repaint();
}
+ // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+ if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+ var ts = this.getLayoutTargetSize();
+ if (ts.width != size.width || ts.height != size.height){
+ this.adjustmentPass = true;
+ this.onLayout(ct, target);
+ }
+ }
+ delete this.adjustmentPass;
},
destroy: function() {
- var r = ['north', 'south', 'east', 'west'];
- for (var i = 0; i < r.length; i++) {
- var region = this[r[i]];
+ var r = ['north', 'south', 'east', 'west'], i, region;
+ for (i = 0; i < r.length; i++) {
+ region = this[r[i]];
if(region){
if(region.destroy){
region.destroy();
return;
}
this.isSlid = true;
- var ts = this.panel.tools;
+ var ts = this.panel.tools, dh, pc;
if(ts && ts.toggle){
ts.toggle.hide();
}
this.el.show();
+
+ // Temporarily clear the collapsed flag so we can onResize the panel on the slide
+ pc = this.panel.collapsed;
+ this.panel.collapsed = false;
+
if(this.position == 'east' || this.position == 'west'){
+ // Temporarily clear the deferHeight flag so we can size the height on the slide
+ dh = this.panel.deferHeight;
+ this.panel.deferHeight = false;
+
this.panel.setSize(undefined, this.collapsedEl.getHeight());
+
+ // Put the deferHeight flag back after setSize
+ this.panel.deferHeight = dh;
}else{
this.panel.setSize(this.collapsedEl.getWidth(), undefined);
}
+
+ // Put the collapsed flag back after onResize
+ this.panel.collapsed = pc;
+
this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
this.el.setStyle("z-index", this.floatingZIndex+2);
*/
trackLabels: false,
+ type: 'form',
+
onRemove: function(c){
Ext.layout.FormLayout.superclass.onRemove.call(this, c);
*/\r
activeOnTop : false,\r
\r
+ type: 'accordion',\r
+\r
renderItem : function(c){\r
if(this.animate === false){\r
c.animCollapse = false;\r
c.header.addClass('x-accordion-hd');\r
c.on('beforeexpand', this.beforeExpand, this);\r
},\r
- \r
+\r
onRemove: function(c){\r
Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
if(c.rendered){\r
if(this.activeOnTop){\r
p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
}\r
+ // Items have been hidden an possibly rearranged, we need to get the container size again.\r
this.layout();\r
},\r
\r
// private\r
setItemSize : function(item, size){\r
if(this.fill && item){\r
- var hh = 0;\r
- this.container.items.each(function(p){\r
- if(p != item){\r
+ var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;\r
+ // Add up all the header heights\r
+ for (i = 0; i < len; i++) {\r
+ if((p = ct[i]) != item){\r
hh += p.header.getHeight();\r
- } \r
- });\r
+ }\r
+ };\r
+ // Subtract the header heights from the container size\r
size.height -= hh;\r
+ // Call setSize on the container to set the correct height. For Panels, deferedHeight\r
+ // will simply store this size for when the expansion is done.\r
item.setSize(size);\r
}\r
},\r
setActiveItem : function(item){\r
this.setActive(item, true);\r
},\r
- \r
+\r
// private\r
setActive : function(item, expand){\r
var ai = this.activeItem;\r
\r
// private\r
monitorResize:false,\r
- \r
+\r
+ type: 'table',\r
+\r
targetCls: 'x-table-layout-ct',\r
\r
/**\r
layout: 'table',\r
layoutConfig: {\r
tableAttrs: {\r
- style: {\r
- width: '100%'\r
- }\r
+ style: {\r
+ width: '100%'\r
+ }\r
},\r
columns: 3\r
}\r
}</code></pre>\r
*/\r
tableAttrs:null,\r
- \r
+\r
// private\r
setContainer : function(ct){\r
Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
this.currentColumn = 0;\r
this.cells = [];\r
},\r
-\r
+ \r
// private\r
onLayout : function(ct, target){\r
var cs = ct.items.items, len = cs.length, c, i;\r
\r
if(!this.table){\r
+ target.addClass('x-table-layout-ct');\r
+\r
this.table = target.createChild(\r
Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
}\r
this.getRow(curRow).appendChild(td);\r
return td;\r
},\r
- \r
+\r
// private\r
getNextNonSpan: function(colIndex, rowIndex){\r
var cols = this.columns;\r
\r
// private\r
renderItem : function(c, position, target){\r
+ // Ensure we have our inner table to get cells to render into.\r
+ if(!this.table){\r
+ this.table = target.createChild(\r
+ Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
+ }\r
if(c && !c.rendered){\r
c.render(this.getNextCell(c));\r
this.configureItem(c, position);\r
*/\r
});\r
\r
-Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**\r
- * @class Ext.layout.AbsoluteLayout\r
- * @extends Ext.layout.AnchorLayout\r
- * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the\r
- * ability for x/y positioning using the standard x and y component config options.</p>\r
- * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
- * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
- * <p>Example usage:</p>\r
- * <pre><code>\r
-var form = new Ext.form.FormPanel({\r
- title: 'Absolute Layout',\r
- layout:'absolute',\r
- layoutConfig: {\r
- // layout-specific configs go here\r
- extraCls: 'x-abs-layout-item',\r
- },\r
- baseCls: 'x-plain',\r
- url:'save-form.php',\r
- defaultType: 'textfield',\r
- items: [{\r
- x: 0,\r
- y: 5,\r
- xtype:'label',\r
- text: 'Send To:'\r
- },{\r
- x: 60,\r
- y: 0,\r
- name: 'to',\r
- anchor:'100%' // anchor width by percentage\r
- },{\r
- x: 0,\r
- y: 35,\r
- xtype:'label',\r
- text: 'Subject:'\r
- },{\r
- x: 60,\r
- y: 30,\r
- name: 'subject',\r
- anchor: '100%' // anchor width by percentage\r
- },{\r
- x:0,\r
- y: 60,\r
- xtype: 'textarea',\r
- name: 'msg',\r
- anchor: '100% 100%' // anchor width and height\r
- }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
-\r
- extraCls: 'x-abs-layout-item',\r
-\r
- onLayout : function(ct, target){\r
- target.position();\r
- this.paddingLeft = target.getPadding('l');\r
- this.paddingTop = target.getPadding('t');\r
-\r
- Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
- },\r
-\r
- // private\r
- adjustWidthAnchor : function(value, comp){\r
- return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;\r
- },\r
-\r
- // private\r
- adjustHeightAnchor : function(value, comp){\r
- return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;\r
- }\r
- /**\r
- * @property activeItem\r
- * @hide\r
- */\r
-});\r
-Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
-/**
- * @class Ext.layout.BoxLayout
- * @extends Ext.layout.ContainerLayout
- * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
- */
-Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
- /**
- * @cfg {Object} defaultMargins
- * <p>If the individual contained items do not have a <tt>margins</tt>
- * property specified, the default margins from this property will be
- * applied to each item.</p>
- * <br><p>This property may be specified as an object containing margins
- * to apply in the format:</p><pre><code>
-{
- top: (top margin),
- right: (right margin),
- bottom: (bottom margin),
- left: (left margin)
+Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
+ * @class Ext.layout.AbsoluteLayout
+ * @extends Ext.layout.AnchorLayout
+ * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
+ * ability for x/y positioning using the standard x and y component config options.</p>
+ * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
+ * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
+ * <p>Example usage:</p>
+ * <pre><code>
+var form = new Ext.form.FormPanel({
+ title: 'Absolute Layout',
+ layout:'absolute',
+ layoutConfig: {
+ // layout-specific configs go here
+ extraCls: 'x-abs-layout-item',
+ },
+ baseCls: 'x-plain',
+ url:'save-form.php',
+ defaultType: 'textfield',
+ items: [{
+ x: 0,
+ y: 5,
+ xtype:'label',
+ text: 'Send To:'
+ },{
+ x: 60,
+ y: 0,
+ name: 'to',
+ anchor:'100%' // anchor width by percentage
+ },{
+ x: 0,
+ y: 35,
+ xtype:'label',
+ text: 'Subject:'
+ },{
+ x: 60,
+ y: 30,
+ name: 'subject',
+ anchor: '100%' // anchor width by percentage
+ },{
+ x:0,
+ y: 60,
+ xtype: 'textarea',
+ name: 'msg',
+ anchor: '100% 100%' // anchor width and height
+ }]
+});
+</code></pre>
+ */
+Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
+
+ extraCls: 'x-abs-layout-item',
+
+ type: 'anchor',
+
+ onLayout : function(ct, target){
+ target.position();
+ this.paddingLeft = target.getPadding('l');
+ this.paddingTop = target.getPadding('t');
+ Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
+ },
+
+ // private
+ adjustWidthAnchor : function(value, comp){
+ return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
+ },
+
+ // private
+ adjustHeightAnchor : function(value, comp){
+ return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
+ }
+ /**
+ * @property activeItem
+ * @hide
+ */
+});
+Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
+/**
+ * @class Ext.layout.BoxLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
+ */
+Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ /**
+ * @cfg {Object} defaultMargins
+ * <p>If the individual contained items do not have a <tt>margins</tt>
+ * property specified, the default margins from this property will be
+ * applied to each item.</p>
+ * <br><p>This property may be specified as an object containing margins
+ * to apply in the format:</p><pre><code>
+{
+ top: (top margin),
+ right: (right margin),
+ bottom: (bottom margin),
+ left: (left margin)
}</code></pre>
* <p>This property may also be specified as a string containing
* space-separated, numeric margin values. The order of the sides associated
// private
monitorResize : true,
+ type: 'box',
scrollOffset : 0,
extraCls : 'x-box-item',
targetCls : 'x-box-layout-ct',
// private
isValidParent : function(c, target){
- return c.getPositionEl().dom.parentNode == this.innerCt.dom;
+ return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
},
// private
- onLayout : function(ct, target){
- var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
-
+ renderAll : function(ct, target){
if(!this.innerCt){
// the innerCt prevents wrapping and shuffling while
// the container is resizing
this.innerCt = target.createChild({cls:this.innerCls});
this.padding = this.parseMargins(this.padding);
}
- this.renderAll(ct, this.innerCt);
+ Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
+ },
+
+ onLayout : function(ct, target){
+ this.renderAll(ct, target);
+ },
+
+ getLayoutTargetSize : function(){
+ var target = this.container.getLayoutTarget(), ret;
+ if (target) {
+ ret = target.getViewSize();
+ ret.width -= target.getPadding('lr');
+ ret.height -= target.getPadding('tb');
+ }
+ return ret;
},
// private
c.margins = this.defaultMargins;
}
Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
- },
-
- // deprecate
- getTargetSize : function(target){
- return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize(true);
- },
-
- getItems: function(ct){
- var items = [];
- ct.items.each(function(c){
- if(c.isVisible()){
- items.push(c);
- }
- });
- return items;
}
});
* </ul></div>
*/
align : 'left', // left, center, stretch, strechmax
+ type: 'vbox',
/**
* @cfg {String} pack
* Controls how the child items of the container are packed together. Acceptable configuration values
onLayout : function(ct, target){
Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
- var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw,
- size = target.getViewSize(true),
+ var cs = this.getRenderedItems(ct), csLen = cs.length,
+ c, i, cm, ch, margin, cl, diff, aw, availHeight,
+ size = this.getLayoutTargetSize(),
w = size.width,
h = size.height - this.scrollOffset,
- l = this.padding.left, t = this.padding.top,
+ l = this.padding.left,
+ t = this.padding.top,
isStart = this.pack == 'start',
- stretchWidth = w - (this.padding.left + this.padding.right),
extraHeight = 0,
maxWidth = 0,
totalFlex = 0,
- flexHeight = 0,
usedHeight = 0,
idx = 0,
heights = [],
- restore = [],
- c,
- csLen = cs.length;
+ restore = [];
// Do only width calculations and apply those first, as they can affect height
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
margin = cm.top + cm.bottom;
+ // Max height for align
maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
}
c = cs[i];
cm = c.margins;
if(this.align == 'stretch'){
- c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
+ c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain(
c.minWidth || 0, c.maxWidth || 1000000));
}else if(this.align == 'stretchmax'){
c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
}
- // Do height calculations
+ // Height calculations
for (i = 0 ; i < csLen; i++) {
c = cs[i];
- cm = c.margins;
+ // Total of all the flex values
totalFlex += c.flex || 0;
- ch = c.getHeight();
- margin = cm.top + cm.bottom;
- extraHeight += ch + margin;
- flexHeight += margin + (c.flex ? 0 : ch);
+ // Don't run height calculations on flexed items
+ if (!c.flex) {
+ // Render and layout sub-containers without a flex or height, once
+ if (!c.height && !c.hasLayout && c.doLayout) {
+ c.doLayout();
+ }
+ ch = c.getHeight();
+ } else {
+ ch = 0;
+ }
+
+ cm = c.margins;
+ // Determine how much height is available to flex
+ extraHeight += ch + cm.top + cm.bottom;
}
- extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
+ // Final avail height calc
+ availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
- var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
- leftOver = availHeight;
+ var leftOver = availHeight;
for (i = 0 ; i < csLen; i++) {
c = cs[i];
if(isStart && c.flex){
}
}
if(this.pack == 'center'){
- t += extraHeight ? extraHeight / 2 : 0;
+ t += availHeight ? availHeight / 2 : 0;
}else if(this.pack == 'end'){
- t += extraHeight;
+ t += availHeight;
}
idx = 0;
// Apply heights
aw = availableWidth;
cl = l + cm.left // default left pos
-// Adjust left pos for centering
+ // Adjust left pos for centering
if(this.align == 'center'){
if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
cl += (diff/2);
}
t += ch + cm.bottom;
}
+ // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+ if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+ var ts = this.getLayoutTargetSize();
+ if (ts.width != size.width || ts.height != size.height){
+ this.adjustmentPass = true;
+ this.onLayout(ct, target);
+ }
+ }
+ delete this.adjustmentPass;
}
});
* the height of the largest item.</div></li>
*/
align : 'top', // top, middle, stretch, strechmax
+ type: 'hbox',
/**
* @cfg {String} pack
* Controls how the child items of the container are packed together. Acceptable configuration values
onLayout : function(ct, target){
Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
- var cs = this.getItems(ct), cm, cw, margin, ch, diff,
- size = target.getViewSize(true),
+ var cs = this.getRenderedItems(ct), csLen = cs.length,
+ c, i, cm, cw, ch, diff, availWidth,
+ size = this.getLayoutTargetSize(),
w = size.width - this.scrollOffset,
h = size.height,
- l = this.padding.left, t = this.padding.top,
+ l = this.padding.left,
+ t = this.padding.top,
isStart = this.pack == 'start',
isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
- stretchHeight = h - (this.padding.top + this.padding.bottom),
extraWidth = 0,
maxHeight = 0,
totalFlex = 0,
- flexWidth = 0,
usedWidth = 0;
- Ext.each(cs, function(c){
- cm = c.margins;
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ // Total of all the flex values
totalFlex += c.flex || 0;
- cw = c.getWidth();
- margin = cm.left + cm.right;
- extraWidth += cw + margin;
- flexWidth += margin + (c.flex ? 0 : cw);
+ // Don't run width calculations on flexed items
+ if (!c.flex) {
+ // Render and layout sub-containers without a flex or width, once
+ if (!c.width && !c.hasLayout && c.doLayout) {
+ c.doLayout();
+ }
+ cw = c.getWidth();
+ } else {
+ cw = 0;
+ }
+ cm = c.margins;
+ // Determine how much width is available to flex
+ extraWidth += cw + cm.left + cm.right;
+ // Max height for align
maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
- });
- extraWidth = w - extraWidth - this.padding.left - this.padding.right;
+ }
+ // Final avail width calc
+ availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right));
var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
switch(this.align){
break;
}
-
- var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
- leftOver = availWidth,
+ var leftOver = availWidth,
widths = [],
restore = [],
idx = 0,
availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
-
- Ext.each(cs, function(c){
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
if(isStart && c.flex){
cw = Math.floor(availWidth * (c.flex / totalFlex));
leftOver -= cw;
widths.push(cw);
}
- });
+ }
if(this.pack == 'center'){
- l += extraWidth ? extraWidth / 2 : 0;
+ l += availWidth ? availWidth / 2 : 0;
}else if(this.pack == 'end'){
- l += extraWidth;
+ l += availWidth;
}
- Ext.each(cs, function(c){
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
cm = c.margins;
l += cm.left;
c.setPosition(l, t + cm.top);
cw = c.getWidth();
}
l += cw + cm.right;
- });
+ }
idx = 0;
- Ext.each(cs, function(c){
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
cm = c.margins;
ch = c.getHeight();
if(isStart && c.flex){
ch = restore[idx++];
}
if(this.align == 'stretch'){
- c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
+ c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain(
c.minHeight || 0, c.maxHeight || 1000000));
}else if(this.align == 'stretchmax'){
c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
c.setHeight(ch);
}
}
- }, this);
+ }
+ // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+ if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+ var ts = this.getLayoutTargetSize();
+ if (ts.width != size.width || ts.height != size.height){
+ this.adjustmentPass = true;
+ this.onLayout(ct, target);
+ }
+ }
+ delete this.adjustmentPass;
}
});
Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
-/**\r
+/**
+ * @class Ext.layout.ToolbarLayout
+ * @extends Ext.layout.ContainerLayout
+ * Layout manager implicitly used by Ext.Toolbar.
+ */
+Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ monitorResize : true,
+ triggerWidth : 18,
+ lastOverflow : false,
+
+ noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+
+ // private
+ onLayout : function(ct, target){
+ if(!this.leftTr){
+ var align = ct.buttonAlign == 'center' ? 'center' : 'left';
+ target.addClass('x-toolbar-layout-ct');
+ target.insertHtml('beforeEnd',
+ '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
+ this.leftTr = target.child('tr.x-toolbar-left-row', true);
+ this.rightTr = target.child('tr.x-toolbar-right-row', true);
+ this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
+ }
+
+ var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
+ pos = 0,
+ items = ct.items.items;
+
+ for(var i = 0, len = items.length, c; i < len; i++, pos++) {
+ c = items[i];
+ if(c.isFill){
+ side = this.rightTr;
+ pos = -1;
+ }else if(!c.rendered){
+ c.render(this.insertCell(c, side, pos));
+ }else{
+ if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
+ var td = this.insertCell(c, side, pos);
+ td.appendChild(c.getPositionEl().dom);
+ c.container = Ext.get(td);
+ }
+ }
+ }
+ //strip extra empty cells
+ this.cleanup(this.leftTr);
+ this.cleanup(this.rightTr);
+ this.cleanup(this.extrasTr);
+ this.fitToSize(target);
+ },
+
+ cleanup : function(row){
+ var cn = row.childNodes, i, c;
+ for(i = cn.length-1; i >= 0 && (c = cn[i]); i--){
+ if(!c.firstChild){
+ row.removeChild(c);
+ }
+ }
+ },
+
+ insertCell : function(c, side, pos){
+ var td = document.createElement('td');
+ td.className='x-toolbar-cell';
+ side.insertBefore(td, side.childNodes[pos]||null);
+ return td;
+ },
+
+ hideItem : function(item){
+ var h = (this.hiddens = this.hiddens || []);
+ h.push(item);
+ item.xtbHidden = true;
+ item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
+ item.hide();
+ },
+
+ unhideItem : function(item){
+ item.show();
+ item.xtbHidden = false;
+ this.hiddens.remove(item);
+ if(this.hiddens.length < 1){
+ delete this.hiddens;
+ }
+ },
+
+ getItemWidth : function(c){
+ return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+ },
+
+ fitToSize : function(t){
+ if(this.container.enableOverflow === false){
+ return;
+ }
+ var w = t.dom.clientWidth,
+ lw = this.lastWidth || 0,
+ iw = t.dom.firstChild.offsetWidth,
+ clipWidth = w - this.triggerWidth,
+ hideIndex = -1;
+
+ this.lastWidth = w;
+
+ if(iw > w || (this.hiddens && w >= lw)){
+ var i, items = this.container.items.items,
+ len = items.length, c,
+ loopWidth = 0;
+
+ for(i = 0; i < len; i++) {
+ c = items[i];
+ if(!c.isFill){
+ loopWidth += this.getItemWidth(c);
+ if(loopWidth > clipWidth){
+ if(!(c.hidden || c.xtbHidden)){
+ this.hideItem(c);
+ }
+ }else if(c.xtbHidden){
+ this.unhideItem(c);
+ }
+ }
+ }
+ }
+ if(this.hiddens){
+ this.initMore();
+ if(!this.lastOverflow){
+ this.container.fireEvent('overflowchange', this.container, true);
+ this.lastOverflow = true;
+ }
+ }else if(this.more){
+ this.clearMenu();
+ this.more.destroy();
+ delete this.more;
+ if(this.lastOverflow){
+ this.container.fireEvent('overflowchange', this.container, false);
+ this.lastOverflow = false;
+ }
+ }
+ },
+
+ createMenuConfig : function(c, hideOnClick){
+ var cfg = Ext.apply({}, c.initialConfig),
+ group = c.toggleGroup;
+
+ Ext.apply(cfg, {
+ text: c.overflowText || c.text,
+ iconCls: c.iconCls,
+ icon: c.icon,
+ itemId: c.itemId,
+ disabled: c.disabled,
+ handler: c.handler,
+ scope: c.scope,
+ menu: c.menu,
+ hideOnClick: hideOnClick
+ });
+ if(group || c.enableToggle){
+ Ext.apply(cfg, {
+ group: group,
+ checked: c.pressed,
+ listeners: {
+ checkchange: function(item, checked){
+ c.toggle(checked);
+ }
+ }
+ });
+ }
+ delete cfg.ownerCt;
+ delete cfg.xtype;
+ delete cfg.id;
+ return cfg;
+ },
+
+ // private
+ addComponentToMenu : function(m, c){
+ if(c instanceof Ext.Toolbar.Separator){
+ m.add('-');
+ }else if(Ext.isFunction(c.isXType)){
+ if(c.isXType('splitbutton')){
+ m.add(this.createMenuConfig(c, true));
+ }else if(c.isXType('button')){
+ m.add(this.createMenuConfig(c, !c.menu));
+ }else if(c.isXType('buttongroup')){
+ c.items.each(function(item){
+ this.addComponentToMenu(m, item);
+ }, this);
+ }
+ }
+ },
+
+ clearMenu : function(){
+ var m = this.moreMenu;
+ if(m && m.items){
+ m.items.each(function(item){
+ delete item.menu;
+ });
+ }
+ },
+
+ // private
+ beforeMoreShow : function(m){
+ var h = this.container.items.items,
+ len = h.length,
+ c,
+ prev,
+ needsSep = function(group, item){
+ return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+ };
+
+ this.clearMenu();
+ m.removeAll();
+ for(var i = 0; i < len; i++){
+ c = h[i];
+ if(c.xtbHidden){
+ if(prev && (needsSep(c, prev) || needsSep(prev, c))){
+ m.add('-');
+ }
+ this.addComponentToMenu(m, c);
+ prev = c;
+ }
+ }
+ // put something so the menu isn't empty
+ // if no compatible items found
+ if(m.items.length < 1){
+ m.add(this.noItemsMenuText);
+ }
+ },
+
+ initMore : function(){
+ if(!this.more){
+ this.moreMenu = new Ext.menu.Menu({
+ ownerCt : this.container,
+ listeners: {
+ beforeshow: this.beforeMoreShow,
+ scope: this
+ }
+
+ });
+ this.more = new Ext.Button({
+ iconCls : 'x-toolbar-more-icon',
+ cls : 'x-toolbar-more',
+ menu : this.moreMenu,
+ ownerCt : this.container
+ });
+ var td = this.insertCell(this.more, this.extrasTr, 100);
+ this.more.render(td);
+ }
+ },
+
+ destroy : function(){
+ Ext.destroy(this.more, this.moreMenu);
+ delete this.leftTr;
+ delete this.rightTr;
+ delete this.extrasTr;
+ Ext.layout.ToolbarLayout.superclass.destroy.call(this);
+ }
+});
+
+Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;/**
+ * @class Ext.layout.MenuLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
+ */
+ Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ monitorResize : true,
+
+ setContainer : function(ct){
+ this.monitorResize = !ct.floating;
+ // This event is only fired by the menu in IE, used so we don't couple
+ // the menu with the layout.
+ ct.on('autosize', this.doAutoSize, this);
+ Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
+ },
+
+ renderItem : function(c, position, target){
+ if (!this.itemTpl) {
+ this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
+ '<li id="{itemId}" class="{itemCls}">',
+ '<tpl if="needsIcon">',
+ '<img src="{icon}" class="{iconCls}"/>',
+ '</tpl>',
+ '</li>'
+ );
+ }
+
+ if(c && !c.rendered){
+ if(Ext.isNumber(position)){
+ position = target.dom.childNodes[position];
+ }
+ var a = this.getItemArgs(c);
+
+// The Component's positionEl is the <li> it is rendered into
+ c.render(c.positionEl = position ?
+ this.itemTpl.insertBefore(position, a, true) :
+ this.itemTpl.append(target, a, true));
+
+// Link the containing <li> to the item.
+ c.positionEl.menuItemId = c.getItemId();
+
+// If rendering a regular Component, and it needs an icon,
+// move the Component rightwards.
+ if (!a.isMenuItem && a.needsIcon) {
+ c.positionEl.addClass('x-menu-list-item-indent');
+ }
+ this.configureItem(c, position);
+ }else if(c && !this.isValidParent(c, target)){
+ if(Ext.isNumber(position)){
+ position = target.dom.childNodes[position];
+ }
+ target.dom.insertBefore(c.getActionEl().dom, position || null);
+ }
+ },
+
+ getItemArgs : function(c) {
+ var isMenuItem = c instanceof Ext.menu.Item;
+ return {
+ isMenuItem: isMenuItem,
+ needsIcon: !isMenuItem && (c.icon || c.iconCls),
+ icon: c.icon || Ext.BLANK_IMAGE_URL,
+ iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
+ itemId: 'x-menu-el-' + c.id,
+ itemCls: 'x-menu-list-item '
+ };
+ },
+
+ // Valid if the Component is in a <li> which is part of our target <ul>
+ isValidParent : function(c, target) {
+ return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
+ },
+
+ onLayout : function(ct, target){
+ Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
+ this.doAutoSize();
+ },
+
+ doAutoSize : function(){
+ var ct = this.container, w = ct.width;
+ if(ct.floating){
+ if(w){
+ ct.setWidth(w);
+ }else if(Ext.isIE){
+ ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
+ var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
+ ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
+ }
+ }
+ }
+});
+Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;/**\r
* @class Ext.Viewport\r
* @extends Ext.Container\r
* <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
},\r
\r
fireResize : function(w, h){\r
- this.onResize(w, h, w, h);\r
+ this.fireEvent('resize', this, w, h, w, h);\r
}\r
});\r
Ext.reg('viewport', Ext.Viewport);\r
* @event bodyresize
* Fires after the Panel has been resized.
* @param {Ext.Panel} p the Panel which has been resized.
- * @param {Number} width The Panel's new width.
- * @param {Number} height The Panel's new height.
+ * @param {Number} width The Panel body's new width.
+ * @param {Number} height The Panel body's new height.
*/
'bodyresize',
/**
};
}
result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
- result.ownerCt = this;
- result.bufferResize = false;
this.toolbars.push(result);
return result;
},
if(ts){
this.addTool.apply(this, ts);
}
+
+ // Render Toolbars.
if(this.fbar){
this.footer.addClass('x-panel-btns');
+ this.fbar.ownerCt = this;
this.fbar.render(this.footer);
this.footer.createChild({cls:'x-clear'});
}
-
if(this.tbar && this.topToolbar){
+ this.topToolbar.ownerCt = this;
this.topToolbar.render(this.tbar);
}
if(this.bbar && this.bottomToolbar){
+ this.bottomToolbar.ownerCt = this;
this.bottomToolbar.render(this.bbar);
-
}
},
var tc = a[i];
if(!this.tools[tc.id]){
var overCls = 'x-tool-'+tc.id+'-over';
- var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
+ var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
this.tools[tc.id] = t;
t.enableDisplayMode('block');
this.mon(t, 'click', this.createToolHandler(t, tc, overCls, this));
},
onLayout : function(shallow, force){
+ Ext.Panel.superclass.onLayout.apply(this, arguments);
if(this.hasLayout && this.toolbars.length > 0){
Ext.each(this.toolbars, function(tb){
tb.doLayout(undefined, force);
};
},
- // private
+ // private
afterRender : function(){
if(this.floating && !this.hidden){
this.el.show();
if(this.title){
this.setTitle(this.title);
}
- if(this.collapsed){
+ Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
+ if (this.collapsed) {
this.collapsed = false;
this.collapse(false);
}
- Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
this.initEvents();
- },
+ },
// private
getKeyMap : function(){
remove: this.syncHeight
});
}, this);
- if(!this.ownerCt){
- this.syncHeight();
- }
+ this.syncHeight();
}
},
afterExpand : function(anim){
this.collapsed = false;
this.afterEffect(anim);
- if(Ext.isDefined(this.deferLayout)){
+ if (this.deferLayout) {
+ delete this.deferLayout;
this.doLayout(true);
}
this.fireEvent('expand', this);
this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
}
}else{
+ // Adds an event to set the correct height afterExpand. This accounts for the deferHeight flag in panel
this.queuedBodySize = {width: w, height: h};
if(!this.queuedExpand && this.allowQueuedExpand !== false){
this.queuedExpand = true;
Ext.destroy(this.tools[k]);
}
}
+ if(this.toolbars.length > 0){
+ Ext.each(this.toolbars, function(tb){
+ tb.un('afterlayout', this.syncHeight, this);
+ tb.un('remove', this.syncHeight, this);
+ }, this);
+ }
if(Ext.isArray(this.buttons)){
while(this.buttons.length) {
Ext.destroy(this.buttons[0]);
this.cancelEdit();
}
if(field.triggerBlur){
- field.triggerBlur();
+ field.triggerBlur();
}
}
this.fireEvent('specialkey', field, e);
this.fireEvent("canceledit", this, v, this.startValue);
}
},
-
+
// private
hideEdit: function(remainVisible){
if(remainVisible !== true){
// private
onBlur : function(){
- if(this.allowBlur !== true && this.editing){
+ // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
+ if(this.allowBlur !== true && this.editing && this.selectSameEditor !== true){
this.completeEdit();
}
},
beforeDestroy : function(){
Ext.destroyMembers(this, 'field');
-
+
delete this.parentEl;
delete this.boundEl;
}
</code></pre>\r
*/\r
Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
- /**\r
- * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
- */\r
- /**\r
- * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
- */\r
+ /**\r
+ * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
+ */\r
+ /**\r
+ * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
+ */\r
vertical: false,\r
- /**\r
- * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
- */\r
+ /**\r
+ * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
+ */\r
minValue: 0,\r
- /**\r
- * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
- */\r
+ /**\r
+ * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
+ */\r
maxValue: 100,\r
/**\r
* @cfg {Number/Boolean} decimalPrecision.\r
* <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
*/\r
decimalPrecision: 0,\r
- /**\r
- * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
- */\r
+ /**\r
+ * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
+ */\r
keyIncrement: 1,\r
- /**\r
- * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
- */\r
+ /**\r
+ * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
+ */\r
increment: 0,\r
- // private\r
+ // private\r
clickRange: [5,15],\r
- /**\r
- * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
- */\r
+ /**\r
+ * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
+ */\r
clickToChange : true,\r
- /**\r
- * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
- */\r
+ /**\r
+ * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
+ */\r
animate: true,\r
\r
/**\r
* @event beforechange\r
* Fires before the slider value is changed. By returning false from an event handler,\r
* you can cancel the event and prevent the slider from changing.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Number} newValue The new value which the slider is being changed to.\r
- * @param {Number} oldValue The old value which the slider was previously.\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Number} newValue The new value which the slider is being changed to.\r
+ * @param {Number} oldValue The old value which the slider was previously.\r
+ */\r
+ 'beforechange',\r
+ /**\r
+ * @event change\r
+ * Fires when the slider value is changed.\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Number} newValue The new value which the slider has been changed to.\r
*/\r
- 'beforechange',\r
- /**\r
- * @event change\r
- * Fires when the slider value is changed.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Number} newValue The new value which the slider has been changed to.\r
- */\r
- 'change',\r
- /**\r
- * @event changecomplete\r
- * Fires when the slider value is changed by the user and any drag operations have completed.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Number} newValue The new value which the slider has been changed to.\r
- */\r
- 'changecomplete',\r
- /**\r
- * @event dragstart\r
+ 'change',\r
+ /**\r
+ * @event changecomplete\r
+ * Fires when the slider value is changed by the user and any drag operations have completed.\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Number} newValue The new value which the slider has been changed to.\r
+ */\r
+ 'changecomplete',\r
+ /**\r
+ * @event dragstart\r
* Fires after a drag operation has started.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
- */\r
- 'dragstart',\r
- /**\r
- * @event drag\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+ */\r
+ 'dragstart',\r
+ /**\r
+ * @event drag\r
* Fires continuously during the drag operation while the mouse is moving.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
- */\r
- 'drag',\r
- /**\r
- * @event dragend\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+ */\r
+ 'drag',\r
+ /**\r
+ * @event dragend\r
* Fires after the drag operation has completed.\r
- * @param {Ext.Slider} slider The slider\r
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
- */\r
- 'dragend'\r
- );\r
+ * @param {Ext.Slider} slider The slider\r
+ * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+ */\r
+ 'dragend'\r
+ );\r
\r
if(this.vertical){\r
Ext.apply(this, Ext.Slider.Vertical);\r
}\r
},\r
\r
- // private override\r
+ // private override\r
onRender : function(){\r
this.autoEl = {\r
cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
this.initEvents();\r
},\r
\r
- // private override\r
+ // private override\r
initEvents : function(){\r
this.thumb.addClassOnOver('x-slider-thumb-over');\r
this.mon(this.el, {\r
this.tracker.initEl(this.thumb);\r
},\r
\r
- // private override\r
+ // private override\r
onMouseDown : function(e){\r
if(this.disabled){\r
return;\r
this.focus();\r
},\r
\r
- // private\r
+ // private\r
onClickChange : function(local){\r
if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
}\r
},\r
\r
- // private\r
+ // private\r
onKeyDown : function(e){\r
if(this.disabled){e.preventDefault();return;}\r
var k = e.getKey();\r
}\r
},\r
\r
- // private\r
+ // private\r
doSnap : function(value){\r
if(!(this.increment && value)){\r
return value;\r
}\r
- var newValue = value, \r
+ var newValue = value,\r
inc = this.increment,\r
m = value % inc;\r
if(m != 0){\r
return newValue.constrain(this.minValue, this.maxValue);\r
},\r
\r
- // private\r
+ // private\r
afterRender : function(){\r
Ext.Slider.superclass.afterRender.apply(this, arguments);\r
if(this.value !== undefined){\r
}\r
},\r
\r
- // private\r
+ // private\r
getRatio : function(){\r
var w = this.innerEl.getWidth(),\r
v = this.maxValue - this.minValue;\r
return v == 0 ? w : (w/v);\r
},\r
\r
- // private\r
+ // private\r
normalizeValue : function(v){\r
v = this.doSnap(v);\r
v = Ext.util.Format.round(v, this.decimalPrecision);\r
v = v.constrain(this.minValue, this.maxValue);\r
return v;\r
},\r
+ \r
+ /**\r
+ * Sets the minimum value for the slider instance. If the current value is less than the \r
+ * minimum value, the current value will be changed.\r
+ * @param {Number} val The new minimum value\r
+ */\r
+ setMinValue : function(val){\r
+ this.minValue = val;\r
+ this.syncThumb();\r
+ if(this.value < val){\r
+ this.setValue(val);\r
+ }\r
+ },\r
+ \r
+ /**\r
+ * Sets the maximum value for the slider instance. If the current value is more than the \r
+ * maximum value, the current value will be changed.\r
+ * @param {Number} val The new maximum value\r
+ */\r
+ setMaxValue : function(val){\r
+ this.maxValue = val;\r
+ this.syncThumb();\r
+ if(this.value > val){\r
+ this.setValue(val);\r
+ }\r
+ },\r
\r
- /**\r
- * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
- * the minValue and maxValue.\r
- * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
- * @param {Boolean} animate Turn on or off animation, defaults to true\r
- */\r
+ /**\r
+ * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
+ * the minValue and maxValue.\r
+ * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
+ * @param {Boolean} animate Turn on or off animation, defaults to true\r
+ */\r
setValue : function(v, animate, changeComplete){\r
v = this.normalizeValue(v);\r
if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
}\r
},\r
\r
- // private\r
+ // private\r
translateValue : function(v){\r
var ratio = this.getRatio();\r
return (v * ratio) - (this.minValue * ratio) - this.halfThumb;\r
},\r
\r
- reverseValue : function(pos){\r
+ reverseValue : function(pos){\r
var ratio = this.getRatio();\r
- return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;\r
+ return (pos + (this.minValue * ratio)) / ratio;\r
},\r
\r
- // private\r
+ // private\r
moveThumb: function(v, animate){\r
if(!animate || this.animate === false){\r
this.thumb.setLeft(v);\r
}\r
},\r
\r
- // private\r
+ // private\r
focus : function(){\r
this.focusEl.focus(10);\r
},\r
\r
- // private\r
+ // private\r
onBeforeDragStart : function(e){\r
return !this.disabled;\r
},\r
\r
- // private\r
+ // private\r
onDragStart: function(e){\r
this.thumb.addClass('x-slider-thumb-drag');\r
this.dragging = true;\r
this.fireEvent('dragstart', this, e);\r
},\r
\r
- // private\r
+ // private\r
onDrag: function(e){\r
var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
this.fireEvent('drag', this, e);\r
},\r
\r
- // private\r
+ // private\r
onDragEnd: function(e){\r
this.thumb.removeClass('x-slider-thumb-drag');\r
this.dragging = false;\r
}\r
},\r
\r
- // private\r
+ // private\r
onResize : function(w, h){\r
this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
this.syncThumb();\r
+ Ext.Slider.superclass.onResize.apply(this, arguments);\r
},\r
- \r
+\r
//private\r
onDisable: function(){\r
Ext.Slider.superclass.onDisable.call(this);\r
this.thumb.hide();\r
this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
if (!this.thumbHolder){\r
- this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass}); \r
+ this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});\r
}\r
this.thumbHolder.show().setXY(xy);\r
}\r
},\r
- \r
+\r
//private\r
onEnable: function(){\r
Ext.Slider.superclass.onEnable.call(this);\r
this.syncThumb();\r
}\r
},\r
- \r
+\r
/**\r
* Synchronizes the thumb position to the proper proportion of the total component width based\r
* on the current slider {@link #value}. This will be called automatically when the Slider\r
}\r
},\r
\r
- /**\r
- * Returns the current value of the slider\r
- * @return {Number} The current value of the slider\r
- */\r
+ /**\r
+ * Returns the current value of the slider\r
+ * @return {Number} The current value of the slider\r
+ */\r
getValue : function(){\r
return this.value;\r
},\r
- \r
+\r
// private\r
beforeDestroy : function(){\r
Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
if(text){\r
this.updateText(text);\r
}\r
- if(this.rendered){\r
+ if(this.rendered && !this.isDestroyed){\r
var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
if(this.textTopEl){\r
if(this.textTopEl){\r
this.textTopEl.addClass('x-hidden');\r
}\r
+ this.clearTimer();\r
+ if(hide === true){\r
+ this.hide();\r
+ }\r
+ return this;\r
+ },\r
+ \r
+ // private\r
+ clearTimer : function(){\r
if(this.waitTimer){\r
this.waitTimer.onStop = null; //prevent recursion\r
Ext.TaskMgr.stop(this.waitTimer);\r
this.waitTimer = null;\r
}\r
- if(hide === true){\r
- this.hide();\r
- }\r
- return this;\r
},\r
\r
onDestroy: function(){\r
+ this.clearTimer();\r
if(this.rendered){\r
if(this.textEl.isComposite){\r
this.textEl.clear();\r