Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
index 2e29ba6..f6bcd75 100644 (file)
@@ -1,8 +1,8 @@
 /*!
 /*!
- * Ext JS Library 3.1.1
- * Copyright(c) 2006-2010 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
  */
 /**
  * @class Ext.ComponentMgr
  */
 /**
  * @class Ext.ComponentMgr
@@ -226,10 +226,11 @@ editorgrid       {@link Ext.grid.EditorGridPanel}
 flash            {@link Ext.FlashComponent}
 grid             {@link Ext.grid.GridPanel}
 listview         {@link Ext.ListView}
 flash            {@link Ext.FlashComponent}
 grid             {@link Ext.grid.GridPanel}
 listview         {@link Ext.ListView}
+multislider      {@link Ext.slider.MultiSlider}
 panel            {@link Ext.Panel}
 progress         {@link Ext.ProgressBar}
 propertygrid     {@link Ext.grid.PropertyGrid}
 panel            {@link Ext.Panel}
 progress         {@link Ext.ProgressBar}
 propertygrid     {@link Ext.grid.PropertyGrid}
-slider           {@link Ext.Slider}
+slider           {@link Ext.slider.SingleSlider}
 spacer           {@link Ext.Spacer}
 splitbutton      {@link Ext.SplitButton}
 tabpanel         {@link Ext.TabPanel}
 spacer           {@link Ext.Spacer}
 splitbutton      {@link Ext.SplitButton}
 tabpanel         {@link Ext.TabPanel}
@@ -266,6 +267,7 @@ form             {@link Ext.form.FormPanel}
 checkbox         {@link Ext.form.Checkbox}
 checkboxgroup    {@link Ext.form.CheckboxGroup}
 combo            {@link Ext.form.ComboBox}
 checkbox         {@link Ext.form.Checkbox}
 checkboxgroup    {@link Ext.form.CheckboxGroup}
 combo            {@link Ext.form.ComboBox}
+compositefield   {@link Ext.form.CompositeField}
 datefield        {@link Ext.form.DateField}
 displayfield     {@link Ext.form.DisplayField}
 field            {@link Ext.form.Field}
 datefield        {@link Ext.form.DateField}
 displayfield     {@link Ext.form.DisplayField}
 field            {@link Ext.form.Field}
@@ -1025,6 +1027,14 @@ new Ext.Panel({
      * The initial set of data to apply to the <code>{@link #tpl}</code> to
      * update the content area of the Component.
      */
      * The initial set of data to apply to the <code>{@link #tpl}</code> to
      * update the content area of the Component.
      */
+    
+    /**
+     * @cfg {Array} bubbleEvents
+     * <p>An array of events that, when fired, should be bubbled to any parent container.
+     * See {@link Ext.util.Observable#enableBubble}.
+     * Defaults to <tt>[]</tt>.
+     */
+    bubbleEvents: [],
 
 
     // private
 
 
     // private
@@ -1079,7 +1089,22 @@ Ext.Foo = Ext.extend(Ext.Bar, {
 }
 </code></pre>
      */
 }
 </code></pre>
      */
-    initComponent : Ext.emptyFn,
+    initComponent : function(){
+        /*
+         * this is double processing, however it allows people to be able to do
+         * Ext.apply(this, {
+         *     listeners: {
+         *         //here
+         *     }
+         * });
+         * MyClass.superclass.initComponent.call(this);
+         */
+        if(this.listeners){
+            this.on(this.listeners);
+            delete this.listeners;
+        }
+        this.enableBubble(this.bubbleEvents);
+    },
 
     /**
      * <p>Render this Component into the passed HTML element.</p>
 
     /**
      * <p>Render this Component into the passed HTML element.</p>
@@ -1454,6 +1479,10 @@ var myGrid = new Ext.grid.EditorGridPanel({
                         this.container.remove();
                     }
                 }
                         this.container.remove();
                     }
                 }
+                // Stop any buffered tasks
+                if(this.focusTask && this.focusTask.cancel){
+                    this.focusTask.cancel();
+                }
                 this.onDestroy();
                 Ext.ComponentMgr.unregister(this);
                 this.fireEvent('destroy', this);
                 this.onDestroy();
                 Ext.ComponentMgr.unregister(this);
                 this.fireEvent('destroy', this);
@@ -1536,10 +1565,11 @@ new Ext.Panel({
      */
     focus : function(selectText, delay){
         if(delay){
      */
     focus : function(selectText, delay){
         if(delay){
-            this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
-            return;
+            this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
+            this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
+            return this;
         }
         }
-        if(this.rendered){
+        if(this.rendered && !this.isDestroyed){
             this.el.focus();
             if(selectText === true){
                 this.el.dom.select();
             this.el.focus();
             if(selectText === true){
                 this.el.dom.select();
@@ -1720,7 +1750,13 @@ var isText = t.isXType('textfield');        // true
 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
 </code></pre>
 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
 </code></pre>
-     * @param {String} xtype The xtype to check for this Component
+     * @param {String/Ext.Component/Class} xtype The xtype to check for this Component. Note that the the component can either be an instance
+     * or a component class:
+     * <pre><code>
+var c = new Ext.Component();
+console.log(c.isXType(c));
+console.log(c.isXType(Ext.Component)); 
+</code></pre>
      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
      * the default), or true to check whether this Component is directly of the specified xtype.
      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
      * the default), or true to check whether this Component is directly of the specified xtype.
      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
@@ -1775,17 +1811,37 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
 
     /**
      * Find a container above this component at any level by xtype or class
 
     /**
      * Find a container above this component at any level by xtype or class
-     * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
+     * @param {String/Ext.Component/Class} xtype The xtype to check for this Component. Note that the the component can either be an instance
+     * or a component class:
+     * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
+     * the default), or true to check whether this Component is directly of the specified xtype.
      * @return {Ext.Container} The first Container which matches the given xtype or class
      */
      * @return {Ext.Container} The first Container which matches the given xtype or class
      */
-    findParentByType : function(xtype) {
-        return Ext.isFunction(xtype) ?
-            this.findParentBy(function(p){
-                return p.constructor === xtype;
-            }) :
-            this.findParentBy(function(p){
-                return p.constructor.xtype === xtype;
-            });
+    findParentByType : function(xtype, shallow){
+        return this.findParentBy(function(c){
+            return c.isXType(xtype, shallow);
+        });
+    },
+    
+    /**
+     * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
+     * function call will be the scope provided or the current component. The arguments to the function
+     * will be the args provided or the current component. If the function returns false at any point,
+     * the bubble is stopped.
+     * @param {Function} fn The function to call
+     * @param {Object} scope (optional) The scope of the function (defaults to current node)
+     * @param {Array} args (optional) The args to call the function with (default to passing the current component)
+     * @return {Ext.Component} this
+     */
+    bubble : function(fn, scope, args){
+        var p = this;
+        while(p){
+            if(fn.apply(scope || p, args || [p]) === false){
+                break;
+            }
+            p = p.ownerCt;
+        }
+        return this;
     },
 
     // protected
     },
 
     // protected
@@ -1931,253 +1987,254 @@ myGridPanel.mon(myGridPanel.getSelectionModel(), {
     }
 });
 
     }
 });
 
-Ext.reg('component', Ext.Component);/**\r
- * @class Ext.Action\r
- * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
- * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
- * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}\r
- * and {@link Ext.menu.Menu} components).</p>\r
- * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support\r
- * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),\r
- * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>\r
- * Example usage:<br>\r
- * <pre><code>\r
-// Define the shared action.  Each component below will have the same\r
-// display text and icon, and will display the same message on click.\r
-var action = new Ext.Action({\r
-    {@link #text}: 'Do something',\r
-    {@link #handler}: function(){\r
-        Ext.Msg.alert('Click', 'You did something.');\r
-    },\r
-    {@link #iconCls}: 'do-something',\r
-    {@link #itemId}: 'myAction'\r
-});\r
-\r
-var panel = new Ext.Panel({\r
-    title: 'Actions',\r
-    width: 500,\r
-    height: 300,\r
-    tbar: [\r
-        // Add the action directly to a toolbar as a menu button\r
-        action,\r
-        {\r
-            text: 'Action Menu',\r
-            // Add the action to a menu as a text item\r
-            menu: [action]\r
-        }\r
-    ],\r
-    items: [\r
-        // Add the action to the panel body as a standard button\r
-        new Ext.Button(action)\r
-    ],\r
-    renderTo: Ext.getBody()\r
-});\r
-\r
-// Change the text for all components using the action\r
-action.setText('Something else');\r
-\r
-// Reference an action through a container using the itemId\r
-var btn = panel.getComponent('myAction');\r
-var aRef = btn.baseAction;\r
-aRef.setText('New text');\r
-</code></pre>\r
- * @constructor\r
- * @param {Object} config The configuration options\r
- */\r
-Ext.Action = Ext.extend(Object, {\r
-    /**\r
-     * @cfg {String} text The text to set for all components using this action (defaults to '').\r
-     */\r
-    /**\r
-     * @cfg {String} iconCls\r
-     * The CSS class selector that specifies a background image to be used as the header icon for\r
-     * all components using this action (defaults to '').\r
-     * <p>An example of specifying a custom icon class would be something like:\r
-     * </p><pre><code>\r
-// specify the property in the config for the class:\r
-     ...\r
-     iconCls: 'do-something'\r
-\r
-// css class that specifies background image to be used as the icon image:\r
-.do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }\r
-</code></pre>\r
-     */\r
-    /**\r
-     * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).\r
-     */\r
-    /**\r
-     * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).\r
-     */\r
-    /**\r
-     * @cfg {Function} handler The function that will be invoked by each component tied to this action\r
-     * when the component's primary event is triggered (defaults to undefined).\r
-     */\r
-    /**\r
-     * @cfg {String} itemId\r
-     * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
-     */\r
-    /**\r
-     * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
-     * <code>{@link #handler}</code> is executed. Defaults to this Button.\r
-     */\r
-\r
-    constructor : function(config){\r
-        this.initialConfig = config;\r
-        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
-        this.items = [];\r
-    },\r
-    \r
-    // private\r
-    isAction : true,\r
-\r
-    /**\r
-     * Sets the text to be displayed by all components using this action.\r
-     * @param {String} text The text to display\r
-     */\r
-    setText : function(text){\r
-        this.initialConfig.text = text;\r
-        this.callEach('setText', [text]);\r
-    },\r
-\r
-    /**\r
-     * Gets the text currently displayed by all components using this action.\r
-     */\r
-    getText : function(){\r
-        return this.initialConfig.text;\r
-    },\r
-\r
-    /**\r
-     * Sets the icon CSS class for all components using this action.  The class should supply\r
-     * a background image that will be used as the icon image.\r
-     * @param {String} cls The CSS class supplying the icon image\r
-     */\r
-    setIconClass : function(cls){\r
-        this.initialConfig.iconCls = cls;\r
-        this.callEach('setIconClass', [cls]);\r
-    },\r
-\r
-    /**\r
-     * Gets the icon CSS class currently used by all components using this action.\r
-     */\r
-    getIconClass : function(){\r
-        return this.initialConfig.iconCls;\r
-    },\r
-\r
-    /**\r
-     * Sets the disabled state of all components using this action.  Shortcut method\r
-     * for {@link #enable} and {@link #disable}.\r
-     * @param {Boolean} disabled True to disable the component, false to enable it\r
-     */\r
-    setDisabled : function(v){\r
-        this.initialConfig.disabled = v;\r
-        this.callEach('setDisabled', [v]);\r
-    },\r
-\r
-    /**\r
-     * Enables all components using this action.\r
-     */\r
-    enable : function(){\r
-        this.setDisabled(false);\r
-    },\r
-\r
-    /**\r
-     * Disables all components using this action.\r
-     */\r
-    disable : function(){\r
-        this.setDisabled(true);\r
-    },\r
-\r
-    /**\r
-     * Returns true if the components using this action are currently disabled, else returns false.  \r
-     */\r
-    isDisabled : function(){\r
-        return this.initialConfig.disabled;\r
-    },\r
-\r
-    /**\r
-     * Sets the hidden state of all components using this action.  Shortcut method\r
-     * for <code>{@link #hide}</code> and <code>{@link #show}</code>.\r
-     * @param {Boolean} hidden True to hide the component, false to show it\r
-     */\r
-    setHidden : function(v){\r
-        this.initialConfig.hidden = v;\r
-        this.callEach('setVisible', [!v]);\r
-    },\r
-\r
-    /**\r
-     * Shows all components using this action.\r
-     */\r
-    show : function(){\r
-        this.setHidden(false);\r
-    },\r
-\r
-    /**\r
-     * Hides all components using this action.\r
-     */\r
-    hide : function(){\r
-        this.setHidden(true);\r
-    },\r
-\r
-    /**\r
-     * Returns true if the components using this action are currently hidden, else returns false.  \r
-     */\r
-    isHidden : function(){\r
-        return this.initialConfig.hidden;\r
-    },\r
-\r
-    /**\r
-     * Sets the function that will be called by each Component using this action when its primary event is triggered.\r
-     * @param {Function} fn The function that will be invoked by the action's components.  The function\r
-     * will be called with no arguments.\r
-     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.\r
-     */\r
-    setHandler : function(fn, scope){\r
-        this.initialConfig.handler = fn;\r
-        this.initialConfig.scope = scope;\r
-        this.callEach('setHandler', [fn, scope]);\r
-    },\r
-\r
-    /**\r
-     * Executes the specified function once for each Component currently tied to this action.  The function passed\r
-     * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
-     * @param {Function} fn The function to execute for each component\r
-     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.\r
-     */\r
-    each : function(fn, scope){\r
-        Ext.each(this.items, fn, scope);\r
-    },\r
-\r
-    // private\r
-    callEach : function(fnName, args){\r
-        var cs = this.items;\r
-        for(var i = 0, len = cs.length; i < len; i++){\r
-            cs[i][fnName].apply(cs[i], args);\r
-        }\r
-    },\r
-\r
-    // private\r
-    addComponent : function(comp){\r
-        this.items.push(comp);\r
-        comp.on('destroy', this.removeComponent, this);\r
-    },\r
-\r
-    // private\r
-    removeComponent : function(comp){\r
-        this.items.remove(comp);\r
-    },\r
-\r
-    /**\r
-     * Executes this action manually using the handler function specified in the original config object\r
-     * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this\r
-     * function will be passed on to the handler function.\r
-     * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function\r
-     * @param {Mixed} arg2 (optional)\r
-     * @param {Mixed} etc... (optional)\r
-     */\r
-    execute : function(){\r
-        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
-    }\r
-});\r
+Ext.reg('component', Ext.Component);
+/**
+ * @class Ext.Action
+ * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
+ * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI
+ * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
+ * and {@link Ext.menu.Menu} components).</p>
+ * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
+ * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
+ * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
+ * Example usage:<br>
+ * <pre><code>
+// Define the shared action.  Each component below will have the same
+// display text and icon, and will display the same message on click.
+var action = new Ext.Action({
+    {@link #text}: 'Do something',
+    {@link #handler}: function(){
+        Ext.Msg.alert('Click', 'You did something.');
+    },
+    {@link #iconCls}: 'do-something',
+    {@link #itemId}: 'myAction'
+});
+
+var panel = new Ext.Panel({
+    title: 'Actions',
+    width: 500,
+    height: 300,
+    tbar: [
+        // Add the action directly to a toolbar as a menu button
+        action,
+        {
+            text: 'Action Menu',
+            // Add the action to a menu as a text item
+            menu: [action]
+        }
+    ],
+    items: [
+        // Add the action to the panel body as a standard button
+        new Ext.Button(action)
+    ],
+    renderTo: Ext.getBody()
+});
+
+// Change the text for all components using the action
+action.setText('Something else');
+
+// Reference an action through a container using the itemId
+var btn = panel.getComponent('myAction');
+var aRef = btn.baseAction;
+aRef.setText('New text');
+</code></pre>
+ * @constructor
+ * @param {Object} config The configuration options
+ */
+Ext.Action = Ext.extend(Object, {
+    /**
+     * @cfg {String} text The text to set for all components using this action (defaults to '').
+     */
+    /**
+     * @cfg {String} iconCls
+     * The CSS class selector that specifies a background image to be used as the header icon for
+     * all components using this action (defaults to '').
+     * <p>An example of specifying a custom icon class would be something like:
+     * </p><pre><code>
+// specify the property in the config for the class:
+     ...
+     iconCls: 'do-something'
+
+// css class that specifies background image to be used as the icon image:
+.do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
+</code></pre>
+     */
+    /**
+     * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
+     */
+    /**
+     * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
+     */
+    /**
+     * @cfg {Function} handler The function that will be invoked by each component tied to this action
+     * when the component's primary event is triggered (defaults to undefined).
+     */
+    /**
+     * @cfg {String} itemId
+     * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
+     */
+    /**
+     * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
+     * <code>{@link #handler}</code> is executed. Defaults to this Button.
+     */
+
+    constructor : function(config){
+        this.initialConfig = config;
+        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
+        this.items = [];
+    },
+    
+    // private
+    isAction : true,
+
+    /**
+     * Sets the text to be displayed by all components using this action.
+     * @param {String} text The text to display
+     */
+    setText : function(text){
+        this.initialConfig.text = text;
+        this.callEach('setText', [text]);
+    },
+
+    /**
+     * Gets the text currently displayed by all components using this action.
+     */
+    getText : function(){
+        return this.initialConfig.text;
+    },
+
+    /**
+     * Sets the icon CSS class for all components using this action.  The class should supply
+     * a background image that will be used as the icon image.
+     * @param {String} cls The CSS class supplying the icon image
+     */
+    setIconClass : function(cls){
+        this.initialConfig.iconCls = cls;
+        this.callEach('setIconClass', [cls]);
+    },
+
+    /**
+     * Gets the icon CSS class currently used by all components using this action.
+     */
+    getIconClass : function(){
+        return this.initialConfig.iconCls;
+    },
+
+    /**
+     * Sets the disabled state of all components using this action.  Shortcut method
+     * for {@link #enable} and {@link #disable}.
+     * @param {Boolean} disabled True to disable the component, false to enable it
+     */
+    setDisabled : function(v){
+        this.initialConfig.disabled = v;
+        this.callEach('setDisabled', [v]);
+    },
+
+    /**
+     * Enables all components using this action.
+     */
+    enable : function(){
+        this.setDisabled(false);
+    },
+
+    /**
+     * Disables all components using this action.
+     */
+    disable : function(){
+        this.setDisabled(true);
+    },
+
+    /**
+     * Returns true if the components using this action are currently disabled, else returns false.  
+     */
+    isDisabled : function(){
+        return this.initialConfig.disabled;
+    },
+
+    /**
+     * Sets the hidden state of all components using this action.  Shortcut method
+     * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
+     * @param {Boolean} hidden True to hide the component, false to show it
+     */
+    setHidden : function(v){
+        this.initialConfig.hidden = v;
+        this.callEach('setVisible', [!v]);
+    },
+
+    /**
+     * Shows all components using this action.
+     */
+    show : function(){
+        this.setHidden(false);
+    },
+
+    /**
+     * Hides all components using this action.
+     */
+    hide : function(){
+        this.setHidden(true);
+    },
+
+    /**
+     * Returns true if the components using this action are currently hidden, else returns false.  
+     */
+    isHidden : function(){
+        return this.initialConfig.hidden;
+    },
+
+    /**
+     * Sets the function that will be called by each Component using this action when its primary event is triggered.
+     * @param {Function} fn The function that will be invoked by the action's components.  The function
+     * will be called with no arguments.
+     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
+     */
+    setHandler : function(fn, scope){
+        this.initialConfig.handler = fn;
+        this.initialConfig.scope = scope;
+        this.callEach('setHandler', [fn, scope]);
+    },
+
+    /**
+     * Executes the specified function once for each Component currently tied to this action.  The function passed
+     * in should accept a single argument that will be an object that supports the basic Action config/method interface.
+     * @param {Function} fn The function to execute for each component
+     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.
+     */
+    each : function(fn, scope){
+        Ext.each(this.items, fn, scope);
+    },
+
+    // private
+    callEach : function(fnName, args){
+        var cs = this.items;
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i][fnName].apply(cs[i], args);
+        }
+    },
+
+    // private
+    addComponent : function(comp){
+        this.items.push(comp);
+        comp.on('destroy', this.removeComponent, this);
+    },
+
+    // private
+    removeComponent : function(comp){
+        this.items.remove(comp);
+    },
+
+    /**
+     * Executes this action manually using the handler function specified in the original config object
+     * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this
+     * function will be passed on to the handler function.
+     * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
+     * @param {Mixed} arg2 (optional)
+     * @param {Mixed} etc... (optional)
+     */
+    execute : function(){
+        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
+    }
+});
 /**
  * @class Ext.Layer
  * @extends Ext.Element
 /**
  * @class Ext.Layer
  * @extends Ext.Element
@@ -2201,9 +2258,10 @@ Ext.Action = Ext.extend(Object, {
 (function(){
 Ext.Layer = function(config, existingEl){
     config = config || {};
 (function(){
 Ext.Layer = function(config, existingEl){
     config = config || {};
-    var dh = Ext.DomHelper;
-    var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
-    if(existingEl){
+    var dh = Ext.DomHelper,
+        cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
+        
+    if (existingEl) {
         this.dom = Ext.getDom(existingEl);
     }
     if(!this.dom){
         this.dom = Ext.getDom(existingEl);
     }
     if(!this.dom){
@@ -2302,41 +2360,39 @@ Ext.extend(Ext.Layer, Ext.Element, {
     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
     sync : function(doShow){
     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
     sync : function(doShow){
-        var sw = this.shadow;
-        if(!this.updating && this.isVisible() && (sw || this.useShim)){
-            var sh = this.getShim();
-
-            var w = this.getWidth(),
-                h = this.getHeight();
-
-            var l = this.getLeft(true),
+        var shadow = this.shadow;
+        if(!this.updating && this.isVisible() && (shadow || this.useShim)){
+            var shim = this.getShim(),
+                w = this.getWidth(),
+                h = this.getHeight(),
+                l = this.getLeft(true),
                 t = this.getTop(true);
 
                 t = this.getTop(true);
 
-            if(sw && !this.shadowDisabled){
-                if(doShow && !sw.isVisible()){
-                    sw.show(this);
+            if(shadow && !this.shadowDisabled){
+                if(doShow && !shadow.isVisible()){
+                    shadow.show(this);
                 }else{
                 }else{
-                    sw.realign(l, t, w, h);
+                    shadow.realign(l, t, w, h);
                 }
                 }
-                if(sh){
+                if(shim){
                     if(doShow){
                     if(doShow){
-                       sh.show();
+                       shim.show();
                     }
                     // fit the shim behind the shadow, so it is shimmed too
                     }
                     // fit the shim behind the shadow, so it is shimmed too
-                    var a = sw.adjusts, s = sh.dom.style;
-                    s.left = (Math.min(l, l+a.l))+'px';
-                    s.top = (Math.min(t, t+a.t))+'px';
-                    s.width = (w+a.w)+'px';
-                    s.height = (h+a.h)+'px';
+                    var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
+                        shadowSize = shadow.el.getSize();
+                    shimStyle.left = (shadowAdj[0])+'px';
+                    shimStyle.top = (shadowAdj[1])+'px';
+                    shimStyle.width = (shadowSize.width)+'px';
+                    shimStyle.height = (shadowSize.height)+'px';
                 }
                 }
-            }else if(sh){
+            }else if(shim){
                 if(doShow){
                 if(doShow){
-                   sh.show();
+                   shim.show();
                 }
                 }
-                sh.setSize(w, h);
-                sh.setLeftTop(l, t);
+                shim.setSize(w, h);
+                shim.setLeftTop(l, t);
             }
             }
-
         }
     },
 
         }
     },
 
@@ -2420,6 +2476,10 @@ Ext.extend(Ext.Layer, Ext.Element, {
         }
         return this;
     },
         }
         return this;
     },
+    
+    getConstrainOffset : function(){
+        return this.shadowOffset;    
+    },
 
     isVisible : function(){
         return this.visible;
 
     isVisible : function(){
         return this.visible;
@@ -2647,19 +2707,23 @@ Ext.extend(Ext.Layer, Ext.Element, {
  * Create a new Shadow
  * @param {Object} config The config object
  */
  * Create a new Shadow
  * @param {Object} config The config object
  */
-Ext.Shadow = function(config){
+Ext.Shadow = function(config) {
     Ext.apply(this, config);
     Ext.apply(this, config);
-    if(typeof this.mode != "string"){
+    if (typeof this.mode != "string") {
         this.mode = this.defaultMode;
     }
         this.mode = this.defaultMode;
     }
-    var o = this.offset, a = {h: 0};
-    var rad = Math.floor(this.offset/2);
-    switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
+    var o = this.offset,
+        a = {
+            h: 0
+        },
+        rad = Math.floor(this.offset / 2);
+    switch (this.mode.toLowerCase()) {
+        // all this hideous nonsense calculates the various offsets for shadows
         case "drop":
             a.w = 0;
             a.l = a.t = o;
             a.t -= 1;
         case "drop":
             a.w = 0;
             a.l = a.t = o;
             a.t -= 1;
-            if(Ext.isIE){
+            if (Ext.isIE) {
                 a.l -= this.offset + rad;
                 a.t -= this.offset + rad;
                 a.w -= rad;
                 a.l -= this.offset + rad;
                 a.t -= this.offset + rad;
                 a.w -= rad;
@@ -2668,24 +2732,24 @@ Ext.Shadow = function(config){
             }
         break;
         case "sides":
             }
         break;
         case "sides":
-            a.w = (o*2);
+            a.w = (o * 2);
             a.l = -o;
             a.l = -o;
-            a.t = o-1;
-            if(Ext.isIE){
+            a.t = o - 1;
+            if (Ext.isIE) {
                 a.l -= (this.offset - rad);
                 a.t -= this.offset + rad;
                 a.l += 1;
                 a.l -= (this.offset - rad);
                 a.t -= this.offset + rad;
                 a.l += 1;
-                a.w -= (this.offset - rad)*2;
+                a.w -= (this.offset - rad) * 2;
                 a.w -= rad + 1;
                 a.h -= 1;
             }
         break;
         case "frame":
                 a.w -= rad + 1;
                 a.h -= 1;
             }
         break;
         case "frame":
-            a.w = a.h = (o*2);
+            a.w = a.h = (o * 2);
             a.l = a.t = -o;
             a.t += 1;
             a.h -= 2;
             a.l = a.t = -o;
             a.t += 1;
             a.h -= 2;
-            if(Ext.isIE){
+            if (Ext.isIE) {
                 a.l -= (this.offset - rad);
                 a.t -= (this.offset - rad);
                 a.l += 1;
                 a.l -= (this.offset - rad);
                 a.t -= (this.offset - rad);
                 a.l += 1;
@@ -2721,23 +2785,23 @@ Ext.Shadow.prototype = {
      * Displays the shadow under the target element
      * @param {Mixed} targetEl The id or element under which the shadow should display
      */
      * Displays the shadow under the target element
      * @param {Mixed} targetEl The id or element under which the shadow should display
      */
-    show : function(target){
+    show: function(target) {
         target = Ext.get(target);
         target = Ext.get(target);
-        if(!this.el){
+        if (!this.el) {
             this.el = Ext.Shadow.Pool.pull();
             this.el = Ext.Shadow.Pool.pull();
-            if(this.el.dom.nextSibling != target.dom){
+            if (this.el.dom.nextSibling != target.dom) {
                 this.el.insertBefore(target);
             }
         }
                 this.el.insertBefore(target);
             }
         }
-        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
-        if(Ext.isIE){
-            this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
+        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
+        if (Ext.isIE) {
+            this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
         }
         this.realign(
         }
         this.realign(
-            target.getLeft(true),
-            target.getTop(true),
-            target.getWidth(),
-            target.getHeight()
+        target.getLeft(true),
+        target.getTop(true),
+        target.getWidth(),
+        target.getHeight()
         );
         this.el.dom.style.display = "block";
     },
         );
         this.el.dom.style.display = "block";
     },
@@ -2745,8 +2809,8 @@ Ext.Shadow.prototype = {
     /**
      * Returns true if the shadow is visible, else false
      */
     /**
      * Returns true if the shadow is visible, else false
      */
-    isVisible : function(){
-        return this.el ? true : false;  
+    isVisible: function() {
+        return this.el ? true: false;
     },
 
     /**
     },
 
     /**
@@ -2757,25 +2821,32 @@ Ext.Shadow.prototype = {
      * @param {Number} width The target element width
      * @param {Number} height The target element height
      */
      * @param {Number} width The target element width
      * @param {Number} height The target element height
      */
-    realign : function(l, t, w, h){
-        if(!this.el){
+    realign: function(l, t, w, h) {
+        if (!this.el) {
             return;
         }
             return;
         }
-        var a = this.adjusts, d = this.el.dom, s = d.style;
-        var iea = 0;
-        s.left = (l+a.l)+"px";
-        s.top = (t+a.t)+"px";
-        var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
-        if(s.width != sws || s.height != shs){
+        var a = this.adjusts,
+            d = this.el.dom,
+            s = d.style,
+            iea = 0,
+            sw = (w + a.w),
+            sh = (h + a.h),
+            sws = sw + "px",
+            shs = sh + "px",
+            cn,
+            sww;
+        s.left = (l + a.l) + "px";
+        s.top = (t + a.t) + "px";
+        if (s.width != sws || s.height != shs) {
             s.width = sws;
             s.height = shs;
             s.width = sws;
             s.height = shs;
-            if(!Ext.isIE){
-                var cn = d.childNodes;
-                var sww = Math.max(0, (sw-12))+"px";
+            if (!Ext.isIE) {
+                cn = d.childNodes;
+                sww = Math.max(0, (sw - 12)) + "px";
                 cn[0].childNodes[1].style.width = sww;
                 cn[1].childNodes[1].style.width = sww;
                 cn[2].childNodes[1].style.width = sww;
                 cn[0].childNodes[1].style.width = sww;
                 cn[1].childNodes[1].style.width = sww;
                 cn[2].childNodes[1].style.width = sww;
-                cn[1].style.height = Math.max(0, (sh-12))+"px";
+                cn[1].style.height = Math.max(0, (sh - 12)) + "px";
             }
         }
     },
             }
         }
     },
@@ -2783,8 +2854,8 @@ Ext.Shadow.prototype = {
     /**
      * Hides this shadow
      */
     /**
      * Hides this shadow
      */
-    hide : function(){
-        if(this.el){
+    hide: function() {
+        if (this.el) {
             this.el.dom.style.display = "none";
             Ext.Shadow.Pool.push(this.el);
             delete this.el;
             this.el.dom.style.display = "none";
             Ext.Shadow.Pool.push(this.el);
             delete this.el;
@@ -2795,31 +2866,31 @@ Ext.Shadow.prototype = {
      * Adjust the z-index of this shadow
      * @param {Number} zindex The new z-index
      */
      * Adjust the z-index of this shadow
      * @param {Number} zindex The new z-index
      */
-    setZIndex : function(z){
+    setZIndex: function(z) {
         this.zIndex = z;
         this.zIndex = z;
-        if(this.el){
+        if (this.el) {
             this.el.setStyle("z-index", z);
         }
     }
 };
 
 // Private utility class that manages the internal Shadow cache
             this.el.setStyle("z-index", z);
         }
     }
 };
 
 // Private utility class that manages the internal Shadow cache
-Ext.Shadow.Pool = function(){
-    var p = [];
-    var markup = Ext.isIE ?
-                 '<div class="x-ie-shadow"></div>' :
-                 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
+Ext.Shadow.Pool = function() {
+    var p = [],
+        markup = Ext.isIE ?
+            '<div class="x-ie-shadow"></div>':
+            '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
     return {
     return {
-        pull : function(){
+        pull: function() {
             var sh = p.shift();
             var sh = p.shift();
-            if(!sh){
+            if (!sh) {
                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
                 sh.autoBoxAdjust = false;
             }
             return sh;
         },
 
                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
                 sh.autoBoxAdjust = false;
             }
             return sh;
         },
 
-        push : function(sh){
+        push: function(sh) {
             p.push(sh);
         }
     };
             p.push(sh);
         }
     };
@@ -3098,7 +3169,8 @@ var myPanel = new Ext.Panel({
 
         // support for standard size objects
         if(typeof w == 'object'){
 
         // support for standard size objects
         if(typeof w == 'object'){
-            h = w.height, w = w.width;
+            h = w.height;
+            w = w.width;
         }
         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
             w = this.boxMinWidth;
         }
         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
             w = this.boxMinWidth;
@@ -3114,7 +3186,8 @@ var myPanel = new Ext.Panel({
         }
         // not rendered
         if(!this.boxReady){
         }
         // not rendered
         if(!this.boxReady){
-            this.width = w, this.height = h;
+            this.width  = w;
+            this.height = h;
             return this;
         }
 
             return this;
         }
 
@@ -3144,8 +3217,8 @@ var myPanel = new Ext.Panel({
 
     /**
      * Sets the width of the component.  This method fires the {@link #resize} event.
 
     /**
      * Sets the width of the component.  This method fires the {@link #resize} event.
-     * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
-     * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
+     * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
+     * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
      * <li>A String used to set the CSS width style.</li>
      * </ul></div>
      * @return {Ext.BoxComponent} this
      * <li>A String used to set the CSS width style.</li>
      * </ul></div>
      * @return {Ext.BoxComponent} this
@@ -3156,8 +3229,8 @@ var myPanel = new Ext.Panel({
 
     /**
      * Sets the height of the component.  This method fires the {@link #resize} event.
 
     /**
      * Sets the height of the component.  This method fires the {@link #resize} event.
-     * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
-     * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
+     * @param {Mixed} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
+     * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
      * <li>A String used to set the CSS height style.</li>
      * <li><i>undefined</i> to leave the height unchanged.</li>
      * </ul></div>
      * <li>A String used to set the CSS height style.</li>
      * <li><i>undefined</i> to leave the height unchanged.</li>
      * </ul></div>
@@ -3405,489 +3478,489 @@ Ext.reg('box', Ext.BoxComponent);
 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
     autoEl:'div'
 });
 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
     autoEl:'div'
 });
-Ext.reg('spacer', Ext.Spacer);/**\r
- * @class Ext.SplitBar\r
- * @extends Ext.util.Observable\r
- * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
- * <br><br>\r
- * Usage:\r
- * <pre><code>\r
-var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
-                   Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
-split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
-split.minSize = 100;\r
-split.maxSize = 600;\r
-split.animate = true;\r
-split.on('moved', splitterMoved);\r
-</code></pre>\r
- * @constructor\r
- * Create a new SplitBar\r
- * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
- * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
- * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
- * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
-                        Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
-                        position of the SplitBar).\r
- */\r
-Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
-\r
-    /** @private */\r
-    this.el = Ext.get(dragElement, true);\r
-    this.el.dom.unselectable = "on";\r
-    /** @private */\r
-    this.resizingEl = Ext.get(resizingElement, true);\r
-\r
-    /**\r
-     * @private\r
-     * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
-     * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
-     * @type Number\r
-     */\r
-    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
-\r
-    /**\r
-     * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
-     * @type Number\r
-     * @property tickSize\r
-     */\r
-    /**\r
-     * The minimum size of the resizing element. (Defaults to 0)\r
-     * @type Number\r
-     */\r
-    this.minSize = 0;\r
-\r
-    /**\r
-     * The maximum size of the resizing element. (Defaults to 2000)\r
-     * @type Number\r
-     */\r
-    this.maxSize = 2000;\r
-\r
-    /**\r
-     * Whether to animate the transition to the new size\r
-     * @type Boolean\r
-     */\r
-    this.animate = false;\r
-\r
-    /**\r
-     * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
-     * @type Boolean\r
-     */\r
-    this.useShim = false;\r
-\r
-    /** @private */\r
-    this.shim = null;\r
-\r
-    if(!existingProxy){\r
-        /** @private */\r
-        this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
-    }else{\r
-        this.proxy = Ext.get(existingProxy).dom;\r
-    }\r
-    /** @private */\r
-    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
-\r
-    /** @private */\r
-    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
-\r
-    /** @private */\r
-    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
-\r
-    /** @private */\r
-    this.dragSpecs = {};\r
-\r
-    /**\r
-     * @private The adapter to use to positon and resize elements\r
-     */\r
-    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
-    this.adapter.init(this);\r
-\r
-    if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
-        /** @private */\r
-        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
-        this.el.addClass("x-splitbar-h");\r
-    }else{\r
-        /** @private */\r
-        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
-        this.el.addClass("x-splitbar-v");\r
-    }\r
-\r
-    this.addEvents(\r
-        /**\r
-         * @event resize\r
-         * Fires when the splitter is moved (alias for {@link #moved})\r
-         * @param {Ext.SplitBar} this\r
-         * @param {Number} newSize the new width or height\r
-         */\r
-        "resize",\r
-        /**\r
-         * @event moved\r
-         * Fires when the splitter is moved\r
-         * @param {Ext.SplitBar} this\r
-         * @param {Number} newSize the new width or height\r
-         */\r
-        "moved",\r
-        /**\r
-         * @event beforeresize\r
-         * Fires before the splitter is dragged\r
-         * @param {Ext.SplitBar} this\r
-         */\r
-        "beforeresize",\r
-\r
-        "beforeapply"\r
-    );\r
-\r
-    Ext.SplitBar.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
-    onStartProxyDrag : function(x, y){\r
-        this.fireEvent("beforeresize", this);\r
-        this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
-        this.overlay.unselectable();\r
-        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
-        this.overlay.show();\r
-        Ext.get(this.proxy).setDisplayed("block");\r
-        var size = this.adapter.getElementSize(this);\r
-        this.activeMinSize = this.getMinimumSize();\r
-        this.activeMaxSize = this.getMaximumSize();\r
-        var c1 = size - this.activeMinSize;\r
-        var c2 = Math.max(this.activeMaxSize - size, 0);\r
-        if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
-            this.dd.resetConstraints();\r
-            this.dd.setXConstraint(\r
-                this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
-                this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
-                this.tickSize\r
-            );\r
-            this.dd.setYConstraint(0, 0);\r
-        }else{\r
-            this.dd.resetConstraints();\r
-            this.dd.setXConstraint(0, 0);\r
-            this.dd.setYConstraint(\r
-                this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
-                this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
-                this.tickSize\r
-            );\r
-         }\r
-        this.dragSpecs.startSize = size;\r
-        this.dragSpecs.startPoint = [x, y];\r
-        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
-    },\r
-\r
-    /**\r
-     * @private Called after the drag operation by the DDProxy\r
-     */\r
-    onEndProxyDrag : function(e){\r
-        Ext.get(this.proxy).setDisplayed(false);\r
-        var endPoint = Ext.lib.Event.getXY(e);\r
-        if(this.overlay){\r
-            Ext.destroy(this.overlay);\r
-            delete this.overlay;\r
-        }\r
-        var newSize;\r
-        if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
-            newSize = this.dragSpecs.startSize +\r
-                (this.placement == Ext.SplitBar.LEFT ?\r
-                    endPoint[0] - this.dragSpecs.startPoint[0] :\r
-                    this.dragSpecs.startPoint[0] - endPoint[0]\r
-                );\r
-        }else{\r
-            newSize = this.dragSpecs.startSize +\r
-                (this.placement == Ext.SplitBar.TOP ?\r
-                    endPoint[1] - this.dragSpecs.startPoint[1] :\r
-                    this.dragSpecs.startPoint[1] - endPoint[1]\r
-                );\r
-        }\r
-        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
-        if(newSize != this.dragSpecs.startSize){\r
-            if(this.fireEvent('beforeapply', this, newSize) !== false){\r
-                this.adapter.setElementSize(this, newSize);\r
-                this.fireEvent("moved", this, newSize);\r
-                this.fireEvent("resize", this, newSize);\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Get the adapter this SplitBar uses\r
-     * @return The adapter object\r
-     */\r
-    getAdapter : function(){\r
-        return this.adapter;\r
-    },\r
-\r
-    /**\r
-     * Set the adapter this SplitBar uses\r
-     * @param {Object} adapter A SplitBar adapter object\r
-     */\r
-    setAdapter : function(adapter){\r
-        this.adapter = adapter;\r
-        this.adapter.init(this);\r
-    },\r
-\r
-    /**\r
-     * Gets the minimum size for the resizing element\r
-     * @return {Number} The minimum size\r
-     */\r
-    getMinimumSize : function(){\r
-        return this.minSize;\r
-    },\r
-\r
-    /**\r
-     * Sets the minimum size for the resizing element\r
-     * @param {Number} minSize The minimum size\r
-     */\r
-    setMinimumSize : function(minSize){\r
-        this.minSize = minSize;\r
-    },\r
-\r
-    /**\r
-     * Gets the maximum size for the resizing element\r
-     * @return {Number} The maximum size\r
-     */\r
-    getMaximumSize : function(){\r
-        return this.maxSize;\r
-    },\r
-\r
-    /**\r
-     * Sets the maximum size for the resizing element\r
-     * @param {Number} maxSize The maximum size\r
-     */\r
-    setMaximumSize : function(maxSize){\r
-        this.maxSize = maxSize;\r
-    },\r
-\r
-    /**\r
-     * Sets the initialize size for the resizing element\r
-     * @param {Number} size The initial size\r
-     */\r
-    setCurrentSize : function(size){\r
-        var oldAnimate = this.animate;\r
-        this.animate = false;\r
-        this.adapter.setElementSize(this, size);\r
-        this.animate = oldAnimate;\r
-    },\r
-\r
-    /**\r
-     * Destroy this splitbar.\r
-     * @param {Boolean} removeEl True to remove the element\r
-     */\r
-    destroy : function(removeEl){\r
-        Ext.destroy(this.shim, Ext.get(this.proxy));\r
-        this.dd.unreg();\r
-        if(removeEl){\r
-            this.el.remove();\r
-        }\r
-        this.purgeListeners();\r
-    }\r
-});\r
-\r
-/**\r
- * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.\r
- */\r
-Ext.SplitBar.createProxy = function(dir){\r
-    var proxy = new Ext.Element(document.createElement("div"));\r
-    document.body.appendChild(proxy.dom);\r
-    proxy.unselectable();\r
-    var cls = 'x-splitbar-proxy';\r
-    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
-    return proxy.dom;\r
-};\r
-\r
-/**\r
- * @class Ext.SplitBar.BasicLayoutAdapter\r
- * Default Adapter. It assumes the splitter and resizing element are not positioned\r
- * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
- */\r
-Ext.SplitBar.BasicLayoutAdapter = function(){\r
-};\r
-\r
-Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
-    // do nothing for now\r
-    init : function(s){\r
-\r
-    },\r
-    /**\r
-     * Called before drag operations to get the current size of the resizing element.\r
-     * @param {Ext.SplitBar} s The SplitBar using this adapter\r
-     */\r
-     getElementSize : function(s){\r
-        if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
-            return s.resizingEl.getWidth();\r
-        }else{\r
-            return s.resizingEl.getHeight();\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Called after drag operations to set the size of the resizing element.\r
-     * @param {Ext.SplitBar} s The SplitBar using this adapter\r
-     * @param {Number} newSize The new size to set\r
-     * @param {Function} onComplete A function to be invoked when resizing is complete\r
-     */\r
-    setElementSize : function(s, newSize, onComplete){\r
-        if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
-            if(!s.animate){\r
-                s.resizingEl.setWidth(newSize);\r
-                if(onComplete){\r
-                    onComplete(s, newSize);\r
-                }\r
-            }else{\r
-                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
-            }\r
-        }else{\r
-\r
-            if(!s.animate){\r
-                s.resizingEl.setHeight(newSize);\r
-                if(onComplete){\r
-                    onComplete(s, newSize);\r
-                }\r
-            }else{\r
-                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
-            }\r
-        }\r
-    }\r
-};\r
-\r
-/**\r
- *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
- * @extends Ext.SplitBar.BasicLayoutAdapter\r
- * Adapter that  moves the splitter element to align with the resized sizing element.\r
- * Used with an absolute positioned SplitBar.\r
- * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
- * document.body, make sure you assign an id to the body element.\r
- */\r
-Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
-    this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
-    this.container = Ext.get(container);\r
-};\r
-\r
-Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
-    init : function(s){\r
-        this.basic.init(s);\r
-    },\r
-\r
-    getElementSize : function(s){\r
-        return this.basic.getElementSize(s);\r
-    },\r
-\r
-    setElementSize : function(s, newSize, onComplete){\r
-        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
-    },\r
-\r
-    moveSplitter : function(s){\r
-        var yes = Ext.SplitBar;\r
-        switch(s.placement){\r
-            case yes.LEFT:\r
-                s.el.setX(s.resizingEl.getRight());\r
-                break;\r
-            case yes.RIGHT:\r
-                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
-                break;\r
-            case yes.TOP:\r
-                s.el.setY(s.resizingEl.getBottom());\r
-                break;\r
-            case yes.BOTTOM:\r
-                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
-                break;\r
-        }\r
-    }\r
-};\r
-\r
-/**\r
- * Orientation constant - Create a vertical SplitBar\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.VERTICAL = 1;\r
-\r
-/**\r
- * Orientation constant - Create a horizontal SplitBar\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.HORIZONTAL = 2;\r
-\r
-/**\r
- * Placement constant - The resizing element is to the left of the splitter element\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.LEFT = 1;\r
-\r
-/**\r
- * Placement constant - The resizing element is to the right of the splitter element\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.RIGHT = 2;\r
-\r
-/**\r
- * Placement constant - The resizing element is positioned above the splitter element\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.TOP = 3;\r
-\r
-/**\r
- * Placement constant - The resizing element is positioned under splitter element\r
- * @static\r
- * @type Number\r
- */\r
-Ext.SplitBar.BOTTOM = 4;\r
-/**
- * @class Ext.Container
- * @extends Ext.BoxComponent
- * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
- * basic behavior of containing items, namely adding, inserting and removing items.</p>
- *
- * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
- * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
- * Container to be encapsulated by an HTML element to your specifications by using the
- * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
- * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
- * for example.</p>
- *
- * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
- * create one using the <b><code>'container'</code></b> xtype:<pre><code>
-// explicitly create a Container
-var embeddedColumns = new Ext.Container({
-    autoEl: 'div',  // This is the default
-    layout: 'column',
-    defaults: {
-        // implicitly create Container by specifying xtype
-        xtype: 'container',
-        autoEl: 'div', // This is the default.
-        layout: 'form',
-        columnWidth: 0.5,
-        style: {
-            padding: '10px'
-        }
-    },
-//  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
-    items: [{
-        items: {
-            xtype: 'datefield',
-            name: 'startDate',
-            fieldLabel: 'Start date'
-        }
-    }, {
-        items: {
-            xtype: 'datefield',
-            name: 'endDate',
-            fieldLabel: 'End date'
-        }
-    }]
-});</code></pre></p>
- *
- * <p><u><b>Layout</b></u></p>
- * <p>Container classes delegate the rendering of child Components to a layout
- * manager class which must be configured into the Container using the
- * <code><b>{@link #layout}</b></code> configuration property.</p>
- * <p>When either specifying child <code>{@link #items}</code> of a Container,
- * or dynamically {@link #add adding} Components to a Container, remember to
- * consider how you wish the Container to arrange those child elements, and
- * whether those child elements need to be sized using one of Ext's built-in
+Ext.reg('spacer', Ext.Spacer);/**
+ * @class Ext.SplitBar
+ * @extends Ext.util.Observable
+ * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
+ * <br><br>
+ * Usage:
+ * <pre><code>
+var split = new Ext.SplitBar("elementToDrag", "elementToSize",
+                   Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
+split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
+split.minSize = 100;
+split.maxSize = 600;
+split.animate = true;
+split.on('moved', splitterMoved);
+</code></pre>
+ * @constructor
+ * Create a new SplitBar
+ * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
+ * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
+ * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
+ * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
+                        Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
+                        position of the SplitBar).
+ */
+Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
+
+    /** @private */
+    this.el = Ext.get(dragElement, true);
+    this.el.dom.unselectable = "on";
+    /** @private */
+    this.resizingEl = Ext.get(resizingElement, true);
+
+    /**
+     * @private
+     * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
+     * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
+     * @type Number
+     */
+    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
+
+    /**
+     * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
+     * @type Number
+     * @property tickSize
+     */
+    /**
+     * The minimum size of the resizing element. (Defaults to 0)
+     * @type Number
+     */
+    this.minSize = 0;
+
+    /**
+     * The maximum size of the resizing element. (Defaults to 2000)
+     * @type Number
+     */
+    this.maxSize = 2000;
+
+    /**
+     * Whether to animate the transition to the new size
+     * @type Boolean
+     */
+    this.animate = false;
+
+    /**
+     * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
+     * @type Boolean
+     */
+    this.useShim = false;
+
+    /** @private */
+    this.shim = null;
+
+    if(!existingProxy){
+        /** @private */
+        this.proxy = Ext.SplitBar.createProxy(this.orientation);
+    }else{
+        this.proxy = Ext.get(existingProxy).dom;
+    }
+    /** @private */
+    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
+
+    /** @private */
+    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
+
+    /** @private */
+    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
+
+    /** @private */
+    this.dragSpecs = {};
+
+    /**
+     * @private The adapter to use to positon and resize elements
+     */
+    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
+    this.adapter.init(this);
+
+    if(this.orientation == Ext.SplitBar.HORIZONTAL){
+        /** @private */
+        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
+        this.el.addClass("x-splitbar-h");
+    }else{
+        /** @private */
+        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
+        this.el.addClass("x-splitbar-v");
+    }
+
+    this.addEvents(
+        /**
+         * @event resize
+         * Fires when the splitter is moved (alias for {@link #moved})
+         * @param {Ext.SplitBar} this
+         * @param {Number} newSize the new width or height
+         */
+        "resize",
+        /**
+         * @event moved
+         * Fires when the splitter is moved
+         * @param {Ext.SplitBar} this
+         * @param {Number} newSize the new width or height
+         */
+        "moved",
+        /**
+         * @event beforeresize
+         * Fires before the splitter is dragged
+         * @param {Ext.SplitBar} this
+         */
+        "beforeresize",
+
+        "beforeapply"
+    );
+
+    Ext.SplitBar.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.SplitBar, Ext.util.Observable, {
+    onStartProxyDrag : function(x, y){
+        this.fireEvent("beforeresize", this);
+        this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
+        this.overlay.unselectable();
+        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
+        this.overlay.show();
+        Ext.get(this.proxy).setDisplayed("block");
+        var size = this.adapter.getElementSize(this);
+        this.activeMinSize = this.getMinimumSize();
+        this.activeMaxSize = this.getMaximumSize();
+        var c1 = size - this.activeMinSize;
+        var c2 = Math.max(this.activeMaxSize - size, 0);
+        if(this.orientation == Ext.SplitBar.HORIZONTAL){
+            this.dd.resetConstraints();
+            this.dd.setXConstraint(
+                this.placement == Ext.SplitBar.LEFT ? c1 : c2,
+                this.placement == Ext.SplitBar.LEFT ? c2 : c1,
+                this.tickSize
+            );
+            this.dd.setYConstraint(0, 0);
+        }else{
+            this.dd.resetConstraints();
+            this.dd.setXConstraint(0, 0);
+            this.dd.setYConstraint(
+                this.placement == Ext.SplitBar.TOP ? c1 : c2,
+                this.placement == Ext.SplitBar.TOP ? c2 : c1,
+                this.tickSize
+            );
+         }
+        this.dragSpecs.startSize = size;
+        this.dragSpecs.startPoint = [x, y];
+        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
+    },
+
+    /**
+     * @private Called after the drag operation by the DDProxy
+     */
+    onEndProxyDrag : function(e){
+        Ext.get(this.proxy).setDisplayed(false);
+        var endPoint = Ext.lib.Event.getXY(e);
+        if(this.overlay){
+            Ext.destroy(this.overlay);
+            delete this.overlay;
+        }
+        var newSize;
+        if(this.orientation == Ext.SplitBar.HORIZONTAL){
+            newSize = this.dragSpecs.startSize +
+                (this.placement == Ext.SplitBar.LEFT ?
+                    endPoint[0] - this.dragSpecs.startPoint[0] :
+                    this.dragSpecs.startPoint[0] - endPoint[0]
+                );
+        }else{
+            newSize = this.dragSpecs.startSize +
+                (this.placement == Ext.SplitBar.TOP ?
+                    endPoint[1] - this.dragSpecs.startPoint[1] :
+                    this.dragSpecs.startPoint[1] - endPoint[1]
+                );
+        }
+        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
+        if(newSize != this.dragSpecs.startSize){
+            if(this.fireEvent('beforeapply', this, newSize) !== false){
+                this.adapter.setElementSize(this, newSize);
+                this.fireEvent("moved", this, newSize);
+                this.fireEvent("resize", this, newSize);
+            }
+        }
+    },
+
+    /**
+     * Get the adapter this SplitBar uses
+     * @return The adapter object
+     */
+    getAdapter : function(){
+        return this.adapter;
+    },
+
+    /**
+     * Set the adapter this SplitBar uses
+     * @param {Object} adapter A SplitBar adapter object
+     */
+    setAdapter : function(adapter){
+        this.adapter = adapter;
+        this.adapter.init(this);
+    },
+
+    /**
+     * Gets the minimum size for the resizing element
+     * @return {Number} The minimum size
+     */
+    getMinimumSize : function(){
+        return this.minSize;
+    },
+
+    /**
+     * Sets the minimum size for the resizing element
+     * @param {Number} minSize The minimum size
+     */
+    setMinimumSize : function(minSize){
+        this.minSize = minSize;
+    },
+
+    /**
+     * Gets the maximum size for the resizing element
+     * @return {Number} The maximum size
+     */
+    getMaximumSize : function(){
+        return this.maxSize;
+    },
+
+    /**
+     * Sets the maximum size for the resizing element
+     * @param {Number} maxSize The maximum size
+     */
+    setMaximumSize : function(maxSize){
+        this.maxSize = maxSize;
+    },
+
+    /**
+     * Sets the initialize size for the resizing element
+     * @param {Number} size The initial size
+     */
+    setCurrentSize : function(size){
+        var oldAnimate = this.animate;
+        this.animate = false;
+        this.adapter.setElementSize(this, size);
+        this.animate = oldAnimate;
+    },
+
+    /**
+     * Destroy this splitbar.
+     * @param {Boolean} removeEl True to remove the element
+     */
+    destroy : function(removeEl){
+        Ext.destroy(this.shim, Ext.get(this.proxy));
+        this.dd.unreg();
+        if(removeEl){
+            this.el.remove();
+        }
+        this.purgeListeners();
+    }
+});
+
+/**
+ * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
+ */
+Ext.SplitBar.createProxy = function(dir){
+    var proxy = new Ext.Element(document.createElement("div"));
+    document.body.appendChild(proxy.dom);
+    proxy.unselectable();
+    var cls = 'x-splitbar-proxy';
+    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
+    return proxy.dom;
+};
+
+/**
+ * @class Ext.SplitBar.BasicLayoutAdapter
+ * Default Adapter. It assumes the splitter and resizing element are not positioned
+ * elements and only gets/sets the width of the element. Generally used for table based layouts.
+ */
+Ext.SplitBar.BasicLayoutAdapter = function(){
+};
+
+Ext.SplitBar.BasicLayoutAdapter.prototype = {
+    // do nothing for now
+    init : function(s){
+
+    },
+    /**
+     * Called before drag operations to get the current size of the resizing element.
+     * @param {Ext.SplitBar} s The SplitBar using this adapter
+     */
+     getElementSize : function(s){
+        if(s.orientation == Ext.SplitBar.HORIZONTAL){
+            return s.resizingEl.getWidth();
+        }else{
+            return s.resizingEl.getHeight();
+        }
+    },
+
+    /**
+     * Called after drag operations to set the size of the resizing element.
+     * @param {Ext.SplitBar} s The SplitBar using this adapter
+     * @param {Number} newSize The new size to set
+     * @param {Function} onComplete A function to be invoked when resizing is complete
+     */
+    setElementSize : function(s, newSize, onComplete){
+        if(s.orientation == Ext.SplitBar.HORIZONTAL){
+            if(!s.animate){
+                s.resizingEl.setWidth(newSize);
+                if(onComplete){
+                    onComplete(s, newSize);
+                }
+            }else{
+                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
+            }
+        }else{
+
+            if(!s.animate){
+                s.resizingEl.setHeight(newSize);
+                if(onComplete){
+                    onComplete(s, newSize);
+                }
+            }else{
+                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
+            }
+        }
+    }
+};
+
+/**
+ *@class Ext.SplitBar.AbsoluteLayoutAdapter
+ * @extends Ext.SplitBar.BasicLayoutAdapter
+ * Adapter that  moves the splitter element to align with the resized sizing element.
+ * Used with an absolute positioned SplitBar.
+ * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
+ * document.body, make sure you assign an id to the body element.
+ */
+Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
+    this.basic = new Ext.SplitBar.BasicLayoutAdapter();
+    this.container = Ext.get(container);
+};
+
+Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
+    init : function(s){
+        this.basic.init(s);
+    },
+
+    getElementSize : function(s){
+        return this.basic.getElementSize(s);
+    },
+
+    setElementSize : function(s, newSize, onComplete){
+        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
+    },
+
+    moveSplitter : function(s){
+        var yes = Ext.SplitBar;
+        switch(s.placement){
+            case yes.LEFT:
+                s.el.setX(s.resizingEl.getRight());
+                break;
+            case yes.RIGHT:
+                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
+                break;
+            case yes.TOP:
+                s.el.setY(s.resizingEl.getBottom());
+                break;
+            case yes.BOTTOM:
+                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
+                break;
+        }
+    }
+};
+
+/**
+ * Orientation constant - Create a vertical SplitBar
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.VERTICAL = 1;
+
+/**
+ * Orientation constant - Create a horizontal SplitBar
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.HORIZONTAL = 2;
+
+/**
+ * Placement constant - The resizing element is to the left of the splitter element
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.LEFT = 1;
+
+/**
+ * Placement constant - The resizing element is to the right of the splitter element
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.RIGHT = 2;
+
+/**
+ * Placement constant - The resizing element is positioned above the splitter element
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.TOP = 3;
+
+/**
+ * Placement constant - The resizing element is positioned under splitter element
+ * @static
+ * @type Number
+ */
+Ext.SplitBar.BOTTOM = 4;
+/**
+ * @class Ext.Container
+ * @extends Ext.BoxComponent
+ * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
+ * basic behavior of containing items, namely adding, inserting and removing items.</p>
+ *
+ * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
+ * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
+ * Container to be encapsulated by an HTML element to your specifications by using the
+ * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
+ * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
+ * for example.</p>
+ *
+ * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
+ * create one using the <b><code>'container'</code></b> xtype:<pre><code>
+// explicitly create a Container
+var embeddedColumns = new Ext.Container({
+    autoEl: 'div',  // This is the default
+    layout: 'column',
+    defaults: {
+        // implicitly create Container by specifying xtype
+        xtype: 'container',
+        autoEl: 'div', // This is the default.
+        layout: 'form',
+        columnWidth: 0.5,
+        style: {
+            padding: '10px'
+        }
+    },
+//  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
+    items: [{
+        items: {
+            xtype: 'datefield',
+            name: 'startDate',
+            fieldLabel: 'Start date'
+        }
+    }, {
+        items: {
+            xtype: 'datefield',
+            name: 'endDate',
+            fieldLabel: 'End date'
+        }
+    }]
+});</code></pre></p>
+ *
+ * <p><u><b>Layout</b></u></p>
+ * <p>Container classes delegate the rendering of child Components to a layout
+ * manager class which must be configured into the Container using the
+ * <code><b>{@link #layout}</b></code> configuration property.</p>
+ * <p>When either specifying child <code>{@link #items}</code> of a Container,
+ * or dynamically {@link #add adding} Components to a Container, remember to
+ * consider how you wish the Container to arrange those child elements, and
+ * whether those child elements need to be sized using one of Ext's built-in
  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
  * renders child components, appending them one after the other inside the
  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
  * renders child components, appending them one after the other inside the
@@ -4107,7 +4180,6 @@ layoutConfig: {
      * 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>.
      */
      * 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,
 
     /**
     bufferResize: 50,
 
     /**
@@ -4272,8 +4344,6 @@ items: [
             'remove'
         );
 
             'remove'
         );
 
-        this.enableBubble(this.bubbleEvents);
-
         /**
          * The collection of components in this container as a {@link Ext.util.MixedCollection}
          * @type MixedCollection
         /**
          * The collection of components in this container as a {@link Ext.util.MixedCollection}
          * @type MixedCollection
@@ -4299,8 +4369,8 @@ items: [
         if(this.layout && this.layout != layout){
             this.layout.setContainer(null);
         }
         if(this.layout && this.layout != layout){
             this.layout.setContainer(null);
         }
-        this.initItems();
         this.layout = layout;
         this.layout = layout;
+        this.initItems();
         layout.setContainer(this);
     },
 
         layout.setContainer(this);
     },
 
@@ -4321,7 +4391,7 @@ items: [
         this.setLayout(this.layout);
 
         // If a CardLayout, the active item set
         this.setLayout(this.layout);
 
         // If a CardLayout, the active item set
-        if(this.activeItem !== undefined){
+        if(this.activeItem !== undefined && this.layout.setActiveItem){
             var item = this.activeItem;
             delete this.activeItem;
             this.layout.setActiveItem(item);
             var item = this.activeItem;
             delete this.activeItem;
             this.layout.setActiveItem(item);
@@ -4381,12 +4451,10 @@ tb.{@link #doLayout}();             // refresh the layout
      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
      * for more details.</li>
      * </ul></div>
      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
      * for more details.</li>
      * </ul></div>
-     * @param {Object/Array} component
-     * <p>Either a single component or an Array of components to add.  See
+     * @param {...Object/Array} component
+     * <p>Either one or more Components to add or an Array of Components to add.  See
      * <code>{@link #items}</code> for additional information.</p>
      * <code>{@link #items}</code> for additional information.</p>
-     * @param {Object} (Optional) component_2
-     * @param {Object} (Optional) component_n
-     * @return {Ext.Component} component The Component (or config object) that was added.
+     * @return {Ext.Component/Array} The Components that were added.
      */
     add : function(comp){
         this.initItems();
      */
     add : function(comp){
         this.initItems();
@@ -4444,20 +4512,26 @@ tb.{@link #doLayout}();             // refresh the layout
      * @return {Ext.Component} component The Component (or config object) that was
      * inserted with the Container's default config values applied.
      */
      * @return {Ext.Component} component The Component (or config object) that was
      * inserted with the Container's default config values applied.
      */
-    insert : function(index, comp){
+    insert : function(index, comp) {
+        var args   = arguments,
+            length = args.length,
+            result = [],
+            i, c;
+        
         this.initItems();
         this.initItems();
-        var a = arguments, len = a.length;
-        if(len > 2){
-            var result = [];
-            for(var i = len-1; i >= 1; --i) {
-                result.push(this.insert(index, a[i]));
+        
+        if (length > 2) {
+            for (i = length - 1; i >= 1; --i) {
+                result.push(this.insert(index, args[i]));
             }
             return result;
         }
             }
             return result;
         }
-        var c = this.lookupComponent(this.applyDefaults(comp));
+        
+        c = this.lookupComponent(this.applyDefaults(comp));
         index = Math.min(index, this.items.length);
         index = Math.min(index, this.items.length);
-        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
-            if(c.ownerCt == this){
+        
+        if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
+            if (c.ownerCt == this) {
                 this.items.remove(c);
             }
             this.items.insert(index, c);
                 this.items.remove(c);
             }
             this.items.insert(index, c);
@@ -4465,6 +4539,7 @@ tb.{@link #doLayout}();             // refresh the layout
             this.onAdd(c);
             this.fireEvent('add', this, c, index);
         }
             this.onAdd(c);
             this.fireEvent('add', this, c, index);
         }
+        
         return c;
     },
 
         return c;
     },
 
@@ -4479,7 +4554,7 @@ tb.{@link #doLayout}();             // refresh the layout
                 c = Ext.ComponentMgr.get(c);
                 Ext.apply(c, d);
             }else if(!c.events){
                 c = Ext.ComponentMgr.get(c);
                 Ext.apply(c, d);
             }else if(!c.events){
-                Ext.applyIf(c, d);
+                Ext.applyIf(c.isAction ? c.initialConfig : c, d);
             }else{
                 Ext.apply(c, d);
             }
             }else{
                 Ext.apply(c, d);
             }
@@ -4592,21 +4667,24 @@ tb.{@link #doLayout}();             // refresh the layout
 
     // private
     createComponent : function(config, defaultType){
 
     // private
     createComponent : function(config, defaultType){
+        if (config.render) {
+            return config;
+        }
         // add in ownerCt at creation time but then immediately
         // remove so that onBeforeAdd can handle it
         // add in ownerCt at creation time but then immediately
         // remove so that onBeforeAdd can handle it
-        var c = config.render ? config : Ext.create(Ext.apply({
+        var c = Ext.create(Ext.apply({
             ownerCt: this
         }, config), defaultType || this.defaultType);
             ownerCt: this
         }, config), defaultType || this.defaultType);
+        delete c.initialConfig.ownerCt;
         delete c.ownerCt;
         return c;
     },
 
     /**
         delete c.ownerCt;
         return 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.
-    */
-
-    // private
+     * @private
+     * 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.getVisibilityEl();
         return el && el.dom && !el.isStyle("display", "none");
     canLayout : function() {
         var el = this.getVisibilityEl();
         return el && el.dom && !el.isStyle("display", "none");
@@ -4702,7 +4780,7 @@ tb.{@link #doLayout}();             // refresh the layout
      */
     getLayout : function(){
         if(!this.layout){
      */
     getLayout : function(){
         if(!this.layout){
-            var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
+            var layout = new Ext.layout.AutoLayout(this.layoutConfig);
             this.setLayout(layout);
         }
         return this.layout;
             this.setLayout(layout);
         }
         return this.layout;
@@ -4724,35 +4802,14 @@ tb.{@link #doLayout}();             // refresh the layout
     },
 
     /**
     },
 
     /**
-     * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
+     * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
+     * each component. The scope (<i>this</i>) of
      * function call will be the scope provided or the current component. The arguments to the function
      * will be the args provided or the current component. If the function returns false at any point,
      * function call will be the scope provided or the current component. The arguments to the function
      * will be the args provided or the current component. If the function returns false at any point,
-     * the bubble is stopped.
+     * the cascade is stopped on that branch.
      * @param {Function} fn The function to call
      * @param {Function} fn The function to call
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)
-     * @param {Array} args (optional) The args to call the function with (default to passing the current component)
-     * @return {Ext.Container} this
-     */
-    bubble : function(fn, scope, args){
-        var p = this;
-        while(p){
-            if(fn.apply(scope || p, args || [p]) === false){
-                break;
-            }
-            p = p.ownerCt;
-        }
-        return this;
-    },
-
-    /**
-     * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
-     * each component. The scope (<i>this</i>) of
-     * function call will be the scope provided or the current component. The arguments to the function
-     * will be the args provided or the current component. If the function returns false at any point,
-     * the cascade is stopped on that branch.
-     * @param {Function} fn The function to call
-     * @param {Object} scope (optional) The scope of the function (defaults to current component)
-     * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
+     * @param {Object} scope (optional) The scope of the function (defaults to current component)
+     * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
      * @return {Ext.Container} this
      */
     cascade : function(fn, scope, args){
      * @return {Ext.Container} this
      */
     cascade : function(fn, scope, args){
@@ -4774,17 +4831,20 @@ tb.{@link #doLayout}();             // refresh the layout
     /**
      * Find a component under this container at any level by id
      * @param {String} id
     /**
      * Find a component under this container at any level by id
      * @param {String} id
+     * @deprecated Fairly useless method, since you can just use Ext.getCmp. Should be removed for 4.0
+     * If you need to test if an id belongs to a container, you can use getCmp and findParent*.
      * @return Ext.Component
      */
     findById : function(id){
      * @return Ext.Component
      */
     findById : function(id){
-        var m, ct = this;
+        var m = null, 
+            ct = this;
         this.cascade(function(c){
             if(ct != c && c.id === id){
                 m = c;
                 return false;
             }
         });
         this.cascade(function(c){
             if(ct != c && c.id === id){
                 m = c;
                 return false;
             }
         });
-        return m || null;
+        return m;
     },
 
     /**
     },
 
     /**
@@ -4832,10 +4892,11 @@ tb.{@link #doLayout}();             // refresh the layout
     /**
      * Get a component contained by this container (alias for items.get(key))
      * @param {String/Number} key The index or id of the component
     /**
      * Get a component contained by this container (alias for items.get(key))
      * @param {String/Number} key The index or id of the component
+     * @deprecated Should be removed in 4.0, since getComponent does the same thing.
      * @return {Ext.Component} Ext.Component
      */
     get : function(key){
      * @return {Ext.Component} Ext.Component
      */
     get : function(key){
-        return this.items.get(key);
+        return this.getComponent(key);
     }
 });
 
     }
 });
 
@@ -4952,19 +5013,27 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
         }
     },
 
         }
     },
 
-    // private
+    /**
+     * @private
+     * Renders the given Component into the target Element. If the Component is already rendered,
+     * it is moved to the provided target instead.
+     * @param {Ext.Component} c The Component to render
+     * @param {Number} position The position within the target to render the item to
+     * @param {Ext.Element} target The target Element
+     */
     renderItem : function(c, position, target){
     renderItem : function(c, position, target){
-        if(c){
-            if(!c.rendered){
+        if (c) {
+            if (!c.rendered) {
                 c.render(target, position);
                 c.render(target, position);
-                this.configureItem(c, position);
-            }else if(!this.isValidParent(c, target)){
-                if(Ext.isNumber(position)){
+                this.configureItem(c);
+            } else if (!this.isValidParent(c, target)) {
+                if (Ext.isNumber(position)) {
                     position = target.dom.childNodes[position];
                 }
                     position = target.dom.childNodes[position];
                 }
+                
                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
                 c.container = target;
                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
                 c.container = target;
-                this.configureItem(c, position);
+                this.configureItem(c);
             }
         }
     },
             }
         }
     },
@@ -4974,21 +5043,25 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
     getRenderedItems: function(ct){
         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
         for (i = 0; i < len; i++) {
     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)){
+            if((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false){
                 items.push(c);
             }
         };
         return items;
     },
 
                 items.push(c);
             }
         };
         return items;
     },
 
-    // private
-    configureItem: function(c, position){
-        if(this.extraCls){
+    /**
+     * @private
+     * Applies extraCls and hides the item if renderHidden is true
+     */
+    configureItem: function(c){
+        if (this.extraCls) {
             var t = c.getPositionEl ? c.getPositionEl() : c;
             t.addClass(this.extraCls);
         }
             var t = c.getPositionEl ? c.getPositionEl() : c;
             t.addClass(this.extraCls);
         }
+        
         // If we are forcing a layout, do so *before* we hide so elements have height/width
         // If we are forcing a layout, do so *before* we hide so elements have height/width
-        if(c.doLayout && this.forceLayout){
+        if (c.doLayout && this.forceLayout) {
             c.doLayout();
         }
         if (this.renderHidden && c != this.activeItem) {
             c.doLayout();
         }
         if (this.renderHidden && c != this.activeItem) {
@@ -4997,10 +5070,10 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
     },
 
     onRemove: function(c){
     },
 
     onRemove: function(c){
-         if(this.activeItem == c){
+        if(this.activeItem == c){
             delete this.activeItem;
             delete this.activeItem;
-         }
-         if(c.rendered && this.extraCls){
+        }
+        if(c.rendered && this.extraCls){
             var t = c.getPositionEl ? c.getPositionEl() : c;
             t.removeClass(this.extraCls);
         }
             var t = c.getPositionEl ? c.getPositionEl() : c;
             t.removeClass(this.extraCls);
         }
@@ -5020,16 +5093,13 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
         if(ct.collapsed){
             return;
         }
         if(ct.collapsed){
             return;
         }
-        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;
-                }
-                ct.layoutPending = true;
-                this.resizeTask.delay(this.resizeBuffer);
+        if(b = ct.bufferResize && ct.shouldBufferLayout()){
+            if(!this.resizeTask){
+                this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
+                this.resizeBuffer = Ext.isNumber(b) ? b : 50;
             }
             }
+            ct.layoutPending = true;
+            this.resizeTask.delay(this.resizeBuffer);
         }else{
             this.runLayout();
         }
         }else{
             this.runLayout();
         }
@@ -5037,27 +5107,20 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
 
     runLayout: function(){
         var ct = this.container;
 
     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();
+        this.layout();
+        ct.onLayout();
         delete ct.layoutPending;
     },
 
     // private
     setContainer : function(ct){
         delete ct.layoutPending;
     },
 
     // private
     setContainer : function(ct){
-        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
-        */
-
+        /**
+         * 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){
         if(this.monitorResize && ct != this.container){
             var old = this.container;
             if(old){
@@ -5070,26 +5133,33 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
         this.container = ct;
     },
 
         this.container = ct;
     },
 
-    // private
+    /**
+     * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
+     * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
+     * @param {Number|String} v The encoded margins
+     * @return {Object} An object with margin sizes for top, right, bottom and left
+     */
     parseMargins : function(v){
     parseMargins : function(v){
-        if(Ext.isNumber(v)){
+        if (Ext.isNumber(v)) {
             v = v.toString();
         }
             v = v.toString();
         }
-        var ms = v.split(' ');
-        var len = ms.length;
-        if(len == 1){
+        var ms  = v.split(' '),
+            len = ms.length;
+            
+        if (len == 1) {
             ms[1] = ms[2] = ms[3] = ms[0];
             ms[1] = ms[2] = ms[3] = ms[0];
-        } else if(len == 2){
+        } else if(len == 2) {
             ms[2] = ms[0];
             ms[3] = ms[1];
             ms[2] = ms[0];
             ms[3] = ms[1];
-        } else if(len == 3){
+        } else if(len == 3) {
             ms[3] = ms[1];
         }
             ms[3] = ms[1];
         }
+        
         return {
         return {
-            top:parseInt(ms[0], 10) || 0,
-            right:parseInt(ms[1], 10) || 0,
+            top   :parseInt(ms[0], 10) || 0,
+            right :parseInt(ms[1], 10) || 0,
             bottom:parseInt(ms[2], 10) || 0,
             bottom:parseInt(ms[2], 10) || 0,
-            left:parseInt(ms[3], 10) || 0
+            left  :parseInt(ms[3], 10) || 0
         };
     },
 
         };
     },
 
@@ -5120,6 +5190,13 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
      * @protected
      */
     destroy : function(){
      * @protected
      */
     destroy : function(){
+        // Stop any buffered layout tasks
+        if(this.resizeTask && this.resizeTask.cancel){
+            this.resizeTask.cancel();
+        }
+        if(this.container) {
+            this.container.un(this.container.resizeEvent, this.onResize, this);
+        }
         if(!Ext.isEmpty(this.targetCls)){
             var target = this.container.getLayoutTarget();
             if(target){
         if(!Ext.isEmpty(this.targetCls)){
             var target = this.container.getLayoutTarget();
             if(target){
@@ -5131,213 +5208,221 @@ Ext.layout.ContainerLayout = Ext.extend(Object, {
  * @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
  * @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>
+ * a {@link Ext.Container Container}.</tt>.  AutoLayout provides only a passthrough of any layout calls
+ * to any child containers.</p>
  */
 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
  */
 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    runLayout: function(){
-        var ct = this.container;
-        ct.doLayout();
-        delete ct.layoutPending;
+    type: 'auto',
+
+    monitorResize: true,
+
+    onLayout : function(ct, target){
+        Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
+        var cs = this.getRenderedItems(ct), len = cs.length, i, c;
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            if (c.doLayout){
+                // Shallow layout children
+                c.doLayout(true);
+            }
+        }
     }
 });
 
 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
     }
 });
 
 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
-/**\r
- * @class Ext.layout.FitLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
- * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}\r
- * config, and should generally not need to be created directly via the new keyword.</p>\r
- * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container\r
- * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has\r
- * multiple panels, only the first one will be displayed.  Example usage:</p>\r
- * <pre><code>\r
-var p = new Ext.Panel({\r
-    title: 'Fit Layout',\r
-    layout:'fit',\r
-    items: {\r
-        title: 'Inner Panel',\r
-        html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',\r
-        border: false\r
-    }\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.FitLayout = Ext.extend(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(!ct.collapsed){\r
-            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());\r
-        }\r
-    },\r
-\r
-    // private\r
-    setItemSize : function(item, size){\r
-        if(item && size.height > 0){ // display none?\r
-            item.setSize(size);\r
-        }\r
-    }\r
-});\r
-Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**\r
- * @class Ext.layout.CardLayout\r
- * @extends Ext.layout.FitLayout\r
- * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be\r
- * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.\r
- * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,\r
- * and should generally not need to be created directly via the new keyword.</p>\r
- * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,\r
- * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of\r
- * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,\r
- * so that functionality must be provided by the developer.</p>\r
- * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added\r
- * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a\r
- * common navigation routine -- for this example, the implementation of that routine has been ommitted since\r
- * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a\r
- * completely different implementation.  For serious implementations, a better approach would be to extend\r
- * CardLayout to provide the custom functionality needed.  Example usage:</p>\r
- * <pre><code>\r
-var navHandler = function(direction){\r
-    // This routine could contain business logic required to manage the navigation steps.\r
-    // It would call setActiveItem as needed, manage navigation button state, handle any\r
-    // branching logic that might be required, handle alternate actions like cancellation\r
-    // or finalization, etc.  A complete wizard implementation could get pretty\r
-    // sophisticated depending on the complexity required, and should probably be\r
-    // done as a subclass of CardLayout in a real-world implementation.\r
-};\r
-\r
-var card = new Ext.Panel({\r
-    title: 'Example Wizard',\r
-    layout:'card',\r
-    activeItem: 0, // make sure the active item is set on the container config!\r
-    bodyStyle: 'padding:15px',\r
-    defaults: {\r
-        // applied to each contained panel\r
-        border:false\r
-    },\r
-    // just an example of one possible navigation scheme, using buttons\r
-    bbar: [\r
-        {\r
-            id: 'move-prev',\r
-            text: 'Back',\r
-            handler: navHandler.createDelegate(this, [-1]),\r
-            disabled: true\r
-        },\r
-        '->', // greedy spacer so that the buttons are aligned to each side\r
-        {\r
-            id: 'move-next',\r
-            text: 'Next',\r
-            handler: navHandler.createDelegate(this, [1])\r
-        }\r
-    ],\r
-    // the panels (or "cards") within the layout\r
-    items: [{\r
-        id: 'card-0',\r
-        html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'\r
-    },{\r
-        id: 'card-1',\r
-        html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'\r
-    },{\r
-        id: 'card-2',\r
-        html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'\r
-    }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
-    /**\r
-     * @cfg {Boolean} deferredRender\r
-     * True to render each contained item at the time it becomes active, false to render all contained items\r
-     * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or\r
-     * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to\r
-     * true might improve performance.\r
-     */\r
-    deferredRender : false,\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
-    layoutOnCardChange : false,\r
-\r
-    /**\r
-     * @cfg {Boolean} renderHidden @hide\r
-     */\r
-    // private\r
-    renderHidden : true,\r
-\r
-    type: 'card',\r
-\r
-    constructor: function(config){\r
-        Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
-    },\r
-\r
-    /**\r
-     * Sets the active (visible) item in the layout.\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
-            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
-            // Change activeItem reference\r
-            this.activeItem = item;\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
-\r
-            if(item.doLayout){\r
-                item.doLayout();\r
-            }\r
-            item.fireEvent('activate', item);\r
-        }\r
-    },\r
-\r
-    // private\r
-    renderAll : function(ct, target){\r
-        if(this.deferredRender){\r
-            this.renderItem(this.activeItem, undefined, target);\r
-        }else{\r
-            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
-        }\r
-    }\r
-});\r
-Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
+/**
+ * @class Ext.layout.FitLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
+ * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
+ * config, and should generally not need to be created directly via the new keyword.</p>
+ * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container
+ * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has
+ * multiple panels, only the first one will be displayed.  Example usage:</p>
+ * <pre><code>
+var p = new Ext.Panel({
+    title: 'Fit Layout',
+    layout:'fit',
+    items: {
+        title: 'Inner Panel',
+        html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',
+        border: false
+    }
+});
+</code></pre>
+ */
+Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    // private
+    monitorResize:true,
+
+    type: 'fit',
+
+    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.FitLayout.superclass.onLayout.call(this, ct, target);
+        if(!ct.collapsed){
+            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
+        }
+    },
+
+    // private
+    setItemSize : function(item, size){
+        if(item && size.height > 0){ // display none?
+            item.setSize(size);
+        }
+    }
+});
+Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
+ * @class Ext.layout.CardLayout
+ * @extends Ext.layout.FitLayout
+ * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
+ * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
+ * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
+ * and should generally not need to be created directly via the new keyword.</p>
+ * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
+ * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
+ * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
+ * so that functionality must be provided by the developer.</p>
+ * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
+ * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
+ * common navigation routine -- for this example, the implementation of that routine has been ommitted since
+ * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
+ * completely different implementation.  For serious implementations, a better approach would be to extend
+ * CardLayout to provide the custom functionality needed.  Example usage:</p>
+ * <pre><code>
+var navHandler = function(direction){
+    // This routine could contain business logic required to manage the navigation steps.
+    // It would call setActiveItem as needed, manage navigation button state, handle any
+    // branching logic that might be required, handle alternate actions like cancellation
+    // or finalization, etc.  A complete wizard implementation could get pretty
+    // sophisticated depending on the complexity required, and should probably be
+    // done as a subclass of CardLayout in a real-world implementation.
+};
+
+var card = new Ext.Panel({
+    title: 'Example Wizard',
+    layout:'card',
+    activeItem: 0, // make sure the active item is set on the container config!
+    bodyStyle: 'padding:15px',
+    defaults: {
+        // applied to each contained panel
+        border:false
+    },
+    // just an example of one possible navigation scheme, using buttons
+    bbar: [
+        {
+            id: 'move-prev',
+            text: 'Back',
+            handler: navHandler.createDelegate(this, [-1]),
+            disabled: true
+        },
+        '->', // greedy spacer so that the buttons are aligned to each side
+        {
+            id: 'move-next',
+            text: 'Next',
+            handler: navHandler.createDelegate(this, [1])
+        }
+    ],
+    // the panels (or "cards") within the layout
+    items: [{
+        id: 'card-0',
+        html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
+    },{
+        id: 'card-1',
+        html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
+    },{
+        id: 'card-2',
+        html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
+    }]
+});
+</code></pre>
+ */
+Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
+    /**
+     * @cfg {Boolean} deferredRender
+     * True to render each contained item at the time it becomes active, false to render all contained items
+     * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
+     * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
+     * true might improve performance.
+     */
+    deferredRender : false,
+
+    /**
+     * @cfg {Boolean} layoutOnCardChange
+     * True to force a layout of the active item when the active card is changed. Defaults to false.
+     */
+    layoutOnCardChange : false,
+
+    /**
+     * @cfg {Boolean} renderHidden @hide
+     */
+    // private
+    renderHidden : true,
+
+    type: 'card',
+
+    /**
+     * Sets the active (visible) item in the layout.
+     * @param {String/Number} item The string component id or numeric index of the item to activate
+     */
+    setActiveItem : function(item){
+        var ai = this.activeItem,
+            ct = this.container;
+        item = ct.getComponent(item);
+
+        // Is this a valid, different card?
+        if(item && ai != item){
+
+            // Changing cards, hide the current one
+            if(ai){
+                ai.hide();
+                if (ai.hidden !== true) {
+                    return false;
+                }
+                ai.fireEvent('deactivate', ai);
+            }
+
+            var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
+
+            // Change activeItem reference
+            this.activeItem = item;
+
+            // The container is about to get a recursive layout, remove any deferLayout reference
+            // because it will trigger a redundant layout.
+            delete item.deferLayout;
+
+            // Show the new component
+            item.show();
+
+            this.layout();
+
+            if(layout){
+                item.doLayout();
+            }
+            item.fireEvent('activate', item);
+        }
+    },
+
+    // private
+    renderAll : function(ct, target){
+        if(this.deferredRender){
+            this.renderItem(this.activeItem, undefined, target);
+        }else{
+            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
+        }
+    }
+});
+Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
+/**
  * @class Ext.layout.AnchorLayout
  * @extends Ext.layout.ContainerLayout
  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
  * @class Ext.layout.AnchorLayout
  * @extends Ext.layout.ContainerLayout
  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
@@ -5424,95 +5509,157 @@ anchor: '-50 75%'
      */
 
     // private
      */
 
     // private
-    monitorResize:true,
-    type: 'anchor',
+    monitorResize : true,
+
+    type : 'anchor',
+
+    /**
+     * @cfg {String} defaultAnchor
+     *
+     * default anchor for all child container items applied if no anchor or specific width is set on the child item.  Defaults to '100%'.
+     *
+     */
+    defaultAnchor : '100%',
+
+    parseAnchorRE : /^(r|right|b|bottom)$/i,
+
 
     getLayoutTargetSize : function() {
 
     getLayoutTargetSize : function() {
-        var target = this.container.getLayoutTarget();
-        if (!target) {
-            return {};
+        var target = this.container.getLayoutTarget(), ret = {};
+        if (target) {
+            ret = target.getViewSize();
+
+            // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
+            // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
+            // with getViewSize
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
         }
         }
-        // Style Sized (scrollbars not included)
-        return target.getStyleSize();
+        return ret;
     },
 
     // private
     },
 
     // private
-    onLayout : function(ct, target){
-        Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
-        var size = this.getLayoutTargetSize();
-
-        var w = size.width, h = size.height;
-
-        if(w < 20 && h < 20){
+    onLayout : function(container, target) {
+        Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
+
+        var size = this.getLayoutTargetSize(),
+            containerWidth = size.width,
+            containerHeight = size.height,
+            overflow = target.getStyle('overflow'),
+            components = this.getRenderedItems(container),
+            len = components.length,
+            boxes = [],
+            box,
+            anchorWidth,
+            anchorHeight,
+            component,
+            anchorSpec,
+            calcWidth,
+            calcHeight,
+            anchorsArray,
+            totalHeight = 0,
+            i,
+            el;
+
+        if(containerWidth < 20 && containerHeight < 20){
             return;
         }
 
         // find the container anchoring size
             return;
         }
 
         // find the container anchoring size
-        var aw, ah;
-        if(ct.anchorSize){
-            if(typeof ct.anchorSize == 'number'){
-                aw = ct.anchorSize;
-            }else{
-                aw = ct.anchorSize.width;
-                ah = ct.anchorSize.height;
+        if(container.anchorSize) {
+            if(typeof container.anchorSize == 'number') {
+                anchorWidth = container.anchorSize;
+            } else {
+                anchorWidth = container.anchorSize.width;
+                anchorHeight = container.anchorSize.height;
             }
             }
-        }else{
-            aw = ct.initialConfig.width;
-            ah = ct.initialConfig.height;
+        } else {
+            anchorWidth = container.initialConfig.width;
+            anchorHeight = container.initialConfig.height;
         }
 
         }
 
-        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();
-            if(c.anchor){
-                a = c.anchorSpec;
-                if(!a){ // cache all anchor values
-                    vs = c.anchor.split(' ');
-                    c.anchorSpec = a = {
-                        right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
-                        bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
+        for(i = 0; i < len; i++) {
+            component = components[i];
+            el = component.getPositionEl();
+
+            // If a child container item has no anchor and no specific width, set the child to the default anchor size
+            if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
+                component.anchor = this.defaultAnchor;
+            }
+
+            if(component.anchor) {
+                anchorSpec = component.anchorSpec;
+                // cache all anchor values
+                if(!anchorSpec){
+                    anchorsArray = component.anchor.split(' ');
+                    component.anchorSpec = anchorSpec = {
+                        right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
+                        bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
                     };
                 }
                     };
                 }
-                cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
-                ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
-
-                if(cw || ch){
-                    c.setSize(cw || undefined, ch || undefined);
+                calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
+                calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
+
+                if(calcWidth || calcHeight) {
+                    boxes.push({
+                        component: component,
+                        width: calcWidth || undefined,
+                        height: calcHeight || undefined
+                    });
                 }
             }
         }
                 }
             }
         }
+        for (i = 0, len = boxes.length; i < len; i++) {
+            box = boxes[i];
+            box.component.setSize(box.width, box.height);
+        }
+
+        if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
+            var newTargetSize = this.getLayoutTargetSize();
+            if (newTargetSize.width != size.width || newTargetSize.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(container, target);
+            }
+        }
+
+        delete this.adjustmentPass;
     },
 
     // private
     },
 
     // private
-    parseAnchor : function(a, start, cstart){
-        if(a && a != 'none'){
+    parseAnchor : function(a, start, cstart) {
+        if (a && a != 'none') {
             var last;
             var last;
-            if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor
+            // standard anchor
+            if (this.parseAnchorRE.test(a)) {
                 var diff = cstart - start;
                 return function(v){
                     if(v !== last){
                         last = v;
                         return v - diff;
                     }
                 var diff = cstart - start;
                 return function(v){
                     if(v !== last){
                         last = v;
                         return v - diff;
                     }
-                }
-            }else if(a.indexOf('%') != -1){
-                var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage
+                };
+            // percentage
+            } else if(a.indexOf('%') != -1) {
+                var ratio = parseFloat(a.replace('%', ''))*.01;
                 return function(v){
                     if(v !== last){
                         last = v;
                         return Math.floor(v*ratio);
                     }
                 return function(v){
                     if(v !== last){
                         last = v;
                         return Math.floor(v*ratio);
                     }
-                }
-            }else{
+                };
+            // simple offset adjustment
+            } else {
                 a = parseInt(a, 10);
                 a = parseInt(a, 10);
-                if(!isNaN(a)){                            // simple offset adjustment
-                    return function(v){
-                        if(v !== last){
+                if (!isNaN(a)) {
+                    return function(v) {
+                        if (v !== last) {
                             last = v;
                             return v + a;
                         }
                             last = v;
                             return v + a;
                         }
-                    }
+                    };
                 }
             }
         }
                 }
             }
         }
@@ -5535,223 +5682,240 @@ anchor: '-50 75%'
      */
 });
 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
      */
 });
 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
-/**\r
- * @class Ext.layout.ColumnLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
- * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.\r
- * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,\r
- * and should generally not need to be created directly via the new keyword.</p>\r
- * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a\r
- * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The\r
- * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.\r
- * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>\r
- * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.\r
- * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and\r
- * less than 1 (e.g., .25).</p>\r
- * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the\r
- * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none\r
- * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second\r
- * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on\r
- * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space\r
- * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns\r
- * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your\r
- * layout may not render as expected.  Example usage:</p>\r
- * <pre><code>\r
-// All columns are percentages -- they must add up to 1\r
-var p = new Ext.Panel({\r
-    title: 'Column Layout - Percentage Only',\r
-    layout:'column',\r
-    items: [{\r
-        title: 'Column 1',\r
-        columnWidth: .25\r
-    },{\r
-        title: 'Column 2',\r
-        columnWidth: .6\r
-    },{\r
-        title: 'Column 3',\r
-        columnWidth: .15\r
-    }]\r
-});\r
-\r
-// Mix of width and columnWidth -- all columnWidth values must add up\r
-// to 1. The first column will take up exactly 120px, and the last two\r
-// columns will fill the remaining container width.\r
-var p = new Ext.Panel({\r
-    title: 'Column Layout - Mixed',\r
-    layout:'column',\r
-    items: [{\r
-        title: 'Column 1',\r
-        width: 120\r
-    },{\r
-        title: 'Column 2',\r
-        columnWidth: .8\r
-    },{\r
-        title: 'Column 3',\r
-        columnWidth: .2\r
-    }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    // private\r
-    monitorResize:true,\r
-\r
-    type: 'column',\r
-\r
-    extraCls: 'x-column',\r
-\r
-    scrollOffset : 0,\r
-\r
-    // private\r
-\r
-    targetCls: 'x-column-layout-ct',\r
-\r
-    isValidParent : function(c, target){\r
-        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
-    },\r
-\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
-        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 = this.getLayoutTargetSize();\r
-\r
-        if(size.width < 1 && size.height < 1){ // display none?\r
-            return;\r
-        }\r
-\r
-        var w = size.width - this.scrollOffset,\r
-            h = size.height,\r
-            pw = w;\r
-\r
-        this.innerCt.setWidth(w);\r
-\r
-        // some columns can be percentages while others are fixed\r
-        // so we need to make 2 passes\r
-\r
-        for(i = 0; i < len; i++){\r
-            c = cs[i];\r
-            if(!c.columnWidth){\r
-                pw -= (c.getWidth() + c.getPositionEl().getMargins('lr'));\r
-            }\r
-        }\r
-\r
-        pw = pw < 0 ? 0 : pw;\r
-\r
-        for(i = 0; i < len; i++){\r
-            c = cs[i];\r
-            if(c.columnWidth){\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
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
- * @class Ext.layout.BorderLayout
+/**
+ * @class Ext.layout.ColumnLayout
  * @extends Ext.layout.ContainerLayout
  * @extends Ext.layout.ContainerLayout
- * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
- * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
- * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
- * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
- * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
- * {@link Ext.Container#layout} config, and should generally not need to be created directly
- * via the new keyword.</p>
- * <p>BorderLayout does not have any direct config options (other than inherited ones).
- * All configuration options available for customizing the BorderLayout are at the
- * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
- * levels.</p>
- * <p>Example usage:</p>
+ * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
+ * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
+ * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
+ * and should generally not need to be created directly via the new keyword.</p>
+ * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
+ * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The
+ * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
+ * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
+ * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
+ * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
+ * less than 1 (e.g., .25).</p>
+ * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the
+ * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none
+ * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second
+ * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
+ * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space
+ * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns
+ * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
+ * layout may not render as expected.  Example usage:</p>
  * <pre><code>
  * <pre><code>
-var myBorderPanel = new Ext.Panel({
-    {@link Ext.Component#renderTo renderTo}: document.body,
-    {@link Ext.BoxComponent#width width}: 700,
-    {@link Ext.BoxComponent#height height}: 500,
-    {@link Ext.Panel#title title}: 'Border Layout',
-    {@link Ext.Container#layout layout}: 'border',
-    {@link Ext.Container#items items}: [{
-        {@link Ext.Panel#title title}: 'South Region is resizable',
-        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
-        {@link Ext.BoxComponent#height height}: 100,
-        {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
-        {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
-        {@link Ext.SplitBar#maxSize maxSize}: 150,
-        {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
+// All columns are percentages -- they must add up to 1
+var p = new Ext.Panel({
+    title: 'Column Layout - Percentage Only',
+    layout:'column',
+    items: [{
+        title: 'Column 1',
+        columnWidth: .25
     },{
     },{
-        // xtype: 'panel' implied by default
-        {@link Ext.Panel#title title}: 'West Region is collapsible',
-        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
-        {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
-        {@link Ext.BoxComponent#width width}: 200,
-        {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
-        {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
-        {@link Ext.Component#id id}: 'west-region-container',
-        {@link Ext.Container#layout layout}: 'fit',
-        {@link Ext.Panel#unstyled unstyled}: true
+        title: 'Column 2',
+        columnWidth: .6
     },{
     },{
-        {@link Ext.Panel#title title}: 'Center Region',
-        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
-        {@link Ext.Component#xtype xtype}: 'container',
-        {@link Ext.Container#layout layout}: 'fit',
-        {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
+        title: 'Column 3',
+        columnWidth: .15
+    }]
+});
+
+// Mix of width and columnWidth -- all columnWidth values must add up
+// to 1. The first column will take up exactly 120px, and the last two
+// columns will fill the remaining container width.
+var p = new Ext.Panel({
+    title: 'Column Layout - Mixed',
+    layout:'column',
+    items: [{
+        title: 'Column 1',
+        width: 120
+    },{
+        title: 'Column 2',
+        columnWidth: .8
+    },{
+        title: 'Column 3',
+        columnWidth: .2
     }]
 });
 </code></pre>
     }]
 });
 </code></pre>
- * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
- * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
- * The child item in the center region will always be resized to fill the remaining space not used by
- * the other regions in the layout.</li>
- * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
- * (an integer representing the number of pixels that the region should take up).</li>
- * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
- * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>.  To add/remove
- * Components within a BorderLayout, have them wrapped by an additional Container which is directly
- * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
- * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
- * is added to the west region:
- * <div style="margin-left:16px"><pre><code>
-wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
+ */
+Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    // private
+    monitorResize:true,
+
+    type: 'column',
+
+    extraCls: 'x-column',
+
+    scrollOffset : 0,
+
+    // private
+
+    targetCls: 'x-column-layout-ct',
+
+    isValidParent : function(c, target){
+        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
+    },
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget(), ret;
+        if (target) {
+            ret = target.getViewSize();
+
+            // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
+            // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
+            // with getViewSize
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        return ret;
+    },
+
+    renderAll : function(ct, target) {
+        if(!this.innerCt){
+            // the innerCt prevents wrapping and shuffling while
+            // the container is resizing
+            this.innerCt = target.createChild({cls:'x-column-inner'});
+            this.innerCt.createChild({cls:'x-clear'});
+        }
+        Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
+    },
+
+    // private
+    onLayout : function(ct, target){
+        var cs = ct.items.items,
+            len = cs.length,
+            c,
+            i,
+            m,
+            margins = [];
+
+        this.renderAll(ct, target);
+
+        var size = this.getLayoutTargetSize();
+
+        if(size.width < 1 && size.height < 1){ // display none?
+            return;
+        }
+
+        var w = size.width - this.scrollOffset,
+            h = size.height,
+            pw = w;
+
+        this.innerCt.setWidth(w);
+
+        // some columns can be percentages while others are fixed
+        // so we need to make 2 passes
+
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            m = c.getPositionEl().getMargins('lr');
+            margins[i] = m;
+            if(!c.columnWidth){
+                pw -= (c.getWidth() + m);
+            }
+        }
+
+        pw = pw < 0 ? 0 : pw;
+
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            m = margins[i];
+            if(c.columnWidth){
+                c.setSize(Math.floor(c.columnWidth * pw) - m);
+            }
+        }
+
+        // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar
+        // spaces were accounted for properly.  If not, re-layout.
+        if (Ext.isIE) {
+            if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+                var ts = this.getLayoutTargetSize();
+                if (ts.width != size.width){
+                    this.adjustmentPass = true;
+                    this.onLayout(ct, target);
+                }
+            }
+        }
+        delete this.adjustmentPass;
+    }
+
+    /**
+     * @property activeItem
+     * @hide
+     */
+});
+
+Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
+/**
+ * @class Ext.layout.BorderLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
+ * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
+ * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
+ * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
+ * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
+ * {@link Ext.Container#layout} config, and should generally not need to be created directly
+ * via the new keyword.</p>
+ * <p>BorderLayout does not have any direct config options (other than inherited ones).
+ * All configuration options available for customizing the BorderLayout are at the
+ * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
+ * levels.</p>
+ * <p>Example usage:</p>
+ * <pre><code>
+var myBorderPanel = new Ext.Panel({
+    {@link Ext.Component#renderTo renderTo}: document.body,
+    {@link Ext.BoxComponent#width width}: 700,
+    {@link Ext.BoxComponent#height height}: 500,
+    {@link Ext.Panel#title title}: 'Border Layout',
+    {@link Ext.Container#layout layout}: 'border',
+    {@link Ext.Container#items items}: [{
+        {@link Ext.Panel#title title}: 'South Region is resizable',
+        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
+        {@link Ext.BoxComponent#height height}: 100,
+        {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
+        {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
+        {@link Ext.SplitBar#maxSize maxSize}: 150,
+        {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
+    },{
+        // xtype: 'panel' implied by default
+        {@link Ext.Panel#title title}: 'West Region is collapsible',
+        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
+        {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
+        {@link Ext.BoxComponent#width width}: 200,
+        {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
+        {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
+        {@link Ext.Component#id id}: 'west-region-container',
+        {@link Ext.Container#layout layout}: 'fit',
+        {@link Ext.Panel#unstyled unstyled}: true
+    },{
+        {@link Ext.Panel#title title}: 'Center Region',
+        {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
+        {@link Ext.Component#xtype xtype}: 'container',
+        {@link Ext.Container#layout layout}: 'fit',
+        {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
+    }]
+});
+</code></pre>
+ * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
+ * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
+ * The child item in the center region will always be resized to fill the remaining space not used by
+ * the other regions in the layout.</li>
+ * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
+ * (an integer representing the number of pixels that the region should take up).</li>
+ * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
+ * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>.  To add/remove
+ * Components within a BorderLayout, have them wrapped by an additional Container which is directly
+ * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
+ * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
+ * is added to the west region:
+ * <div style="margin-left:16px"><pre><code>
+wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
 wrc.{@link Ext.Panel#removeAll removeAll}();
 wrc.{@link Ext.Container#add add}({
     title: 'Added Panel',
 wrc.{@link Ext.Panel#removeAll removeAll}();
 wrc.{@link Ext.Container#add add}({
     title: 'Added Panel',
@@ -6175,7 +6339,7 @@ Ext.layout.BorderLayout.Region.prototype = {
                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
             }else {
                 if(this.collapsible !== false && !this.hideCollapseTool) {
                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
             }else {
                 if(this.collapsible !== false && !this.hideCollapseTool) {
-                    var t = this.toolTemplate.append(
+                    var t = this.expandToolEl = this.toolTemplate.append(
                             this.collapsedEl.dom,
                             {id:'expand-'+this.position}, true);
                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
                             this.collapsedEl.dom,
                             {id:'expand-'+this.position}, true);
                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
@@ -6372,15 +6536,15 @@ Ext.layout.BorderLayout.Region.prototype = {
     initAutoHide : function(){
         if(this.autoHide !== false){
             if(!this.autoHideHd){
     initAutoHide : function(){
         if(this.autoHide !== false){
             if(!this.autoHideHd){
-                var st = new Ext.util.DelayedTask(this.slideIn, this);
+                this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
                 this.autoHideHd = {
                     "mouseout": function(e){
                         if(!e.within(this.el, true)){
                 this.autoHideHd = {
                     "mouseout": function(e){
                         if(!e.within(this.el, true)){
-                            st.delay(500);
+                            this.autoHideSlideTask.delay(500);
                         }
                     },
                     "mouseover" : function(e){
                         }
                     },
                     "mouseover" : function(e){
-                        st.cancel();
+                        this.autoHideSlideTask.cancel();
                     },
                     scope : this
                 };
                     },
                     scope : this
                 };
@@ -6591,7 +6755,10 @@ Ext.layout.BorderLayout.Region.prototype = {
     },
 
     destroy : function(){
     },
 
     destroy : function(){
-        Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
+        if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
+            this.autoHideSlideTask.cancel();
+        }
+        Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
     }
 };
 
     }
 };
 
@@ -6829,7 +6996,8 @@ Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region,
     }
 });
 
     }
 });
 
-Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
+Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
+/**
  * @class Ext.layout.FormLayout
  * @extends Ext.layout.AnchorLayout
  * <p>This layout manager is specifically designed for rendering and managing child Components of
  * @class Ext.layout.FormLayout
  * @extends Ext.layout.AnchorLayout
  * <p>This layout manager is specifically designed for rendering and managing child Components of
@@ -6942,13 +7110,12 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
 
     /**
      * @cfg {Boolean} trackLabels
 
     /**
      * @cfg {Boolean} trackLabels
-     * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
+     * True to show/hide the field label when the field is hidden. Defaults to <tt>true</tt>.
      */
      */
-    trackLabels: false,
+    trackLabels: true,
 
     type: 'form',
 
 
     type: 'form',
 
-
     onRemove: function(c){
         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
         if(this.trackLabels){
     onRemove: function(c){
         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
         if(this.trackLabels){
@@ -6957,14 +7124,14 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
         }
         // check for itemCt, since we may be removing a fieldset or something similar
         var el = c.getPositionEl(),
         }
         // check for itemCt, since we may be removing a fieldset or something similar
         var el = c.getPositionEl(),
-                ct = c.getItemCt && c.getItemCt();
-        if(c.rendered && ct){
+            ct = c.getItemCt && c.getItemCt();
+        if (c.rendered && ct) {
             if (el && el.dom) {
                 el.insertAfter(ct);
             }
             Ext.destroy(ct);
             Ext.destroyMembers(c, 'label', 'itemCt');
             if (el && el.dom) {
                 el.insertAfter(ct);
             }
             Ext.destroy(ct);
             Ext.destroyMembers(c, 'label', 'itemCt');
-            if(c.customItemCt){
+            if (c.customItemCt) {
                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
             }
         }
                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
             }
         }
@@ -6984,7 +7151,7 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
                 labelAdjust: 0
             });
         }else{
                 labelAdjust: 0
             });
         }else{
-            this.labelSeparator = ct.labelSeparator || this.labelSeparator;
+            this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
             ct.labelWidth = ct.labelWidth || 100;
             if(Ext.isNumber(ct.labelWidth)){
                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
             ct.labelWidth = ct.labelWidth || 100;
             if(Ext.isNumber(ct.labelWidth)){
                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
@@ -7011,6 +7178,11 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
 
     onFieldShow: function(c){
         c.getItemCt().removeClass('x-hide-' + c.hideMode);
 
     onFieldShow: function(c){
         c.getItemCt().removeClass('x-hide-' + c.hideMode);
+
+        // Composite fields will need to layout after the container is made visible
+        if (c.isComposite) {
+            c.doLayout();
+        }
     },
 
     onFieldHide: function(c){
     },
 
     onFieldHide: function(c){
@@ -7024,7 +7196,7 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
             if (items[i]){
                 ls += items[i];
                 if (ls.substr(-1, 1) != ';'){
             if (items[i]){
                 ls += items[i];
                 if (ls.substr(-1, 1) != ';'){
-                    ls += ';'
+                    ls += ';';
                 }
             }
         }
                 }
             }
         }
@@ -7065,7 +7237,10 @@ new Ext.Template(
      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
      */
 
      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
      */
 
-    // private
+    /**
+     * @private
+     *
+     */
     renderItem : function(c, position, target){
         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
             var args = this.getTemplateArgs(c);
     renderItem : function(c, position, target){
         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
             var args = this.getTemplateArgs(c);
@@ -7123,7 +7298,7 @@ new Ext.Template(
      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
-     * field (defaults to <tt>''</tt>)</div></li>
+     * field (defaults to the field's configured fieldLabel property)</div></li>
      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
@@ -7132,18 +7307,19 @@ new Ext.Template(
      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
      * </ul></div>
      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
      * </ul></div>
      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
-     * @return An object hash containing the properties required to render the Field.
+     * @return {Object} An object hash containing the properties required to render the Field.
      */
     getTemplateArgs: function(field) {
         var noLabelSep = !field.fieldLabel || field.hideLabel;
      */
     getTemplateArgs: function(field) {
         var noLabelSep = !field.fieldLabel || field.hideLabel;
+
         return {
         return {
-            id: field.id,
-            label: field.fieldLabel,
-            labelStyle: this.getLabelStyle(field.labelStyle),
-            elementStyle: this.elementStyle||'',
-            labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
-            itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
-            clearCls: field.clearCls || 'x-form-clear-left'
+            id            : field.id,
+            label         : field.fieldLabel,
+            itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
+            clearCls      : field.clearCls || 'x-form-clear-left',
+            labelStyle    : this.getLabelStyle(field.labelStyle),
+            elementStyle  : this.elementStyle || '',
+            labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
         };
     },
 
         };
     },
 
@@ -7175,478 +7351,483 @@ new Ext.Template(
 });
 
 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
 });
 
 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
-/**\r
- * @class Ext.layout.AccordionLayout\r
- * @extends Ext.layout.FitLayout\r
- * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
- * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>\r
- * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</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 accordion = new Ext.Panel({\r
-    title: 'Accordion Layout',\r
-    layout:'accordion',\r
-    defaults: {\r
-        // applied to each contained panel\r
-        bodyStyle: 'padding:15px'\r
-    },\r
-    layoutConfig: {\r
-        // layout-specific configs go here\r
-        titleCollapse: false,\r
-        animate: true,\r
-        activeOnTop: true\r
-    },\r
-    items: [{\r
-        title: 'Panel 1',\r
-        html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
-    },{\r
-        title: 'Panel 2',\r
-        html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
-    },{\r
-        title: 'Panel 3',\r
-        html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
-    }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {\r
-    /**\r
-     * @cfg {Boolean} fill\r
-     * True to adjust the active item's height to fill the available space in the container, false to use the\r
-     * item's current height, or auto height if not explicitly set (defaults to true).\r
-     */\r
-    fill : true,\r
-    /**\r
-     * @cfg {Boolean} autoWidth\r
-     * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).\r
-     * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within\r
-     * layouts if they have auto width, so in such cases this config should be set to false.\r
-     */\r
-    autoWidth : true,\r
-    /**\r
-     * @cfg {Boolean} titleCollapse\r
-     * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow\r
-     * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,\r
-     * {@link #hideCollapseTool} should be false also.\r
-     */\r
-    titleCollapse : true,\r
-    /**\r
-     * @cfg {Boolean} hideCollapseTool\r
-     * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).\r
-     * When set to true, {@link #titleCollapse} should be true also.\r
-     */\r
-    hideCollapseTool : false,\r
-    /**\r
-     * @cfg {Boolean} collapseFirst\r
-     * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools\r
-     * in the contained panels' title bars, false to render it last (defaults to false).\r
-     */\r
-    collapseFirst : false,\r
-    /**\r
-     * @cfg {Boolean} animate\r
-     * True to slide the contained panels open and closed during expand/collapse using animation, false to open and\r
-     * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each\r
-     * contained panel for this property, set this to undefined at the layout level.\r
-     */\r
-    animate : false,\r
-    /**\r
-     * @cfg {Boolean} sequence\r
-     * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.\r
-     */\r
-    sequence : false,\r
-    /**\r
-     * @cfg {Boolean} activeOnTop\r
-     * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,\r
-     * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).\r
-     */\r
-    activeOnTop : false,\r
-\r
-    type: 'accordion',\r
-\r
-    renderItem : function(c){\r
-        if(this.animate === false){\r
-            c.animCollapse = false;\r
-        }\r
-        c.collapsible = true;\r
-        if(this.autoWidth){\r
-            c.autoWidth = true;\r
-        }\r
-        if(this.titleCollapse){\r
-            c.titleCollapse = true;\r
-        }\r
-        if(this.hideCollapseTool){\r
-            c.hideCollapseTool = true;\r
-        }\r
-        if(this.collapseFirst !== undefined){\r
-            c.collapseFirst = this.collapseFirst;\r
-        }\r
-        if(!this.activeItem && !c.collapsed){\r
-            this.setActiveItem(c, true);\r
-        }else if(this.activeItem && this.activeItem != c){\r
-            c.collapsed = true;\r
-        }\r
-        Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\r
-        c.header.addClass('x-accordion-hd');\r
-        c.on('beforeexpand', this.beforeExpand, this);\r
-    },\r
-\r
-    onRemove: function(c){\r
-        Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
-        if(c.rendered){\r
-            c.header.removeClass('x-accordion-hd');\r
-        }\r
-        c.un('beforeexpand', this.beforeExpand, this);\r
-    },\r
-\r
-    // private\r
-    beforeExpand : function(p, anim){\r
-        var ai = this.activeItem;\r
-        if(ai){\r
-            if(this.sequence){\r
-                delete this.activeItem;\r
-                if (!ai.collapsed){\r
-                    ai.collapse({callback:function(){\r
-                        p.expand(anim || true);\r
-                    }, scope: this});\r
-                    return false;\r
-                }\r
-            }else{\r
-                ai.collapse(this.animate);\r
-            }\r
-        }\r
-        this.setActive(p);\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, 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
-            // 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
-\r
-    /**\r
-     * Sets the active (expanded) item in the layout.\r
-     * @param {String/Number} item The string component id or numeric index of the item to activate\r
-     */\r
-    setActiveItem : function(item){\r
-        this.setActive(item, true);\r
-    },\r
-\r
-    // private\r
-    setActive : function(item, expand){\r
-        var ai = this.activeItem;\r
-        item = this.container.getComponent(item);\r
-        if(ai != item){\r
-            if(item.rendered && item.collapsed && expand){\r
-                item.expand();\r
-            }else{\r
-                if(ai){\r
-                   ai.fireEvent('deactivate', ai);\r
-                }\r
-                this.activeItem = item;\r
-                item.fireEvent('activate', item);\r
-            }\r
-        }\r
-    }\r
-});\r
-Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
-\r
-//backwards compat\r
-Ext.layout.Accordion = Ext.layout.AccordionLayout;/**\r
- * @class Ext.layout.TableLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
- * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
- * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
- * and should generally not need to be created directly via the new keyword.</p>\r
- * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
- * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
- * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
- * TableLayout can supply the following table-specific config properties:</p>\r
- * <ul>\r
- * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
- * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
- * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
- * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
- * </ul>\r
- * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
- * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
- * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
- * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
- * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
- * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
- * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
- * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
- * <pre><code>\r
-// This code will generate a layout table that is 3 columns by 2 rows\r
-// with some spanning included.  The basic layout will be:\r
-// +--------+-----------------+\r
-// |   A    |   B             |\r
-// |        |--------+--------|\r
-// |        |   C    |   D    |\r
-// +--------+--------+--------+\r
-var table = new Ext.Panel({\r
-    title: 'Table Layout',\r
-    layout:'table',\r
-    defaults: {\r
-        // applied to each contained panel\r
-        bodyStyle:'padding:20px'\r
-    },\r
-    layoutConfig: {\r
-        // The total column count must be specified here\r
-        columns: 3\r
-    },\r
-    items: [{\r
-        html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
-        rowspan: 2\r
-    },{\r
-        html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
-        colspan: 2\r
-    },{\r
-        html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
-        cellCls: 'highlight'\r
-    },{\r
-        html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
-    }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    /**\r
-     * @cfg {Number} columns\r
-     * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
-     * this layout will be rendered into a single row using one column per Component.\r
-     */\r
-\r
-    // private\r
-    monitorResize:false,\r
-\r
-    type: 'table',\r
-\r
-    targetCls: 'x-table-layout-ct',\r
-\r
-    /**\r
-     * @cfg {Object} tableAttrs\r
-     * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
-     * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
-{\r
-    xtype: 'panel',\r
-    layout: 'table',\r
-    layoutConfig: {\r
-        tableAttrs: {\r
-            style: {\r
-                width: '100%'\r
-            }\r
-        },\r
-        columns: 3\r
-    }\r
-}</code></pre>\r
-     */\r
-    tableAttrs:null,\r
-\r
-    // private\r
-    setContainer : function(ct){\r
-        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
-\r
-        this.currentRow = 0;\r
-        this.currentColumn = 0;\r
-        this.cells = [];\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.renderAll(ct, target);\r
-    },\r
-\r
-    // private\r
-    getRow : function(index){\r
-        var row = this.table.tBodies[0].childNodes[index];\r
-        if(!row){\r
-            row = document.createElement('tr');\r
-            this.table.tBodies[0].appendChild(row);\r
-        }\r
-        return row;\r
-    },\r
-\r
-    // private\r
-    getNextCell : function(c){\r
-        var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
-        var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
-        for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
-            if(!this.cells[rowIndex]){\r
-                this.cells[rowIndex] = [];\r
-            }\r
-            for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
-                this.cells[rowIndex][colIndex] = true;\r
-            }\r
-        }\r
-        var td = document.createElement('td');\r
-        if(c.cellId){\r
-            td.id = c.cellId;\r
-        }\r
-        var cls = 'x-table-layout-cell';\r
-        if(c.cellCls){\r
-            cls += ' ' + c.cellCls;\r
-        }\r
-        td.className = cls;\r
-        if(c.colspan){\r
-            td.colSpan = c.colspan;\r
-        }\r
-        if(c.rowspan){\r
-            td.rowSpan = c.rowspan;\r
-        }\r
-        this.getRow(curRow).appendChild(td);\r
-        return td;\r
-    },\r
-\r
-    // private\r
-    getNextNonSpan: function(colIndex, rowIndex){\r
-        var cols = this.columns;\r
-        while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
-            if(cols && colIndex >= cols){\r
-                rowIndex++;\r
-                colIndex = 0;\r
-            }else{\r
-                colIndex++;\r
-            }\r
-        }\r
-        return [colIndex, rowIndex];\r
-    },\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
-        }else if(c && !this.isValidParent(c, target)){\r
-            var container = this.getNextCell(c);\r
-            container.insertBefore(c.getPositionEl().dom, null);\r
-            c.container = Ext.get(container);\r
-            this.configureItem(c, position);\r
-        }\r
-    },\r
-\r
-    // private\r
-    isValidParent : function(c, target){\r
-        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
-    }\r
-\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-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>
+/**
+ * @class Ext.layout.AccordionLayout
+ * @extends Ext.layout.FitLayout
+ * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
+ * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
+ * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</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>
  * <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',
+var accordion = new Ext.Panel({
+    title: 'Accordion Layout',
+    layout:'accordion',
+    defaults: {
+        // applied to each contained panel
+        bodyStyle: 'padding:15px'
+    },
     layoutConfig: {
         // layout-specific configs go here
     layoutConfig: {
         // layout-specific configs go here
-        extraCls: 'x-abs-layout-item',
+        titleCollapse: false,
+        animate: true,
+        activeOnTop: true
     },
     },
-    baseCls: 'x-plain',
-    url:'save-form.php',
-    defaultType: 'textfield',
     items: [{
     items: [{
-        x: 0,
-        y: 5,
-        xtype:'label',
-        text: 'Send To:'
-    },{
-        x: 60,
-        y: 0,
-        name: 'to',
-        anchor:'100%'  // anchor width by percentage
+        title: 'Panel 1',
+        html: '&lt;p&gt;Panel content!&lt;/p&gt;'
     },{
     },{
-        x: 0,
-        y: 35,
-        xtype:'label',
-        text: 'Subject:'
-    },{
-        x: 60,
-        y: 30,
-        name: 'subject',
-        anchor: '100%'  // anchor width by percentage
+        title: 'Panel 2',
+        html: '&lt;p&gt;Panel content!&lt;/p&gt;'
     },{
     },{
-        x:0,
-        y: 60,
-        xtype: 'textarea',
-        name: 'msg',
-        anchor: '100% 100%'  // anchor width and height
+        title: 'Panel 3',
+        html: '&lt;p&gt;Panel content!&lt;/p&gt;'
     }]
 });
 </code></pre>
  */
     }]
 });
 </code></pre>
  */
-Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
+Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
+    /**
+     * @cfg {Boolean} fill
+     * True to adjust the active item's height to fill the available space in the container, false to use the
+     * item's current height, or auto height if not explicitly set (defaults to true).
+     */
+    fill : true,
+    /**
+     * @cfg {Boolean} autoWidth
+     * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
+     * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
+     * layouts if they have auto width, so in such cases this config should be set to false.
+     */
+    autoWidth : true,
+    /**
+     * @cfg {Boolean} titleCollapse
+     * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
+     * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,
+     * {@link #hideCollapseTool} should be false also.
+     */
+    titleCollapse : true,
+    /**
+     * @cfg {Boolean} hideCollapseTool
+     * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
+     * When set to true, {@link #titleCollapse} should be true also.
+     */
+    hideCollapseTool : false,
+    /**
+     * @cfg {Boolean} collapseFirst
+     * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
+     * in the contained panels' title bars, false to render it last (defaults to false).
+     */
+    collapseFirst : false,
+    /**
+     * @cfg {Boolean} animate
+     * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
+     * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each
+     * contained panel for this property, set this to undefined at the layout level.
+     */
+    animate : false,
+    /**
+     * @cfg {Boolean} sequence
+     * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
+     */
+    sequence : false,
+    /**
+     * @cfg {Boolean} activeOnTop
+     * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
+     * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
+     */
+    activeOnTop : false,
 
 
-    extraCls: 'x-abs-layout-item',
+    type: 'accordion',
 
 
-    type: 'anchor',
+    renderItem : function(c){
+        if(this.animate === false){
+            c.animCollapse = false;
+        }
+        c.collapsible = true;
+        if(this.autoWidth){
+            c.autoWidth = true;
+        }
+        if(this.titleCollapse){
+            c.titleCollapse = true;
+        }
+        if(this.hideCollapseTool){
+            c.hideCollapseTool = true;
+        }
+        if(this.collapseFirst !== undefined){
+            c.collapseFirst = this.collapseFirst;
+        }
+        if(!this.activeItem && !c.collapsed){
+            this.setActiveItem(c, true);
+        }else if(this.activeItem && this.activeItem != c){
+            c.collapsed = true;
+        }
+        Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
+        c.header.addClass('x-accordion-hd');
+        c.on('beforeexpand', this.beforeExpand, this);
+    },
 
 
-    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);
+    onRemove: function(c){
+        Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
+        if(c.rendered){
+            c.header.removeClass('x-accordion-hd');
+        }
+        c.un('beforeexpand', this.beforeExpand, this);
     },
 
     // private
     },
 
     // private
-    adjustWidthAnchor : function(value, comp){
-        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
+    beforeExpand : function(p, anim){
+        var ai = this.activeItem;
+        if(ai){
+            if(this.sequence){
+                delete this.activeItem;
+                if (!ai.collapsed){
+                    ai.collapse({callback:function(){
+                        p.expand(anim || true);
+                    }, scope: this});
+                    return false;
+                }
+            }else{
+                ai.collapse(this.animate);
+            }
+        }
+        this.setActive(p);
+        if(this.activeOnTop){
+            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
+        }
+        // Items have been hidden an possibly rearranged, we need to get the container size again.
+        this.layout();
     },
 
     // private
     },
 
     // private
-    adjustHeightAnchor : function(value, comp){
-        return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
-    }
+    setItemSize : function(item, size){
+        if(this.fill && item){
+            var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
+            // Add up all the header heights
+            for (i = 0; i < len; i++) {
+                if((p = ct[i]) != item && !p.hidden){
+                    hh += p.header.getHeight();
+                }
+            };
+            // Subtract the header heights from the container size
+            size.height -= hh;
+            // Call setSize on the container to set the correct height.  For Panels, deferedHeight
+            // will simply store this size for when the expansion is done.
+            item.setSize(size);
+        }
+    },
+
     /**
     /**
-     * @property activeItem
-     * @hide
+     * Sets the active (expanded) item in the layout.
+     * @param {String/Number} item The string component id or numeric index of the item to activate
      */
      */
+    setActiveItem : function(item){
+        this.setActive(item, true);
+    },
+
+    // private
+    setActive : function(item, expand){
+        var ai = this.activeItem;
+        item = this.container.getComponent(item);
+        if(ai != item){
+            if(item.rendered && item.collapsed && expand){
+                item.expand();
+            }else{
+                if(ai){
+                   ai.fireEvent('deactivate', ai);
+                }
+                this.activeItem = item;
+                item.fireEvent('activate', item);
+            }
+        }
+    }
 });
 });
-Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
-/**
- * @class Ext.layout.BoxLayout
+Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
+
+//backwards compat
+Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
+ * @class Ext.layout.TableLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be
+ * specified, and rowspan and colspan can be used to create complex layouts within the table.
+ * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
+ * and should generally not need to be created directly via the new keyword.</p>
+ * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
+ * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the
+ * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a
+ * TableLayout can supply the following table-specific config properties:</p>
+ * <ul>
+ * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
+ * <li><b>colspan</b> Applied to the table cell containing the item.</li>
+ * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
+ * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
+ * </ul>
+ * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
+ * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes
+ * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
+ * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
+ * total column count in the layoutConfig and start adding panels in their natural order from left to right,
+ * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,
+ * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add
+ * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>
+ * <pre><code>
+// This code will generate a layout table that is 3 columns by 2 rows
+// with some spanning included.  The basic layout will be:
+// +--------+-----------------+
+// |   A    |   B             |
+// |        |--------+--------|
+// |        |   C    |   D    |
+// +--------+--------+--------+
+var table = new Ext.Panel({
+    title: 'Table Layout',
+    layout:'table',
+    defaults: {
+        // applied to each contained panel
+        bodyStyle:'padding:20px'
+    },
+    layoutConfig: {
+        // The total column count must be specified here
+        columns: 3
+    },
+    items: [{
+        html: '&lt;p&gt;Cell A content&lt;/p&gt;',
+        rowspan: 2
+    },{
+        html: '&lt;p&gt;Cell B content&lt;/p&gt;',
+        colspan: 2
+    },{
+        html: '&lt;p&gt;Cell C content&lt;/p&gt;',
+        cellCls: 'highlight'
+    },{
+        html: '&lt;p&gt;Cell D content&lt;/p&gt;'
+    }]
+});
+</code></pre>
+ */
+Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    /**
+     * @cfg {Number} columns
+     * The total number of columns to create in the table for this layout.  If not specified, all Components added to
+     * this layout will be rendered into a single row using one column per Component.
+     */
+
+    // private
+    monitorResize:false,
+
+    type: 'table',
+
+    targetCls: 'x-table-layout-ct',
+
+    /**
+     * @cfg {Object} tableAttrs
+     * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
+     * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>
+{
+    xtype: 'panel',
+    layout: 'table',
+    layoutConfig: {
+        tableAttrs: {
+            style: {
+                width: '100%'
+            }
+        },
+        columns: 3
+    }
+}</code></pre>
+     */
+    tableAttrs:null,
+
+    // private
+    setContainer : function(ct){
+        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
+
+        this.currentRow = 0;
+        this.currentColumn = 0;
+        this.cells = [];
+    },
+    
+    // private
+    onLayout : function(ct, target){
+        var cs = ct.items.items, len = cs.length, c, i;
+
+        if(!this.table){
+            target.addClass('x-table-layout-ct');
+
+            this.table = target.createChild(
+                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
+        }
+        this.renderAll(ct, target);
+    },
+
+    // private
+    getRow : function(index){
+        var row = this.table.tBodies[0].childNodes[index];
+        if(!row){
+            row = document.createElement('tr');
+            this.table.tBodies[0].appendChild(row);
+        }
+        return row;
+    },
+
+    // private
+    getNextCell : function(c){
+        var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
+        var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
+        for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
+            if(!this.cells[rowIndex]){
+                this.cells[rowIndex] = [];
+            }
+            for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
+                this.cells[rowIndex][colIndex] = true;
+            }
+        }
+        var td = document.createElement('td');
+        if(c.cellId){
+            td.id = c.cellId;
+        }
+        var cls = 'x-table-layout-cell';
+        if(c.cellCls){
+            cls += ' ' + c.cellCls;
+        }
+        td.className = cls;
+        if(c.colspan){
+            td.colSpan = c.colspan;
+        }
+        if(c.rowspan){
+            td.rowSpan = c.rowspan;
+        }
+        this.getRow(curRow).appendChild(td);
+        return td;
+    },
+
+    // private
+    getNextNonSpan: function(colIndex, rowIndex){
+        var cols = this.columns;
+        while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
+            if(cols && colIndex >= cols){
+                rowIndex++;
+                colIndex = 0;
+            }else{
+                colIndex++;
+            }
+        }
+        return [colIndex, rowIndex];
+    },
+
+    // private
+    renderItem : function(c, position, target){
+        // Ensure we have our inner table to get cells to render into.
+        if(!this.table){
+            this.table = target.createChild(
+                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
+        }
+        if(c && !c.rendered){
+            c.render(this.getNextCell(c));
+            this.configureItem(c);
+        }else if(c && !this.isValidParent(c, target)){
+            var container = this.getNextCell(c);
+            container.insertBefore(c.getPositionEl().dom, null);
+            c.container = Ext.get(container);
+            this.configureItem(c);
+        }
+    },
+
+    // private
+    isValidParent : function(c, target){
+        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
+    },
+    
+    destroy: function(){
+        delete this.table;
+        Ext.layout.TableLayout.superclass.destroy.call(this);
+    }
+
+    /**
+     * @property activeItem
+     * @hide
+     */
+});
+
+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: 'absolute',
+
+    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>
  */
  * @extends Ext.layout.ContainerLayout
  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
  */
@@ -7712,1013 +7893,2478 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
 
     constructor : function(config){
         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
 
     constructor : function(config){
         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
-        if(Ext.isString(this.defaultMargins)){
+
+        if (Ext.isString(this.defaultMargins)) {
             this.defaultMargins = this.parseMargins(this.defaultMargins);
         }
             this.defaultMargins = this.parseMargins(this.defaultMargins);
         }
+        
+        var handler = this.overflowHandler;
+        
+        if (typeof handler == 'string') {
+            handler = {
+                type: handler
+            };
+        }
+        
+        var handlerType = 'none';
+        if (handler && handler.type != undefined) {
+            handlerType = handler.type;
+        }
+        
+        var constructor = Ext.layout.boxOverflow[handlerType];
+        if (constructor[this.type]) {
+            constructor = constructor[this.type];
+        }
+        
+        this.overflowHandler = new constructor(this, handler);
+    },
+
+    /**
+     * @private
+     * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
+     * when laying out
+     */
+    onLayout: function(container, target) {
+        Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
+
+        var tSize = this.getLayoutTargetSize(),
+            items = this.getVisibleItems(container),
+            calcs = this.calculateChildBoxes(items, tSize),
+            boxes = calcs.boxes,
+            meta  = calcs.meta;
+        
+        //invoke the overflow handler, if one is configured
+        if (tSize.width > 0) {
+            var handler = this.overflowHandler,
+                method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
+            
+            var results = handler[method](calcs, tSize);
+            
+            if (results) {
+                if (results.targetSize) {
+                    tSize = results.targetSize;
+                }
+                
+                if (results.recalculate) {
+                    items = this.getVisibleItems(container);
+                    calcs = this.calculateChildBoxes(items, tSize);
+                    boxes = calcs.boxes;
+                }
+            }
+        }
+        
+        /**
+         * @private
+         * @property layoutTargetLastSize
+         * @type Object
+         * Private cache of the last measured size of the layout target. This should never be used except by
+         * BoxLayout subclasses during their onLayout run.
+         */
+        this.layoutTargetLastSize = tSize;
+        
+        /**
+         * @private
+         * @property childBoxCache
+         * @type Array
+         * Array of the last calculated height, width, top and left positions of each visible rendered component
+         * within the Box layout.
+         */
+        this.childBoxCache = calcs;
+        
+        this.updateInnerCtSize(tSize, calcs);
+        this.updateChildBoxes(boxes);
+
+        // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+        this.handleTargetOverflow(tSize, container, target);
+    },
+
+    /**
+     * Resizes and repositions each child component
+     * @param {Array} boxes The box measurements
+     */
+    updateChildBoxes: function(boxes) {
+        for (var i = 0, length = boxes.length; i < length; i++) {
+            var box  = boxes[i],
+                comp = box.component;
+            
+            if (box.dirtySize) {
+                comp.setSize(box.width, box.height);
+            }
+            // Don't set positions to NaN
+            if (isNaN(box.left) || isNaN(box.top)) {
+                continue;
+            }
+            
+            comp.setPosition(box.left, box.top);
+        }
+    },
+
+    /**
+     * @private
+     * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
+     * to make sure all child items fit within it. We call this before sizing the children because if our child
+     * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
+     * again immediately afterwards, giving a performance hit.
+     * Subclasses should provide an implementation.
+     * @param {Object} currentSize The current height and width of the innerCt
+     * @param {Array} calculations The new box calculations of all items to be laid out
+     */
+    updateInnerCtSize: function(tSize, calcs) {
+        var align   = this.align,
+            padding = this.padding,
+            width   = tSize.width,
+            height  = tSize.height;
+        
+        if (this.type == 'hbox') {
+            var innerCtWidth  = width,
+                innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
+
+            if (align == 'stretch') {
+                innerCtHeight = height;
+            } else if (align == 'middle') {
+                innerCtHeight = Math.max(height, innerCtHeight);
+            }
+        } else {
+            var innerCtHeight = height,
+                innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
+
+            if (align == 'stretch') {
+                innerCtWidth = width;
+            } else if (align == 'center') {
+                innerCtWidth = Math.max(width, innerCtWidth);
+            }
+        }
+
+        this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+    },
+
+    /**
+     * @private
+     * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
+     * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
+     * target. Having a Box layout inside such a target is therefore not recommended.
+     * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
+     * @param {Ext.Container} container The container
+     * @param {Ext.Element} target The target element
+     */
+    handleTargetOverflow: function(previousTargetSize, container, target) {
+        var overflow = target.getStyle('overflow');
+
+        if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
+            var newTargetSize = this.getLayoutTargetSize();
+            if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
+                this.adjustmentPass = true;
+                this.onLayout(container, target);
+            }
+        }
+
+        delete this.adjustmentPass;
     },
 
     // private
     },
 
     // private
-    isValidParent : function(c, target){
+    isValidParent : function(c, target) {
         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
     },
 
         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
     },
 
+    /**
+     * @private
+     * Returns all items that are both rendered and visible
+     * @return {Array} All matching items
+     */
+    getVisibleItems: function(ct) {
+        var ct  = ct || this.container,
+            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) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
+                items.push(c);
+            }
+        }
+
+        return items;
+    },
+
     // private
     // private
-    renderAll : function(ct, target){
-        if(!this.innerCt){
-            // the innerCt prevents wrapping and shuffling while
-            // the container is resizing
+    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);
         }
         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
     },
 
             this.innerCt = target.createChild({cls:this.innerCls});
             this.padding = this.parseMargins(this.padding);
         }
         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
     },
 
-    onLayout : function(ct, target){
-        this.renderAll(ct, target);
-    },
-
-    getLayoutTargetSize : function(){
+    getLayoutTargetSize : function() {
         var target = this.container.getLayoutTarget(), ret;
         var target = this.container.getLayoutTarget(), ret;
+        
         if (target) {
             ret = target.getViewSize();
         if (target) {
             ret = target.getViewSize();
-            ret.width -= target.getPadding('lr');
-            ret.height -= target.getPadding('tb');
-        }
+
+            // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
+            // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
+            // with getViewSize
+            if (Ext.isIE && Ext.isStrict && ret.width == 0){
+                ret =  target.getStyleSize();
+            }
+
+            ret.width  -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        
         return ret;
     },
 
     // private
         return ret;
     },
 
     // private
-    renderItem : function(c){
+    renderItem : function(c) {
         if(Ext.isString(c.margins)){
             c.margins = this.parseMargins(c.margins);
         }else if(!c.margins){
             c.margins = this.defaultMargins;
         }
         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
         if(Ext.isString(c.margins)){
             c.margins = this.parseMargins(c.margins);
         }else if(!c.margins){
             c.margins = this.defaultMargins;
         }
         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
+    },
+    
+    /**
+     * @private
+     */
+    destroy: function() {
+        Ext.destroy(this.overflowHandler);
+        
+        Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
     }
 });
 
     }
 });
 
+
+
+Ext.ns('Ext.layout.boxOverflow');
+
 /**
 /**
- * @class Ext.layout.VBoxLayout
- * @extends Ext.layout.BoxLayout
- * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
- * space between child items containing a numeric <code>flex</code> configuration.</p>
- * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
+ * @class Ext.layout.boxOverflow.None
+ * @extends Object
+ * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
+ * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
+ * for its container.
  */
  */
-Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+
+Ext.layout.boxOverflow.None = Ext.extend(Object, {
+    constructor: function(layout, config) {
+        this.layout = layout;
+        
+        Ext.apply(this, config || {});
+    },
+    
+    handleOverflow: Ext.emptyFn,
+    
+    clearOverflow: Ext.emptyFn
+});
+
+
+Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
+/**
+ * @class Ext.layout.boxOverflow.Menu
+ * @extends Ext.layout.boxOverflow.None
+ * Description
+ */
+Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
     /**
     /**
-     * @cfg {String} align
-     * Controls how the child items of the container are aligned. Acceptable configuration values for this
-     * property are:
-     * <div class="mdetail-params"><ul>
-     * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
-     * at the <b>left</b> side of the container</div></li>
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
-     * <b>mid-width</b> of the container</div></li>
-     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
-     * the width of the container</div></li>
-     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
-     * the size of the largest item.</div></li>
-     * </ul></div>
+     * @cfg afterCls
+     * @type String
+     * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
+     * which must always be present at the rightmost edge of the Container
      */
      */
-    align : 'left', // left, center, stretch, strechmax
-    type: 'vbox',
+    afterCls: 'x-strip-right',
+    
     /**
     /**
-     * @cfg {String} pack
-     * Controls how the child items of the container are packed together. Acceptable configuration values
-     * for this property are:
-     * <div class="mdetail-params"><ul>
-     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
-     * <b>top</b> side of container</div></li>
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
-     * <b>mid-height</b> of container</div></li>
-     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
-     * side of container</div></li>
-     * </ul></div>
+     * @property noItemsMenuText
+     * @type String
+     * HTML fragment to render into the toolbar overflow menu if there are no items to display
+     */
+    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+    
+    constructor: function(layout) {
+        Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
+        
+        /**
+         * @property menuItems
+         * @type Array
+         * Array of all items that are currently hidden and should go into the dropdown menu
+         */
+        this.menuItems = [];
+    },
+    
+    /**
+     * @private
+     * Creates the beforeCt, innerCt and afterCt elements if they have not already been created
+     * @param {Ext.Container} container The Container attached to this Layout instance
+     * @param {Ext.Element} target The target Element
      */
      */
+    createInnerElements: function() {
+        if (!this.afterCt) {
+            this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
+        }
+    },
+    
     /**
     /**
-     * @cfg {Number} flex
-     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
-     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
-     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
-     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
-     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     * @private
      */
      */
-
-    // private
-    onLayout : function(ct, target){
-        Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
-
-        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,
-            isStart = this.pack == 'start',
-            extraHeight = 0,
-            maxWidth = 0,
-            totalFlex = 0,
-            usedHeight = 0,
-            idx = 0,
-            heights = [],
-            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);
+    clearOverflow: function(calculations, targetSize) {
+        var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
+            items    = this.menuItems;
+        
+        this.hideTrigger();
+        
+        for (var index = 0, length = items.length; index < length; index++) {
+            items.pop().component.show();
         }
         }
-
-        var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
-        switch(this.align){
-            case 'stretch':
-                this.innerCt.setSize(w, h);
-                break;
-            case 'stretchmax':
-            case 'left':
-                this.innerCt.setSize(innerCtWidth, h);
-                break;
-            case 'center':
-                this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
-                break;
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            }
+        };
+    },
+    
+    /**
+     * @private
+     */
+    showTrigger: function() {
+        this.createMenu();
+        this.menuTrigger.show();
+    },
+    
+    /**
+     * @private
+     */
+    hideTrigger: function() {
+        if (this.menuTrigger != undefined) {
+            this.menuTrigger.hide();
         }
         }
+    },
+    
+    /**
+     * @private
+     * Called before the overflow menu is shown. This constructs the menu's items, caching them for as long as it can.
+     */
+    beforeMenuShow: function(menu) {
+        var items = this.menuItems,
+            len   = items.length,
+            item,
+            prev;
 
 
-        var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
-        // Apply widths
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            cm = c.margins;
-            if(this.align == 'stretch'){
-                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(
-                    c.minWidth || 0, c.maxWidth || 1000000));
-            }else if(isStart && c.flex){
-                c.setWidth();
+        var needsSep = function(group, item){
+            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+        };
+        
+        this.clearMenu();
+        menu.removeAll();
+        
+        for (var i = 0; i < len; i++) {
+            item = items[i].component;
+            
+            if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
+                menu.add('-');
             }
             }
+            
+            this.addComponentToMenu(menu, item);
+            prev = item;
+        }
 
 
+        // put something so the menu isn't empty if no compatible items found
+        if (menu.items.length < 1) {
+            menu.add(this.noItemsMenuText);
         }
         }
+    },
+    
+    /**
+     * @private
+     * Returns a menu config for a given component. This config is used to create a menu item
+     * to be added to the expander menu
+     * @param {Ext.Component} component The component to create the config for
+     * @param {Boolean} hideOnClick Passed through to the menu item
+     */
+    createMenuConfig : function(component, hideOnClick){
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
 
 
-        // Height calculations
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            // Total of all the flex values
-            totalFlex += c.flex || 0;
-            // 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;
-            }
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
 
 
-            cm = c.margins;
-            // Determine how much height is available to flex
-            extraHeight += ch + cm.top + cm.bottom;
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
         }
         }
-        // Final avail height calc
-        availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
 
 
-        var leftOver = availHeight;
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            if(isStart && c.flex){
-                ch = Math.floor(availHeight * (c.flex / totalFlex));
-                leftOver -= ch;
-                heights.push(ch);
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+
+        return config;
+    },
+
+    /**
+     * @private
+     * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
+     * @param {Ext.menu.Menu} menu The menu to add to
+     * @param {Ext.Component} component The component to add
+     */
+    addComponentToMenu : function(menu, component) {
+        if (component instanceof Ext.Toolbar.Separator) {
+            menu.add('-');
+
+        } else if (Ext.isFunction(component.isXType)) {
+            if (component.isXType('splitbutton')) {
+                menu.add(this.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(this.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     this.addComponentToMenu(menu, item);
+                }, this);
             }
         }
             }
         }
-        if(this.pack == 'center'){
-            t += availHeight ? availHeight / 2 : 0;
-        }else if(this.pack == 'end'){
-            t += availHeight;
+    },
+    
+    /**
+     * @private
+     * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
+     * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
+     */
+    clearMenu : function(){
+        var menu = this.moreMenu;
+        if (menu && menu.items) {
+            menu.items.each(function(item){
+                delete item.menu;
+            });
         }
         }
-        idx = 0;
-        // Apply heights
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            cm = c.margins;
-            t += cm.top;
-            aw = availableWidth;
-            cl = l + cm.left // default left pos
-
-            // Adjust left pos for centering
-            if(this.align == 'center'){
-                if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
-                    cl += (diff/2);
-                    aw -= diff;
+    },
+    
+    /**
+     * @private
+     * Creates the overflow trigger and menu used when enableOverflow is set to true and the items
+     * in the layout are too wide to fit in the space available
+     */
+    createMenu: function() {
+        if (!this.menuTrigger) {
+            this.createInnerElements();
+            
+            /**
+             * @private
+             * @property menu
+             * @type Ext.menu.Menu
+             * The expand menu - holds items for every item that cannot be shown
+             * because the container is currently not large enough.
+             */
+            this.menu = new Ext.menu.Menu({
+                ownerCt : this.layout.container,
+                listeners: {
+                    scope: this,
+                    beforeshow: this.beforeMenuShow
                 }
                 }
-            }
+            });
 
 
-            c.setPosition(cl, t);
-            if(isStart && c.flex){
-                ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
-                c.setSize(aw, ch);
-            }else{
-                ch = c.getHeight();
+            /**
+             * @private
+             * @property menuTrigger
+             * @type Ext.Button
+             * The expand button which triggers the overflow menu to be shown
+             */
+            this.menuTrigger = new Ext.Button({
+                iconCls : 'x-toolbar-more-icon',
+                cls     : 'x-toolbar-more',
+                menu    : this.menu,
+                renderTo: this.afterCt
+            });
+        }
+    },
+    
+    /**
+     * @private
+     */
+    destroy: function() {
+        Ext.destroy(this.menu, this.menuTrigger);
+    }
+});
+
+Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
+
+
+/**
+ * @class Ext.layout.boxOverflow.HorizontalMenu
+ * @extends Ext.layout.boxOverflow.Menu
+ * Description
+ */
+Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
+    
+    constructor: function() {
+        Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
+        
+        var me = this,
+            layout = me.layout,
+            origFunction = layout.calculateChildBoxes;
+        
+        layout.calculateChildBoxes = function(visibleItems, targetSize) {
+            var calcs = origFunction.apply(layout, arguments),
+                meta  = calcs.meta,
+                items = me.menuItems;
+            
+            //calculate the width of the items currently hidden solely because there is not enough space
+            //to display them
+            var hiddenWidth = 0;
+            for (var index = 0, length = items.length; index < length; index++) {
+                hiddenWidth += items[index].width;
+            }
+            
+            meta.minimumWidth += hiddenWidth;
+            meta.tooNarrow = meta.minimumWidth > targetSize.width;
+            
+            return calcs;
+        };        
+    },
+    
+    handleOverflow: function(calculations, targetSize) {
+        this.showTrigger();
+        
+        var newWidth    = targetSize.width - this.afterCt.getWidth(),
+            boxes       = calculations.boxes,
+            usedWidth   = 0,
+            recalculate = false;
+        
+        //calculate the width of all visible items and any spare width
+        for (var index = 0, length = boxes.length; index < length; index++) {
+            usedWidth += boxes[index].width;
+        }
+        
+        var spareWidth = newWidth - usedWidth,
+            showCount  = 0;
+        
+        //see if we can re-show any of the hidden components
+        for (var index = 0, length = this.menuItems.length; index < length; index++) {
+            var hidden = this.menuItems[index],
+                comp   = hidden.component,
+                width  = hidden.width;
+            
+            if (width < spareWidth) {
+                comp.show();
+                
+                spareWidth -= width;
+                showCount ++;
+                recalculate = true;
+            } else {
+                break;
             }
             }
-            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);
+                
+        if (recalculate) {
+            this.menuItems = this.menuItems.slice(showCount);
+        } else {
+            for (var i = boxes.length - 1; i >= 0; i--) {
+                var item  = boxes[i].component,
+                    right = boxes[i].left + boxes[i].width;
+
+                if (right >= newWidth) {
+                    this.menuItems.unshift({
+                        component: item,
+                        width    : boxes[i].width
+                    });
+
+                    item.hide();
+                } else {
+                    break;
+                }
             }
         }
             }
         }
-        delete this.adjustmentPass;
+        
+        if (this.menuItems.length == 0) {
+            this.hideTrigger();
+        }
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            },
+            recalculate: recalculate
+        };
     }
 });
 
     }
 });
 
-Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
-
-/**
- * @class Ext.layout.HBoxLayout
- * @extends Ext.layout.BoxLayout
- * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
- * space between child items containing a numeric <code>flex</code> configuration.</p>
- * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
+Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;/**
+ * @class Ext.layout.boxOverflow.Scroller
+ * @extends Ext.layout.boxOverflow.None
+ * Description
  */
  */
-Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
     /**
     /**
-     * @cfg {String} align
-     * Controls how the child items of the container are aligned. Acceptable configuration values for this
-     * property are:
-     * <div class="mdetail-params"><ul>
-     * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
-     * at the <b>top</b> of the container</div></li>
-     * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
-     * <b>middle</b> of the container</div></li>
-     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
-     * the height of the container</div></li>
-     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
-     * the height of the largest item.</div></li>
+     * @cfg animateScroll
+     * @type Boolean
+     * True to animate the scrolling of items within the layout (defaults to true, ignored if enableScroll is false)
      */
      */
-    align : 'top', // top, middle, stretch, strechmax
-    type: 'hbox',
+    animateScroll: true,
+    
     /**
     /**
-     * @cfg {String} pack
-     * Controls how the child items of the container are packed together. Acceptable configuration values
-     * for this property are:
-     * <div class="mdetail-params"><ul>
-     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
-     * <b>left</b> side of container</div></li>
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
-     * <b>mid-width</b> of container</div></li>
-     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
-     * side of container</div></li>
-     * </ul></div>
+     * @cfg scrollIncrement
+     * @type Number
+     * The number of pixels to scroll by on scroller click (defaults to 100)
      */
      */
+    scrollIncrement: 100,
+    
     /**
     /**
-     * @cfg {Number} flex
-     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
-     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
-     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
-     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
-     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     * @cfg wheelIncrement
+     * @type Number
+     * The number of pixels to increment on mouse wheel scrolling (defaults to <tt>3</tt>).
      */
      */
+    wheelIncrement: 3,
+    
+    /**
+     * @cfg scrollRepeatInterval
+     * @type Number
+     * Number of milliseconds between each scroll while a scroller button is held down (defaults to 400)
+     */
+    scrollRepeatInterval: 400,
+    
+    /**
+     * @cfg scrollDuration
+     * @type Number
+     * Number of seconds that each scroll animation lasts (defaults to 0.4)
+     */
+    scrollDuration: 0.4,
+    
+    /**
+     * @cfg beforeCls
+     * @type String
+     * CSS class added to the beforeCt element. This is the element that holds any special items such as scrollers,
+     * which must always be present at the leftmost edge of the Container
+     */
+    beforeCls: 'x-strip-left',
+    
+    /**
+     * @cfg afterCls
+     * @type String
+     * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
+     * which must always be present at the rightmost edge of the Container
+     */
+    afterCls: 'x-strip-right',
+    
+    /**
+     * @cfg scrollerCls
+     * @type String
+     * CSS class added to both scroller elements if enableScroll is used
+     */
+    scrollerCls: 'x-strip-scroller',
+    
+    /**
+     * @cfg beforeScrollerCls
+     * @type String
+     * CSS class added to the left scroller element if enableScroll is used
+     */
+    beforeScrollerCls: 'x-strip-scroller-left',
+    
+    /**
+     * @cfg afterScrollerCls
+     * @type String
+     * CSS class added to the right scroller element if enableScroll is used
+     */
+    afterScrollerCls: 'x-strip-scroller-right',
+    
+    /**
+     * @private
+     * Sets up an listener to scroll on the layout's innerCt mousewheel event
+     */
+    createWheelListener: function() {
+        this.layout.innerCt.on({
+            scope     : this,
+            mousewheel: function(e) {
+                e.stopEvent();
 
 
-    // private
-    onLayout : function(ct, target){
-        Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
-
-        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,
-            isStart = this.pack == 'start',
-            isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
-            extraWidth = 0,
-            maxHeight = 0,
-            totalFlex = 0,
-            usedWidth = 0;
-
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            // Total of all the flex values
-            totalFlex += c.flex || 0;
-            // 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;
+                this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
             }
             }
-            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);
-        }
-        // 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){
-            case 'stretch':
-                this.innerCt.setSize(w, h);
-                break;
-            case 'stretchmax':
-            case 'top':
-                this.innerCt.setSize(w, innerCtHeight);
-                break;
-            case 'middle':
-                this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
-                break;
+        });
+    },
+    
+    /**
+     * @private
+     * Most of the heavy lifting is done in the subclasses
+     */
+    handleOverflow: function(calculations, targetSize) {
+        this.createInnerElements();
+        this.showScrollers();
+    },
+    
+    /**
+     * @private
+     */
+    clearOverflow: function() {
+        this.hideScrollers();
+    },
+    
+    /**
+     * @private
+     * Shows the scroller elements in the beforeCt and afterCt. Creates the scrollers first if they are not already
+     * present. 
+     */
+    showScrollers: function() {
+        this.createScrollers();
+        
+        this.beforeScroller.show();
+        this.afterScroller.show();
+        
+        this.updateScrollButtons();
+    },
+    
+    /**
+     * @private
+     * Hides the scroller elements in the beforeCt and afterCt
+     */
+    hideScrollers: function() {
+        if (this.beforeScroller != undefined) {
+            this.beforeScroller.hide();
+            this.afterScroller.hide();          
         }
         }
-
-        var leftOver = availWidth,
-            widths = [],
-            restore = [],
-            idx = 0,
-            availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
-
-        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);
-            }
+    },
+    
+    /**
+     * @private
+     * Creates the clickable scroller elements and places them into the beforeCt and afterCt
+     */
+    createScrollers: function() {
+        if (!this.beforeScroller && !this.afterScroller) {
+            var before = this.beforeCt.createChild({
+                cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
+            });
+            
+            var after = this.afterCt.createChild({
+                cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
+            });
+            
+            before.addClassOnOver(this.beforeScrollerCls + '-hover');
+            after.addClassOnOver(this.afterScrollerCls + '-hover');
+            
+            before.setVisibilityMode(Ext.Element.DISPLAY);
+            after.setVisibilityMode(Ext.Element.DISPLAY);
+            
+            this.beforeRepeater = new Ext.util.ClickRepeater(before, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollLeft,
+                scope   : this
+            });
+            
+            this.afterRepeater = new Ext.util.ClickRepeater(after, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollRight,
+                scope   : this
+            });
+            
+            /**
+             * @property beforeScroller
+             * @type Ext.Element
+             * The left scroller element. Only created when needed.
+             */
+            this.beforeScroller = before;
+            
+            /**
+             * @property afterScroller
+             * @type Ext.Element
+             * The left scroller element. Only created when needed.
+             */
+            this.afterScroller = after;
         }
         }
-
-        if(this.pack == 'center'){
-            l += availWidth ? availWidth / 2 : 0;
-        }else if(this.pack == 'end'){
-            l += availWidth;
+    },
+    
+    /**
+     * @private
+     */
+    destroy: function() {
+        Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
+    },
+    
+    /**
+     * @private
+     * Scrolls left or right by the number of pixels specified
+     * @param {Number} delta Number of pixels to scroll to the right by. Use a negative number to scroll left
+     */
+    scrollBy: function(delta, animate) {
+        this.scrollTo(this.getScrollPosition() + delta, animate);
+    },
+    
+    /**
+     * @private
+     * Normalizes an item reference, string id or numerical index into a reference to the item
+     * @param {Ext.Component|String|Number} item The item reference, id or index
+     * @return {Ext.Component} The item
+     */
+    getItem: function(item) {
+        if (Ext.isString(item)) {
+            item = Ext.getCmp(item);
+        } else if (Ext.isNumber(item)) {
+            item = this.items[item];
         }
         }
-        for (i = 0 ; i < csLen; i++) {
-            c = cs[i];
-            cm = c.margins;
-            l += cm.left;
-            c.setPosition(l, t + cm.top);
-            if(isStart && c.flex){
-                cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
-                if(isRestore){
-                    restore.push(c.getHeight());
-                }
-                c.setSize(cw, availableHeight);
-            }else{
-                cw = c.getWidth();
-            }
-            l += cw + cm.right;
+        
+        return item;
+    },
+    
+    /**
+     * @private
+     * @return {Object} Object passed to scrollTo when scrolling
+     */
+    getScrollAnim: function() {
+        return {
+            duration: this.scrollDuration, 
+            callback: this.updateScrollButtons, 
+            scope   : this
+        };
+    },
+    
+    /**
+     * @private
+     * Enables or disables each scroller button based on the current scroll position
+     */
+    updateScrollButtons: function() {
+        if (this.beforeScroller == undefined || this.afterScroller == undefined) {
+            return;
         }
         }
-
-        idx = 0;
-        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(((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.minHeight || 0, c.maxHeight || 1000000));
-            }else{
-                if(this.align == 'middle'){
-                    diff = availableHeight - (ch + cm.top + cm.bottom);
-                    ch = t + cm.top + (diff/2);
-                    if(diff > 0){
-                        c.setPosition(c.x, ch);
-                    }
-                }
-                if(isStart && c.flex){
-                    c.setHeight(ch);
+        
+        var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
+            afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
+            beforeCls  = this.beforeScrollerCls + '-disabled',
+            afterCls   = this.afterScrollerCls  + '-disabled';
+        
+        this.beforeScroller[beforeMeth](beforeCls);
+        this.afterScroller[afterMeth](afterCls);
+        this.scrolling = false;
+    },
+    
+    /**
+     * @private
+     * Returns true if the innerCt scroll is already at its left-most point
+     * @return {Boolean} True if already at furthest left point
+     */
+    atExtremeBefore: function() {
+        return this.getScrollPosition() === 0;
+    },
+    
+    /**
+     * @private
+     * Scrolls to the left by the configured amount
+     */
+    scrollLeft: function(animate) {
+        this.scrollBy(-this.scrollIncrement, animate);
+    },
+    
+    /**
+     * @private
+     * Scrolls to the right by the configured amount
+     */
+    scrollRight: function(animate) {
+        this.scrollBy(this.scrollIncrement, animate);
+    },
+    
+    /**
+     * Scrolls to the given component.
+     * @param {String|Number|Ext.Component} item The item to scroll to. Can be a numerical index, component id 
+     * or a reference to the component itself.
+     * @param {Boolean} animate True to animate the scrolling
+     */
+    scrollToItem: function(item, animate) {
+        item = this.getItem(item);
+        
+        if (item != undefined) {
+            var visibility = this.getItemVisibility(item);
+            
+            if (!visibility.fullyVisible) {
+                var box  = item.getBox(true, true),
+                    newX = box.x;
+                    
+                if (visibility.hiddenRight) {
+                    newX -= (this.layout.innerCt.getWidth() - box.width);
                 }
                 }
+                
+                this.scrollTo(newX, animate);
             }
         }
             }
         }
-        // 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;
+    },
+    
+    /**
+     * @private
+     * For a given item in the container, return an object with information on whether the item is visible
+     * with the current innerCt scroll value.
+     * @param {Ext.Component} item The item
+     * @return {Object} Values for fullyVisible, hiddenLeft and hiddenRight
+     */
+    getItemVisibility: function(item) {
+        var box         = this.getItem(item).getBox(true, true),
+            itemLeft    = box.x,
+            itemRight   = box.x + box.width,
+            scrollLeft  = this.getScrollPosition(),
+            scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
+        
+        return {
+            hiddenLeft  : itemLeft < scrollLeft,
+            hiddenRight : itemRight > scrollRight,
+            fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
+        };
     }
 });
 
     }
 });
 
-Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
-/**
- * @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);
-        }
+Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
 
 
-        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);
-                }
+/**\r
+ * @class Ext.layout.boxOverflow.VerticalScroller\r
+ * @extends Ext.layout.boxOverflow.Scroller\r
+ * Description\r
+ */\r
+Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
+    scrollIncrement: 75,
+    wheelIncrement : 2,
+    
+    handleOverflow: function(calculations, targetSize) {
+        Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
+        
+        return {
+            targetSize: {
+                height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
+                width : targetSize.width
             }
             }
-        }
-        //strip extra empty cells
-        this.cleanup(this.leftTr);
-        this.cleanup(this.rightTr);
-        this.cleanup(this.extrasTr);
-        this.fitToSize(target);
+        };
     },
     },
+    
+    /**
+     * @private
+     * Creates the beforeCt and afterCt elements if they have not already been created
+     */
+    createInnerElements: function() {
+        var target = this.layout.innerCt;
+        
+        //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
+        //special items such as scrollers or dropdown menu triggers
+        if (!this.beforeCt) {
+            this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
+            this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
 
 
-    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);
-            }
+            this.createWheelListener();
         }
     },
         }
     },
-
-    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;
+    
+    /**
+     * @private
+     * Scrolls to the given position. Performs bounds checking.
+     * @param {Number} position The position to scroll to. This is constrained.
+     * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
+     */
+    scrollTo: function(position, animate) {
+        var oldPosition = this.getScrollPosition(),
+            newPosition = position.constrain(0, this.getMaxScrollBottom());
+        
+        if (newPosition != oldPosition && !this.scrolling) {
+            if (animate == undefined) {
+                animate = this.animateScroll;
+            }
+            
+            this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
+            
+            if (animate) {
+                this.scrolling = true;
+            } else {
+                this.scrolling = false;
+                this.updateScrollButtons();
+            }
         }
     },
         }
     },
-
-    getItemWidth : function(c){
-        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+    
+    /**
+     * Returns the current scroll position of the innerCt element
+     * @return {Number} The current scroll position
+     */
+    getScrollPosition: function(){
+        return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
     },
     },
+    
+    /**
+     * @private
+     * Returns the maximum value we can scrollTo
+     * @return {Number} The max scroll value
+     */
+    getMaxScrollBottom: function() {
+        return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
+    },
+    
+    /**
+     * @private
+     * Returns true if the innerCt scroll is already at its right-most point
+     * @return {Boolean} True if already at furthest right point
+     */
+    atExtremeAfter: function() {
+        return this.getScrollPosition() >= this.getMaxScrollBottom();
+    }
+});
 
 
-    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;
+Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
 
 
-        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);
-                    }
-                }
+/**
+ * @class Ext.layout.boxOverflow.HorizontalScroller
+ * @extends Ext.layout.boxOverflow.Scroller
+ * Description
+ */
+Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
+    handleOverflow: function(calculations, targetSize) {
+        Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
+        
+        return {
+            targetSize: {
+                height: targetSize.height,
+                width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
             }
             }
-        }
-        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;
+        };
+    },
+    
+    /**
+     * @private
+     * Creates the beforeCt and afterCt elements if they have not already been created
+     */
+    createInnerElements: function() {
+        var target = this.layout.innerCt;
+        
+        //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
+        //special items such as scrollers or dropdown menu triggers
+        if (!this.beforeCt) {
+            this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
+            this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
+            
+            this.createWheelListener();
+        }
+    },
+    
+    /**
+     * @private
+     * Scrolls to the given position. Performs bounds checking.
+     * @param {Number} position The position to scroll to. This is constrained.
+     * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
+     */
+    scrollTo: function(position, animate) {
+        var oldPosition = this.getScrollPosition(),
+            newPosition = position.constrain(0, this.getMaxScrollRight());
+        
+        if (newPosition != oldPosition && !this.scrolling) {
+            if (animate == undefined) {
+                animate = this.animateScroll;
+            }
+            
+            this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
+            
+            if (animate) {
+                this.scrolling = true;
+            } else {
+                this.scrolling = false;
+                this.updateScrollButtons();
             }
         }
     },
             }
         }
     },
+    
+    /**
+     * Returns the current scroll position of the innerCt element
+     * @return {Number} The current scroll position
+     */
+    getScrollPosition: function(){
+        return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
+    },
+    
+    /**
+     * @private
+     * Returns the maximum value we can scrollTo
+     * @return {Number} The max scroll value
+     */
+    getMaxScrollRight: function() {
+        return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
+    },
+    
+    /**
+     * @private
+     * Returns true if the innerCt scroll is already at its right-most point
+     * @return {Boolean} True if already at furthest right point
+     */
+    atExtremeAfter: function() {
+        return this.getScrollPosition() >= this.getMaxScrollRight();
+    }
+});
+
+Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;/**
+ * @class Ext.layout.HBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
+ */
+Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    /**
+     * @cfg {String} align
+     * Controls how the child items of the container are aligned. Acceptable configuration values for this
+     * property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
+     * at the <b>top</b> of the container</div></li>
+     * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
+     * <b>middle</b> of the container</div></li>
+     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
+     * the height of the container</div></li>
+     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
+     * the height of the largest item.</div></li>
+     */
+    align: 'top', // top, middle, stretch, strechmax
 
 
-    createMenuConfig : function(c, hideOnClick){
-        var cfg = Ext.apply({}, c.initialConfig),
-            group = c.toggleGroup;
+    type : 'hbox',
 
 
-        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);
+    /**
+     * @cfg {String} pack
+     * Controls how the child items of the container are packed together. Acceptable configuration values
+     * for this property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+     * <b>left</b> side of container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+     * <b>mid-width</b> of container</div></li>
+     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
+     * side of container</div></li>
+     * </ul></div>
+     */
+    /**
+     * @cfg {Number} flex
+     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
+     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
+     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     */
+
+    /**
+     * @private
+     * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
+     * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
+     * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
+     * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
+     * @param {Object} targetSize Object containing target size and height
+     * @return {Object} Object containing box measurements for each child, plus meta data
+     */
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var visibleCount = visibleItems.length,
+
+            padding      = this.padding,
+            topOffset    = padding.top,
+            leftOffset   = padding.left,
+            paddingVert  = topOffset  + padding.bottom,
+            paddingHoriz = leftOffset + padding.right,
+
+            width        = targetSize.width - this.scrollOffset,
+            height       = targetSize.height,
+            availHeight  = Math.max(0, height - paddingVert),
+
+            isStart      = this.pack == 'start',
+            isCenter     = this.pack == 'center',
+            isEnd        = this.pack == 'end',
+
+            nonFlexWidth = 0,
+            maxHeight    = 0,
+            totalFlex    = 0,
+            desiredWidth = 0,
+            minimumWidth = 0,
+
+            //used to cache the calculated size and position values for each child item
+            boxes        = [],
+
+            //used in the for loops below, just declared here for brevity
+            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
+            horizMargins, vertMargins, stretchHeight;
+
+        //gather the total flex of all flexed items and the width taken up by fixed width items
+        for (i = 0; i < visibleCount; i++) {
+            child       = visibleItems[i];
+            childHeight = child.height;
+            childWidth  = child.width;
+            canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
+
+            // Static width (numeric) requires no calcs
+            if (typeof childWidth != 'number') {
+
+                // flex and not 'auto' width
+                if (child.flex && !childWidth) {
+                    totalFlex += child.flex;
+
+                // Not flexed or 'auto' width or undefined width
+                } else {
+                    //Render and layout sub-containers without a flex or width defined, as otherwise we
+                    //don't know how wide the sub-container should be and cannot calculate flexed widths
+                    if (!childWidth && canLayout) {
+                        child.doLayout();
                     }
                     }
+
+                    childSize   = child.getSize();
+                    childWidth  = childSize.width;
+                    childHeight = childSize.height;
                 }
                 }
-            });
-        }
-        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);
+            childMargins = child.margins;
+            horizMargins = childMargins.left + childMargins.right;
+
+            nonFlexWidth += horizMargins + (childWidth || 0);
+            desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
+            minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
+
+            // Max height for align - force layout of non-laid out subcontainers without a numeric height
+            if (typeof childHeight != 'number') {
+                if (canLayout) {
+                    child.doLayout();
+                }
+                childHeight = child.getHeight();
             }
             }
-        }
-    },
 
 
-    clearMenu : function(){
-        var m = this.moreMenu;
-        if(m && m.items){
-            m.items.each(function(item){
-                delete item.menu;
+            maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
+
+            //cache the size of each child component. Don't set height or width to 0, keep undefined instead
+            boxes.push({
+                component: child,
+                height   : childHeight || undefined,
+                width    : childWidth  || undefined
             });
         }
             });
         }
-    },
+                
+        var shortfall = desiredWidth - width,
+            tooNarrow = minimumWidth > width;
+            
+        //the width available to the flexed items
+        var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
+        
+        if (tooNarrow) {
+            for (i = 0; i < visibleCount; i++) {
+                boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
+            }
+        } else {
+            //all flexed items should be sized to their minimum width, other items should be shrunk down until
+            //the shortfall has been accounted for
+            if (shortfall > 0) {
+                var minWidths = [];
+                
+                /**
+                 * When we have a shortfall but are not tooNarrow, we need to shrink the width of each non-flexed item.
+                 * Flexed items are immediately reduced to their minWidth and anything already at minWidth is ignored.
+                 * The remaining items are collected into the minWidths array, which is later used to distribute the shortfall.
+                 */
+                for (var index = 0, length = visibleCount; index < length; index++) {
+                    var item     = visibleItems[index],
+                        minWidth = item.minWidth || 0;
+
+                    //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
+                    //shrunk to their minWidth because they're flexible and should be the first to lose width
+                    if (item.flex) {
+                        boxes[index].width = minWidth;
+                    } else {
+                        minWidths.push({
+                            minWidth : minWidth,
+                            available: boxes[index].width - minWidth,
+                            index    : index
+                        });
+                    }
+                }
+                
+                //sort by descending amount of width remaining before minWidth is reached
+                minWidths.sort(function(a, b) {
+                    return a.available > b.available ? 1 : -1;
+                });
+                
+                /*
+                 * Distribute the shortfall (difference between total desired with of all items and actual width available)
+                 * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
+                 * smallest difference between their width and minWidth first, so that if reducing the width by the average
+                 * amount would make that item less than its minWidth, we carry the remainder over to the next item.
+                 */
+                for (var i = 0, length = minWidths.length; i < length; i++) {
+                    var itemIndex = minWidths[i].index;
+                    
+                    if (itemIndex == undefined) {
+                        continue;
+                    }
+                        
+                    var item      = visibleItems[itemIndex],
+                        box       = boxes[itemIndex],
+                        oldWidth  = box.width,
+                        minWidth  = item.minWidth,
+                        newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
+                        reduction = oldWidth - newWidth;
+                    
+                    boxes[itemIndex].width = newWidth;
+                    shortfall -= reduction;                    
+                }
+            } else {
+                //temporary variables used in the flex width calculations below
+                var remainingWidth = availableWidth,
+                    remainingFlex  = totalFlex;
 
 
-    // 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);
-            };
+                //calculate the widths of each flexed item
+                for (i = 0; i < visibleCount; i++) {
+                    child = visibleItems[i];
+                    calcs = boxes[i];
 
 
-        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('-');
+                    childMargins = child.margins;
+                    vertMargins  = childMargins.top + childMargins.bottom;
+
+                    if (isStart && child.flex && !child.width) {
+                        flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
+                        remainingWidth -= flexedWidth;
+                        remainingFlex  -= child.flex;
+
+                        calcs.width = flexedWidth;
+                        calcs.dirtySize = true;
+                    }
                 }
                 }
-                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);
+        
+        if (isCenter) {
+            leftOffset += availableWidth / 2;
+        } else if (isEnd) {
+            leftOffset += availableWidth;
         }
         }
-    },
-
-    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);
+        
+        //finally, calculate the left and top position of each item
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            calcs = boxes[i];
+            
+            childMargins = child.margins;
+            leftOffset  += childMargins.left;
+            vertMargins  = childMargins.top + childMargins.bottom;
+            
+            calcs.left = leftOffset;
+            calcs.top  = topOffset + childMargins.top;
+
+            switch (this.align) {
+                case 'stretch':
+                    stretchHeight = availHeight - vertMargins;
+                    calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'stretchmax':
+                    stretchHeight = maxHeight - vertMargins;
+                    calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'middle':
+                    var diff = availHeight - calcs.height - vertMargins;
+                    if (diff > 0) {
+                        calcs.top = topOffset + vertMargins + (diff / 2);
+                    }
+            }
+            
+            leftOffset += calcs.width + childMargins.right;
         }
         }
-    },
 
 
-    destroy : function(){
-        Ext.destroy(this.more, this.moreMenu);
-        delete this.leftTr;
-        delete this.rightTr;
-        delete this.extrasTr;
-        Ext.layout.ToolbarLayout.superclass.destroy.call(this);
+        return {
+            boxes: boxes,
+            meta : {
+                maxHeight   : maxHeight,
+                nonFlexWidth: nonFlexWidth,
+                desiredWidth: desiredWidth,
+                minimumWidth: minimumWidth,
+                shortfall   : desiredWidth - width,
+                tooNarrow   : tooNarrow
+            }
+        };
     }
 });
 
     }
 });
 
-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.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;/**
+ * @class Ext.layout.VBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
  */
  */
- Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    monitorResize : true,
+Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    /**
+     * @cfg {String} align
+     * Controls how the child items of the container are aligned. Acceptable configuration values for this
+     * property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
+     * at the <b>left</b> side of the container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
+     * <b>mid-width</b> of the container</div></li>
+     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
+     * the width of the container</div></li>
+     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
+     * the size of the largest item.</div></li>
+     * </ul></div>
+     */
+    align : 'left', // left, center, stretch, strechmax
+    type: 'vbox',
 
 
-    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);
-    },
+    /**
+     * @cfg {String} pack
+     * Controls how the child items of the container are packed together. Acceptable configuration values
+     * for this property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+     * <b>top</b> side of container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+     * <b>mid-height</b> of container</div></li>
+     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
+     * side of container</div></li>
+     * </ul></div>
+     */
 
 
-    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>'
-            );
-        }
+    /**
+     * @cfg {Number} flex
+     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
+     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
+     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     */
 
 
-        if(c && !c.rendered){
-            if(Ext.isNumber(position)){
-                position = target.dom.childNodes[position];
-            }
-            var a = this.getItemArgs(c);
+    /**
+     * @private
+     * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
+     * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
+     * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
+     * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
+     * @param {Object} targetSize Object containing target size and height
+     * @return {Object} Object containing box measurements for each child, plus meta data
+     */
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var visibleCount = visibleItems.length,
+
+            padding      = this.padding,
+            topOffset    = padding.top,
+            leftOffset   = padding.left,
+            paddingVert  = topOffset  + padding.bottom,
+            paddingHoriz = leftOffset + padding.right,
+
+            width        = targetSize.width - this.scrollOffset,
+            height       = targetSize.height,
+            availWidth   = Math.max(0, width - paddingHoriz),
+
+            isStart      = this.pack == 'start',
+            isCenter     = this.pack == 'center',
+            isEnd        = this.pack == 'end',
+
+            nonFlexHeight= 0,
+            maxWidth     = 0,
+            totalFlex    = 0,
+            desiredHeight= 0,
+            minimumHeight= 0,
+
+            //used to cache the calculated size and position values for each child item
+            boxes        = [],
+            
+            //used in the for loops below, just declared here for brevity
+            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
+            horizMargins, vertMargins, stretchWidth;
+
+        //gather the total flex of all flexed items and the width taken up by fixed width items
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            childHeight = child.height;
+            childWidth  = child.width;
+            canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
+
+            // Static height (numeric) requires no calcs
+            if (typeof childHeight != 'number') {
+
+                // flex and not 'auto' height
+                if (child.flex && !childHeight) {
+                    totalFlex += child.flex;
+
+                // Not flexed or 'auto' height or undefined height
+                } else {
+                    //Render and layout sub-containers without a flex or width defined, as otherwise we
+                    //don't know how wide the sub-container should be and cannot calculate flexed widths
+                    if (!childHeight && canLayout) {
+                        child.doLayout();
+                    }
 
 
-//          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));
+                    childSize = child.getSize();
+                    childWidth = childSize.width;
+                    childHeight = childSize.height;
+                }
+            }
+            
+            childMargins = child.margins;
+            vertMargins  = childMargins.top + childMargins.bottom;
 
 
-//          Link the containing <li> to the item.
-            c.positionEl.menuItemId = c.getItemId();
+            nonFlexHeight += vertMargins + (childHeight || 0);
+            desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
+            minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
 
 
-//          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];
+            // Max width for align - force layout of non-layed out subcontainers without a numeric width
+            if (typeof childWidth != 'number') {
+                if (canLayout) {
+                    child.doLayout();
+                }
+                childWidth = child.getWidth();
             }
             }
-            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 '
-        };
-    },
+            maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
 
 
-    //  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);
-    },
+            //cache the size of each child component
+            boxes.push({
+                component: child,
+                height   : childHeight || undefined,
+                width    : childWidth || undefined
+            });
+        }
+                
+        var shortfall = desiredHeight - height,
+            tooNarrow = minimumHeight > height;
 
 
-    onLayout : function(ct, target){
-        Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
-        this.doAutoSize();
-    },
+        //the height available to the flexed items
+        var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
+        
+        if (tooNarrow) {
+            for (i = 0, length = visibleCount; i < length; i++) {
+                boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
+            }
+        } else {
+            //all flexed items should be sized to their minimum width, other items should be shrunk down until
+            //the shortfall has been accounted for
+            if (shortfall > 0) {
+                var minHeights = [];
 
 
-    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'));
+                /**
+                 * When we have a shortfall but are not tooNarrow, we need to shrink the height of each non-flexed item.
+                 * Flexed items are immediately reduced to their minHeight and anything already at minHeight is ignored.
+                 * The remaining items are collected into the minHeights array, which is later used to distribute the shortfall.
+                 */
+                for (var index = 0, length = visibleCount; index < length; index++) {
+                    var item      = visibleItems[index],
+                        minHeight = item.minHeight || 0;
+
+                    //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
+                    //shrunk to their minHeight because they're flexible and should be the first to lose height
+                    if (item.flex) {
+                        boxes[index].height = minHeight;
+                    } else {
+                        minHeights.push({
+                            minHeight: minHeight, 
+                            available: boxes[index].height - minHeight,
+                            index    : index
+                        });
+                    }
+                }
+
+                //sort by descending minHeight value
+                minHeights.sort(function(a, b) {
+                    return a.available > b.available ? 1 : -1;
+                });
+
+                /*
+                 * Distribute the shortfall (difference between total desired with of all items and actual height available)
+                 * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
+                 * smallest difference between their height and minHeight first, so that if reducing the height by the average
+                 * amount would make that item less than its minHeight, we carry the remainder over to the next item.
+                 */
+                for (var i = 0, length = minHeights.length; i < length; i++) {
+                    var itemIndex = minHeights[i].index;
+
+                    if (itemIndex == undefined) {
+                        continue;
+                    }
+
+                    var item      = visibleItems[itemIndex],
+                        box       = boxes[itemIndex],
+                        oldHeight  = box.height,
+                        minHeight  = item.minHeight,
+                        newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
+                        reduction = oldHeight - newHeight;
+
+                    boxes[itemIndex].height = newHeight;
+                    shortfall -= reduction;
+                }
+            } else {
+                //temporary variables used in the flex height calculations below
+                var remainingHeight = availableHeight,
+                    remainingFlex   = totalFlex;
+                
+                //calculate the height of each flexed item
+                for (i = 0; i < visibleCount; i++) {
+                    child = visibleItems[i];
+                    calcs = boxes[i];
+
+                    childMargins = child.margins;
+                    horizMargins = childMargins.left + childMargins.right;
+
+                    if (isStart && child.flex && !child.height) {
+                        flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
+                        remainingHeight -= flexedHeight;
+                        remainingFlex   -= child.flex;
+
+                        calcs.height = flexedHeight;
+                        calcs.dirtySize = true;
+                    }
+                }
+            }
+        }
+
+        if (isCenter) {
+            topOffset += availableHeight / 2;
+        } else if (isEnd) {
+            topOffset += availableHeight;
+        }
+
+        //finally, calculate the left and top position of each item
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            calcs = boxes[i];
+
+            childMargins = child.margins;
+            topOffset   += childMargins.top;
+            horizMargins = childMargins.left + childMargins.right;
+            
+
+            calcs.left = leftOffset + childMargins.left;
+            calcs.top  = topOffset;
+            
+            switch (this.align) {
+                case 'stretch':
+                    stretchWidth = availWidth - horizMargins;
+                    calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'stretchmax':
+                    stretchWidth = maxWidth - horizMargins;
+                    calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
+                    calcs.dirtySize = true;
+                    break;
+                case 'center':
+                    var diff = availWidth - calcs.width - horizMargins;
+                    if (diff > 0) {
+                        calcs.left = leftOffset + horizMargins + (diff / 2);
+                    }
             }
             }
+
+            topOffset += calcs.height + childMargins.bottom;
         }
         }
+        
+        return {
+            boxes: boxes,
+            meta : {
+                maxWidth     : maxWidth,
+                nonFlexHeight: nonFlexHeight,
+                desiredHeight: desiredHeight,
+                minimumHeight: minimumHeight,
+                shortfall    : desiredHeight - height,
+                tooNarrow    : tooNarrow
+            }
+        };
     }
 });
     }
 });
-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
- * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
- * the browser viewport and manages window resizing. There may only be one Viewport created\r
- * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
- * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
- * method of any of its child Panels may themselves have a layout.</p>\r
- * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
- * for scrolling if needed using the {@link #autoScroll} config.</p>\r
- * <p>An example showing a classic application border layout:</p><pre><code>\r
-new Ext.Viewport({\r
-    layout: 'border',\r
-    items: [{\r
-        region: 'north',\r
-        html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
-        autoHeight: true,\r
-        border: false,\r
-        margins: '0 0 5 0'\r
-    }, {\r
-        region: 'west',\r
-        collapsible: true,\r
-        title: 'Navigation',\r
-        width: 200\r
-        // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}\r
-    }, {\r
-        region: 'south',\r
-        title: 'Title for Panel',\r
-        collapsible: true,\r
-        html: 'Information goes here',\r
-        split: true,\r
-        height: 100,\r
-        minHeight: 100\r
-    }, {\r
-        region: 'east',\r
-        title: 'Title for the Grid Panel',\r
-        collapsible: true,\r
-        split: true,\r
-        width: 200,\r
-        xtype: 'grid',\r
-        // remaining grid configuration not shown ...\r
-        // notice that the GridPanel is added directly as the region\r
-        // it is not "overnested" inside another Panel\r
-    }, {\r
-        region: 'center',\r
-        xtype: 'tabpanel', // TabPanel itself has no title\r
-        items: {\r
-            title: 'Default Tab',\r
-            html: 'The first tab\'s content. Others may be added dynamically'\r
-        }\r
-    }]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Create a new Viewport\r
- * @param {Object} config The config object\r
- * @xtype viewport\r
- */\r
-Ext.Viewport = Ext.extend(Ext.Container, {\r
-    /*\r
-     * Privatize config options which, if used, would interfere with the\r
-     * correct operation of the Viewport as the sole manager of the\r
-     * layout of the document body.\r
-     */\r
-    /**\r
-     * @cfg {Mixed} applyTo @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} allowDomMove @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} hideParent @hide\r
-     */\r
-    /**\r
-     * @cfg {Mixed} renderTo @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} hideParent @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} height @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} width @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} autoHeight @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} autoWidth @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} deferHeight @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} monitorResize @hide\r
-     */\r
-\r
-    initComponent : function() {\r
-        Ext.Viewport.superclass.initComponent.call(this);\r
-        document.getElementsByTagName('html')[0].className += ' x-viewport';\r
-        this.el = Ext.getBody();\r
-        this.el.setHeight = Ext.emptyFn;\r
-        this.el.setWidth = Ext.emptyFn;\r
-        this.el.setSize = Ext.emptyFn;\r
-        this.el.dom.scroll = 'no';\r
-        this.allowDomMove = false;\r
-        this.autoWidth = true;\r
-        this.autoHeight = true;\r
-        Ext.EventManager.onWindowResize(this.fireResize, this);\r
-        this.renderTo = this.el;\r
-    },\r
-\r
-    fireResize : function(w, h){\r
-        this.fireEvent('resize', this, w, h, w, h);\r
-    }\r
-});\r
-Ext.reg('viewport', Ext.Viewport);\r
+
+Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
 /**
 /**
- * @class Ext.Panel
- * @extends Ext.Container
- * <p>Panel is a container that has specific functionality and structural components that make
- * it the perfect building block for application-oriented user interfaces.</p>
- * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
- * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
- * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
- * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
- * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By
- * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
- * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
- * at all.</p>
- * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
- * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
- * information).</p>
- * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
- * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
- * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
- * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
- * @constructor
- * @param {Object} config The config object
- * @xtype panel
+ * @class Ext.layout.ToolbarLayout
+ * @extends Ext.layout.ContainerLayout
+ * Layout manager used by Ext.Toolbar. This is highly specialised for use by Toolbars and would not
+ * usually be used by any other class.
  */
  */
-Ext.Panel = Ext.extend(Ext.Container, {
-    /**
-     * The Panel's header {@link Ext.Element Element}. Read-only.
-     * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
-     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
-     * @type Ext.Element
-     * @property header
-     */
+Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    monitorResize : true,
+
+    type: 'toolbar',
+
     /**
     /**
-     * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
-     * The content may be specified in the {@link #html} config, or it may be loaded using the
-     * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
-     * <p>If this is used to load visible HTML elements in either way, then
-     * the Panel may not be used as a Layout for hosting nested Panels.</p>
-     * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
-     * then the body Element must not be loaded or changed - it is under the control
-     * of the Panel's Layout.
-     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
-     * @type Ext.Element
-     * @property body
+     * @property triggerWidth
+     * @type Number
+     * The width allocated for the menu trigger at the extreme right end of the Toolbar
      */
      */
+    triggerWidth: 18,
+
     /**
     /**
-     * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
-     * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
-     * @type Ext.Element
-     * @property bwrap
+     * @property noItemsMenuText
+     * @type String
+     * HTML fragment to render into the toolbar overflow menu if there are no items to display
      */
      */
+    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+
     /**
     /**
-     * True if this panel is collapsed. Read-only.
+     * @private
+     * @property lastOverflow
      * @type Boolean
      * @type Boolean
-     * @property collapsed
+     * Used internally to record whether the last layout caused an overflow or not
      */
      */
+    lastOverflow: false,
+
     /**
     /**
-     * @cfg {Object} bodyCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
-     * Panel Element.</p>
-     * <p>By default, the Default element in the table below will be used for the html markup to
-     * create a child element with the commensurate Default class name (<code>baseCls</code> will be
-     * replaced by <code>{@link #baseCls}</code>):</p>
-     * <pre>
-     * Panel      Default  Default             Custom      Additional       Additional
-     * Element    element  class               element     class            style
-     * ========   ==========================   =========   ==============   ===========
-     * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
-     * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
-     * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
-     * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
-     * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
-     * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
-     * </pre>
-     * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
-     * to use a different form of markup than is created by default. An example of this might be
-     * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
-     * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
-     * element:</p>
-     * <pre><code>
-new Ext.Panel({
-    title: 'Message Title',
-    renderTo: Ext.getBody(),
-    width: 200, height: 130,
-    <b>bodyCfg</b>: {
-        tag: 'center',
-        cls: 'x-panel-body',  // Default class not applied if Custom element specified
-        html: 'Message'
-    },
-    footerCfg: {
-        tag: 'h2',
-        cls: 'x-panel-footer'        // same as the Default class
-        html: 'footer html'
-    },
-    footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
-    footerStyle:    'background-color:red' // see {@link #bodyStyle}
-});
-     * </code></pre>
-     * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
-     * styling applied.</p>
-     */
+     * @private
+     * @property tableHTML
+     * @type String
+     * String used to build the HTML injected to support the Toolbar's layout. The align property is
+     * injected into this string inside the td.x-toolbar-left element during onLayout.
+     */
+    tableHTML: [
+        '<table cellspacing="0" class="x-toolbar-ct">',
+            '<tbody>',
+                '<tr>',
+                    '<td class="x-toolbar-left" align="{0}">',
+                        '<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>'
+    ].join(""),
+
     /**
     /**
-     * @cfg {Object} headerCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
-     * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     * @private
+     * Create the wrapping Toolbar HTML and render/move all the items into the correct places
      */
      */
+    onLayout : function(ct, target) {
+        //render the Toolbar <table> HTML if it's not already present
+        if (!this.leftTr) {
+            var align = ct.buttonAlign == 'center' ? 'center' : 'left';
+
+            target.addClass('x-toolbar-layout-ct');
+            target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
+
+            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);
+
+            if (this.hiddenItem == undefined) {
+                /**
+                 * @property hiddenItems
+                 * @type Array
+                 * Holds all items that are currently hidden due to there not being enough space to render them
+                 * These items will appear on the expand menu.
+                 */
+                this.hiddenItems = [];
+            }
+        }
+
+        var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
+            items    = ct.items.items,
+            position = 0;
+
+        //render each item if not already rendered, place it into the correct (left or right) target
+        for (var i = 0, len = items.length, c; i < len; i++, position++) {
+            c = items[i];
+
+            if (c.isFill) {
+                side   = this.rightTr;
+                position = -1;
+            } else if (!c.rendered) {
+                c.render(this.insertCell(c, side, position));
+                this.configureItem(c);
+            } else {
+                if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
+                    var td = this.insertCell(c, side, position);
+                    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);
+    },
+
     /**
     /**
-     * @cfg {Object} bwrapCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
-     * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     * @private
+     * Removes any empty nodes from the given element
+     * @param {Ext.Element} el The element to clean up
      */
      */
+    cleanup : function(el) {
+        var cn = el.childNodes, i, c;
+
+        for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
+            if (!c.firstChild) {
+                el.removeChild(c);
+            }
+        }
+    },
+
     /**
     /**
-     * @cfg {Object} tbarCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
-     * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     * @private
+     * Inserts the given Toolbar item into the given element
+     * @param {Ext.Component} c The component to add
+     * @param {Ext.Element} target The target to add the component to
+     * @param {Number} position The position to add the component at
      */
      */
+    insertCell : function(c, target, position) {
+        var td = document.createElement('td');
+        td.className = 'x-toolbar-cell';
+
+        target.insertBefore(td, target.childNodes[position] || null);
+
+        return td;
+    },
+
     /**
     /**
-     * @cfg {Object} bbarCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
-     * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     * @private
+     * Hides an item because it will not fit in the available width. The item will be unhidden again
+     * if the Toolbar is resized to be large enough to show it
+     * @param {Ext.Component} item The item to hide
      */
      */
+    hideItem : function(item) {
+        this.hiddenItems.push(item);
+
+        item.xtbHidden = true;
+        item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
+        item.hide();
+    },
+
     /**
     /**
-     * @cfg {Object} footerCfg
-     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
-     * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     * @private
+     * Unhides an item that was previously hidden due to there not being enough space left on the Toolbar
+     * @param {Ext.Component} item The item to show
      */
      */
+    unhideItem : function(item) {
+        item.show();
+        item.xtbHidden = false;
+        this.hiddenItems.remove(item);
+    },
+
     /**
     /**
-     * @cfg {Boolean} closable
-     * Panels themselves do not directly support being closed, but some Panel subclasses do (like
-     * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
-     * to enable closing in such situations. Defaults to <code>false</code>.
+     * @private
+     * Returns the width of the given toolbar item. If the item is currently hidden because there
+     * is not enough room to render it, its previous width is returned
+     * @param {Ext.Component} c The component to measure
+     * @return {Number} The width of the item
      */
      */
+    getItemWidth : function(c) {
+        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+    },
+
     /**
     /**
-     * The Panel's footer {@link Ext.Element Element}. Read-only.
-     * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
-     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
-     * @type Ext.Element
-     * @property footer
+     * @private
+     * Called at the end of onLayout. At this point the Toolbar has already been resized, so we need
+     * to fit the items into the available width. We add up the width required by all of the items in
+     * the toolbar - if we don't have enough space we hide the extra items and render the expand menu
+     * trigger.
+     * @param {Ext.Element} target The Element the Toolbar is currently laid out within
+     */
+    fitToSize : function(target) {
+        if (this.container.enableOverflow === false) {
+            return;
+        }
+
+        var width       = target.dom.clientWidth,
+            tableWidth  = target.dom.firstChild.offsetWidth,
+            clipWidth   = width - this.triggerWidth,
+            lastWidth   = this.lastWidth || 0,
+
+            hiddenItems = this.hiddenItems,
+            hasHiddens  = hiddenItems.length != 0,
+            isLarger    = width >= lastWidth;
+
+        this.lastWidth  = width;
+
+        if (tableWidth > width || (hasHiddens && isLarger)) {
+            var items     = this.container.items.items,
+                len       = items.length,
+                loopWidth = 0,
+                item;
+
+            for (var i = 0; i < len; i++) {
+                item = items[i];
+
+                if (!item.isFill) {
+                    loopWidth += this.getItemWidth(item);
+                    if (loopWidth > clipWidth) {
+                        if (!(item.hidden || item.xtbHidden)) {
+                            this.hideItem(item);
+                        }
+                    } else if (item.xtbHidden) {
+                        this.unhideItem(item);
+                    }
+                }
+            }
+        }
+
+        //test for number of hidden items again here because they may have changed above
+        hasHiddens = hiddenItems.length != 0;
+
+        if (hasHiddens) {
+            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;
+            }
+        }
+    },
+
+    /**
+     * @private
+     * Returns a menu config for a given component. This config is used to create a menu item
+     * to be added to the expander menu
+     * @param {Ext.Component} component The component to create the config for
+     * @param {Boolean} hideOnClick Passed through to the menu item
+     */
+    createMenuConfig : function(component, hideOnClick){
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
+
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
+
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
+        }
+
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+
+        return config;
+    },
+
+    /**
+     * @private
+     * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
+     * @param {Ext.menu.Menu} menu The menu to add to
+     * @param {Ext.Component} component The component to add
+     */
+    addComponentToMenu : function(menu, component) {
+        if (component instanceof Ext.Toolbar.Separator) {
+            menu.add('-');
+
+        } else if (Ext.isFunction(component.isXType)) {
+            if (component.isXType('splitbutton')) {
+                menu.add(this.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(this.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     this.addComponentToMenu(menu, item);
+                }, this);
+            }
+        }
+    },
+
+    /**
+     * @private
+     * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
+     * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
+     */
+    clearMenu : function(){
+        var menu = this.moreMenu;
+        if (menu && menu.items) {
+            menu.items.each(function(item){
+                delete item.menu;
+            });
+        }
+    },
+
+    /**
+     * @private
+     * Called before the expand menu is shown, this rebuilds the menu since it was last shown because
+     * it is possible that the items hidden due to space limitations on the Toolbar have changed since.
+     * @param {Ext.menu.Menu} m The menu
+     */
+    beforeMoreShow : function(menu) {
+        var items = this.container.items.items,
+            len   = items.length,
+            item,
+            prev;
+
+        var needsSep = function(group, item){
+            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+        };
+
+        this.clearMenu();
+        menu.removeAll();
+        for (var i = 0; i < len; i++) {
+            item = items[i];
+            if (item.xtbHidden) {
+                if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
+                    menu.add('-');
+                }
+                this.addComponentToMenu(menu, item);
+                prev = item;
+            }
+        }
+
+        // put something so the menu isn't empty if no compatible items found
+        if (menu.items.length < 1) {
+            menu.add(this.noItemsMenuText);
+        }
+    },
+
+    /**
+     * @private
+     * Creates the expand trigger and menu, adding them to the <tr> at the extreme right of the
+     * Toolbar table
+     */
+    initMore : function(){
+        if (!this.more) {
+            /**
+             * @private
+             * @property moreMenu
+             * @type Ext.menu.Menu
+             * The expand menu - holds items for every Toolbar item that cannot be shown
+             * because the Toolbar is currently not wide enough.
+             */
+            this.moreMenu = new Ext.menu.Menu({
+                ownerCt : this.container,
+                listeners: {
+                    beforeshow: this.beforeMoreShow,
+                    scope: this
+                }
+            });
+
+            /**
+             * @private
+             * @property more
+             * @type Ext.Button
+             * The expand button which triggers the overflow menu to be shown
+             */
+            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,
+
+    type: 'menu',
+
+    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 alt="{altText}" 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);
+        }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,
+            canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
+
+        return {
+            isMenuItem: isMenuItem,
+            needsIcon: canHaveIcon && (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 ',
+            altText: c.altText || ''
+        };
+    },
+
+    //  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;
+/**
+ * @class Ext.Viewport
+ * @extends Ext.Container
+ * <p>A specialized container representing the viewable application area (the browser viewport).</p>
+ * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
+ * the browser viewport and manages window resizing. There may only be one Viewport created
+ * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
+ * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
+ * method of any of its child Panels may themselves have a layout.</p>
+ * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
+ * for scrolling if needed using the {@link #autoScroll} config.</p>
+ * <p>An example showing a classic application border layout:</p><pre><code>
+new Ext.Viewport({
+    layout: 'border',
+    items: [{
+        region: 'north',
+        html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',
+        autoHeight: true,
+        border: false,
+        margins: '0 0 5 0'
+    }, {
+        region: 'west',
+        collapsible: true,
+        title: 'Navigation',
+        width: 200
+        // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
+    }, {
+        region: 'south',
+        title: 'Title for Panel',
+        collapsible: true,
+        html: 'Information goes here',
+        split: true,
+        height: 100,
+        minHeight: 100
+    }, {
+        region: 'east',
+        title: 'Title for the Grid Panel',
+        collapsible: true,
+        split: true,
+        width: 200,
+        xtype: 'grid',
+        // remaining grid configuration not shown ...
+        // notice that the GridPanel is added directly as the region
+        // it is not "overnested" inside another Panel
+    }, {
+        region: 'center',
+        xtype: 'tabpanel', // TabPanel itself has no title
+        items: {
+            title: 'Default Tab',
+            html: 'The first tab\'s content. Others may be added dynamically'
+        }
+    }]
+});
+</code></pre>
+ * @constructor
+ * Create a new Viewport
+ * @param {Object} config The config object
+ * @xtype viewport
+ */
+Ext.Viewport = Ext.extend(Ext.Container, {
+    /*
+     * Privatize config options which, if used, would interfere with the
+     * correct operation of the Viewport as the sole manager of the
+     * layout of the document body.
+     */
+    /**
+     * @cfg {Mixed} applyTo @hide
+     */
+    /**
+     * @cfg {Boolean} allowDomMove @hide
+     */
+    /**
+     * @cfg {Boolean} hideParent @hide
+     */
+    /**
+     * @cfg {Mixed} renderTo @hide
+     */
+    /**
+     * @cfg {Boolean} hideParent @hide
+     */
+    /**
+     * @cfg {Number} height @hide
+     */
+    /**
+     * @cfg {Number} width @hide
+     */
+    /**
+     * @cfg {Boolean} autoHeight @hide
+     */
+    /**
+     * @cfg {Boolean} autoWidth @hide
+     */
+    /**
+     * @cfg {Boolean} deferHeight @hide
+     */
+    /**
+     * @cfg {Boolean} monitorResize @hide
+     */
+
+    initComponent : function() {
+        Ext.Viewport.superclass.initComponent.call(this);
+        document.getElementsByTagName('html')[0].className += ' x-viewport';
+        this.el = Ext.getBody();
+        this.el.setHeight = Ext.emptyFn;
+        this.el.setWidth = Ext.emptyFn;
+        this.el.setSize = Ext.emptyFn;
+        this.el.dom.scroll = 'no';
+        this.allowDomMove = false;
+        this.autoWidth = true;
+        this.autoHeight = true;
+        Ext.EventManager.onWindowResize(this.fireResize, this);
+        this.renderTo = this.el;
+    },
+
+    fireResize : function(w, h){
+        this.fireEvent('resize', this, w, h, w, h);
+    }
+});
+Ext.reg('viewport', Ext.Viewport);
+/**
+ * @class Ext.Panel
+ * @extends Ext.Container
+ * <p>Panel is a container that has specific functionality and structural components that make
+ * it the perfect building block for application-oriented user interfaces.</p>
+ * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
+ * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
+ * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
+ * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
+ * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By
+ * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
+ * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
+ * at all.</p>
+ * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
+ * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
+ * information).</p>
+ * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
+ * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
+ * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
+ * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
+ * @constructor
+ * @param {Object} config The config object
+ * @xtype panel
+ */
+Ext.Panel = Ext.extend(Ext.Container, {
+    /**
+     * The Panel's header {@link Ext.Element Element}. Read-only.
+     * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
+     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
+     * @type Ext.Element
+     * @property header
+     */
+    /**
+     * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
+     * The content may be specified in the {@link #html} config, or it may be loaded using the
+     * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
+     * <p>If this is used to load visible HTML elements in either way, then
+     * the Panel may not be used as a Layout for hosting nested Panels.</p>
+     * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
+     * then the body Element must not be loaded or changed - it is under the control
+     * of the Panel's Layout.
+     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
+     * @type Ext.Element
+     * @property body
+     */
+    /**
+     * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
+     * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
+     * @type Ext.Element
+     * @property bwrap
+     */
+    /**
+     * True if this panel is collapsed. Read-only.
+     * @type Boolean
+     * @property collapsed
+     */
+    /**
+     * @cfg {Object} bodyCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
+     * Panel Element.</p>
+     * <p>By default, the Default element in the table below will be used for the html markup to
+     * create a child element with the commensurate Default class name (<code>baseCls</code> will be
+     * replaced by <code>{@link #baseCls}</code>):</p>
+     * <pre>
+     * Panel      Default  Default             Custom      Additional       Additional
+     * Element    element  class               element     class            style
+     * ========   ==========================   =========   ==============   ===========
+     * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
+     * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
+     * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
+     * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
+     * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
+     * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
+     * </pre>
+     * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
+     * to use a different form of markup than is created by default. An example of this might be
+     * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
+     * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
+     * element:</p>
+     * <pre><code>
+new Ext.Panel({
+    title: 'Message Title',
+    renderTo: Ext.getBody(),
+    width: 200, height: 130,
+    <b>bodyCfg</b>: {
+        tag: 'center',
+        cls: 'x-panel-body',  // Default class not applied if Custom element specified
+        html: 'Message'
+    },
+    footerCfg: {
+        tag: 'h2',
+        cls: 'x-panel-footer',        // same as the Default class
+        html: 'footer html'
+    },
+    footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
+    footerStyle:    'background-color:red' // see {@link #bodyStyle}
+});
+     * </code></pre>
+     * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
+     * styling applied.</p>
+     */
+    /**
+     * @cfg {Object} headerCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
+     * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     */
+    /**
+     * @cfg {Object} bwrapCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
+     * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     */
+    /**
+     * @cfg {Object} tbarCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
+     * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     */
+    /**
+     * @cfg {Object} bbarCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
+     * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     */
+    /**
+     * @cfg {Object} footerCfg
+     * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
+     * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
+     */
+    /**
+     * @cfg {Boolean} closable
+     * Panels themselves do not directly support being closed, but some Panel subclasses do (like
+     * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
+     * to enable closing in such situations. Defaults to <code>false</code>.
+     */
+    /**
+     * The Panel's footer {@link Ext.Element Element}. Read-only.
+     * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
+     * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
+     * @type Ext.Element
+     * @property footer
      */
     /**
      * @cfg {Mixed} applyTo
      */
     /**
      * @cfg {Mixed} applyTo
@@ -9360,30 +11006,30 @@ new Ext.Panel({
         if(this.tbar){
             this.elements += ',tbar';
             this.topToolbar = this.createToolbar(this.tbar);
         if(this.tbar){
             this.elements += ',tbar';
             this.topToolbar = this.createToolbar(this.tbar);
-            delete this.tbar;
+            this.tbar = null;
 
         }
         if(this.bbar){
             this.elements += ',bbar';
             this.bottomToolbar = this.createToolbar(this.bbar);
 
         }
         if(this.bbar){
             this.elements += ',bbar';
             this.bottomToolbar = this.createToolbar(this.bbar);
-            delete this.bbar;
+            this.bbar = null;
         }
 
         if(this.header === true){
             this.elements += ',header';
         }
 
         if(this.header === true){
             this.elements += ',header';
-            delete this.header;
+            this.header = null;
         }else if(this.headerCfg || (this.title && this.header !== false)){
             this.elements += ',header';
         }
 
         if(this.footerCfg || this.footer === true){
             this.elements += ',footer';
         }else if(this.headerCfg || (this.title && this.header !== false)){
             this.elements += ',header';
         }
 
         if(this.footerCfg || this.footer === true){
             this.elements += ',footer';
-            delete this.footer;
+            this.footer = null;
         }
 
         if(this.buttons){
             this.fbar = this.buttons;
         }
 
         if(this.buttons){
             this.fbar = this.buttons;
-            delete this.buttons;
+            this.buttons = null;
         }
         if(this.fbar){
             this.createFbar(this.fbar);
         }
         if(this.fbar){
             this.createFbar(this.fbar);
@@ -9407,8 +11053,8 @@ new Ext.Panel({
                 };
             }
         });
                 };
             }
         });
-        //@compat addButton and buttons could possibly be removed
-        //@target 4.0
+        // @compat addButton and buttons could possibly be removed
+        // @target 4.0
         /**
          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
          * config property. Read only.
         /**
          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
          * config property. Read only.
@@ -9503,3062 +11149,3606 @@ new Ext.Panel({
             el.addClass(this.cls);
         }
 
             el.addClass(this.cls);
         }
 
-        if(this.buttons){
-            this.elements += ',footer';
+        if(this.buttons){
+            this.elements += ',footer';
+        }
+
+        // This block allows for maximum flexibility and performance when using existing markup
+
+        // framing requires special markup
+        if(this.frame){
+            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
+
+            this.createElement('header', d.firstChild.firstChild.firstChild);
+            this.createElement('bwrap', d);
+
+            // append the mid and bottom frame to the bwrap
+            bw = this.bwrap.dom;
+            var ml = d.childNodes[1], bl = d.childNodes[2];
+            bw.appendChild(ml);
+            bw.appendChild(bl);
+
+            var mc = bw.firstChild.firstChild.firstChild;
+            this.createElement('tbar', mc);
+            this.createElement('body', mc);
+            this.createElement('bbar', mc);
+            this.createElement('footer', bw.lastChild.firstChild.firstChild);
+
+            if(!this.footer){
+                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
+            }
+            /*
+             * Store a reference to this element so:
+             * a) We aren't looking it up all the time
+             * b) The last element is reported incorrectly when using a loadmask
+             */
+            this.ft = Ext.get(this.bwrap.dom.lastChild);
+            this.mc = Ext.get(mc);
+        }else{
+            this.createElement('header', d);
+            this.createElement('bwrap', d);
+
+            // append the mid and bottom frame to the bwrap
+            bw = this.bwrap.dom;
+            this.createElement('tbar', bw);
+            this.createElement('body', bw);
+            this.createElement('bbar', bw);
+            this.createElement('footer', bw);
+
+            if(!this.header){
+                this.body.addClass(this.bodyCls + '-noheader');
+                if(this.tbar){
+                    this.tbar.addClass(this.tbarCls + '-noheader');
+                }
+            }
+        }
+
+        if(Ext.isDefined(this.padding)){
+            this.body.setStyle('padding', this.body.addUnits(this.padding));
+        }
+
+        if(this.border === false){
+            this.el.addClass(this.baseCls + '-noborder');
+            this.body.addClass(this.bodyCls + '-noborder');
+            if(this.header){
+                this.header.addClass(this.headerCls + '-noborder');
+            }
+            if(this.footer){
+                this.footer.addClass(this.footerCls + '-noborder');
+            }
+            if(this.tbar){
+                this.tbar.addClass(this.tbarCls + '-noborder');
+            }
+            if(this.bbar){
+                this.bbar.addClass(this.bbarCls + '-noborder');
+            }
+        }
+
+        if(this.bodyBorder === false){
+           this.body.addClass(this.bodyCls + '-noborder');
+        }
+
+        this.bwrap.enableDisplayMode('block');
+
+        if(this.header){
+            this.header.unselectable();
+
+            // for tools, we need to wrap any existing header markup
+            if(this.headerAsText){
+                this.header.dom.innerHTML =
+                    '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
+
+                if(this.iconCls){
+                    this.setIconClass(this.iconCls);
+                }
+            }
+        }
+
+        if(this.floating){
+            this.makeFloating(this.floating);
+        }
+
+        if(this.collapsible && this.titleCollapse && this.header){
+            this.mon(this.header, 'click', this.toggleCollapse, this);
+            this.header.setStyle('cursor', 'pointer');
+        }
+        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);
+        }
+    },
+
+    /**
+     * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
+     * icon class if one has already been set and fire the {@link #iconchange} event after completion.
+     * @param {String} cls The new CSS class name
+     */
+    setIconClass : function(cls){
+        var old = this.iconCls;
+        this.iconCls = cls;
+        if(this.rendered && this.header){
+            if(this.frame){
+                this.header.addClass('x-panel-icon');
+                this.header.replaceClass(old, this.iconCls);
+            }else{
+                var hd = this.header,
+                    img = hd.child('img.x-panel-inline-icon');
+                if(img){
+                    Ext.fly(img).replaceClass(old, this.iconCls);
+                }else{
+                    var hdspan = hd.child('span.' + this.headerTextCls);
+                    if (hdspan) {
+                        Ext.DomHelper.insertBefore(hdspan.dom, {
+                            tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
+                        });
+                    }
+                 }
+            }
+        }
+        this.fireEvent('iconchange', this, cls, old);
+    },
+
+    // private
+    makeFloating : function(cfg){
+        this.floating = true;
+        this.el = new Ext.Layer(Ext.apply({}, cfg, {
+            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
+            shadowOffset: this.shadowOffset,
+            constrain:false,
+            shim: this.shim === false ? false : undefined
+        }), this.el);
+    },
+
+    /**
+     * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
+     * @return {Ext.Toolbar} The toolbar
+     */
+    getTopToolbar : function(){
+        return this.topToolbar;
+    },
+
+    /**
+     * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
+     * @return {Ext.Toolbar} The toolbar
+     */
+    getBottomToolbar : function(){
+        return this.bottomToolbar;
+    },
+
+    /**
+     * Returns the {@link Ext.Toolbar toolbar} from the footer (<code>{@link #fbar}</code>) section of the panel.
+     * @return {Ext.Toolbar} The toolbar
+     */
+    getFooterToolbar : function() {
+        return this.fbar;
+    },
+
+    /**
+     * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
+     * approach is to add buttons via the {@link #buttons} config.
+     * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
+     * button config, an object will be treated as a button config object.
+     * @param {Function} handler The function to be called on button {@link Ext.Button#click}
+     * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
+     * @return {Ext.Button} The button that was added
+     */
+    addButton : function(config, handler, scope){
+        if(!this.fbar){
+            this.createFbar([]);
+        }
+        if(handler){
+            if(Ext.isString(config)){
+                config = {text: config};
+            }
+            config = Ext.apply({
+                handler: handler,
+                scope: scope
+            }, config);
+        }
+        return this.fbar.add(config);
+    },
+
+    // private
+    addTool : function(){
+        if(!this.rendered){
+            if(!this.tools){
+                this.tools = [];
+            }
+            Ext.each(arguments, function(arg){
+                this.tools.push(arg);
+            }, this);
+            return;
+        }
+         // nowhere to render tools!
+        if(!this[this.toolTarget]){
+            return;
+        }
+        if(!this.toolTemplate){
+            // initialize the global tool template on first use
+            var tt = new Ext.Template(
+                 '<div class="x-tool x-tool-{id}">&#160;</div>'
+            );
+            tt.disableFormats = true;
+            tt.compile();
+            Ext.Panel.prototype.toolTemplate = tt;
+        }
+        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
+            var tc = a[i];
+            if(!this.tools[tc.id]){
+                var overCls = 'x-tool-'+tc.id+'-over';
+                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));
+                if(tc.on){
+                    this.mon(t, tc.on);
+                }
+                if(tc.hidden){
+                    t.hide();
+                }
+                if(tc.qtip){
+                    if(Ext.isObject(tc.qtip)){
+                        Ext.QuickTips.register(Ext.apply({
+                              target: t.id
+                        }, tc.qtip));
+                    } else {
+                        t.dom.qtip = tc.qtip;
+                    }
+                }
+                t.addClassOnOver(overCls);
+            }
+        }
+    },
+
+    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);
+            });
+            this.syncHeight();
         }
         }
+    },
 
 
-        // This block allows for maximum flexibility and performance when using existing markup
-
-        // framing requires special markup
-        if(this.frame){
-            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
-
-            this.createElement('header', d.firstChild.firstChild.firstChild);
-            this.createElement('bwrap', d);
-
-            // append the mid and bottom frame to the bwrap
-            bw = this.bwrap.dom;
-            var ml = d.childNodes[1], bl = d.childNodes[2];
-            bw.appendChild(ml);
-            bw.appendChild(bl);
+    syncHeight : function(){
+        var h = this.toolbarHeight,
+                bd = this.body,
+                lsh = this.lastSize.height,
+                sz;
 
 
-            var mc = bw.firstChild.firstChild.firstChild;
-            this.createElement('tbar', mc);
-            this.createElement('body', mc);
-            this.createElement('bbar', mc);
-            this.createElement('footer', bw.lastChild.firstChild.firstChild);
+        if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
+            return;
+        }
 
 
-            if(!this.footer){
-                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
-            }
-            /*
-             * Store a reference to this element so:
-             * a) We aren't looking it up all the time
-             * b) The last element is reported incorrectly when using a loadmask
-             */
-            this.ft = Ext.get(this.bwrap.dom.lastChild);
-            this.mc = Ext.get(mc);
-        }else{
-            this.createElement('header', d);
-            this.createElement('bwrap', d);
 
 
-            // append the mid and bottom frame to the bwrap
-            bw = this.bwrap.dom;
-            this.createElement('tbar', bw);
-            this.createElement('body', bw);
-            this.createElement('bbar', bw);
-            this.createElement('footer', bw);
+        if(h != this.getToolbarHeight()){
+            h = Math.max(0, lsh - this.getFrameHeight());
+            bd.setHeight(h);
+            sz = bd.getSize();
+            this.toolbarHeight = this.getToolbarHeight();
+            this.onBodyResize(sz.width, sz.height);
+        }
+    },
 
 
-            if(!this.header){
-                this.body.addClass(this.bodyCls + '-noheader');
-                if(this.tbar){
-                    this.tbar.addClass(this.tbarCls + '-noheader');
-                }
-            }
+    // private
+    onShow : function(){
+        if(this.floating){
+            return this.el.show();
         }
         }
+        Ext.Panel.superclass.onShow.call(this);
+    },
 
 
-        if(Ext.isDefined(this.padding)){
-            this.body.setStyle('padding', this.body.addUnits(this.padding));
+    // private
+    onHide : function(){
+        if(this.floating){
+            return this.el.hide();
         }
         }
+        Ext.Panel.superclass.onHide.call(this);
+    },
 
 
-        if(this.border === false){
-            this.el.addClass(this.baseCls + '-noborder');
-            this.body.addClass(this.bodyCls + '-noborder');
-            if(this.header){
-                this.header.addClass(this.headerCls + '-noborder');
-            }
-            if(this.footer){
-                this.footer.addClass(this.footerCls + '-noborder');
-            }
-            if(this.tbar){
-                this.tbar.addClass(this.tbarCls + '-noborder');
+    // private
+    createToolHandler : function(t, tc, overCls, panel){
+        return function(e){
+            t.removeClass(overCls);
+            if(tc.stopEvent !== false){
+                e.stopEvent();
             }
             }
-            if(this.bbar){
-                this.bbar.addClass(this.bbarCls + '-noborder');
+            if(tc.handler){
+                tc.handler.call(tc.scope || t, e, t, panel, tc);
             }
             }
-        }
+        };
+    },
 
 
-        if(this.bodyBorder === false){
-           this.body.addClass(this.bodyCls + '-noborder');
+    // private
+    afterRender : function(){
+        if(this.floating && !this.hidden){
+            this.el.show();
+        }
+        if(this.title){
+            this.setTitle(this.title);
+        }
+        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
+        if (this.collapsed) {
+            this.collapsed = false;
+            this.collapse(false);
         }
         }
+        this.initEvents();
+    },
 
 
-        this.bwrap.enableDisplayMode('block');
+    // private
+    getKeyMap : function(){
+        if(!this.keyMap){
+            this.keyMap = new Ext.KeyMap(this.el, this.keys);
+        }
+        return this.keyMap;
+    },
 
 
-        if(this.header){
-            this.header.unselectable();
+    // private
+    initEvents : function(){
+        if(this.keys){
+            this.getKeyMap();
+        }
+        if(this.draggable){
+            this.initDraggable();
+        }
+        if(this.toolbars.length > 0){
+            Ext.each(this.toolbars, function(tb){
+                tb.doLayout();
+                tb.on({
+                    scope: this,
+                    afterlayout: this.syncHeight,
+                    remove: this.syncHeight
+                });
+            }, this);
+            this.syncHeight();
+        }
 
 
-            // for tools, we need to wrap any existing header markup
-            if(this.headerAsText){
-                this.header.dom.innerHTML =
-                    '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
+    },
 
 
-                if(this.iconCls){
-                    this.setIconClass(this.iconCls);
-                }
-            }
-        }
+    // private
+    initDraggable : function(){
+        /**
+         * <p>If this Panel is configured {@link #draggable}, this property will contain
+         * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
+         * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
+         * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
+         * @type Ext.dd.DragSource.
+         * @property dd
+         */
+        this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
+    },
 
 
+    // private
+    beforeEffect : function(anim){
         if(this.floating){
         if(this.floating){
-            this.makeFloating(this.floating);
+            this.el.beforeAction();
         }
         }
-
-        if(this.collapsible && this.titleCollapse && this.header){
-            this.mon(this.header, 'click', this.toggleCollapse, this);
-            this.header.setStyle('cursor', 'pointer');
+        if(anim !== false){
+            this.el.addClass('x-panel-animated');
         }
         }
-        if(ts){
-            this.addTool.apply(this, ts);
+    },
+
+    // private
+    afterEffect : function(anim){
+        this.syncShadow();
+        this.el.removeClass('x-panel-animated');
+    },
+
+    // private - wraps up an animation param with internal callbacks
+    createEffect : function(a, cb, scope){
+        var o = {
+            scope:scope,
+            block:true
+        };
+        if(a === true){
+            o.callback = cb;
+            return o;
+        }else if(!a.callback){
+            o.callback = cb;
+        }else { // wrap it up
+            o.callback = function(){
+                cb.call(scope);
+                Ext.callback(a.callback, a.scope);
+            };
         }
         }
+        return Ext.applyIf(o, a);
+    },
 
 
-        // 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'});
+    /**
+     * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
+     * cancel the collapse action if it returns false.
+     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
+     * {@link #animCollapse} panel config)
+     * @return {Ext.Panel} this
+     */
+    collapse : function(animate){
+        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
+            return;
         }
         }
-        if(this.tbar && this.topToolbar){
-            this.topToolbar.ownerCt = this;
-            this.topToolbar.render(this.tbar);
+        var doAnim = animate === true || (animate !== false && this.animCollapse);
+        this.beforeEffect(doAnim);
+        this.onCollapse(doAnim, animate);
+        return this;
+    },
+
+    // private
+    onCollapse : function(doAnim, animArg){
+        if(doAnim){
+            this[this.collapseEl].slideOut(this.slideAnchor,
+                    Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
+                        this.collapseDefaults));
+        }else{
+            this[this.collapseEl].hide(this.hideMode);
+            this.afterCollapse(false);
         }
         }
-        if(this.bbar && this.bottomToolbar){
-            this.bottomToolbar.ownerCt = this;
-            this.bottomToolbar.render(this.bbar);
+    },
+
+    // private
+    afterCollapse : function(anim){
+        this.collapsed = true;
+        this.el.addClass(this.collapsedCls);
+        if(anim !== false){
+            this[this.collapseEl].hide(this.hideMode);
         }
         }
+        this.afterEffect(anim);
+
+        // Reset lastSize of all sub-components so they KNOW they are in a collapsed container
+        this.cascade(function(c) {
+            if (c.lastSize) {
+                c.lastSize = { width: undefined, height: undefined };
+            }
+        });
+        this.fireEvent('collapse', this);
     },
 
     /**
     },
 
     /**
-     * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
-     * icon class if one has already been set and fire the {@link #iconchange} event after completion.
-     * @param {String} cls The new CSS class name
+     * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
+     * cancel the expand action if it returns false.
+     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
+     * {@link #animCollapse} panel config)
+     * @return {Ext.Panel} this
      */
      */
-    setIconClass : function(cls){
-        var old = this.iconCls;
-        this.iconCls = cls;
-        if(this.rendered && this.header){
-            if(this.frame){
-                this.header.addClass('x-panel-icon');
-                this.header.replaceClass(old, this.iconCls);
-            }else{
-                var hd = this.header,
-                    img = hd.child('img.x-panel-inline-icon');
-                if(img){
-                    Ext.fly(img).replaceClass(old, this.iconCls);
-                }else{
-                    Ext.DomHelper.insertBefore(hd.dom.firstChild, {
-                        tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
-                    });
-                 }
-            }
+    expand : function(animate){
+        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
+            return;
         }
         }
-        this.fireEvent('iconchange', this, cls, old);
+        var doAnim = animate === true || (animate !== false && this.animCollapse);
+        this.el.removeClass(this.collapsedCls);
+        this.beforeEffect(doAnim);
+        this.onExpand(doAnim, animate);
+        return this;
     },
 
     // private
     },
 
     // private
-    makeFloating : function(cfg){
-        this.floating = true;
-        this.el = new Ext.Layer(Ext.apply({}, cfg, {
-            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
-            shadowOffset: this.shadowOffset,
-            constrain:false,
-            shim: this.shim === false ? false : undefined
-        }), this.el);
+    onExpand : function(doAnim, animArg){
+        if(doAnim){
+            this[this.collapseEl].slideIn(this.slideAnchor,
+                    Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
+                        this.expandDefaults));
+        }else{
+            this[this.collapseEl].show(this.hideMode);
+            this.afterExpand(false);
+        }
     },
 
     },
 
-    /**
-     * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
-     * @return {Ext.Toolbar} The toolbar
-     */
-    getTopToolbar : function(){
-        return this.topToolbar;
+    // private
+    afterExpand : function(anim){
+        this.collapsed = false;
+        if(anim !== false){
+            this[this.collapseEl].show(this.hideMode);
+        }
+        this.afterEffect(anim);
+        if (this.deferLayout) {
+            delete this.deferLayout;
+            this.doLayout(true);
+        }
+        this.fireEvent('expand', this);
     },
 
     /**
     },
 
     /**
-     * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
-     * @return {Ext.Toolbar} The toolbar
+     * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
+     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
+     * {@link #animCollapse} panel config)
+     * @return {Ext.Panel} this
      */
      */
-    getBottomToolbar : function(){
-        return this.bottomToolbar;
+    toggleCollapse : function(animate){
+        this[this.collapsed ? 'expand' : 'collapse'](animate);
+        return this;
     },
 
     },
 
-    /**
-     * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
-     * approach is to add buttons via the {@link #buttons} config.
-     * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
-     * button config, an object will be treated as a button config object.
-     * @param {Function} handler The function to be called on button {@link Ext.Button#click}
-     * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
-     * @return {Ext.Button} The button that was added
-     */
-    addButton : function(config, handler, scope){
-        if(!this.fbar){
-            this.createFbar([]);
-        }
-        if(handler){
-            if(Ext.isString(config)){
-                config = {text: config};
-            }
-            config = Ext.apply({
-                handler: handler,
-                scope: scope
-            }, config)
+    // private
+    onDisable : function(){
+        if(this.rendered && this.maskDisabled){
+            this.el.mask();
         }
         }
-        return this.fbar.add(config);
+        Ext.Panel.superclass.onDisable.call(this);
     },
 
     // private
     },
 
     // private
-    addTool : function(){
-        if(!this.rendered){
-            if(!this.tools){
-                this.tools = [];
-            }
-            Ext.each(arguments, function(arg){
-                this.tools.push(arg)
-            }, this);
-            return;
-        }
-         // nowhere to render tools!
-        if(!this[this.toolTarget]){
-            return;
-        }
-        if(!this.toolTemplate){
-            // initialize the global tool template on first use
-            var tt = new Ext.Template(
-                 '<div class="x-tool x-tool-{id}">&#160;</div>'
-            );
-            tt.disableFormats = true;
-            tt.compile();
-            Ext.Panel.prototype.toolTemplate = tt;
+    onEnable : function(){
+        if(this.rendered && this.maskDisabled){
+            this.el.unmask();
         }
         }
-        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
-            var tc = a[i];
-            if(!this.tools[tc.id]){
-                var overCls = 'x-tool-'+tc.id+'-over';
-                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));
-                if(tc.on){
-                    this.mon(t, tc.on);
+        Ext.Panel.superclass.onEnable.call(this);
+    },
+
+    // private
+    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
+        var w = adjWidth,
+            h = adjHeight;
+
+        if(Ext.isDefined(w) || Ext.isDefined(h)){
+            if(!this.collapsed){
+                // First, set the the Panel's body width.
+                // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
+                // The Toolbars must not buffer this resize operation because we need to know their heights.
+
+                if(Ext.isNumber(w)){
+                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
+                } else if (w == 'auto') {
+                    w = this.body.setWidth('auto').dom.offsetWidth;
+                } else {
+                    w = this.body.dom.offsetWidth;
                 }
                 }
-                if(tc.hidden){
-                    t.hide();
+
+                if(this.tbar){
+                    this.tbar.setWidth(w);
+                    if(this.topToolbar){
+                        this.topToolbar.setSize(w);
+                    }
                 }
                 }
-                if(tc.qtip){
-                    if(Ext.isObject(tc.qtip)){
-                        Ext.QuickTips.register(Ext.apply({
-                              target: t.id
-                        }, tc.qtip));
-                    } else {
-                        t.dom.qtip = tc.qtip;
+                if(this.bbar){
+                    this.bbar.setWidth(w);
+                    if(this.bottomToolbar){
+                        this.bottomToolbar.setSize(w);
+                        // The bbar does not move on resize without this.
+                        if (Ext.isIE) {
+                            this.bbar.setStyle('position', 'static');
+                            this.bbar.setStyle('position', '');
+                        }
+                    }
+                }
+                if(this.footer){
+                    this.footer.setWidth(w);
+                    if(this.fbar){
+                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
                     }
                 }
                     }
                 }
-                t.addClassOnOver(overCls);
-            }
-        }
-    },
-
-    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);
-            });
-            this.syncHeight();
-        }
-    },
 
 
-    syncHeight : function(){
-        var h = this.toolbarHeight,
-                bd = this.body,
-                lsh = this.lastSize.height,
-                sz;
+                // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
+                if(Ext.isNumber(h)){
+                    h = Math.max(0, h - this.getFrameHeight());
+                    //h = Math.max(0, h - (this.getHeight() - this.body.getHeight()));
+                    this.body.setHeight(h);
+                }else if(h == 'auto'){
+                    this.body.setHeight(h);
+                }
 
 
-        if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
-            return;
+                if(this.disabled && this.el._mask){
+                    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;
+                    this.on('expand', function(){
+                        delete this.queuedExpand;
+                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
+                    }, this, {single:true});
+                }
+            }
+            this.onBodyResize(w, h);
         }
         }
+        this.syncShadow();
+        Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
 
 
+    },
 
 
-        if(h != this.getToolbarHeight()){
-            h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
-            bd.setHeight(h);
-            sz = bd.getSize();
-            this.toolbarHeight = this.getToolbarHeight();
-            this.onBodyResize(sz.width, sz.height);
-        }
+    // private
+    onBodyResize: function(w, h){
+        this.fireEvent('bodyresize', this, w, h);
     },
 
     // private
     },
 
     // private
-    onShow : function(){
-        if(this.floating){
-            return this.el.show();
+    getToolbarHeight: function(){
+        var h = 0;
+        if(this.rendered){
+            Ext.each(this.toolbars, function(tb){
+                h += tb.getHeight();
+            }, this);
         }
         }
-        Ext.Panel.superclass.onShow.call(this);
+        return h;
     },
 
     },
 
-    // private
-    onHide : function(){
-        if(this.floating){
-            return this.el.hide();
-        }
-        Ext.Panel.superclass.onHide.call(this);
+    // deprecate
+    adjustBodyHeight : function(h){
+        return h;
     },
 
     // private
     },
 
     // private
-    createToolHandler : function(t, tc, overCls, panel){
-        return function(e){
-            t.removeClass(overCls);
-            if(tc.stopEvent !== false){
-                e.stopEvent();
-            }
-            if(tc.handler){
-                tc.handler.call(tc.scope || t, e, t, panel, tc);
-            }
-        };
+    adjustBodyWidth : function(w){
+        return w;
     },
 
     // private
     },
 
     // private
-    afterRender : function(){
-        if(this.floating && !this.hidden){
-            this.el.show();
-        }
-        if(this.title){
-            this.setTitle(this.title);
-        }
-        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
-        if (this.collapsed) {
-            this.collapsed = false;
-            this.collapse(false);
-        }
-        this.initEvents();
+    onPosition : function(){
+        this.syncShadow();
     },
 
     },
 
-    // private
-    getKeyMap : function(){
-        if(!this.keyMap){
-            this.keyMap = new Ext.KeyMap(this.el, this.keys);
+    /**
+     * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
+     * retrieve the body width see {@link #getInnerWidth}.
+     * @return {Number} The frame width
+     */
+    getFrameWidth : function(){
+        var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
+
+        if(this.frame){
+            var l = this.bwrap.dom.firstChild;
+            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
+            w += this.mc.getFrameWidth('lr');
         }
         }
-        return this.keyMap;
+        return w;
     },
 
     },
 
-    // private
-    initEvents : function(){
-        if(this.keys){
-            this.getKeyMap();
-        }
-        if(this.draggable){
-            this.initDraggable();
-        }
-        if(this.toolbars.length > 0){
-            Ext.each(this.toolbars, function(tb){
-                tb.doLayout();
-                tb.on({
-                    scope: this,
-                    afterlayout: this.syncHeight,
-                    remove: this.syncHeight
-                });
-            }, this);
-            this.syncHeight();
+    /**
+     * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
+     * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
+     * @return {Number} The frame height
+     */
+    getFrameHeight : function() {
+        var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
+        h += (this.tbar ? this.tbar.getHeight() : 0) +
+             (this.bbar ? this.bbar.getHeight() : 0);
+
+        if(this.frame){
+            h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
+        }else{
+            h += (this.header ? this.header.getHeight() : 0) +
+                (this.footer ? this.footer.getHeight() : 0);
         }
         }
+        return h;
+    },
 
 
+    /**
+     * Returns the width in pixels of the body element (not including the width of any framing elements).
+     * For the frame width see {@link #getFrameWidth}.
+     * @return {Number} The body width
+     */
+    getInnerWidth : function(){
+        return this.getSize().width - this.getFrameWidth();
     },
 
     },
 
-    // private
-    initDraggable : function(){
-        /**
-         * <p>If this Panel is configured {@link #draggable}, this property will contain
-         * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
-         * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
-         * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
-         * @type Ext.dd.DragSource.
-         * @property dd
-         */
-        this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
+    /**
+     * Returns the height in pixels of the body element (not including the height of any framing elements).
+     * For the frame height see {@link #getFrameHeight}.
+     * @return {Number} The body height
+     */
+    getInnerHeight : function(){
+        return this.body.getHeight();
+        /* Deprecate
+            return this.getSize().height - this.getFrameHeight();
+        */
     },
 
     // private
     },
 
     // private
-    beforeEffect : function(anim){
+    syncShadow : function(){
         if(this.floating){
         if(this.floating){
-            this.el.beforeAction();
-        }
-        if(anim !== false){
-            this.el.addClass('x-panel-animated');
+            this.el.sync(true);
         }
     },
 
     // private
         }
     },
 
     // private
-    afterEffect : function(anim){
-        this.syncShadow();
-        if(anim !== false){
-            this.el.removeClass('x-panel-animated');
-        }
+    getLayoutTarget : function(){
+        return this.body;
     },
 
     },
 
-    // private - wraps up an animation param with internal callbacks
-    createEffect : function(a, cb, scope){
-        var o = {
-            scope:scope,
-            block:true
-        };
-        if(a === true){
-            o.callback = cb;
-            return o;
-        }else if(!a.callback){
-            o.callback = cb;
-        }else { // wrap it up
-            o.callback = function(){
-                cb.call(scope);
-                Ext.callback(a.callback, a.scope);
-            };
+    // private
+    getContentTarget : function(){
+        return this.body;
+    },
+
+    /**
+     * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
+     * <p>In order to be able to set the title, a header element must have been created
+     * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
+     * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
+     * @param {String} title The title text to set
+     * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
+     */
+    setTitle : function(title, iconCls){
+        this.title = title;
+        if(this.header && this.headerAsText){
+            this.header.child('span').update(title);
         }
         }
-        return Ext.applyIf(o, a);
+        if(iconCls){
+            this.setIconClass(iconCls);
+        }
+        this.fireEvent('titlechange', this, title);
+        return this;
     },
 
     /**
     },
 
     /**
-     * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
-     * cancel the collapse action if it returns false.
-     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
-     * {@link #animCollapse} panel config)
+     * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
+     * @return {Ext.Updater} The Updater
+     */
+    getUpdater : function(){
+        return this.body.getUpdater();
+    },
+
+     /**
+     * Loads this content panel immediately with content returned from an XHR call.
+     * @param {Object/String/Function} config A config object containing any of the following options:
+<pre><code>
+panel.load({
+    url: 'your-url.php',
+    params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
+    callback: yourFunction,
+    scope: yourObject, // optional scope for the callback
+    discardUrl: false,
+    nocache: false,
+    text: 'Loading...',
+    timeout: 30,
+    scripts: false
+});
+</code></pre>
+     * The only required property is url. The optional properties nocache, text and scripts
+     * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
+     * associated property on this panel Updater instance.
      * @return {Ext.Panel} this
      */
      * @return {Ext.Panel} this
      */
-    collapse : function(animate){
-        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
-            return;
-        }
-        var doAnim = animate === true || (animate !== false && this.animCollapse);
-        this.beforeEffect(doAnim);
-        this.onCollapse(doAnim, animate);
+    load : function(){
+        var um = this.body.getUpdater();
+        um.update.apply(um, arguments);
         return this;
     },
 
     // private
         return this;
     },
 
     // private
-    onCollapse : function(doAnim, animArg){
-        if(doAnim){
-            this[this.collapseEl].slideOut(this.slideAnchor,
-                    Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
-                        this.collapseDefaults));
-        }else{
-            this[this.collapseEl].hide();
-            this.afterCollapse(false);
+    beforeDestroy : function(){
+        Ext.Panel.superclass.beforeDestroy.call(this);
+        if(this.header){
+            this.header.removeAllListeners();
+        }
+        if(this.tools){
+            for(var k in this.tools){
+                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]);
+            }
+        }
+        if(this.rendered){
+            Ext.destroy(
+                this.ft,
+                this.header,
+                this.footer,
+                this.tbar,
+                this.bbar,
+                this.body,
+                this.mc,
+                this.bwrap,
+                this.dd
+            );
+            if (this.fbar) {
+                Ext.destroy(
+                    this.fbar,
+                    this.fbar.el
+                );
+            }
         }
         }
+        Ext.destroy(this.toolbars);
     },
 
     // private
     },
 
     // private
-    afterCollapse : function(anim){
-        this.collapsed = true;
-        this.el.addClass(this.collapsedCls);
-        this.afterEffect(anim);
-        this.fireEvent('collapse', this);
-    },
-
-    /**
-     * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
-     * cancel the expand action if it returns false.
-     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
-     * {@link #animCollapse} panel config)
-     * @return {Ext.Panel} this
-     */
-    expand : function(animate){
-        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
-            return;
-        }
-        var doAnim = animate === true || (animate !== false && this.animCollapse);
-        this.el.removeClass(this.collapsedCls);
-        this.beforeEffect(doAnim);
-        this.onExpand(doAnim, animate);
-        return this;
+    createClasses : function(){
+        this.headerCls = this.baseCls + '-header';
+        this.headerTextCls = this.baseCls + '-header-text';
+        this.bwrapCls = this.baseCls + '-bwrap';
+        this.tbarCls = this.baseCls + '-tbar';
+        this.bodyCls = this.baseCls + '-body';
+        this.bbarCls = this.baseCls + '-bbar';
+        this.footerCls = this.baseCls + '-footer';
     },
 
     // private
     },
 
     // private
-    onExpand : function(doAnim, animArg){
-        if(doAnim){
-            this[this.collapseEl].slideIn(this.slideAnchor,
-                    Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
-                        this.expandDefaults));
+    createGhost : function(cls, useShim, appendTo){
+        var el = document.createElement('div');
+        el.className = 'x-panel-ghost ' + (cls ? cls : '');
+        if(this.header){
+            el.appendChild(this.el.dom.firstChild.cloneNode(true));
+        }
+        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
+        el.style.width = this.el.dom.offsetWidth + 'px';;
+        if(!appendTo){
+            this.container.dom.appendChild(el);
         }else{
         }else{
-            this[this.collapseEl].show();
-            this.afterExpand(false);
+            Ext.getDom(appendTo).appendChild(el);
+        }
+        if(useShim !== false && this.el.useShim !== false){
+            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
+            layer.show();
+            return layer;
+        }else{
+            return new Ext.Element(el);
         }
     },
 
     // private
         }
     },
 
     // private
-    afterExpand : function(anim){
-        this.collapsed = false;
-        this.afterEffect(anim);
-        if (this.deferLayout) {
-            delete this.deferLayout;
-            this.doLayout(true);
+    doAutoLoad : function(){
+        var u = this.body.getUpdater();
+        if(this.renderer){
+            u.setRenderer(this.renderer);
         }
         }
-        this.fireEvent('expand', this);
+        u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
     },
 
     /**
     },
 
     /**
-     * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
-     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
-     * {@link #animCollapse} panel config)
-     * @return {Ext.Panel} this
+     * Retrieve a tool by id.
+     * @param {String} id
+     * @return {Object} tool
      */
      */
-    toggleCollapse : function(animate){
-        this[this.collapsed ? 'expand' : 'collapse'](animate);
-        return this;
+    getTool : function(id) {
+        return this.tools[id];
+    }
+
+/**
+ * @cfg {String} autoEl @hide
+ */
+});
+Ext.reg('panel', Ext.Panel);
+/**
+ * @class Ext.Editor
+ * @extends Ext.Component
+ * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
+ * @constructor
+ * Create a new Editor
+ * @param {Object} config The config object
+ * @xtype editor
+ */
+Ext.Editor = function(field, config){
+    if(field.field){
+        this.field = Ext.create(field.field, 'textfield');
+        config = Ext.apply({}, field); // copy so we don't disturb original config
+        delete config.field;
+    }else{
+        this.field = field;
+    }
+    Ext.Editor.superclass.constructor.call(this, config);
+};
+
+Ext.extend(Ext.Editor, Ext.Component, {
+    /**
+    * @cfg {Ext.form.Field} field
+    * The Field object (or descendant) or config object for field
+    */
+    /**
+     * @cfg {Boolean} allowBlur
+     * True to {@link #completeEdit complete the editing process} if in edit mode when the
+     * field is blurred. Defaults to <tt>true</tt>.
+     */
+    allowBlur: true,
+    /**
+     * @cfg {Boolean/String} autoSize
+     * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
+     * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
+     */
+    /**
+     * @cfg {Boolean} revertInvalid
+     * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
+     * validation fails (defaults to true)
+     */
+    /**
+     * @cfg {Boolean} ignoreNoChange
+     * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
+     * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
+     * will never be ignored.
+     */
+    /**
+     * @cfg {Boolean} hideEl
+     * False to keep the bound element visible while the editor is displayed (defaults to true)
+     */
+    /**
+     * @cfg {Mixed} value
+     * The data value of the underlying field (defaults to "")
+     */
+    value : "",
+    /**
+     * @cfg {String} alignment
+     * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
+     */
+    alignment: "c-c?",
+    /**
+     * @cfg {Array} offsets
+     * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
+     */
+    offsets: [0, 0],
+    /**
+     * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
+     * for bottom-right shadow (defaults to "frame")
+     */
+    shadow : "frame",
+    /**
+     * @cfg {Boolean} constrain True to constrain the editor to the viewport
+     */
+    constrain : false,
+    /**
+     * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
+     */
+    swallowKeys : true,
+    /**
+     * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
+     */
+    completeOnEnter : true,
+    /**
+     * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
+     */
+    cancelOnEsc : true,
+    /**
+     * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
+     */
+    updateEl : false,
+
+    initComponent : function(){
+        Ext.Editor.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event beforestartedit
+             * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
+             * false from the handler of this event.
+             * @param {Editor} this
+             * @param {Ext.Element} boundEl The underlying element bound to this editor
+             * @param {Mixed} value The field value being set
+             */
+            "beforestartedit",
+            /**
+             * @event startedit
+             * Fires when this editor is displayed
+             * @param {Ext.Element} boundEl The underlying element bound to this editor
+             * @param {Mixed} value The starting field value
+             */
+            "startedit",
+            /**
+             * @event beforecomplete
+             * Fires after a change has been made to the field, but before the change is reflected in the underlying
+             * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
+             * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
+             * event will not fire since no edit actually occurred.
+             * @param {Editor} this
+             * @param {Mixed} value The current field value
+             * @param {Mixed} startValue The original field value
+             */
+            "beforecomplete",
+            /**
+             * @event complete
+             * Fires after editing is complete and any changed value has been written to the underlying field.
+             * @param {Editor} this
+             * @param {Mixed} value The current field value
+             * @param {Mixed} startValue The original field value
+             */
+            "complete",
+            /**
+             * @event canceledit
+             * Fires after editing has been canceled and the editor's value has been reset.
+             * @param {Editor} this
+             * @param {Mixed} value The user-entered field value that was discarded
+             * @param {Mixed} startValue The original field value that was set back into the editor after cancel
+             */
+            "canceledit",
+            /**
+             * @event specialkey
+             * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
+             * {@link Ext.EventObject#getKey} to determine which key was pressed.
+             * @param {Ext.form.Field} this
+             * @param {Ext.EventObject} e The event object
+             */
+            "specialkey"
+        );
     },
 
     // private
     },
 
     // private
-    onDisable : function(){
-        if(this.rendered && this.maskDisabled){
-            this.el.mask();
+    onRender : function(ct, position){
+        this.el = new Ext.Layer({
+            shadow: this.shadow,
+            cls: "x-editor",
+            parentEl : ct,
+            shim : this.shim,
+            shadowOffset: this.shadowOffset || 4,
+            id: this.id,
+            constrain: this.constrain
+        });
+        if(this.zIndex){
+            this.el.setZIndex(this.zIndex);
+        }
+        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
+        if(this.field.msgTarget != 'title'){
+            this.field.msgTarget = 'qtip';
+        }
+        this.field.inEditor = true;
+        this.mon(this.field, {
+            scope: this,
+            blur: this.onBlur,
+            specialkey: this.onSpecialKey
+        });
+        if(this.field.grow){
+            this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
         }
         }
-        Ext.Panel.superclass.onDisable.call(this);
-    },
-
-    // private
-    onEnable : function(){
-        if(this.rendered && this.maskDisabled){
-            this.el.unmask();
+        this.field.render(this.el).show();
+        this.field.getEl().dom.name = '';
+        if(this.swallowKeys){
+            this.field.el.swallowEvent([
+                'keypress', // *** Opera
+                'keydown'   // *** all other browsers
+            ]);
         }
         }
-        Ext.Panel.superclass.onEnable.call(this);
     },
 
     // private
     },
 
     // private
-    onResize : function(w, h){
-        if(Ext.isDefined(w) || Ext.isDefined(h)){
-            if(!this.collapsed){
-                // First, set the the Panel's body width.
-                // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
-                // The Toolbars must not buffer this resize operation because we need to know their heights.
-
-                if(Ext.isNumber(w)){
-                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
-                } else if (w == 'auto') {
-                    w = this.body.setWidth('auto').dom.offsetWidth;
-                } else {
-                    w = this.body.dom.offsetWidth;
-                }
-
-                if(this.tbar){
-                    this.tbar.setWidth(w);
-                    if(this.topToolbar){
-                        this.topToolbar.setSize(w);
-                    }
-                }
-                if(this.bbar){
-                    this.bbar.setWidth(w);
-                    if(this.bottomToolbar){
-                        this.bottomToolbar.setSize(w);
-                        // The bbar does not move on resize without this.
-                        if (Ext.isIE) {
-                            this.bbar.setStyle('position', 'static');
-                            this.bbar.setStyle('position', '');
-                        }
-                    }
-                }
-                if(this.footer){
-                    this.footer.setWidth(w);
-                    if(this.fbar){
-                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
-                    }
-                }
-
-                // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
-                if(Ext.isNumber(h)){
-                    h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
-                    this.body.setHeight(h);
-                }else if(h == 'auto'){
-                    this.body.setHeight(h);
-                }
-
-                if(this.disabled && this.el._mask){
-                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
-                }
+    onSpecialKey : function(field, e){
+        var key = e.getKey(),
+            complete = this.completeOnEnter && key == e.ENTER,
+            cancel = this.cancelOnEsc && key == e.ESC;
+        if(complete || cancel){
+            e.stopEvent();
+            if(complete){
+                this.completeEdit();
             }else{
             }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;
-                    this.on('expand', function(){
-                        delete this.queuedExpand;
-                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
-                    }, this, {single:true});
-                }
+                this.cancelEdit();
+            }
+            if(field.triggerBlur){
+                field.triggerBlur();
             }
             }
-            this.onBodyResize(w, h);
         }
         }
-        this.syncShadow();
-        Ext.Panel.superclass.onResize.call(this);
-    },
-
-    // private
-    onBodyResize: function(w, h){
-        this.fireEvent('bodyresize', this, w, h);
+        this.fireEvent('specialkey', field, e);
     },
 
     },
 
-    // private
-    getToolbarHeight: function(){
-        var h = 0;
-        if(this.rendered){
-            Ext.each(this.toolbars, function(tb){
-                h += tb.getHeight();
-            }, this);
+    /**
+     * Starts the editing process and shows the editor.
+     * @param {Mixed} el The element to edit
+     * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
+      * to the innerHTML of el.
+     */
+    startEdit : function(el, value){
+        if(this.editing){
+            this.completeEdit();
+        }
+        this.boundEl = Ext.get(el);
+        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
+        if(!this.rendered){
+            this.render(this.parentEl || document.body);
+        }
+        if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
+            this.startValue = v;
+            this.field.reset();
+            this.field.setValue(v);
+            this.realign(true);
+            this.editing = true;
+            this.show();
         }
         }
-        return h;
-    },
-
-    // private
-    adjustBodyHeight : function(h){
-        return h;
     },
 
     // private
     },
 
     // private
-    adjustBodyWidth : function(w){
-        return w;
-    },
+    doAutoSize : function(){
+        if(this.autoSize){
+            var sz = this.boundEl.getSize(),
+                fs = this.field.getSize();
 
 
-    // private
-    onPosition : function(){
-        this.syncShadow();
+            switch(this.autoSize){
+                case "width":
+                    this.setSize(sz.width, fs.height);
+                    break;
+                case "height":
+                    this.setSize(fs.width, sz.height);
+                    break;
+                case "none":
+                    this.setSize(fs.width, fs.height);
+                    break;
+                default:
+                    this.setSize(sz.width, sz.height);
+            }
+        }
     },
 
     /**
     },
 
     /**
-     * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
-     * retrieve the body width see {@link #getInnerWidth}.
-     * @return {Number} The frame width
+     * Sets the height and width of this editor.
+     * @param {Number} width The new width
+     * @param {Number} height The new height
      */
      */
-    getFrameWidth : function(){
-        var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
-
-        if(this.frame){
-            var l = this.bwrap.dom.firstChild;
-            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
-            w += this.mc.getFrameWidth('lr');
+    setSize : function(w, h){
+        delete this.field.lastSize;
+        this.field.setSize(w, h);
+        if(this.el){
+            // IE7 in strict mode doesn't size properly.
+            if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
+                // prevent layer scrollbars
+                this.el.setSize(w, h);
+            }
+            this.el.sync();
         }
         }
-        return w;
     },
 
     /**
     },
 
     /**
-     * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
-     * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
-     * @return {Number} The frame height
+     * Realigns the editor to the bound field based on the current alignment config value.
+     * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
      */
      */
-    getFrameHeight : function(){
-        var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
-        h += (this.tbar ? this.tbar.getHeight() : 0) +
-             (this.bbar ? this.bbar.getHeight() : 0);
-
-        if(this.frame){
-            h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
-        }else{
-            h += (this.header ? this.header.getHeight() : 0) +
-                (this.footer ? this.footer.getHeight() : 0);
+    realign : function(autoSize){
+        if(autoSize === true){
+            this.doAutoSize();
         }
         }
-        return h;
+        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
     },
 
     /**
     },
 
     /**
-     * Returns the width in pixels of the body element (not including the width of any framing elements).
-     * For the frame width see {@link #getFrameWidth}.
-     * @return {Number} The body width
+     * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
+     * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
      */
      */
-    getInnerWidth : function(){
-        return this.getSize().width - this.getFrameWidth();
+    completeEdit : function(remainVisible){
+        if(!this.editing){
+            return;
+        }
+        // Assert combo values first
+        if (this.field.assertValue) {
+            this.field.assertValue();
+        }
+        var v = this.getValue();
+        if(!this.field.isValid()){
+            if(this.revertInvalid !== false){
+                this.cancelEdit(remainVisible);
+            }
+            return;
+        }
+        if(String(v) === String(this.startValue) && this.ignoreNoChange){
+            this.hideEdit(remainVisible);
+            return;
+        }
+        if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
+            v = this.getValue();
+            if(this.updateEl && this.boundEl){
+                this.boundEl.update(v);
+            }
+            this.hideEdit(remainVisible);
+            this.fireEvent("complete", this, v, this.startValue);
+        }
+    },
+
+    // private
+    onShow : function(){
+        this.el.show();
+        if(this.hideEl !== false){
+            this.boundEl.hide();
+        }
+        this.field.show().focus(false, true);
+        this.fireEvent("startedit", this.boundEl, this.startValue);
     },
 
     /**
     },
 
     /**
-     * Returns the height in pixels of the body element (not including the height of any framing elements).
-     * For the frame height see {@link #getFrameHeight}.
-     * @return {Number} The body height
+     * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
+     * reverted to the original starting value.
+     * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
+     * cancel (defaults to false)
      */
      */
-    getInnerHeight : function(){
-        return this.getSize().height - this.getFrameHeight();
+    cancelEdit : function(remainVisible){
+        if(this.editing){
+            var v = this.getValue();
+            this.setValue(this.startValue);
+            this.hideEdit(remainVisible);
+            this.fireEvent("canceledit", this, v, this.startValue);
+        }
     },
 
     // private
     },
 
     // private
-    syncShadow : function(){
-        if(this.floating){
-            this.el.sync(true);
+    hideEdit: function(remainVisible){
+        if(remainVisible !== true){
+            this.editing = false;
+            this.hide();
         }
     },
 
     // private
         }
     },
 
     // private
-    getLayoutTarget : function(){
-        return this.body;
+    onBlur : function(){
+        // 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();
+        }
     },
 
     // private
     },
 
     // private
-    getContentTarget : function(){
-        return this.body;
+    onHide : function(){
+        if(this.editing){
+            this.completeEdit();
+            return;
+        }
+        this.field.blur();
+        if(this.field.collapse){
+            this.field.collapse();
+        }
+        this.el.hide();
+        if(this.hideEl !== false){
+            this.boundEl.show();
+        }
     },
 
     /**
     },
 
     /**
-     * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
-     * <p>In order to be able to set the title, a header element must have been created
-     * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
-     * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
-     * @param {String} title The title text to set
-     * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
+     * Sets the data value of the editor
+     * @param {Mixed} value Any valid value supported by the underlying field
      */
      */
-    setTitle : function(title, iconCls){
-        this.title = title;
-        if(this.header && this.headerAsText){
-            this.header.child('span').update(title);
-        }
-        if(iconCls){
-            this.setIconClass(iconCls);
-        }
-        this.fireEvent('titlechange', this, title);
-        return this;
+    setValue : function(v){
+        this.field.setValue(v);
     },
 
     /**
     },
 
     /**
-     * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
-     * @return {Ext.Updater} The Updater
+     * Gets the data value of the editor
+     * @return {Mixed} The data value
      */
      */
-    getUpdater : function(){
-        return this.body.getUpdater();
+    getValue : function(){
+        return this.field.getValue();
     },
 
     },
 
-     /**
-     * Loads this content panel immediately with content returned from an XHR call.
-     * @param {Object/String/Function} config A config object containing any of the following options:
-<pre><code>
-panel.load({
-    url: 'your-url.php',
-    params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
-    callback: yourFunction,
-    scope: yourObject, // optional scope for the callback
-    discardUrl: false,
-    nocache: false,
-    text: 'Loading...',
-    timeout: 30,
-    scripts: false
+    beforeDestroy : function(){
+        Ext.destroyMembers(this, 'field');
+
+        delete this.parentEl;
+        delete this.boundEl;
+    }
+});
+Ext.reg('editor', Ext.Editor);
+/**
+ * @class Ext.ColorPalette
+ * @extends Ext.Component
+ * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
+ * Here's an example of typical usage:
+ * <pre><code>
+var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
+cp.render('my-div');
+
+cp.on('select', function(palette, selColor){
+    // do something with selColor
 });
 </code></pre>
 });
 </code></pre>
-     * The only required property is url. The optional properties nocache, text and scripts
-     * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
-     * associated property on this panel Updater instance.
-     * @return {Ext.Panel} this
+ * @constructor
+ * Create a new ColorPalette
+ * @param {Object} config The config object
+ * @xtype colorpalette
+ */
+Ext.ColorPalette = Ext.extend(Ext.Component, {
+       /**
+        * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
+        */
+    /**
+     * @cfg {String} itemCls
+     * The CSS class to apply to the containing element (defaults to 'x-color-palette')
      */
      */
-    load : function(){
-        var um = this.body.getUpdater();
-        um.update.apply(um, arguments);
-        return this;
-    },
-
+    itemCls : 'x-color-palette',
+    /**
+     * @cfg {String} value
+     * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
+     * the hex codes are case-sensitive.
+     */
+    value : null,
+    /**
+     * @cfg {String} clickEvent
+     * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
+     * Defaults to <tt>'click'</tt>.
+     */
+    clickEvent :'click',
     // private
     // private
-    beforeDestroy : function(){
-        Ext.Panel.superclass.beforeDestroy.call(this);
-        if(this.header){
-            this.header.removeAllListeners();
-        }
-        if(this.tools){
-            for(var k in this.tools){
-                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]);
-            }
-        }
-        if(this.rendered){
-            Ext.destroy(
-                this.ft,
-                this.header,
-                this.footer,
-                this.toolbars,
-                this.tbar,
-                this.bbar,
-                this.body,
-                this.mc,
-                this.bwrap
-            );
-            if (this.fbar) {
-                Ext.destroy(
-                    this.fbar,
-                    this.fbar.el
-                );
-            }
-        }else{
-            Ext.destroy(
-                this.topToolbar,
-                this.bottomToolbar
-            );
-        }
-    },
+    ctype : 'Ext.ColorPalette',
+
+    /**
+     * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
+     */
+    allowReselect : false,
+
+    /**
+     * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
+     * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
+     * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
+     * of colors with the width setting until the box is symmetrical.</p>
+     * <p>You can override individual colors if needed:</p>
+     * <pre><code>
+var cp = new Ext.ColorPalette();
+cp.colors[0] = 'FF0000';  // change the first box to red
+</code></pre>
+
+Or you can provide a custom array of your own for complete control:
+<pre><code>
+var cp = new Ext.ColorPalette();
+cp.colors = ['000000', '993300', '333300'];
+</code></pre>
+     * @type Array
+     */
+    colors : [
+        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
+        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
+        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
+        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
+        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
+    ],
 
 
+    /**
+     * @cfg {Function} handler
+     * Optional. A function that will handle the select event of this palette.
+     * The handler is passed the following parameters:<div class="mdetail-params"><ul>
+     * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
+     * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
+     * </ul></div>
+     */
+    /**
+     * @cfg {Object} scope
+     * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
+     * function will be called.  Defaults to this ColorPalette instance.
+     */
+    
     // private
     // private
-    createClasses : function(){
-        this.headerCls = this.baseCls + '-header';
-        this.headerTextCls = this.baseCls + '-header-text';
-        this.bwrapCls = this.baseCls + '-bwrap';
-        this.tbarCls = this.baseCls + '-tbar';
-        this.bodyCls = this.baseCls + '-body';
-        this.bbarCls = this.baseCls + '-bbar';
-        this.footerCls = this.baseCls + '-footer';
+    initComponent : function(){
+        Ext.ColorPalette.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event select
+             * Fires when a color is selected
+             * @param {ColorPalette} this
+             * @param {String} color The 6-digit color hex code (without the # symbol)
+             */
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler, this.scope, true);
+        }    
     },
 
     // private
     },
 
     // private
-    createGhost : function(cls, useShim, appendTo){
-        var el = document.createElement('div');
-        el.className = 'x-panel-ghost ' + (cls ? cls : '');
-        if(this.header){
-            el.appendChild(this.el.dom.firstChild.cloneNode(true));
-        }
-        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
-        el.style.width = this.el.dom.offsetWidth + 'px';;
-        if(!appendTo){
-            this.container.dom.appendChild(el);
-        }else{
-            Ext.getDom(appendTo).appendChild(el);
+    onRender : function(container, position){
+        this.autoEl = {
+            tag: 'div',
+            cls: this.itemCls
+        };
+        Ext.ColorPalette.superclass.onRender.call(this, container, position);
+        var t = this.tpl || new Ext.XTemplate(
+            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
+        );
+        t.overwrite(this.el, this.colors);
+        this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
+        if(this.clickEvent != 'click'){
+               this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
         }
         }
-        if(useShim !== false && this.el.useShim !== false){
-            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
-            layer.show();
-            return layer;
-        }else{
-            return new Ext.Element(el);
+    },
+
+    // private
+    afterRender : function(){
+        Ext.ColorPalette.superclass.afterRender.call(this);
+        if(this.value){
+            var s = this.value;
+            this.value = null;
+            this.select(s, true);
         }
     },
 
     // private
         }
     },
 
     // private
-    doAutoLoad : function(){
-        var u = this.body.getUpdater();
-        if(this.renderer){
-            u.setRenderer(this.renderer);
+    handleClick : function(e, t){
+        e.preventDefault();
+        if(!this.disabled){
+            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
+            this.select(c.toUpperCase());
         }
         }
-        u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
     },
 
     /**
     },
 
     /**
-     * Retrieve a tool by id.
-     * @param {String} id
-     * @return {Object} tool
+     * Selects the specified color in the palette (fires the {@link #select} event)
+     * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
+     * @param {Boolean} suppressEvent (optional) True to stop the select event from firing. Defaults to <tt>false</tt>.
      */
      */
-    getTool : function(id) {
-        return this.tools[id];
+    select : function(color, suppressEvent){
+        color = color.replace('#', '');
+        if(color != this.value || this.allowReselect){
+            var el = this.el;
+            if(this.value){
+                el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
+            }
+            el.child('a.color-'+color).addClass('x-color-palette-sel');
+            this.value = color;
+            if(suppressEvent !== true){
+                this.fireEvent('select', this, color);
+            }
+        }
     }
 
     }
 
-/**
- * @cfg {String} autoEl @hide
- */
+    /**
    * @cfg {String} autoEl @hide
    */
 });
 });
-Ext.reg('panel', Ext.Panel);
-/**
- * @class Ext.Editor
+Ext.reg('colorpalette', Ext.ColorPalette);/**
+ * @class Ext.DatePicker
  * @extends Ext.Component
  * @extends Ext.Component
- * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
+ * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
+ * to allow browsing and selection of valid dates.</p>
+ * <p>All the string values documented below may be overridden by including an Ext locale file in
+ * your page.</p>
  * @constructor
  * @constructor
- * Create a new Editor
+ * Create a new DatePicker
  * @param {Object} config The config object
  * @param {Object} config The config object
- * @xtype editor
+ * @xtype datepicker
  */
  */
-Ext.Editor = function(field, config){
-    if(field.field){
-        this.field = Ext.create(field.field, 'textfield');
-        config = Ext.apply({}, field); // copy so we don't disturb original config
-        delete config.field;
-    }else{
-        this.field = field;
-    }
-    Ext.Editor.superclass.constructor.call(this, config);
-};
-
-Ext.extend(Ext.Editor, Ext.Component, {
+Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
     /**
     /**
-    * @cfg {Ext.form.Field} field
-    * The Field object (or descendant) or config object for field
-    */
+     * @cfg {String} todayText
+     * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
+     */
+    todayText : 'Today',
     /**
     /**
-     * @cfg {Boolean} allowBlur
-     * True to {@link #completeEdit complete the editing process} if in edit mode when the
-     * field is blurred. Defaults to <tt>false</tt>.
+     * @cfg {String} okText
+     * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
      */
      */
+    okText : '&#160;OK&#160;',
     /**
     /**
-     * @cfg {Boolean/String} autoSize
-     * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
-     * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
+     * @cfg {String} cancelText
+     * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
      */
      */
+    cancelText : 'Cancel',
     /**
     /**
-     * @cfg {Boolean} revertInvalid
-     * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
-     * validation fails (defaults to true)
+     * @cfg {Function} handler
+     * Optional. A function that will handle the select event of this picker.
+     * The handler is passed the following parameters:<div class="mdetail-params"><ul>
+     * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
+     * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
+     * </ul></div>
      */
     /**
      */
     /**
-     * @cfg {Boolean} ignoreNoChange
-     * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
-     * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
-     * will never be ignored.
+     * @cfg {Object} scope
+     * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
+     * function will be called.  Defaults to this DatePicker instance.
      */
     /**
      */
     /**
-     * @cfg {Boolean} hideEl
-     * False to keep the bound element visible while the editor is displayed (defaults to true)
+     * @cfg {String} todayTip
+     * A string used to format the message for displaying in a tooltip over the button that
+     * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
+     * the <code>{0}</code> token is replaced by today's date.
      */
      */
+    todayTip : '{0} (Spacebar)',
     /**
     /**
-     * @cfg {Mixed} value
-     * The data value of the underlying field (defaults to "")
+     * @cfg {String} minText
+     * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
      */
      */
-    value : "",
+    minText : 'This date is before the minimum date',
     /**
     /**
-     * @cfg {String} alignment
-     * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
+     * @cfg {String} maxText
+     * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
      */
      */
-    alignment: "c-c?",
+    maxText : 'This date is after the maximum date',
     /**
     /**
-     * @cfg {Array} offsets
-     * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
+     * @cfg {String} format
+     * The default date format string which can be overriden for localization support.  The format must be
+     * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
      */
      */
-    offsets: [0, 0],
+    format : 'm/d/y',
+    /**
+     * @cfg {String} disabledDaysText
+     * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
+     */
+    disabledDaysText : 'Disabled',
+    /**
+     * @cfg {String} disabledDatesText
+     * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
+     */
+    disabledDatesText : 'Disabled',
+    /**
+     * @cfg {Array} monthNames
+     * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
+     */
+    monthNames : Date.monthNames,
+    /**
+     * @cfg {Array} dayNames
+     * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
+     */
+    dayNames : Date.dayNames,
+    /**
+     * @cfg {String} nextText
+     * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
+     */
+    nextText : 'Next Month (Control+Right)',
+    /**
+     * @cfg {String} prevText
+     * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
+     */
+    prevText : 'Previous Month (Control+Left)',
+    /**
+     * @cfg {String} monthYearText
+     * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
+     */
+    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+    /**
+     * @cfg {Number} startDay
+     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
+     */
+    startDay : 0,
+    /**
+     * @cfg {Boolean} showToday
+     * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
+     * that selects the current date (defaults to <code>true</code>).
+     */
+    showToday : true,
+    /**
+     * @cfg {Date} minDate
+     * Minimum allowable date (JavaScript date object, defaults to null)
+     */
+    /**
+     * @cfg {Date} maxDate
+     * Maximum allowable date (JavaScript date object, defaults to null)
+     */
+    /**
+     * @cfg {Array} disabledDays
+     * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
+     */
+    /**
+     * @cfg {RegExp} disabledDatesRE
+     * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
+     * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
+     * disabledDates value.
+     */
+    /**
+     * @cfg {Array} disabledDates
+     * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
+     * expression so they are very powerful. Some examples:
+     * <ul>
+     * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
+     * <li>['03/08', '09/16'] would disable those days for every year</li>
+     * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
+     * <li>['03/../2006'] would disable every day in March 2006</li>
+     * <li>['^03'] would disable every day in every March</li>
+     * </ul>
+     * Note that the format of the dates included in the array should exactly match the {@link #format} config.
+     * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
+     * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
+     */
+
+    // private
+    // Set by other components to stop the picker focus being updated when the value changes.
+    focusOnSelect: true,
+
+    // default value used to initialise each date in the DatePicker
+    // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
+    initHour: 12, // 24-hour format
+
+    // private
+    initComponent : function(){
+        Ext.DatePicker.superclass.initComponent.call(this);
+
+        this.value = this.value ?
+                 this.value.clearTime(true) : new Date().clearTime();
+
+        this.addEvents(
+            /**
+             * @event select
+             * Fires when a date is selected
+             * @param {DatePicker} this DatePicker
+             * @param {Date} date The selected date
+             */
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler,  this.scope || this);
+        }
+
+        this.initDisabledDays();
+    },
+
+    // private
+    initDisabledDays : function(){
+        if(!this.disabledDatesRE && this.disabledDates){
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = '(?:';
+
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
+                if(i != len){
+                    re += '|';
+                }
+            }, this);
+            this.disabledDatesRE = new RegExp(re + ')');
+        }
+    },
+
     /**
     /**
-     * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
-     * for bottom-right shadow (defaults to "frame")
+     * Replaces any existing disabled dates with new values and refreshes the DatePicker.
+     * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
+     * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
      */
      */
-    shadow : "frame",
+    setDisabledDates : function(dd){
+        if(Ext.isArray(dd)){
+            this.disabledDates = dd;
+            this.disabledDatesRE = null;
+        }else{
+            this.disabledDatesRE = dd;
+        }
+        this.initDisabledDays();
+        this.update(this.value, true);
+    },
+
     /**
     /**
-     * @cfg {Boolean} constrain True to constrain the editor to the viewport
+     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
+     * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
+     * for details on supported values.
      */
      */
-    constrain : false,
+    setDisabledDays : function(dd){
+        this.disabledDays = dd;
+        this.update(this.value, true);
+    },
+
     /**
     /**
-     * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
+     * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
+     * @param {Date} value The minimum date that can be selected
      */
      */
-    swallowKeys : true,
+    setMinDate : function(dt){
+        this.minDate = dt;
+        this.update(this.value, true);
+    },
+
     /**
     /**
-     * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
+     * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
+     * @param {Date} value The maximum date that can be selected
      */
      */
-    completeOnEnter : true,
+    setMaxDate : function(dt){
+        this.maxDate = dt;
+        this.update(this.value, true);
+    },
+
     /**
     /**
-     * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
+     * Sets the value of the date field
+     * @param {Date} value The date to set
      */
      */
-    cancelOnEsc : true,
+    setValue : function(value){
+        this.value = value.clearTime(true);
+        this.update(this.value);
+    },
+
     /**
     /**
-     * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
+     * Gets the current selected value of the date field
+     * @return {Date} The selected date
      */
      */
-    updateEl : false,
+    getValue : function(){
+        return this.value;
+    },
 
 
-    initComponent : function(){
-        Ext.Editor.superclass.initComponent.call(this);
-        this.addEvents(
-            /**
-             * @event beforestartedit
-             * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
-             * false from the handler of this event.
-             * @param {Editor} this
-             * @param {Ext.Element} boundEl The underlying element bound to this editor
-             * @param {Mixed} value The field value being set
-             */
-            "beforestartedit",
-            /**
-             * @event startedit
-             * Fires when this editor is displayed
-             * @param {Ext.Element} boundEl The underlying element bound to this editor
-             * @param {Mixed} value The starting field value
-             */
-            "startedit",
-            /**
-             * @event beforecomplete
-             * Fires after a change has been made to the field, but before the change is reflected in the underlying
-             * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
-             * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
-             * event will not fire since no edit actually occurred.
-             * @param {Editor} this
-             * @param {Mixed} value The current field value
-             * @param {Mixed} startValue The original field value
-             */
-            "beforecomplete",
-            /**
-             * @event complete
-             * Fires after editing is complete and any changed value has been written to the underlying field.
-             * @param {Editor} this
-             * @param {Mixed} value The current field value
-             * @param {Mixed} startValue The original field value
-             */
-            "complete",
-            /**
-             * @event canceledit
-             * Fires after editing has been canceled and the editor's value has been reset.
-             * @param {Editor} this
-             * @param {Mixed} value The user-entered field value that was discarded
-             * @param {Mixed} startValue The original field value that was set back into the editor after cancel
-             */
-            "canceledit",
-            /**
-             * @event specialkey
-             * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
-             * {@link Ext.EventObject#getKey} to determine which key was pressed.
-             * @param {Ext.form.Field} this
-             * @param {Ext.EventObject} e The event object
+    // private
+    focus : function(){
+        this.update(this.activeDate);
+    },
+
+    // private
+    onEnable: function(initial){
+        Ext.DatePicker.superclass.onEnable.call(this);
+        this.doDisabled(false);
+        this.update(initial ? this.value : this.activeDate);
+        if(Ext.isIE){
+            this.el.repaint();
+        }
+
+    },
+
+    // private
+    onDisable : function(){
+        Ext.DatePicker.superclass.onDisable.call(this);
+        this.doDisabled(true);
+        if(Ext.isIE && !Ext.isIE8){
+            /* Really strange problem in IE6/7, when disabled, have to explicitly
+             * repaint each of the nodes to get them to display correctly, simply
+             * calling repaint on the main element doesn't appear to be enough.
              */
              */
-            "specialkey"
-        );
+             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
+                 Ext.fly(el).repaint();
+             });
+        }
     },
 
     // private
     },
 
     // private
-    onRender : function(ct, position){
-        this.el = new Ext.Layer({
-            shadow: this.shadow,
-            cls: "x-editor",
-            parentEl : ct,
-            shim : this.shim,
-            shadowOffset: this.shadowOffset || 4,
-            id: this.id,
-            constrain: this.constrain
+    doDisabled : function(disabled){
+        this.keyNav.setDisabled(disabled);
+        this.prevRepeater.setDisabled(disabled);
+        this.nextRepeater.setDisabled(disabled);
+        if(this.showToday){
+            this.todayKeyListener.setDisabled(disabled);
+            this.todayBtn.setDisabled(disabled);
+        }
+    },
+
+    // private
+    onRender : function(container, position){
+        var m = [
+             '<table cellspacing="0">',
+                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
+                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
+                dn = this.dayNames,
+                i;
+        for(i = 0; i < 7; i++){
+            var d = this.startDay+i;
+            if(d > 6){
+                d = d-7;
+            }
+            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
+        }
+        m[m.length] = '</tr></thead><tbody><tr>';
+        for(i = 0; i < 42; i++) {
+            if(i % 7 === 0 && i !== 0){
+                m[m.length] = '</tr><tr>';
+            }
+            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
+        }
+        m.push('</tr></tbody></table></td></tr>',
+                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
+                '</table><div class="x-date-mp"></div>');
+
+        var el = document.createElement('div');
+        el.className = 'x-date-picker';
+        el.innerHTML = m.join('');
+
+        container.dom.insertBefore(el, position);
+
+        this.el = Ext.get(el);
+        this.eventEl = Ext.get(el.firstChild);
+
+        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
+            handler: this.showPrevMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
+            handler: this.showNextMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.monthPicker = this.el.down('div.x-date-mp');
+        this.monthPicker.enableDisplayMode('block');
+
+        this.keyNav = new Ext.KeyNav(this.eventEl, {
+            'left' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevMonth();
+                }else{
+                    this.update(this.activeDate.add('d', -1));
+                }
+            },
+
+            'right' : function(e){
+                if(e.ctrlKey){
+                    this.showNextMonth();
+                }else{
+                    this.update(this.activeDate.add('d', 1));
+                }
+            },
+
+            'up' : function(e){
+                if(e.ctrlKey){
+                    this.showNextYear();
+                }else{
+                    this.update(this.activeDate.add('d', -7));
+                }
+            },
+
+            'down' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevYear();
+                }else{
+                    this.update(this.activeDate.add('d', 7));
+                }
+            },
+
+            'pageUp' : function(e){
+                this.showNextMonth();
+            },
+
+            'pageDown' : function(e){
+                this.showPrevMonth();
+            },
+
+            'enter' : function(e){
+                e.stopPropagation();
+                return true;
+            },
+
+            scope : this
         });
         });
-        if(this.zIndex){
-            this.el.setZIndex(this.zIndex);
-        }
-        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
-        if(this.field.msgTarget != 'title'){
-            this.field.msgTarget = 'qtip';
-        }
-        this.field.inEditor = true;
-        this.mon(this.field, {
-            scope: this,
-            blur: this.onBlur,
-            specialkey: this.onSpecialKey
+
+        this.el.unselectable();
+
+        this.cells = this.el.select('table.x-date-inner tbody td');
+        this.textNodes = this.el.query('table.x-date-inner tbody span');
+
+        this.mbtn = new Ext.Button({
+            text: '&#160;',
+            tooltip: this.monthYearText,
+            renderTo: this.el.child('td.x-date-middle', true)
         });
         });
-        if(this.field.grow){
-            this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
-        }
-        this.field.render(this.el).show();
-        this.field.getEl().dom.name = '';
-        if(this.swallowKeys){
-            this.field.el.swallowEvent([
-                'keypress', // *** Opera
-                'keydown'   // *** all other browsers
-            ]);
+        this.mbtn.el.child('em').addClass('x-btn-arrow');
+
+        if(this.showToday){
+            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
+            var today = (new Date()).dateFormat(this.format);
+            this.todayBtn = new Ext.Button({
+                renderTo: this.el.child('td.x-date-bottom', true),
+                text: String.format(this.todayText, today),
+                tooltip: String.format(this.todayTip, today),
+                handler: this.selectToday,
+                scope: this
+            });
         }
         }
+        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
+        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
+        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
+        this.onEnable(true);
     },
 
     // private
     },
 
     // private
-    onSpecialKey : function(field, e){
-        var key = e.getKey(),
-            complete = this.completeOnEnter && key == e.ENTER,
-            cancel = this.cancelOnEsc && key == e.ESC;
-        if(complete || cancel){
-            e.stopEvent();
-            if(complete){
-                this.completeEdit();
-            }else{
-                this.cancelEdit();
-            }
-            if(field.triggerBlur){
-                field.triggerBlur();
+    createMonthPicker : function(){
+        if(!this.monthPicker.dom.firstChild){
+            var buf = ['<table border="0" cellspacing="0">'];
+            for(var i = 0; i < 6; i++){
+                buf.push(
+                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
+                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
+                    i === 0 ?
+                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
+                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
+                );
             }
             }
-        }
-        this.fireEvent('specialkey', field, e);
-    },
+            buf.push(
+                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
+                    this.okText,
+                    '</button><button type="button" class="x-date-mp-cancel">',
+                    this.cancelText,
+                    '</button></td></tr>',
+                '</table>'
+            );
+            this.monthPicker.update(buf.join(''));
 
 
-    /**
-     * Starts the editing process and shows the editor.
-     * @param {Mixed} el The element to edit
-     * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
-      * to the innerHTML of el.
-     */
-    startEdit : function(el, value){
-        if(this.editing){
-            this.completeEdit();
-        }
-        this.boundEl = Ext.get(el);
-        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
-        if(!this.rendered){
-            this.render(this.parentEl || document.body);
-        }
-        if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
-            this.startValue = v;
-            this.field.reset();
-            this.field.setValue(v);
-            this.realign(true);
-            this.editing = true;
-            this.show();
+            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
+            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+
+            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
+            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+
+            this.mpMonths.each(function(m, a, i){
+                i += 1;
+                if((i%2) === 0){
+                    m.dom.xmonth = 5 + Math.round(i * 0.5);
+                }else{
+                    m.dom.xmonth = Math.round((i-1) * 0.5);
+                }
+            });
         }
     },
 
     // private
         }
     },
 
     // private
-    doAutoSize : function(){
-        if(this.autoSize){
-            var sz = this.boundEl.getSize(),
-                fs = this.field.getSize();
+    showMonthPicker : function(){
+        if(!this.disabled){
+            this.createMonthPicker();
+            var size = this.el.getSize();
+            this.monthPicker.setSize(size);
+            this.monthPicker.child('table').setSize(size);
 
 
-            switch(this.autoSize){
-                case "width":
-                    this.setSize(sz.width, fs.height);
-                    break;
-                case "height":
-                    this.setSize(fs.width, sz.height);
-                    break;
-                case "none":
-                    this.setSize(fs.width, fs.height);
-                    break;
-                default:
-                    this.setSize(sz.width, sz.height);
-            }
+            this.mpSelMonth = (this.activeDate || this.value).getMonth();
+            this.updateMPMonth(this.mpSelMonth);
+            this.mpSelYear = (this.activeDate || this.value).getFullYear();
+            this.updateMPYear(this.mpSelYear);
+
+            this.monthPicker.slideIn('t', {duration:0.2});
         }
     },
 
         }
     },
 
-    /**
-     * Sets the height and width of this editor.
-     * @param {Number} width The new width
-     * @param {Number} height The new height
-     */
-    setSize : function(w, h){
-        delete this.field.lastSize;
-        this.field.setSize(w, h);
-        if(this.el){
-            if(Ext.isGecko2 || Ext.isOpera){
-                // prevent layer scrollbars
-                this.el.setSize(w, h);
+    // private
+    updateMPYear : function(y){
+        this.mpyear = y;
+        var ys = this.mpYears.elements;
+        for(var i = 1; i <= 10; i++){
+            var td = ys[i-1], y2;
+            if((i%2) === 0){
+                y2 = y + Math.round(i * 0.5);
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
+            }else{
+                y2 = y - (5-Math.round(i * 0.5));
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
             }
             }
-            this.el.sync();
+            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
         }
     },
 
         }
     },
 
-    /**
-     * Realigns the editor to the bound field based on the current alignment config value.
-     * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
-     */
-    realign : function(autoSize){
-        if(autoSize === true){
-            this.doAutoSize();
-        }
-        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
+    // private
+    updateMPMonth : function(sm){
+        this.mpMonths.each(function(m, a, i){
+            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
+        });
     },
 
     },
 
-    /**
-     * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
-     * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
-     */
-    completeEdit : function(remainVisible){
-        if(!this.editing){
-            return;
+    // private
+    selectMPMonth : function(m){
+
+    },
+
+    // private
+    onMonthClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if(el.is('button.x-date-mp-cancel')){
+            this.hideMonthPicker();
         }
         }
-        var v = this.getValue();
-        if(!this.field.isValid()){
-            if(this.revertInvalid !== false){
-                this.cancelEdit(remainVisible);
+        else if(el.is('button.x-date-mp-ok')){
+            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
+            if(d.getMonth() != this.mpSelMonth){
+                // 'fix' the JS rolling date conversion if needed
+                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
             }
             }
-            return;
+            this.update(d);
+            this.hideMonthPicker();
         }
         }
-        if(String(v) === String(this.startValue) && this.ignoreNoChange){
-            this.hideEdit(remainVisible);
-            return;
+        else if((pn = el.up('td.x-date-mp-month', 2))){
+            this.mpMonths.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelMonth = pn.dom.xmonth;
+        }
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.mpYears.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelYear = pn.dom.xyear;
+        }
+        else if(el.is('a.x-date-mp-prev')){
+            this.updateMPYear(this.mpyear-10);
+        }
+        else if(el.is('a.x-date-mp-next')){
+            this.updateMPYear(this.mpyear+10);
+        }
+    },
+
+    // private
+    onMonthDblClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if((pn = el.up('td.x-date-mp-month', 2))){
+            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
         }
         }
-        if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
-            v = this.getValue();
-            if(this.updateEl && this.boundEl){
-                this.boundEl.update(v);
-            }
-            this.hideEdit(remainVisible);
-            this.fireEvent("complete", this, v, this.startValue);
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
         }
     },
 
     // private
         }
     },
 
     // private
-    onShow : function(){
-        this.el.show();
-        if(this.hideEl !== false){
-            this.boundEl.hide();
+    hideMonthPicker : function(disableAnim){
+        if(this.monthPicker){
+            if(disableAnim === true){
+                this.monthPicker.hide();
+            }else{
+                this.monthPicker.slideOut('t', {duration:0.2});
+            }
         }
         }
-        this.field.show().focus(false, true);
-        this.fireEvent("startedit", this.boundEl, this.startValue);
     },
 
     },
 
-    /**
-     * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
-     * reverted to the original starting value.
-     * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
-     * cancel (defaults to false)
-     */
-    cancelEdit : function(remainVisible){
-        if(this.editing){
-            var v = this.getValue();
-            this.setValue(this.startValue);
-            this.hideEdit(remainVisible);
-            this.fireEvent("canceledit", this, v, this.startValue);
-        }
+    // private
+    showPrevMonth : function(e){
+        this.update(this.activeDate.add('mo', -1));
     },
 
     // private
     },
 
     // private
-    hideEdit: function(remainVisible){
-        if(remainVisible !== true){
-            this.editing = false;
-            this.hide();
-        }
+    showNextMonth : function(e){
+        this.update(this.activeDate.add('mo', 1));
     },
 
     // private
     },
 
     // private
-    onBlur : function(){
-        // 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();
-        }
+    showPrevYear : function(){
+        this.update(this.activeDate.add('y', -1));
     },
 
     // private
     },
 
     // private
-    onHide : function(){
-        if(this.editing){
-            this.completeEdit();
-            return;
-        }
-        this.field.blur();
-        if(this.field.collapse){
-            this.field.collapse();
-        }
-        this.el.hide();
-        if(this.hideEl !== false){
-            this.boundEl.show();
+    showNextYear : function(){
+        this.update(this.activeDate.add('y', 1));
+    },
+
+    // private
+    handleMouseWheel : function(e){
+        e.stopEvent();
+        if(!this.disabled){
+            var delta = e.getWheelDelta();
+            if(delta > 0){
+                this.showPrevMonth();
+            } else if(delta < 0){
+                this.showNextMonth();
+            }
         }
     },
 
         }
     },
 
-    /**
-     * Sets the data value of the editor
-     * @param {Mixed} value Any valid value supported by the underlying field
-     */
-    setValue : function(v){
-        this.field.setValue(v);
+    // private
+    handleDateClick : function(e, t){
+        e.stopEvent();
+        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
+            this.cancelFocus = this.focusOnSelect === false;
+            this.setValue(new Date(t.dateValue));
+            delete this.cancelFocus;
+            this.fireEvent('select', this, this.value);
+        }
     },
 
     },
 
-    /**
-     * Gets the data value of the editor
-     * @return {Mixed} The data value
-     */
-    getValue : function(){
-        return this.field.getValue();
+    // private
+    selectToday : function(){
+        if(this.todayBtn && !this.todayBtn.disabled){
+            this.setValue(new Date().clearTime());
+            this.fireEvent('select', this, this.value);
+        }
     },
 
     },
 
-    beforeDestroy : function(){
-        Ext.destroyMembers(this, 'field');
+    // private
+    update : function(date, forceRefresh){
+        if(this.rendered){
+            var vd = this.activeDate, vis = this.isVisible();
+            this.activeDate = date;
+            if(!forceRefresh && vd && this.el){
+                var t = date.getTime();
+                if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
+                    this.cells.removeClass('x-date-selected');
+                    this.cells.each(function(c){
+                       if(c.dom.firstChild.dateValue == t){
+                           c.addClass('x-date-selected');
+                           if(vis && !this.cancelFocus){
+                               Ext.fly(c.dom.firstChild).focus(50);
+                           }
+                           return false;
+                       }
+                    }, this);
+                    return;
+                }
+            }
+            var days = date.getDaysInMonth(),
+                firstOfMonth = date.getFirstDateOfMonth(),
+                startingPos = firstOfMonth.getDay()-this.startDay;
+
+            if(startingPos < 0){
+                startingPos += 7;
+            }
+            days += startingPos;
+
+            var pm = date.add('mo', -1),
+                prevStart = pm.getDaysInMonth()-startingPos,
+                cells = this.cells.elements,
+                textEls = this.textNodes,
+                // convert everything to numbers so it's fast
+                d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
+                today = new Date().clearTime().getTime(),
+                sel = date.clearTime(true).getTime(),
+                min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
+                max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
+                ddMatch = this.disabledDatesRE,
+                ddText = this.disabledDatesText,
+                ddays = this.disabledDays ? this.disabledDays.join('') : false,
+                ddaysText = this.disabledDaysText,
+                format = this.format;
+
+            if(this.showToday){
+                var td = new Date().clearTime(),
+                    disable = (td < min || td > max ||
+                    (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
+                    (ddays && ddays.indexOf(td.getDay()) != -1));
+
+                if(!this.disabled){
+                    this.todayBtn.setDisabled(disable);
+                    this.todayKeyListener[disable ? 'disable' : 'enable']();
+                }
+            }
 
 
-        delete this.parentEl;
-        delete this.boundEl;
+            var setCellClass = function(cal, cell){
+                cell.title = '';
+                var t = d.clearTime(true).getTime();
+                cell.firstChild.dateValue = t;
+                if(t == today){
+                    cell.className += ' x-date-today';
+                    cell.title = cal.todayText;
+                }
+                if(t == sel){
+                    cell.className += ' x-date-selected';
+                    if(vis){
+                        Ext.fly(cell.firstChild).focus(50);
+                    }
+                }
+                // disabling
+                if(t < min) {
+                    cell.className = ' x-date-disabled';
+                    cell.title = cal.minText;
+                    return;
+                }
+                if(t > max) {
+                    cell.className = ' x-date-disabled';
+                    cell.title = cal.maxText;
+                    return;
+                }
+                if(ddays){
+                    if(ddays.indexOf(d.getDay()) != -1){
+                        cell.title = ddaysText;
+                        cell.className = ' x-date-disabled';
+                    }
+                }
+                if(ddMatch && format){
+                    var fvalue = d.dateFormat(format);
+                    if(ddMatch.test(fvalue)){
+                        cell.title = ddText.replace('%0', fvalue);
+                        cell.className = ' x-date-disabled';
+                    }
+                }
+            };
+
+            var i = 0;
+            for(; i < startingPos; i++) {
+                textEls[i].innerHTML = (++prevStart);
+                d.setDate(d.getDate()+1);
+                cells[i].className = 'x-date-prevday';
+                setCellClass(this, cells[i]);
+            }
+            for(; i < days; i++){
+                var intDay = i - startingPos + 1;
+                textEls[i].innerHTML = (intDay);
+                d.setDate(d.getDate()+1);
+                cells[i].className = 'x-date-active';
+                setCellClass(this, cells[i]);
+            }
+            var extraDays = 0;
+            for(; i < 42; i++) {
+                 textEls[i].innerHTML = (++extraDays);
+                 d.setDate(d.getDate()+1);
+                 cells[i].className = 'x-date-nextday';
+                 setCellClass(this, cells[i]);
+            }
+
+            this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
+
+            if(!this.internalRender){
+                var main = this.el.dom.firstChild,
+                    w = main.offsetWidth;
+                this.el.setWidth(w + this.el.getBorderWidth('lr'));
+                Ext.fly(main).setWidth(w);
+                this.internalRender = true;
+                // opera does not respect the auto grow header center column
+                // then, after it gets a width opera refuses to recalculate
+                // without a second pass
+                if(Ext.isOpera && !this.secondPass){
+                    main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
+                    this.secondPass = true;
+                    this.update.defer(10, this, [date]);
+                }
+            }
+        }
+    },
+
+    // private
+    beforeDestroy : function() {
+        if(this.rendered){
+            Ext.destroy(
+                this.keyNav,
+                this.monthPicker,
+                this.eventEl,
+                this.mbtn,
+                this.nextRepeater,
+                this.prevRepeater,
+                this.cells.el,
+                this.todayBtn
+            );
+            delete this.textNodes;
+            delete this.cells.elements;
+        }
     }
     }
-});
-Ext.reg('editor', Ext.Editor);
-/**
- * @class Ext.ColorPalette
- * @extends Ext.Component
- * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
- * Here's an example of typical usage:
- * <pre><code>
-var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
-cp.render('my-div');
 
 
-cp.on('select', function(palette, selColor){
-    // do something with selColor
+    /**
+     * @cfg {String} autoEl @hide
+     */
 });
 });
+
+Ext.reg('datepicker', Ext.DatePicker);
+/**
+ * @class Ext.LoadMask
+ * A simple utility class for generically masking elements while loading data.  If the {@link #store}
+ * config option is specified, the masking will be automatically synchronized with the store's loading
+ * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
+ * element's Updater load indicator and will be destroyed after the initial load.
+ * <p>Example usage:</p>
+ *<pre><code>
+// Basic mask:
+var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
+myMask.show();
 </code></pre>
  * @constructor
 </code></pre>
  * @constructor
- * Create a new ColorPalette
+ * Create a new LoadMask
+ * @param {Mixed} el The element or DOM node, or its id
  * @param {Object} config The config object
  * @param {Object} config The config object
- * @xtype colorpalette
  */
  */
-Ext.ColorPalette = Ext.extend(Ext.Component, {
-       /**
-        * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
-        */
-    /**
-     * @cfg {String} itemCls
-     * The CSS class to apply to the containing element (defaults to 'x-color-palette')
-     */
-    itemCls : 'x-color-palette',
+Ext.LoadMask = function(el, config){
+    this.el = Ext.get(el);
+    Ext.apply(this, config);
+    if(this.store){
+        this.store.on({
+            scope: this,
+            beforeload: this.onBeforeLoad,
+            load: this.onLoad,
+            exception: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, false);
+    }else{
+        var um = this.el.getUpdater();
+        um.showLoadIndicator = false; // disable the default indicator
+        um.on({
+            scope: this,
+            beforeupdate: this.onBeforeLoad,
+            update: this.onLoad,
+            failure: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, true);
+    }
+};
+
+Ext.LoadMask.prototype = {
     /**
     /**
-     * @cfg {String} value
-     * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
-     * the hex codes are case-sensitive.
+     * @cfg {Ext.data.Store} store
+     * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
+     * hidden on either load sucess, or load fail.
      */
      */
-    value : null,
     /**
     /**
-     * @cfg {String} clickEvent
-     * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
-     * Defaults to <tt>'click'</tt>.
+     * @cfg {Boolean} removeMask
+     * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
+     * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
      */
      */
-    clickEvent :'click',
-    // private
-    ctype : 'Ext.ColorPalette',
-
     /**
     /**
-     * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
+     * @cfg {String} msg
+     * The text to display in a centered loading message box (defaults to 'Loading...')
      */
      */
-    allowReselect : false,
-
+    msg : 'Loading...',
     /**
     /**
-     * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
-     * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
-     * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
-     * of colors with the width setting until the box is symmetrical.</p>
-     * <p>You can override individual colors if needed:</p>
-     * <pre><code>
-var cp = new Ext.ColorPalette();
-cp.colors[0] = 'FF0000';  // change the first box to red
-</code></pre>
-
-Or you can provide a custom array of your own for complete control:
-<pre><code>
-var cp = new Ext.ColorPalette();
-cp.colors = ['000000', '993300', '333300'];
-</code></pre>
-     * @type Array
+     * @cfg {String} msgCls
+     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
      */
      */
-    colors : [
-        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
-        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
-        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
-        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
-        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
-    ],
+    msgCls : 'x-mask-loading',
 
     /**
 
     /**
-     * @cfg {Function} handler
-     * Optional. A function that will handle the select event of this palette.
-     * The handler is passed the following parameters:<div class="mdetail-params"><ul>
-     * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
-     * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
-     * </ul></div>
+     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
+     * @type Boolean
      */
      */
+    disabled: false,
+
     /**
     /**
-     * @cfg {Object} scope
-     * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
-     * function will be called.  Defaults to this ColorPalette instance.
+     * Disables the mask to prevent it from being displayed
      */
      */
-    
-    // private
-    initComponent : function(){
-        Ext.ColorPalette.superclass.initComponent.call(this);
-        this.addEvents(
-            /**
-             * @event select
-             * Fires when a color is selected
-             * @param {ColorPalette} this
-             * @param {String} color The 6-digit color hex code (without the # symbol)
-             */
-            'select'
-        );
-
-        if(this.handler){
-            this.on('select', this.handler, this.scope, true);
-        }    
+    disable : function(){
+       this.disabled = true;
     },
 
     },
 
-    // private
-    onRender : function(container, position){
-        this.autoEl = {
-            tag: 'div',
-            cls: this.itemCls
-        };
-        Ext.ColorPalette.superclass.onRender.call(this, container, position);
-        var t = this.tpl || new Ext.XTemplate(
-            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
-        );
-        t.overwrite(this.el, this.colors);
-        this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
-        if(this.clickEvent != 'click'){
-               this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
-        }
+    /**
+     * Enables the mask so that it can be displayed
+     */
+    enable : function(){
+        this.disabled = false;
     },
 
     // private
     },
 
     // private
-    afterRender : function(){
-        Ext.ColorPalette.superclass.afterRender.call(this);
-        if(this.value){
-            var s = this.value;
-            this.value = null;
-            this.select(s);
-        }
+    onLoad : function(){
+        this.el.unmask(this.removeMask);
     },
 
     // private
     },
 
     // private
-    handleClick : function(e, t){
-        e.preventDefault();
+    onBeforeLoad : function(){
         if(!this.disabled){
         if(!this.disabled){
-            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
-            this.select(c.toUpperCase());
+            this.el.mask(this.msg, this.msgCls);
         }
     },
 
     /**
         }
     },
 
     /**
-     * Selects the specified color in the palette (fires the {@link #select} event)
-     * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
+     * Show this LoadMask over the configured Element.
      */
      */
-    select : function(color){
-        color = color.replace('#', '');
-        if(color != this.value || this.allowReselect){
-            var el = this.el;
-            if(this.value){
-                el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
-            }
-            el.child('a.color-'+color).addClass('x-color-palette-sel');
-            this.value = color;
-            this.fireEvent('select', this, color);
-        }
-    }
+    show: function(){
+        this.onBeforeLoad();
+    },
 
     /**
 
     /**
-     * @cfg {String} autoEl @hide
+     * Hide this LoadMask.
      */
      */
-});
-Ext.reg('colorpalette', Ext.ColorPalette);
+    hide: function(){
+        this.onLoad();
+    },
+
+    // private
+    destroy : function(){
+        if(this.store){
+            this.store.un('beforeload', this.onBeforeLoad, this);
+            this.store.un('load', this.onLoad, this);
+            this.store.un('exception', this.onLoad, this);
+        }else{
+            var um = this.el.getUpdater();
+            um.un('beforeupdate', this.onBeforeLoad, this);
+            um.un('update', this.onLoad, this);
+            um.un('failure', this.onLoad, this);
+        }
+    }
+};Ext.ns('Ext.slider');
+
 /**
 /**
- * @class Ext.DatePicker
- * @extends Ext.Component
- * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
- * to allow browsing and selection of valid dates.</p>
- * <p>All the string values documented below may be overridden by including an Ext locale file in
- * your page.</p>
- * @constructor
- * Create a new DatePicker
- * @param {Object} config The config object
- * @xtype datepicker
+ * @class Ext.slider.Thumb
+ * @extends Object
+ * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
+ * be created internally by an {@link Ext.slider.MultiSlider Ext.Slider}.
  */
  */
-Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
+Ext.slider.Thumb = Ext.extend(Object, {
+    
     /**
     /**
-     * @cfg {String} todayText
-     * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
+     * True while the thumb is in a drag operation
+     * @type Boolean
      */
      */
-    todayText : 'Today',
+    dragging: false,
+
     /**
     /**
-     * @cfg {String} okText
-     * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
+     * @constructor
+     * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
      */
      */
-    okText : '&#160;OK&#160;',
+    constructor: function(config) {
+        /**
+         * @property slider
+         * @type Ext.slider.MultiSlider
+         * The slider this thumb is contained within
+         */
+        Ext.apply(this, config || {}, {
+            cls: 'x-slider-thumb',
+
+            /**
+             * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
+             */
+            constrain: false
+        });
+
+        Ext.slider.Thumb.superclass.constructor.call(this, config);
+
+        if (this.slider.vertical) {
+            Ext.apply(this, Ext.slider.Thumb.Vertical);
+        }
+    },
+
     /**
     /**
-     * @cfg {String} cancelText
-     * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
+     * Renders the thumb into a slider
      */
      */
-    cancelText : 'Cancel',
+    render: function() {
+        this.el = this.slider.innerEl.insertFirst({cls: this.cls});
+
+        this.initEvents();
+    },
+
     /**
     /**
-     * @cfg {Function} handler
-     * Optional. A function that will handle the select event of this picker.
-     * The handler is passed the following parameters:<div class="mdetail-params"><ul>
-     * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
-     * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
-     * </ul></div>
+     * Enables the thumb if it is currently disabled
      */
      */
+    enable: function() {
+        this.disabled = false;
+        this.el.removeClass(this.slider.disabledClass);
+    },
+
     /**
     /**
-     * @cfg {Object} scope
-     * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
-     * function will be called.  Defaults to this DatePicker instance.
-     */ 
+     * Disables the thumb if it is currently enabled
+     */
+    disable: function() {
+        this.disabled = true;
+        this.el.addClass(this.slider.disabledClass);
+    },
+
     /**
     /**
-     * @cfg {String} todayTip
-     * A string used to format the message for displaying in a tooltip over the button that
-     * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
-     * the <code>{0}</code> token is replaced by today's date.
+     * Sets up an Ext.dd.DragTracker for this thumb
      */
      */
-    todayTip : '{0} (Spacebar)',
+    initEvents: function() {
+        var el = this.el;
+
+        el.addClassOnOver('x-slider-thumb-over');
+
+        this.tracker = new Ext.dd.DragTracker({
+            onBeforeStart: this.onBeforeDragStart.createDelegate(this),
+            onStart      : this.onDragStart.createDelegate(this),
+            onDrag       : this.onDrag.createDelegate(this),
+            onEnd        : this.onDragEnd.createDelegate(this),
+            tolerance    : 3,
+            autoStart    : 300
+        });
+
+        this.tracker.initEl(el);
+    },
+
     /**
     /**
-     * @cfg {String} minText
-     * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
+     * @private
+     * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
+     * this returns false to disable the DragTracker too.
+     * @return {Boolean} False if the slider is currently disabled
      */
      */
-    minText : 'This date is before the minimum date',
+    onBeforeDragStart : function(e) {
+        if (this.disabled) {
+            return false;
+        } else {
+            this.slider.promoteThumb(this);
+            return true;
+        }
+    },
+
     /**
     /**
-     * @cfg {String} maxText
-     * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
+     * @private
+     * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
+     * to the thumb and fires the 'dragstart' event
      */
      */
-    maxText : 'This date is after the maximum date',
+    onDragStart: function(e){
+        this.el.addClass('x-slider-thumb-drag');
+        this.dragging = true;
+        this.dragStartValue = this.value;
+
+        this.slider.fireEvent('dragstart', this.slider, e, this);
+    },
+
     /**
     /**
-     * @cfg {String} format
-     * The default date format string which can be overriden for localization support.  The format must be
-     * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
+     * @private
+     * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
+     * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
      */
      */
-    format : 'm/d/y',
+    onDrag: function(e) {
+        var slider   = this.slider,
+            index    = this.index,
+            newValue = this.getNewValue();
+
+        if (this.constrain) {
+            var above = slider.thumbs[index + 1],
+                below = slider.thumbs[index - 1];
+
+            if (below != undefined && newValue <= below.value) newValue = below.value;
+            if (above != undefined && newValue >= above.value) newValue = above.value;
+        }
+
+        slider.setValue(index, newValue, false);
+        slider.fireEvent('drag', slider, e, this);
+    },
+
+    getNewValue: function() {
+        var slider   = this.slider,
+            pos      = slider.innerEl.translatePoints(this.tracker.getXY());
+
+        return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
+    },
+
     /**
     /**
-     * @cfg {String} disabledDaysText
-     * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
+     * @private
+     * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
+     * fires the 'changecomplete' event with the new value
      */
      */
-    disabledDaysText : 'Disabled',
+    onDragEnd: function(e) {
+        var slider = this.slider,
+            value  = this.value;
+
+        this.el.removeClass('x-slider-thumb-drag');
+
+        this.dragging = false;
+        slider.fireEvent('dragend', slider, e);
+
+        if (this.dragStartValue != value) {
+            slider.fireEvent('changecomplete', slider, value, this);
+        }
+    },
+    
     /**
     /**
-     * @cfg {String} disabledDatesText
-     * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
+     * @private
+     * Destroys the thumb
      */
      */
-    disabledDatesText : 'Disabled',
+    destroy: function(){
+        Ext.destroyMembers(this, 'tracker', 'el');
+    }
+});
+
+/**
+ * @class Ext.slider.MultiSlider
+ * @extends Ext.BoxComponent
+ * Slider which supports vertical or horizontal orientation, keyboard adjustments, configurable snapping, axis clicking and animation. Can be added as an item to any container. Example usage:
+<pre>
+new Ext.Slider({
+    renderTo: Ext.getBody(),
+    width: 200,
+    value: 50,
+    increment: 10,
+    minValue: 0,
+    maxValue: 100
+});
+</pre>
+ * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
+<pre>
+new Ext.Slider({
+    renderTo: Ext.getBody(),
+    width: 200,
+    values: [25, 50, 75],
+    minValue: 0,
+    maxValue: 100,
+
+    //this defaults to true, setting to false allows the thumbs to pass each other
+    {@link #constrainThumbs}: false
+});
+</pre>
+ */
+Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
     /**
     /**
-     * @cfg {Array} monthNames
-     * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
+     * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
      */
      */
-    monthNames : Date.monthNames,
     /**
     /**
-     * @cfg {Array} dayNames
-     * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
+     * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
      */
      */
-    dayNames : Date.dayNames,
+    vertical: false,
     /**
     /**
-     * @cfg {String} nextText
-     * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
+     * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
      */
      */
-    nextText : 'Next Month (Control+Right)',
+    minValue: 0,
     /**
     /**
-     * @cfg {String} prevText
-     * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
+     * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
      */
      */
-    prevText : 'Previous Month (Control+Left)',
+    maxValue: 100,
     /**
     /**
-     * @cfg {String} monthYearText
-     * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
+     * @cfg {Number/Boolean} decimalPrecision.
+     * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
+     * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
      */
      */
-    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+    decimalPrecision: 0,
     /**
     /**
-     * @cfg {Number} startDay
-     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
+     * @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.
      */
      */
-    startDay : 0,
+    keyIncrement: 1,
     /**
     /**
-     * @cfg {Boolean} showToday
-     * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
-     * that selects the current date (defaults to <code>true</code>).
+     * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
      */
      */
-    showToday : true,
+    increment: 0,
+
     /**
     /**
-     * @cfg {Date} minDate
-     * Minimum allowable date (JavaScript date object, defaults to null)
+     * @private
+     * @property clickRange
+     * @type Array
+     * Determines whether or not a click to the slider component is considered to be a user request to change the value. Specified as an array of [top, bottom],
+     * the click event's 'top' property is compared to these numbers and the click only considered a change request if it falls within them. e.g. if the 'top'
+     * value of the click event is 4 or 16, the click is not considered a change request as it falls outside of the [5, 15] range
      */
      */
+    clickRange: [5,15],
+
     /**
     /**
-     * @cfg {Date} maxDate
-     * Maximum allowable date (JavaScript date object, defaults to null)
+     * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
      */
      */
+    clickToChange : true,
     /**
     /**
-     * @cfg {Array} disabledDays
-     * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
+     * @cfg {Boolean} animate Turn on or off animation. Defaults to true
      */
      */
+    animate: true,
     /**
     /**
-     * @cfg {RegExp} disabledDatesRE
-     * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
-     * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
-     * disabledDates value.
+     * @cfg {Boolean} constrainThumbs True to disallow thumbs from overlapping one another. Defaults to true
      */
      */
+    constrainThumbs: true,
+
     /**
     /**
-     * @cfg {Array} disabledDates
-     * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
-     * expression so they are very powerful. Some examples:
-     * <ul>
-     * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
-     * <li>['03/08', '09/16'] would disable those days for every year</li>
-     * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
-     * <li>['03/../2006'] would disable every day in March 2006</li>
-     * <li>['^03'] would disable every day in every March</li>
-     * </ul>
-     * Note that the format of the dates included in the array should exactly match the {@link #format} config.
-     * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
-     * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
+     * @private
+     * @property topThumbZIndex
+     * @type Number
+     * The number used internally to set the z index of the top thumb (see promoteThumb for details)
      */
      */
-    
-    // private
-    // Set by other components to stop the picker focus being updated when the value changes.
-    focusOnSelect: true,
+    topThumbZIndex: 10000,
 
 
-    // private
+    // private override
     initComponent : function(){
     initComponent : function(){
-        Ext.DatePicker.superclass.initComponent.call(this);
+        if(!Ext.isDefined(this.value)){
+            this.value = this.minValue;
+        }
 
 
-        this.value = this.value ?
-                 this.value.clearTime(true) : new Date().clearTime();
+        /**
+         * @property thumbs
+         * @type Array
+         * Array containing references to each thumb
+         */
+        this.thumbs = [];
 
 
+        Ext.slider.MultiSlider.superclass.initComponent.call(this);
+
+        this.keyIncrement = Math.max(this.increment, this.keyIncrement);
         this.addEvents(
             /**
         this.addEvents(
             /**
-             * @event select
-             * Fires when a date is selected
-             * @param {DatePicker} this DatePicker
-             * @param {Date} date The selected date
+             * @event beforechange
+             * Fires before the slider value is changed. By returning false from an event handler,
+             * you can cancel the event and prevent the slider from changing.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Number} newValue The new value which the slider is being changed to.
+             * @param {Number} oldValue The old value which the slider was previously.
              */
              */
-            'select'
+            'beforechange',
+
+            /**
+             * @event change
+             * Fires when the slider value is changed.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Number} newValue The new value which the slider has been changed to.
+             * @param {Ext.slider.Thumb} thumb The thumb that was changed
+             */
+            'change',
+
+            /**
+             * @event changecomplete
+             * Fires when the slider value is changed by the user and any drag operations have completed.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Number} newValue The new value which the slider has been changed to.
+             * @param {Ext.slider.Thumb} thumb The thumb that was changed
+             */
+            'changecomplete',
+
+            /**
+             * @event dragstart
+             * Fires after a drag operation has started.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
+             */
+            'dragstart',
+
+            /**
+             * @event drag
+             * Fires continuously during the drag operation while the mouse is moving.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
+             */
+            'drag',
+
+            /**
+             * @event dragend
+             * Fires after the drag operation has completed.
+             * @param {Ext.slider.MultiSlider} slider The slider
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
+             */
+            'dragend'
         );
 
         );
 
-        if(this.handler){
-            this.on('select', this.handler,  this.scope || this);
-        }
+        /**
+         * @property values
+         * @type Array
+         * Array of values to initalize the thumbs with
+         */
+        if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
 
 
-        this.initDisabledDays();
-    },
+        var values = this.values;
 
 
-    // private
-    initDisabledDays : function(){
-        if(!this.disabledDatesRE && this.disabledDates){
-            var dd = this.disabledDates,
-                len = dd.length - 1,
-                re = '(?:';
-                
-            Ext.each(dd, function(d, i){
-                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
-                if(i != len){
-                    re += '|';
-                }
-            }, this);
-            this.disabledDatesRE = new RegExp(re + ')');
+        for (var i=0; i < values.length; i++) {
+            this.addThumb(values[i]);
+        }
+
+        if(this.vertical){
+            Ext.apply(this, Ext.slider.Vertical);
         }
     },
 
     /**
         }
     },
 
     /**
-     * Replaces any existing disabled dates with new values and refreshes the DatePicker.
-     * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
-     * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
+     * Creates a new thumb and adds it to the slider
+     * @param {Number} value The initial value to set on the thumb. Defaults to 0
      */
      */
-    setDisabledDates : function(dd){
-        if(Ext.isArray(dd)){
-            this.disabledDates = dd;
-            this.disabledDatesRE = null;
-        }else{
-            this.disabledDatesRE = dd;
-        }
-        this.initDisabledDays();
-        this.update(this.value, true);
+    addThumb: function(value) {
+        var thumb = new Ext.slider.Thumb({
+            value    : value,
+            slider   : this,
+            index    : this.thumbs.length,
+            constrain: this.constrainThumbs
+        });
+        this.thumbs.push(thumb);
+
+        //render the thumb now if needed
+        if (this.rendered) thumb.render();
     },
 
     /**
     },
 
     /**
-     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
-     * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
-     * for details on supported values.
+     * @private
+     * Moves the given thumb above all other by increasing its z-index. This is called when as drag
+     * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
+     * required when the thumbs are stacked on top of each other at one of the ends of the slider's
+     * range, which can result in the user not being able to move any of them.
+     * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
      */
      */
-    setDisabledDays : function(dd){
-        this.disabledDays = dd;
-        this.update(this.value, true);
+    promoteThumb: function(topThumb) {
+        var thumbs = this.thumbs,
+            zIndex, thumb;
+
+        for (var i = 0, j = thumbs.length; i < j; i++) {
+            thumb = thumbs[i];
+
+            if (thumb == topThumb) {
+                zIndex = this.topThumbZIndex;
+            } else {
+                zIndex = '';
+            }
+
+            thumb.el.setStyle('zIndex', zIndex);
+        }
+    },
+
+    // private override
+    onRender : function() {
+        this.autoEl = {
+            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
+            cn : {
+                cls: 'x-slider-end',
+                cn : {
+                    cls:'x-slider-inner',
+                    cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
+                }
+            }
+        };
+
+        Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
+
+        this.endEl   = this.el.first();
+        this.innerEl = this.endEl.first();
+        this.focusEl = this.innerEl.child('.x-slider-focus');
+
+        //render each thumb
+        for (var i=0; i < this.thumbs.length; i++) {
+            this.thumbs[i].render();
+        }
+
+        //calculate the size of half a thumb
+        var thumb      = this.innerEl.child('.x-slider-thumb');
+        this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
+
+        this.initEvents();
     },
 
     /**
     },
 
     /**
-     * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
-     * @param {Date} value The minimum date that can be selected
+     * @private
+     * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
+     * Creates a new DragTracker which is used to control what happens when the user drags the thumb around.
      */
      */
-    setMinDate : function(dt){
-        this.minDate = dt;
-        this.update(this.value, true);
+    initEvents : function(){
+        this.mon(this.el, {
+            scope    : this,
+            mousedown: this.onMouseDown,
+            keydown  : this.onKeyDown
+        });
+
+        this.focusEl.swallowEvent("click", true);
     },
 
     /**
     },
 
     /**
-     * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
-     * @param {Date} value The maximum date that can be selected
+     * @private
+     * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
+     * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
+     * @param {Ext.EventObject} e The click event
      */
      */
-    setMaxDate : function(dt){
-        this.maxDate = dt;
-        this.update(this.value, true);
+    onMouseDown : function(e){
+        if(this.disabled){
+            return;
+        }
+
+        //see if the click was on any of the thumbs
+        var thumbClicked = false;
+        for (var i=0; i < this.thumbs.length; i++) {
+            thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
+        }
+
+        if (this.clickToChange && !thumbClicked) {
+            var local = this.innerEl.translatePoints(e.getXY());
+            this.onClickChange(local);
+        }
+        this.focus();
     },
 
     /**
     },
 
     /**
-     * Sets the value of the date field
-     * @param {Date} value The date to set
+     * @private
+     * Moves the thumb to the indicated position. Note that a Vertical implementation is provided in Ext.slider.Vertical.
+     * Only changes the value if the click was within this.clickRange.
+     * @param {Object} local Object containing top and left values for the click event.
      */
      */
-    setValue : function(value){
-        this.value = value.clearTime(true);
-        this.update(this.value);
+    onClickChange : function(local) {
+        if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
+            //find the nearest thumb to the click event
+            var thumb = this.getNearest(local, 'left'),
+                index = thumb.index;
+
+            this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
+        }
     },
 
     /**
     },
 
     /**
-     * Gets the current selected value of the date field
-     * @return {Date} The selected date
+     * @private
+     * Returns the nearest thumb to a click event, along with its distance
+     * @param {Object} local Object containing top and left values from a click event
+     * @param {String} prop The property of local to compare on. Use 'left' for horizontal sliders, 'top' for vertical ones
+     * @return {Object} The closest thumb object and its distance from the click event
      */
      */
-    getValue : function(){
-        return this.value;
-    },
+    getNearest: function(local, prop) {
+        var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
+            clickValue = this.reverseValue(localValue),
+            nearestDistance = (this.maxValue - this.minValue) + 5, //add a small fudge for the end of the slider 
+            index = 0,
+            nearest = null;
 
 
-    // private
-    focus : function(){
-        this.update(this.activeDate);
-    },
-    
-    // private
-    onEnable: function(initial){
-        Ext.DatePicker.superclass.onEnable.call(this);    
-        this.doDisabled(false);
-        this.update(initial ? this.value : this.activeDate);
-        if(Ext.isIE){
-            this.el.repaint();
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                value = thumb.value,
+                dist  = Math.abs(value - clickValue);
+
+            if (Math.abs(dist <= nearestDistance)) {
+                nearest = thumb;
+                index = i;
+                nearestDistance = dist;
+            }
         }
         }
-        
+        return nearest;
     },
     },
-    
-    // private
-    onDisable : function(){
-        Ext.DatePicker.superclass.onDisable.call(this);   
-        this.doDisabled(true);
-        if(Ext.isIE && !Ext.isIE8){
-            /* Really strange problem in IE6/7, when disabled, have to explicitly
-             * repaint each of the nodes to get them to display correctly, simply
-             * calling repaint on the main element doesn't appear to be enough.
-             */
-             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
-                 Ext.fly(el).repaint();
-             });
+
+    /**
+     * @private
+     * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
+     * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
+     * @param {Ext.EventObject} e The Event object
+     */
+    onKeyDown : function(e){
+        /*
+         * The behaviour for keyboard handling with multiple thumbs is currently undefined.
+         * There's no real sane default for it, so leave it like this until we come up
+         * with a better way of doing it.
+         */
+        if(this.disabled || this.thumbs.length !== 1){
+            e.preventDefault();
+            return;
         }
         }
-    },
-    
-    // private
-    doDisabled : function(disabled){
-        this.keyNav.setDisabled(disabled);
-        this.prevRepeater.setDisabled(disabled);
-        this.nextRepeater.setDisabled(disabled);
-        if(this.showToday){
-            this.todayKeyListener.setDisabled(disabled);
-            this.todayBtn.setDisabled(disabled);
+        var k = e.getKey(),
+            val;
+        switch(k){
+            case e.UP:
+            case e.RIGHT:
+                e.stopEvent();
+                val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
+                this.setValue(0, val, undefined, true);
+            break;
+            case e.DOWN:
+            case e.LEFT:
+                e.stopEvent();
+                val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
+                this.setValue(0, val, undefined, true);
+            break;
+            default:
+                e.preventDefault();
         }
     },
 
         }
     },
 
-    // private
-    onRender : function(container, position){
-        var m = [
-             '<table cellspacing="0">',
-                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
-                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
-                dn = this.dayNames,
-                i;
-        for(i = 0; i < 7; i++){
-            var d = this.startDay+i;
-            if(d > 6){
-                d = d-7;
-            }
-            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
+    /**
+     * @private
+     * If using snapping, this takes a desired new value and returns the closest snapped
+     * value to it
+     * @param {Number} value The unsnapped value
+     * @return {Number} The value of the nearest snap target
+     */
+    doSnap : function(value){
+        if (!(this.increment && value)) {
+            return value;
         }
         }
-        m[m.length] = '</tr></thead><tbody><tr>';
-        for(i = 0; i < 42; i++) {
-            if(i % 7 === 0 && i !== 0){
-                m[m.length] = '</tr><tr>';
+        var newValue = value,
+            inc = this.increment,
+            m = value % inc;
+        if (m != 0) {
+            newValue -= m;
+            if (m * 2 >= inc) {
+                newValue += inc;
+            } else if (m * 2 < -inc) {
+                newValue -= inc;
             }
             }
-            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
         }
         }
-        m.push('</tr></tbody></table></td></tr>',
-                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
-                '</table><div class="x-date-mp"></div>');
-
-        var el = document.createElement('div');
-        el.className = 'x-date-picker';
-        el.innerHTML = m.join('');
-
-        container.dom.insertBefore(el, position);
-
-        this.el = Ext.get(el);
-        this.eventEl = Ext.get(el.firstChild);
-
-        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
-            handler: this.showPrevMonth,
-            scope: this,
-            preventDefault:true,
-            stopDefault:true
-        });
+        return newValue.constrain(this.minValue,  this.maxValue);
+    },
 
 
-        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
-            handler: this.showNextMonth,
-            scope: this,
-            preventDefault:true,
-            stopDefault:true
-        });
+    // private
+    afterRender : function(){
+        Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
 
 
-        this.monthPicker = this.el.down('div.x-date-mp');
-        this.monthPicker.enableDisplayMode('block');
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i];
 
 
-        this.keyNav = new Ext.KeyNav(this.eventEl, {
-            'left' : function(e){
-                if(e.ctrlKey){
-                    this.showPrevMonth();
-                }else{
-                    this.update(this.activeDate.add('d', -1));    
-                }
-            },
+            if (thumb.value !== undefined) {
+                var v = this.normalizeValue(thumb.value);
 
 
-            'right' : function(e){
-                if(e.ctrlKey){
-                    this.showNextMonth();
-                }else{
-                    this.update(this.activeDate.add('d', 1));    
+                if (v !== thumb.value) {
+                    // delete this.value;
+                    this.setValue(i, v, false);
+                } else {
+                    this.moveThumb(i, this.translateValue(v), false);
                 }
                 }
-            },
+            }
+        };
+    },
 
 
-            'up' : function(e){
-                if(e.ctrlKey){
-                    this.showNextYear();
-                }else{
-                    this.update(this.activeDate.add('d', -7));
-                }
-            },
+    /**
+     * @private
+     * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
+     * the ratio is 2
+     * @return {Number} The ratio of pixels to mapped values
+     */
+    getRatio : function(){
+        var w = this.innerEl.getWidth(),
+            v = this.maxValue - this.minValue;
+        return v == 0 ? w : (w/v);
+    },
 
 
-            'down' : function(e){
-                if(e.ctrlKey){
-                    this.showPrevYear();
-                }else{
-                    this.update(this.activeDate.add('d', 7));
-                }
-            },
+    /**
+     * @private
+     * Returns a snapped, constrained value when given a desired value
+     * @param {Number} value Raw number value
+     * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
+     */
+    normalizeValue : function(v){
+        v = this.doSnap(v);
+        v = Ext.util.Format.round(v, this.decimalPrecision);
+        v = v.constrain(this.minValue, this.maxValue);
+        return v;
+    },
 
 
-            'pageUp' : function(e){
-                this.showNextMonth();
-            },
+    /**
+     * Sets the minimum value for the slider instance. If the current value is less than the
+     * minimum value, the current value will be changed.
+     * @param {Number} val The new minimum value
+     */
+    setMinValue : function(val){
+        this.minValue = val;
+        var i = 0,
+            thumbs = this.thumbs,
+            len = thumbs.length,
+            t;
+            
+        for(; i < len; ++i){
+            t = thumbs[i];
+            t.value = t.value < val ? val : t.value;
+        }
+        this.syncThumb();
+    },
 
 
-            'pageDown' : function(e){
-                this.showPrevMonth();
-            },
+    /**
+     * Sets the maximum value for the slider instance. If the current value is more than the
+     * maximum value, the current value will be changed.
+     * @param {Number} val The new maximum value
+     */
+    setMaxValue : function(val){
+        this.maxValue = val;
+        var i = 0,
+            thumbs = this.thumbs,
+            len = thumbs.length,
+            t;
+            
+        for(; i < len; ++i){
+            t = thumbs[i];
+            t.value = t.value > val ? val : t.value;
+        }
+        this.syncThumb();
+    },
 
 
-            'enter' : function(e){
-                e.stopPropagation();
-                return true;
-            },
+    /**
+     * Programmatically sets the value of the Slider. Ensures that the value is constrained within
+     * the minValue and maxValue.
+     * @param {Number} index Index of the thumb to move
+     * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
+     * @param {Boolean} animate Turn on or off animation, defaults to true
+     */
+    setValue : function(index, v, animate, changeComplete) {
+        var thumb = this.thumbs[index],
+            el    = thumb.el;
 
 
-            scope : this
-        });
+        v = this.normalizeValue(v);
 
 
-        this.el.unselectable();
+        if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
+            thumb.value = v;
+            if(this.rendered){
+                this.moveThumb(index, this.translateValue(v), animate !== false);
+                this.fireEvent('change', this, v, thumb);
+                if(changeComplete){
+                    this.fireEvent('changecomplete', this, v, thumb);
+                }
+            }
+        }
+    },
 
 
-        this.cells = this.el.select('table.x-date-inner tbody td');
-        this.textNodes = this.el.query('table.x-date-inner tbody span');
+    /**
+     * @private
+     */
+    translateValue : function(v) {
+        var ratio = this.getRatio();
+        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
+    },
 
 
-        this.mbtn = new Ext.Button({
-            text: '&#160;',
-            tooltip: this.monthYearText,
-            renderTo: this.el.child('td.x-date-middle', true)
-        });
-        this.mbtn.el.child('em').addClass('x-btn-arrow');
+    /**
+     * @private
+     * Given a pixel location along the slider, returns the mapped slider value for that pixel.
+     * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reverseValue(50)
+     * returns 200
+     * @param {Number} pos The position along the slider to return a mapped value for
+     * @return {Number} The mapped value for the given position
+     */
+    reverseValue : function(pos){
+        var ratio = this.getRatio();
+        return (pos + (this.minValue * ratio)) / ratio;
+    },
 
 
-        if(this.showToday){
-            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
-            var today = (new Date()).dateFormat(this.format);
-            this.todayBtn = new Ext.Button({
-                renderTo: this.el.child('td.x-date-bottom', true),
-                text: String.format(this.todayText, today),
-                tooltip: String.format(this.todayTip, today),
-                handler: this.selectToday,
-                scope: this
-            });
+    /**
+     * @private
+     * @param {Number} index Index of the thumb to move
+     */
+    moveThumb: function(index, v, animate){
+        var thumb = this.thumbs[index].el;
+
+        if(!animate || this.animate === false){
+            thumb.setLeft(v);
+        }else{
+            thumb.shift({left: v, stopFx: true, duration:.35});
         }
         }
-        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
-        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
-        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
-        this.onEnable(true);
     },
 
     // private
     },
 
     // private
-    createMonthPicker : function(){
-        if(!this.monthPicker.dom.firstChild){
-            var buf = ['<table border="0" cellspacing="0">'];
-            for(var i = 0; i < 6; i++){
-                buf.push(
-                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
-                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
-                    i === 0 ?
-                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
-                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
-                );
-            }
-            buf.push(
-                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
-                    this.okText,
-                    '</button><button type="button" class="x-date-mp-cancel">',
-                    this.cancelText,
-                    '</button></td></tr>',
-                '</table>'
-            );
-            this.monthPicker.update(buf.join(''));
+    focus : function(){
+        this.focusEl.focus(10);
+    },
 
 
-            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
-            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+    // private
+    onResize : function(w, h){
+        var thumbs = this.thumbs,
+            len = thumbs.length,
+            i = 0;
+            
+        /*
+         * If we happen to be animating during a resize, the position of the thumb will likely be off
+         * when the animation stops. As such, just stop any animations before syncing the thumbs.
+         */
+        for(; i < len; ++i){
+            thumbs[i].el.stopFx();    
+        }
+        // check to see if we're using an auto width
+        if(Ext.isNumber(w)){
+            this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
+        }
+        this.syncThumb();
+        Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
+    },
 
 
-            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
-            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+    //private
+    onDisable: function(){
+        Ext.slider.MultiSlider.superclass.onDisable.call(this);
 
 
-            this.mpMonths.each(function(m, a, i){
-                i += 1;
-                if((i%2) === 0){
-                    m.dom.xmonth = 5 + Math.round(i * 0.5);
-                }else{
-                    m.dom.xmonth = Math.round((i-1) * 0.5);
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                el    = thumb.el;
+
+            thumb.disable();
+
+            if(Ext.isIE){
+                //IE breaks when using overflow visible and opacity other than 1.
+                //Create a place holder for the thumb and display it.
+                var xy = el.getXY();
+                el.hide();
+
+                this.innerEl.addClass(this.disabledClass).dom.disabled = true;
+
+                if (!this.thumbHolder) {
+                    this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
                 }
                 }
-            });
+
+                this.thumbHolder.show().setXY(xy);
+            }
         }
     },
 
         }
     },
 
-    // private
-    showMonthPicker : function(){
-        if(!this.disabled){
-            this.createMonthPicker();
-            var size = this.el.getSize();
-            this.monthPicker.setSize(size);
-            this.monthPicker.child('table').setSize(size);
+    //private
+    onEnable: function(){
+        Ext.slider.MultiSlider.superclass.onEnable.call(this);
 
 
-            this.mpSelMonth = (this.activeDate || this.value).getMonth();
-            this.updateMPMonth(this.mpSelMonth);
-            this.mpSelYear = (this.activeDate || this.value).getFullYear();
-            this.updateMPYear(this.mpSelYear);
+        for (var i=0; i < this.thumbs.length; i++) {
+            var thumb = this.thumbs[i],
+                el    = thumb.el;
 
 
-            this.monthPicker.slideIn('t', {duration:0.2});
+            thumb.enable();
+
+            if (Ext.isIE) {
+                this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
+
+                if (this.thumbHolder) this.thumbHolder.hide();
+
+                el.show();
+                this.syncThumb();
+            }
         }
     },
 
         }
     },
 
-    // private
-    updateMPYear : function(y){
-        this.mpyear = y;
-        var ys = this.mpYears.elements;
-        for(var i = 1; i <= 10; i++){
-            var td = ys[i-1], y2;
-            if((i%2) === 0){
-                y2 = y + Math.round(i * 0.5);
-                td.firstChild.innerHTML = y2;
-                td.xyear = y2;
-            }else{
-                y2 = y - (5-Math.round(i * 0.5));
-                td.firstChild.innerHTML = y2;
-                td.xyear = y2;
+    /**
+     * Synchronizes the thumb position to the proper proportion of the total component width based
+     * on the current slider {@link #value}.  This will be called automatically when the Slider
+     * is resized by a layout, but if it is rendered auto width, this method can be called from
+     * another resize handler to sync the Slider if necessary.
+     */
+    syncThumb : function() {
+        if (this.rendered) {
+            for (var i=0; i < this.thumbs.length; i++) {
+                this.moveThumb(i, this.translateValue(this.thumbs[i].value));
             }
             }
-            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
         }
     },
 
         }
     },
 
-    // private
-    updateMPMonth : function(sm){
-        this.mpMonths.each(function(m, a, i){
-            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
-        });
+    /**
+     * Returns the current value of the slider
+     * @param {Number} index The index of the thumb to return a value for
+     * @return {Number} The current value of the slider
+     */
+    getValue : function(index) {
+        return this.thumbs[index].value;
     },
 
     },
 
-    // private
-    selectMPMonth : function(m){
-
-    },
+    /**
+     * Returns an array of values - one for the location of each thumb
+     * @return {Array} The set of thumb values
+     */
+    getValues: function() {
+        var values = [];
 
 
-    // private
-    onMonthClick : function(e, t){
-        e.stopEvent();
-        var el = new Ext.Element(t), pn;
-        if(el.is('button.x-date-mp-cancel')){
-            this.hideMonthPicker();
-        }
-        else if(el.is('button.x-date-mp-ok')){
-            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
-            if(d.getMonth() != this.mpSelMonth){
-                // 'fix' the JS rolling date conversion if needed
-                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
-            }
-            this.update(d);
-            this.hideMonthPicker();
-        }
-        else if((pn = el.up('td.x-date-mp-month', 2))){
-            this.mpMonths.removeClass('x-date-mp-sel');
-            pn.addClass('x-date-mp-sel');
-            this.mpSelMonth = pn.dom.xmonth;
-        }
-        else if((pn = el.up('td.x-date-mp-year', 2))){
-            this.mpYears.removeClass('x-date-mp-sel');
-            pn.addClass('x-date-mp-sel');
-            this.mpSelYear = pn.dom.xyear;
-        }
-        else if(el.is('a.x-date-mp-prev')){
-            this.updateMPYear(this.mpyear-10);
-        }
-        else if(el.is('a.x-date-mp-next')){
-            this.updateMPYear(this.mpyear+10);
+        for (var i=0; i < this.thumbs.length; i++) {
+            values.push(this.thumbs[i].value);
         }
         }
+
+        return values;
     },
 
     // private
     },
 
     // private
-    onMonthDblClick : function(e, t){
-        e.stopEvent();
-        var el = new Ext.Element(t), pn;
-        if((pn = el.up('td.x-date-mp-month', 2))){
-            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
-            this.hideMonthPicker();
-        }
-        else if((pn = el.up('td.x-date-mp-year', 2))){
-            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
-            this.hideMonthPicker();
+    beforeDestroy : function(){
+        var thumbs = this.thumbs;
+        for(var i = 0, len = thumbs.length; i < len; ++i){
+            thumbs[i].destroy();
+            thumbs[i] = null;
         }
         }
+        Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
+        Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
+    }
+});
+
+Ext.reg('multislider', Ext.slider.MultiSlider);
+
+/**
+ * @class Ext.slider.SingleSlider
+ * @extends Ext.slider.MultiSlider
+ * Slider which supports vertical or horizontal orientation, keyboard adjustments,
+ * configurable snapping, axis clicking and animation. Can be added as an item to
+ * any container. Example usage:
+<pre><code>
+new Ext.slider.SingleSlider({
+    renderTo: Ext.getBody(),
+    width: 200,
+    value: 50,
+    increment: 10,
+    minValue: 0,
+    maxValue: 100
+});
+</code></pre>
+ * The class Ext.slider.SingleSlider is aliased to Ext.Slider for backwards compatibility.
+ */
+Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
+    constructor: function(config) {
+      config = config || {};
+
+      Ext.applyIf(config, {
+          values: [config.value || 0]
+      });
+
+      Ext.slider.SingleSlider.superclass.constructor.call(this, config);
+    },
+
+    /**
+     * Returns the current value of the slider
+     * @return {Number} The current value of the slider
+     */
+    getValue: function() {
+        //just returns the value of the first thumb, which should be the only one in a single slider
+        return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
     },
 
     },
 
-    // private
-    hideMonthPicker : function(disableAnim){
-        if(this.monthPicker){
-            if(disableAnim === true){
-                this.monthPicker.hide();
-            }else{
-                this.monthPicker.slideOut('t', {duration:0.2});
-            }
+    /**
+     * Programmatically sets the value of the Slider. Ensures that the value is constrained within
+     * the minValue and maxValue.
+     * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
+     * @param {Boolean} animate Turn on or off animation, defaults to true
+     */
+    setValue: function(value, animate) {
+        var args = Ext.toArray(arguments),
+            len  = args.length;
+
+        //this is to maintain backwards compatiblity for sliders with only one thunb. Usually you must pass the thumb
+        //index to setValue, but if we only have one thumb we inject the index here first if given the multi-slider
+        //signature without the required index. The index will always be 0 for a single slider
+        if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
+            args.unshift(0);
         }
         }
+
+        return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
     },
 
     },
 
+    /**
+     * Synchronizes the thumb position to the proper proportion of the total component width based
+     * on the current slider {@link #value}.  This will be called automatically when the Slider
+     * is resized by a layout, but if it is rendered auto width, this method can be called from
+     * another resize handler to sync the Slider if necessary.
+     */
+    syncThumb : function() {
+        return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
+    },
+    
     // private
     // private
-    showPrevMonth : function(e){
-        this.update(this.activeDate.add('mo', -1));
+    getNearest : function(){
+        // Since there's only 1 thumb, it's always the nearest
+        return this.thumbs[0];    
+    }
+});
+
+//backwards compatibility
+Ext.Slider = Ext.slider.SingleSlider;
+
+Ext.reg('slider', Ext.slider.SingleSlider);
+
+// private class to support vertical sliders
+Ext.slider.Vertical = {
+    onResize : function(w, h){
+        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
+        this.syncThumb();
     },
 
     },
 
-    // private
-    showNextMonth : function(e){
-        this.update(this.activeDate.add('mo', 1));
+    getRatio : function(){
+        var h = this.innerEl.getHeight(),
+            v = this.maxValue - this.minValue;
+        return h/v;
     },
 
     },
 
-    // private
-    showPrevYear : function(){
-        this.update(this.activeDate.add('y', -1));
+    moveThumb: function(index, v, animate) {
+        var thumb = this.thumbs[index],
+            el    = thumb.el;
+
+        if (!animate || this.animate === false) {
+            el.setBottom(v);
+        } else {
+            el.shift({bottom: v, stopFx: true, duration:.35});
+        }
     },
 
     },
 
+    onClickChange : function(local) {
+        if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
+            var thumb = this.getNearest(local, 'top'),
+                index = thumb.index,
+                value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
+
+            this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
+        }
+    }
+};
+
+//private class to support vertical dragging of thumbs within a slider
+Ext.slider.Thumb.Vertical = {
+    getNewValue: function() {
+        var slider   = this.slider,
+            innerEl  = slider.innerEl,
+            pos      = innerEl.translatePoints(this.tracker.getXY()),
+            bottom   = innerEl.getHeight() - pos.top;
+
+        return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
+    }
+};
+/**
+ * @class Ext.ProgressBar
+ * @extends Ext.BoxComponent
+ * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
+ * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
+ * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
+ * throughout an operation that has predictable points of interest at which you can update the control.</p>
+ * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
+ * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
+ * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
+ * which you have no need for indicating intermediate progress.</p>
+ * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
+ * @cfg {String} text The progress bar text (defaults to '')
+ * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
+ * bar's internal text element)
+ * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
+ * @xtype progress
+ */
+Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
+   /**
+    * @cfg {String} baseCls
+    * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
+    */
+    baseCls : 'x-progress',
+    
+    /**
+    * @cfg {Boolean} animate
+    * True to animate the progress bar during transitions (defaults to false)
+    */
+    animate : false,
+
     // private
     // private
-    showNextYear : function(){
-        this.update(this.activeDate.add('y', 1));
-    },
+    waitTimer : null,
 
     // private
 
     // private
-    handleMouseWheel : function(e){
-        e.stopEvent();
-        if(!this.disabled){
-            var delta = e.getWheelDelta();
-            if(delta > 0){
-                this.showPrevMonth();
-            } else if(delta < 0){
-                this.showNextMonth();
-            }
-        }
+    initComponent : function(){
+        Ext.ProgressBar.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event update
+             * Fires after each update interval
+             * @param {Ext.ProgressBar} this
+             * @param {Number} The current progress value
+             * @param {String} The current progress text
+             */
+            "update"
+        );
     },
 
     // private
     },
 
     // private
-    handleDateClick : function(e, t){
-        e.stopEvent();
-        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
-            this.cancelFocus = this.focusOnSelect === false;
-            this.setValue(new Date(t.dateValue));
-            delete this.cancelFocus;
-            this.fireEvent('select', this, this.value);
+    onRender : function(ct, position){
+        var tpl = new Ext.Template(
+            '<div class="{cls}-wrap">',
+                '<div class="{cls}-inner">',
+                    '<div class="{cls}-bar">',
+                        '<div class="{cls}-text">',
+                            '<div>&#160;</div>',
+                        '</div>',
+                    '</div>',
+                    '<div class="{cls}-text {cls}-text-back">',
+                        '<div>&#160;</div>',
+                    '</div>',
+                '</div>',
+            '</div>'
+        );
+
+        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
+            : tpl.append(ct, {cls: this.baseCls}, true);
+                
+        if(this.id){
+            this.el.dom.id = this.id;
         }
         }
-    },
+        var inner = this.el.dom.firstChild;
+        this.progressBar = Ext.get(inner.firstChild);
 
 
-    // private
-    selectToday : function(){
-        if(this.todayBtn && !this.todayBtn.disabled){
-            this.setValue(new Date().clearTime());
-            this.fireEvent('select', this, this.value);
+        if(this.textEl){
+            //use an external text el
+            this.textEl = Ext.get(this.textEl);
+            delete this.textTopEl;
+        }else{
+            //setup our internal layered text els
+            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
+            var textBackEl = Ext.get(inner.childNodes[1]);
+            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
+            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
+            this.textEl.setWidth(inner.offsetWidth);
         }
         }
+        this.progressBar.setHeight(inner.offsetHeight);
     },
     },
-
+    
     // private
     // private
-    update : function(date, forceRefresh){
-        if(this.rendered){
-               var vd = this.activeDate, vis = this.isVisible();
-               this.activeDate = date;
-               if(!forceRefresh && vd && this.el){
-                   var t = date.getTime();
-                   if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
-                       this.cells.removeClass('x-date-selected');
-                       this.cells.each(function(c){
-                          if(c.dom.firstChild.dateValue == t){
-                              c.addClass('x-date-selected');
-                              if(vis && !this.cancelFocus){
-                                  Ext.fly(c.dom.firstChild).focus(50);
-                              }
-                              return false;
-                          }
-                       }, this);
-                       return;
-                   }
-               }
-               var days = date.getDaysInMonth(),
-                   firstOfMonth = date.getFirstDateOfMonth(),
-                   startingPos = firstOfMonth.getDay()-this.startDay;
-       
-               if(startingPos < 0){
-                   startingPos += 7;
-               }
-               days += startingPos;
-       
-               var pm = date.add('mo', -1),
-                   prevStart = pm.getDaysInMonth()-startingPos,
-                   cells = this.cells.elements,
-                   textEls = this.textNodes,
-                   // convert everything to numbers so it's fast
-                   day = 86400000,
-                   d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
-                   today = new Date().clearTime().getTime(),
-                   sel = date.clearTime(true).getTime(),
-                   min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
-                   max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
-                   ddMatch = this.disabledDatesRE,
-                   ddText = this.disabledDatesText,
-                   ddays = this.disabledDays ? this.disabledDays.join('') : false,
-                   ddaysText = this.disabledDaysText,
-                   format = this.format;
-       
-               if(this.showToday){
-                   var td = new Date().clearTime(),
-                       disable = (td < min || td > max ||
-                       (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
-                       (ddays && ddays.indexOf(td.getDay()) != -1));
-       
-                   if(!this.disabled){
-                       this.todayBtn.setDisabled(disable);
-                       this.todayKeyListener[disable ? 'disable' : 'enable']();
-                   }
-               }
-       
-               var setCellClass = function(cal, cell){
-                   cell.title = '';
-                   var t = d.getTime();
-                   cell.firstChild.dateValue = t;
-                   if(t == today){
-                       cell.className += ' x-date-today';
-                       cell.title = cal.todayText;
-                   }
-                   if(t == sel){
-                       cell.className += ' x-date-selected';
-                       if(vis){
-                           Ext.fly(cell.firstChild).focus(50);
-                       }
-                   }
-                   // disabling
-                   if(t < min) {
-                       cell.className = ' x-date-disabled';
-                       cell.title = cal.minText;
-                       return;
-                   }
-                   if(t > max) {
-                       cell.className = ' x-date-disabled';
-                       cell.title = cal.maxText;
-                       return;
-                   }
-                   if(ddays){
-                       if(ddays.indexOf(d.getDay()) != -1){
-                           cell.title = ddaysText;
-                           cell.className = ' x-date-disabled';
-                       }
-                   }
-                   if(ddMatch && format){
-                       var fvalue = d.dateFormat(format);
-                       if(ddMatch.test(fvalue)){
-                           cell.title = ddText.replace('%0', fvalue);
-                           cell.className = ' x-date-disabled';
-                       }
-                   }
-               };
-       
-               var i = 0;
-               for(; i < startingPos; i++) {
-                   textEls[i].innerHTML = (++prevStart);
-                   d.setDate(d.getDate()+1);
-                   cells[i].className = 'x-date-prevday';
-                   setCellClass(this, cells[i]);
-               }
-               for(; i < days; i++){
-                   var intDay = i - startingPos + 1;
-                   textEls[i].innerHTML = (intDay);
-                   d.setDate(d.getDate()+1);
-                   cells[i].className = 'x-date-active';
-                   setCellClass(this, cells[i]);
-               }
-               var extraDays = 0;
-               for(; i < 42; i++) {
-                    textEls[i].innerHTML = (++extraDays);
-                    d.setDate(d.getDate()+1);
-                    cells[i].className = 'x-date-nextday';
-                    setCellClass(this, cells[i]);
-               }
-       
-               this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
-       
-               if(!this.internalRender){
-                   var main = this.el.dom.firstChild,
-                       w = main.offsetWidth;
-                   this.el.setWidth(w + this.el.getBorderWidth('lr'));
-                   Ext.fly(main).setWidth(w);
-                   this.internalRender = true;
-                   // opera does not respect the auto grow header center column
-                   // then, after it gets a width opera refuses to recalculate
-                   // without a second pass
-                   if(Ext.isOpera && !this.secondPass){
-                       main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
-                       this.secondPass = true;
-                       this.update.defer(10, this, [date]);
-                   }
-               }
+    afterRender : function(){
+        Ext.ProgressBar.superclass.afterRender.call(this);
+        if(this.value){
+            this.updateProgress(this.value, this.text);
+        }else{
+            this.updateText(this.text);
         }
     },
 
         }
     },
 
-    // private
-    beforeDestroy : function() {
-        if(this.rendered){
-            Ext.destroy(
-                this.keyNav,
-                this.monthPicker,
-                this.eventEl,
-                this.mbtn,
-                this.nextRepeater,
-                this.prevRepeater,
-                this.cells.el,
-                this.todayBtn
-            );
-            delete this.textNodes;
-            delete this.cells.elements;
+    /**
+     * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
+     * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
+     * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
+     * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
+     * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
+     * @param {String} text (optional) The string to display in the progress text element (defaults to '')
+     * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
+     * not specified, the default for the class is used (default to false)
+     * @return {Ext.ProgressBar} this
+     */
+    updateProgress : function(value, text, animate){
+        this.value = value || 0;
+        if(text){
+            this.updateText(text);
         }
         }
-    }
+        if(this.rendered && !this.isDestroyed){
+            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
+            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
+            if(this.textTopEl){
+                //textTopEl should be the same width as the bar so overflow will clip as the bar moves
+                this.textTopEl.removeClass('x-hidden').setWidth(w);
+            }
+        }
+        this.fireEvent('update', this, value, text);
+        return this;
+    },
 
     /**
 
     /**
-     * @cfg {String} autoEl @hide
-     */
+     * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
+     * bar will automatically reset after a fixed amount of time and optionally call a callback function
+     * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
+     * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
+     * the following properties:
+     * <pre>
+Property   Type          Description
+---------- ------------  ----------------------------------------------------------------------
+duration   Number        The length of time in milliseconds that the progress bar should
+                         run before resetting itself (defaults to undefined, in which case it
+                         will run indefinitely until reset is called)
+interval   Number        The length of time in milliseconds between each progress update
+                         (defaults to 1000 ms)
+animate    Boolean       Whether to animate the transition of the progress bar. If this value is
+                         not specified, the default for the class is used.                                                   
+increment  Number        The number of progress update segments to display within the progress
+                         bar (defaults to 10).  If the bar reaches the end and is still
+                         updating, it will automatically wrap back to the beginning.
+text       String        Optional text to display in the progress bar element (defaults to '').
+fn         Function      A callback function to execute after the progress bar finishes auto-
+                         updating.  The function will be called with no arguments.  This function
+                         will be ignored if duration is not specified since in that case the
+                         progress bar can only be stopped programmatically, so any required function
+                         should be called by the same code after it resets the progress bar.
+scope      Object        The scope that is passed to the callback function (only applies when
+                         duration and fn are both passed).
+</pre>
+         *
+         * Example usage:
+         * <pre><code>
+var p = new Ext.ProgressBar({
+   renderTo: 'my-el'
 });
 
 });
 
-Ext.reg('datepicker', Ext.DatePicker);
-/**
- * @class Ext.LoadMask
- * A simple utility class for generically masking elements while loading data.  If the {@link #store}
- * config option is specified, the masking will be automatically synchronized with the store's loading
- * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
- * element's Updater load indicator and will be destroyed after the initial load.
- * <p>Example usage:</p>
- *<pre><code>
-// Basic mask:
-var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
-myMask.show();
-</code></pre>
- * @constructor
- * Create a new LoadMask
- * @param {Mixed} el The element or DOM node, or its id
- * @param {Object} config The config object
- */
-Ext.LoadMask = function(el, config){
-    this.el = Ext.get(el);
-    Ext.apply(this, config);
-    if(this.store){
-        this.store.on({
-            scope: this,
-            beforeload: this.onBeforeLoad,
-            load: this.onLoad,
-            exception: this.onLoad
-        });
-        this.removeMask = Ext.value(this.removeMask, false);
-    }else{
-        var um = this.el.getUpdater();
-        um.showLoadIndicator = false; // disable the default indicator
-        um.on({
-            scope: this,
-            beforeupdate: this.onBeforeLoad,
-            update: this.onLoad,
-            failure: this.onLoad
-        });
-        this.removeMask = Ext.value(this.removeMask, true);
-    }
-};
+//Wait for 5 seconds, then update the status el (progress bar will auto-reset)
+p.wait({
+   interval: 100, //bar will move fast!
+   duration: 5000,
+   increment: 15,
+   text: 'Updating...',
+   scope: this,
+   fn: function(){
+      Ext.fly('status').update('Done!');
+   }
+});
 
 
-Ext.LoadMask.prototype = {
-    /**
-     * @cfg {Ext.data.Store} store
-     * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
-     * hidden on either load sucess, or load fail.
-     */
-    /**
-     * @cfg {Boolean} removeMask
-     * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
-     * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
-     */
-    /**
-     * @cfg {String} msg
-     * The text to display in a centered loading message box (defaults to 'Loading...')
-     */
-    msg : 'Loading...',
-    /**
-     * @cfg {String} msgCls
-     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
-     */
-    msgCls : 'x-mask-loading',
+//Or update indefinitely until some async action completes, then reset manually
+p.wait();
+myAction.on('complete', function(){
+    p.reset();
+    Ext.fly('status').update('Done!');
+});
+</code></pre>
+     * @param {Object} config (optional) Configuration options
+     * @return {Ext.ProgressBar} this
+     */
+    wait : function(o){
+        if(!this.waitTimer){
+            var scope = this;
+            o = o || {};
+            this.updateText(o.text);
+            this.waitTimer = Ext.TaskMgr.start({
+                run: function(i){
+                    var inc = o.increment || 10;
+                    i -= 1;
+                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
+                },
+                interval: o.interval || 1000,
+                duration: o.duration,
+                onStop: function(){
+                    if(o.fn){
+                        o.fn.apply(o.scope || this);
+                    }
+                    this.reset();
+                },
+                scope: scope
+            });
+        }
+        return this;
+    },
 
     /**
 
     /**
-     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
-     * @type Boolean
+     * Returns true if the progress bar is currently in a {@link #wait} operation
+     * @return {Boolean} True if waiting, else false
      */
      */
-    disabled: false,
+    isWaiting : function(){
+        return this.waitTimer !== null;
+    },
 
     /**
 
     /**
-     * Disables the mask to prevent it from being displayed
+     * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
+     * bar itself will display the updated text.
+     * @param {String} text (optional) The string to display in the progress text element (defaults to '')
+     * @return {Ext.ProgressBar} this
      */
      */
-    disable : function(){
-       this.disabled = true;
+    updateText : function(text){
+        this.text = text || '&#160;';
+        if(this.rendered){
+            this.textEl.update(this.text);
+        }
+        return this;
     },
     },
-
+    
     /**
     /**
-     * Enables the mask so that it can be displayed
+     * Synchronizes the inner bar width to the proper proportion of the total componet width based
+     * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
+     * is resized by a layout, but if it is rendered auto width, this method can be called from
+     * another resize handler to sync the ProgressBar if necessary.
      */
      */
-    enable : function(){
-        this.disabled = false;
-    },
-
-    // private
-    onLoad : function(){
-        this.el.unmask(this.removeMask);
-    },
-
-    // private
-    onBeforeLoad : function(){
-        if(!this.disabled){
-            this.el.mask(this.msg, this.msgCls);
+    syncProgressBar : function(){
+        if(this.value){
+            this.updateProgress(this.value, this.text);
         }
         }
+        return this;
     },
 
     /**
     },
 
     /**
-     * Show this LoadMask over the configured Element.
+     * Sets the size of the progress bar.
+     * @param {Number} width The new width in pixels
+     * @param {Number} height The new height in pixels
+     * @return {Ext.ProgressBar} this
      */
      */
-    show: function(){
-        this.onBeforeLoad();
+    setSize : function(w, h){
+        Ext.ProgressBar.superclass.setSize.call(this, w, h);
+        if(this.textTopEl){
+            var inner = this.el.dom.firstChild;
+            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
+        }
+        this.syncProgressBar();
+        return this;
     },
 
     /**
     },
 
     /**
-     * Hide this LoadMask.
+     * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
+     * bar will also be hidden (using the {@link #hideMode} property internally).
+     * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
+     * @return {Ext.ProgressBar} this
      */
      */
-    hide: function(){
-        this.onLoad();
+    reset : function(hide){
+        this.updateProgress(0);
+        if(this.textTopEl){
+            this.textTopEl.addClass('x-hidden');
+        }
+        this.clearTimer();
+        if(hide === true){
+            this.hide();
+        }
+        return this;
     },
     },
-
+    
     // private
     // private
-    destroy : function(){
-        if(this.store){
-            this.store.un('beforeload', this.onBeforeLoad, this);
-            this.store.un('load', this.onLoad, this);
-            this.store.un('exception', this.onLoad, this);
-        }else{
-            var um = this.el.getUpdater();
-            um.un('beforeupdate', this.onBeforeLoad, this);
-            um.un('update', this.onLoad, this);
-            um.un('failure', this.onLoad, this);
+    clearTimer : function(){
+        if(this.waitTimer){
+            this.waitTimer.onStop = null; //prevent recursion
+            Ext.TaskMgr.stop(this.waitTimer);
+            this.waitTimer = null;
         }
         }
+    },
+    
+    onDestroy: function(){
+        this.clearTimer();
+        if(this.rendered){
+            if(this.textEl.isComposite){
+                this.textEl.clear();
+            }
+            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
+        }
+        Ext.ProgressBar.superclass.onDestroy.call(this);
     }
     }
-};/**\r
- * @class Ext.Slider\r
- * @extends Ext.BoxComponent\r
- * Slider which supports vertical or horizontal orientation, keyboard adjustments,\r
- * configurable snapping, axis clicking and animation. Can be added as an item to\r
- * any container. Example usage:\r
-<pre><code>\r
-new Ext.Slider({\r
-    renderTo: Ext.getBody(),\r
-    width: 200,\r
-    value: 50,\r
-    increment: 10,\r
-    minValue: 0,\r
-    maxValue: 100\r
-});\r
-</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
-    vertical: false,\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
-    maxValue: 100,\r
-    /**\r
-     * @cfg {Number/Boolean} decimalPrecision.\r
-     * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>\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
-    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
-    increment: 0,\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
-    clickToChange : true,\r
-    /**\r
-     * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
-     */\r
-    animate: true,\r
-\r
-    /**\r
-     * True while the thumb is in a drag operation\r
-     * @type boolean\r
-     */\r
-    dragging: false,\r
-\r
-    // private override\r
-    initComponent : function(){\r
-        if(!Ext.isDefined(this.value)){\r
-            this.value = this.minValue;\r
-        }\r
-        Ext.Slider.superclass.initComponent.call(this);\r
-        this.keyIncrement = Math.max(this.increment, this.keyIncrement);\r
-        this.addEvents(\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
-             */\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
-             * 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
-             * 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
-             * 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
-\r
-        if(this.vertical){\r
-            Ext.apply(this, Ext.Slider.Vertical);\r
-        }\r
-    },\r
-\r
-    // private override\r
-    onRender : function(){\r
-        this.autoEl = {\r
-            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
-            cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}\r
-        };\r
-        Ext.Slider.superclass.onRender.apply(this, arguments);\r
-        this.endEl = this.el.first();\r
-        this.innerEl = this.endEl.first();\r
-        this.thumb = this.innerEl.first();\r
-        this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
-        this.focusEl = this.thumb.next();\r
-        this.initEvents();\r
-    },\r
-\r
-    // private override\r
-    initEvents : function(){\r
-        this.thumb.addClassOnOver('x-slider-thumb-over');\r
-        this.mon(this.el, {\r
-            scope: this,\r
-            mousedown: this.onMouseDown,\r
-            keydown: this.onKeyDown\r
-        });\r
-\r
-        this.focusEl.swallowEvent("click", true);\r
-\r
-        this.tracker = new Ext.dd.DragTracker({\r
-            onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
-            onStart: this.onDragStart.createDelegate(this),\r
-            onDrag: this.onDrag.createDelegate(this),\r
-            onEnd: this.onDragEnd.createDelegate(this),\r
-            tolerance: 3,\r
-            autoStart: 300\r
-        });\r
-        this.tracker.initEl(this.thumb);\r
-    },\r
-\r
-    // private override\r
-    onMouseDown : function(e){\r
-        if(this.disabled){\r
-            return;\r
-        }\r
-        if(this.clickToChange && e.target != this.thumb.dom){\r
-            var local = this.innerEl.translatePoints(e.getXY());\r
-            this.onClickChange(local);\r
-        }\r
-        this.focus();\r
-    },\r
-\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
-    onKeyDown : function(e){\r
-        if(this.disabled){e.preventDefault();return;}\r
-        var k = e.getKey();\r
-        switch(k){\r
-            case e.UP:\r
-            case e.RIGHT:\r
-                e.stopEvent();\r
-                if(e.ctrlKey){\r
-                    this.setValue(this.maxValue, undefined, true);\r
-                }else{\r
-                    this.setValue(this.value+this.keyIncrement, undefined, true);\r
-                }\r
-            break;\r
-            case e.DOWN:\r
-            case e.LEFT:\r
-                e.stopEvent();\r
-                if(e.ctrlKey){\r
-                    this.setValue(this.minValue, undefined, true);\r
-                }else{\r
-                    this.setValue(this.value-this.keyIncrement, undefined, true);\r
-                }\r
-            break;\r
-            default:\r
-                e.preventDefault();\r
-        }\r
-    },\r
-\r
-    // private\r
-    doSnap : function(value){\r
-        if(!(this.increment && value)){\r
-            return value;\r
-        }\r
-        var newValue = value,\r
-            inc = this.increment,\r
-            m = value % inc;\r
-        if(m != 0){\r
-            newValue -= m;\r
-            if(m * 2 > inc){\r
-                newValue += inc;\r
-            }else if(m * 2 < -inc){\r
-                newValue -= inc;\r
-            }\r
-        }\r
-        return newValue.constrain(this.minValue,  this.maxValue);\r
-    },\r
-\r
-    // private\r
-    afterRender : function(){\r
-        Ext.Slider.superclass.afterRender.apply(this, arguments);\r
-        if(this.value !== undefined){\r
-            var v = this.normalizeValue(this.value);\r
-            if(v !== this.value){\r
-                delete this.value;\r
-                this.setValue(v, false);\r
-            }else{\r
-                this.moveThumb(this.translateValue(v), false);\r
-            }\r
-        }\r
-    },\r
-\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
-    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
-    setValue : function(v, animate, changeComplete){\r
-        v = this.normalizeValue(v);\r
-        if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
-            this.value = v;\r
-            this.moveThumb(this.translateValue(v), animate !== false);\r
-            this.fireEvent('change', this, v);\r
-            if(changeComplete){\r
-                this.fireEvent('changecomplete', this, v);\r
-            }\r
-        }\r
-    },\r
-\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
-        var ratio = this.getRatio();\r
-        return (pos + (this.minValue * ratio)) / ratio;\r
-    },\r
-\r
-    // private\r
-    moveThumb: function(v, animate){\r
-        if(!animate || this.animate === false){\r
-            this.thumb.setLeft(v);\r
-        }else{\r
-            this.thumb.shift({left: v, stopFx: true, duration:.35});\r
-        }\r
-    },\r
-\r
-    // private\r
-    focus : function(){\r
-        this.focusEl.focus(10);\r
-    },\r
-\r
-    // private\r
-    onBeforeDragStart : function(e){\r
-        return !this.disabled;\r
-    },\r
-\r
-    // private\r
-    onDragStart: function(e){\r
-        this.thumb.addClass('x-slider-thumb-drag');\r
-        this.dragging = true;\r
-        this.dragStartValue = this.value;\r
-        this.fireEvent('dragstart', this, e);\r
-    },\r
-\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
-    onDragEnd: function(e){\r
-        this.thumb.removeClass('x-slider-thumb-drag');\r
-        this.dragging = false;\r
-        this.fireEvent('dragend', this, e);\r
-        if(this.dragStartValue != this.value){\r
-            this.fireEvent('changecomplete', this, this.value);\r
-        }\r
-    },\r
-\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
-    //private\r
-    onDisable: function(){\r
-        Ext.Slider.superclass.onDisable.call(this);\r
-        this.thumb.addClass(this.disabledClass);\r
-        if(Ext.isIE){\r
-            //IE breaks when using overflow visible and opacity other than 1.\r
-            //Create a place holder for the thumb and display it.\r
-            var xy = this.thumb.getXY();\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
-            }\r
-            this.thumbHolder.show().setXY(xy);\r
-        }\r
-    },\r
-\r
-    //private\r
-    onEnable: function(){\r
-        Ext.Slider.superclass.onEnable.call(this);\r
-        this.thumb.removeClass(this.disabledClass);\r
-        if(Ext.isIE){\r
-            this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
-            if(this.thumbHolder){\r
-                this.thumbHolder.hide();\r
-            }\r
-            this.thumb.show();\r
-            this.syncThumb();\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
-     * is resized by a layout, but if it is rendered auto width, this method can be called from\r
-     * another resize handler to sync the Slider if necessary.\r
-     */\r
-    syncThumb : function(){\r
-        if(this.rendered){\r
-            this.moveThumb(this.translateValue(this.value));\r
-        }\r
-    },\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
-    // private\r
-    beforeDestroy : function(){\r
-        Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
-        Ext.Slider.superclass.beforeDestroy.call(this);\r
-    }\r
-});\r
-Ext.reg('slider', Ext.Slider);\r
-\r
-// private class to support vertical sliders\r
-Ext.Slider.Vertical = {\r
-    onResize : function(w, h){\r
-        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
-        this.syncThumb();\r
-    },\r
-\r
-    getRatio : function(){\r
-        var h = this.innerEl.getHeight(),\r
-            v = this.maxValue - this.minValue;\r
-        return h/v;\r
-    },\r
-\r
-    moveThumb: function(v, animate){\r
-        if(!animate || this.animate === false){\r
-            this.thumb.setBottom(v);\r
-        }else{\r
-            this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
-        }\r
-    },\r
-\r
-    onDrag: function(e){\r
-        var pos = this.innerEl.translatePoints(this.tracker.getXY()),\r
-            bottom = this.innerEl.getHeight()-pos.top;\r
-        this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
-        this.fireEvent('drag', this, e);\r
-    },\r
-\r
-    onClickChange : function(local){\r
-        if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
-            var bottom = this.innerEl.getHeight() - local.top;\r
-            this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
-        }\r
-    }\r
-};/**\r
- * @class Ext.ProgressBar\r
- * @extends Ext.BoxComponent\r
- * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
- * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
- * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
- * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
- * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
- * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
- * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
- * which you have no need for indicating intermediate progress.</p>\r
- * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
- * @cfg {String} text The progress bar text (defaults to '')\r
- * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
- * bar's internal text element)\r
- * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
- * @xtype progress\r
- */\r
-Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
-   /**\r
-    * @cfg {String} baseCls\r
-    * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
-    */\r
-    baseCls : 'x-progress',\r
-    \r
-    /**\r
-    * @cfg {Boolean} animate\r
-    * True to animate the progress bar during transitions (defaults to false)\r
-    */\r
-    animate : false,\r
-\r
-    // private\r
-    waitTimer : null,\r
-\r
-    // private\r
-    initComponent : function(){\r
-        Ext.ProgressBar.superclass.initComponent.call(this);\r
-        this.addEvents(\r
-            /**\r
-             * @event update\r
-             * Fires after each update interval\r
-             * @param {Ext.ProgressBar} this\r
-             * @param {Number} The current progress value\r
-             * @param {String} The current progress text\r
-             */\r
-            "update"\r
-        );\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        var tpl = new Ext.Template(\r
-            '<div class="{cls}-wrap">',\r
-                '<div class="{cls}-inner">',\r
-                    '<div class="{cls}-bar">',\r
-                        '<div class="{cls}-text">',\r
-                            '<div>&#160;</div>',\r
-                        '</div>',\r
-                    '</div>',\r
-                    '<div class="{cls}-text {cls}-text-back">',\r
-                        '<div>&#160;</div>',\r
-                    '</div>',\r
-                '</div>',\r
-            '</div>'\r
-        );\r
-\r
-        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
-               : tpl.append(ct, {cls: this.baseCls}, true);\r
-                       \r
-        if(this.id){\r
-            this.el.dom.id = this.id;\r
-        }\r
-        var inner = this.el.dom.firstChild;\r
-        this.progressBar = Ext.get(inner.firstChild);\r
-\r
-        if(this.textEl){\r
-            //use an external text el\r
-            this.textEl = Ext.get(this.textEl);\r
-            delete this.textTopEl;\r
-        }else{\r
-            //setup our internal layered text els\r
-            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
-            var textBackEl = Ext.get(inner.childNodes[1]);\r
-            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
-            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
-            this.textEl.setWidth(inner.offsetWidth);\r
-        }\r
-        this.progressBar.setHeight(inner.offsetHeight);\r
-    },\r
-    \r
-    // private\r
-    afterRender : function(){\r
-        Ext.ProgressBar.superclass.afterRender.call(this);\r
-        if(this.value){\r
-            this.updateProgress(this.value, this.text);\r
-        }else{\r
-            this.updateText(this.text);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
-     * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
-     * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
-     * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
-     * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
-     * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
-     * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
-     * not specified, the default for the class is used (default to false)\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    updateProgress : function(value, text, animate){\r
-        this.value = value || 0;\r
-        if(text){\r
-            this.updateText(text);\r
-        }\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
-                //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
-                this.textTopEl.removeClass('x-hidden').setWidth(w);\r
-            }\r
-        }\r
-        this.fireEvent('update', this, value, text);\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
-     * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
-     * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
-     * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
-     * the following properties:\r
-     * <pre>\r
-Property   Type          Description\r
----------- ------------  ----------------------------------------------------------------------\r
-duration   Number        The length of time in milliseconds that the progress bar should\r
-                         run before resetting itself (defaults to undefined, in which case it\r
-                         will run indefinitely until reset is called)\r
-interval   Number        The length of time in milliseconds between each progress update\r
-                         (defaults to 1000 ms)\r
-animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
-                         not specified, the default for the class is used.                                                   \r
-increment  Number        The number of progress update segments to display within the progress\r
-                         bar (defaults to 10).  If the bar reaches the end and is still\r
-                         updating, it will automatically wrap back to the beginning.\r
-text       String        Optional text to display in the progress bar element (defaults to '').\r
-fn         Function      A callback function to execute after the progress bar finishes auto-\r
-                         updating.  The function will be called with no arguments.  This function\r
-                         will be ignored if duration is not specified since in that case the\r
-                         progress bar can only be stopped programmatically, so any required function\r
-                         should be called by the same code after it resets the progress bar.\r
-scope      Object        The scope that is passed to the callback function (only applies when\r
-                         duration and fn are both passed).\r
-</pre>\r
-         *\r
-         * Example usage:\r
-         * <pre><code>\r
-var p = new Ext.ProgressBar({\r
-   renderTo: 'my-el'\r
-});\r
-\r
-//Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
-p.wait({\r
-   interval: 100, //bar will move fast!\r
-   duration: 5000,\r
-   increment: 15,\r
-   text: 'Updating...',\r
-   scope: this,\r
-   fn: function(){\r
-      Ext.fly('status').update('Done!');\r
-   }\r
-});\r
-\r
-//Or update indefinitely until some async action completes, then reset manually\r
-p.wait();\r
-myAction.on('complete', function(){\r
-    p.reset();\r
-    Ext.fly('status').update('Done!');\r
-});\r
-</code></pre>\r
-     * @param {Object} config (optional) Configuration options\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    wait : function(o){\r
-        if(!this.waitTimer){\r
-            var scope = this;\r
-            o = o || {};\r
-            this.updateText(o.text);\r
-            this.waitTimer = Ext.TaskMgr.start({\r
-                run: function(i){\r
-                    var inc = o.increment || 10;\r
-                    i -= 1;\r
-                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
-                },\r
-                interval: o.interval || 1000,\r
-                duration: o.duration,\r
-                onStop: function(){\r
-                    if(o.fn){\r
-                        o.fn.apply(o.scope || this);\r
-                    }\r
-                    this.reset();\r
-                },\r
-                scope: scope\r
-            });\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Returns true if the progress bar is currently in a {@link #wait} operation\r
-     * @return {Boolean} True if waiting, else false\r
-     */\r
-    isWaiting : function(){\r
-        return this.waitTimer !== null;\r
-    },\r
-\r
-    /**\r
-     * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
-     * bar itself will display the updated text.\r
-     * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    updateText : function(text){\r
-        this.text = text || '&#160;';\r
-        if(this.rendered){\r
-            this.textEl.update(this.text);\r
-        }\r
-        return this;\r
-    },\r
-    \r
-    /**\r
-     * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
-     * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
-     * is resized by a layout, but if it is rendered auto width, this method can be called from\r
-     * another resize handler to sync the ProgressBar if necessary.\r
-     */\r
-    syncProgressBar : function(){\r
-        if(this.value){\r
-            this.updateProgress(this.value, this.text);\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Sets the size of the progress bar.\r
-     * @param {Number} width The new width in pixels\r
-     * @param {Number} height The new height in pixels\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    setSize : function(w, h){\r
-        Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
-        if(this.textTopEl){\r
-            var inner = this.el.dom.firstChild;\r
-            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
-        }\r
-        this.syncProgressBar();\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
-     * bar will also be hidden (using the {@link #hideMode} property internally).\r
-     * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
-     * @return {Ext.ProgressBar} this\r
-     */\r
-    reset : function(hide){\r
-        this.updateProgress(0);\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
-    },\r
-    \r
-    onDestroy: function(){\r
-        this.clearTimer();\r
-        if(this.rendered){\r
-            if(this.textEl.isComposite){\r
-                this.textEl.clear();\r
-            }\r
-            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');\r
-        }\r
-        Ext.ProgressBar.superclass.onDestroy.call(this);\r
-    }\r
-});\r
+});
 Ext.reg('progress', Ext.ProgressBar);
\ No newline at end of file
 Ext.reg('progress', Ext.ProgressBar);
\ No newline at end of file