Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Accordion.html
index 61cebad..e62c136 100644 (file)
@@ -3,8 +3,8 @@
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
-  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
   <style type="text/css">
     .highlight { display: block; background-color: #ddd; }
   </style>
   <pre class="prettyprint lang-js"><span id='Ext-layout-container-Accordion'>/**
 </span> * @class Ext.layout.container.Accordion
  * @extends Ext.layout.container.VBox
- * &lt;p&gt;This is a layout that manages multiple Panels in an expandable accordion style such that only
- * &lt;b&gt;one Panel can be expanded at any given time&lt;/b&gt;. Each Panel has built-in support for expanding and collapsing.&lt;/p&gt;
- * &lt;p&gt;Note: Only Ext.Panels &lt;b&gt;and all subclasses of Ext.panel.Panel&lt;/b&gt; may be used in an accordion layout Container.&lt;/p&gt;
- * {@img Ext.layout.container.Accordion/Ext.layout.container.Accordion.png Ext.layout.container.Accordion container layout}
- * &lt;p&gt;Example usage:&lt;/p&gt;
- * &lt;pre&gt;&lt;code&gt;
-Ext.create('Ext.panel.Panel', {
-    title: 'Accordion Layout',
   width: 300,
   height: 300,
   layout:'accordion',
-    defaults: {
-        // applied to each contained panel
-        bodyStyle: 'padding:15px'
-    },
-    layoutConfig: {
-        // layout-specific configs go here
-        titleCollapse: false,
       animate: true,
-        activeOnTop: true
-    },
-    items: [{
-        title: 'Panel 1',
-        html: 'Panel content!'
-    },{
-        title: 'Panel 2',
-        html: 'Panel content!'
-    },{
-        title: 'Panel 3',
-        html: 'Panel content!'
-    }],
-    renderTo: Ext.getBody()
-});
-&lt;/code&gt;&lt;/pre&gt;
+ *
+ * This is a layout that manages multiple Panels in an expandable accordion style such that only
+ * **one Panel can be expanded at any given time**. Each Panel has built-in support for expanding and collapsing.
+ *
+ * Note: Only Ext Panels and all subclasses of Ext.panel.Panel may be used in an accordion layout Container.
+ *
+ *     @example
+ *     Ext.create('Ext.panel.Panel', {
*         title: 'Accordion Layout',
*         width: 300,
*         height: 300,
+ *         layout:'accordion',
+ *         defaults: {
+ *             // applied to each contained panel
+ *             bodyStyle: 'padding:15px'
+ *         },
+ *         layoutConfig: {
+ *             // layout-specific configs go here
*             titleCollapse: false,
+ *             animate: true,
+ *             activeOnTop: true
+ *         },
+ *         items: [{
+ *             title: 'Panel 1',
+ *             html: 'Panel content!'
+ *         },{
+ *             title: 'Panel 2',
+ *             html: 'Panel content!'
+ *         },{
+ *             title: 'Panel 3',
+ *             html: 'Panel content!'
+ *         }],
+ *         renderTo: Ext.getBody()
+ *     });
  */
 Ext.define('Ext.layout.container.Accordion', {
     extend: 'Ext.layout.container.VBox',
     alias: ['layout.accordion'],
     alternateClassName: 'Ext.layout.AccordionLayout',
-    
+
+    itemCls: Ext.baseCSSPrefix + 'box-item ' + Ext.baseCSSPrefix + 'accordion-item',
+
     align: 'stretch',
 
 <span id='Ext-layout-container-Accordion-cfg-fill'>    /**
 </span>     * @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).
+     * item's current height, or auto height if not explicitly set.
      */
     fill : true,
+
 <span id='Ext-layout-container-Accordion-cfg-autoWidth'>    /**
 </span>     * @cfg {Boolean} autoWidth
-     * &lt;p&gt;&lt;b&gt;This config is ignored in ExtJS 4.x.&lt;/b&gt;&lt;/p&gt;
      * Child Panels have their width actively managed to fit within the accordion's width.
+     * @deprecated This config is ignored in ExtJS 4
      */
     autoWidth : true,
+
 <span id='Ext-layout-container-Accordion-cfg-titleCollapse'>    /**
 </span>     * @cfg {Boolean} titleCollapse
-     * &lt;p&gt;&lt;b&gt;Not implemented in PR2.&lt;/b&gt;&lt;/p&gt;
      * 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,
+     * expand/collapse only when the toggle tool button is clicked.  When set to false,
      * {@link #hideCollapseTool} should be false also.
      */
     titleCollapse : true,
+
 <span id='Ext-layout-container-Accordion-cfg-hideCollapseTool'>    /**
 </span>     * @cfg {Boolean} hideCollapseTool
-     * True to hide the contained Panels' collapse/expand toggle buttons, false to display them (defaults to false).
+     * True to hide the contained Panels' collapse/expand toggle buttons, false to display them.
      * When set to true, {@link #titleCollapse} is automatically set to &lt;code&gt;true&lt;/code&gt;.
      */
     hideCollapseTool : false,
+
 <span id='Ext-layout-container-Accordion-cfg-collapseFirst'>    /**
 </span>     * @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).
+     * in the contained Panels' title bars, false to render it last.
      */
     collapseFirst : false,
+
 <span id='Ext-layout-container-Accordion-cfg-animate'>    /**
 </span>     * @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 &lt;code&gt;true&lt;/code&gt;). Note: The layout performs animated collapsing
+     * close directly with no animation. Note: The layout performs animated collapsing
      * and expanding, &lt;i&gt;not&lt;/i&gt; the child Panels.
      */
     animate : true,
 <span id='Ext-layout-container-Accordion-cfg-activeOnTop'>    /**
 </span>     * @cfg {Boolean} activeOnTop
-     * &lt;p&gt;&lt;b&gt;Not implemented in PR4.&lt;/b&gt;&lt;/p&gt;
-     * &lt;p&gt;Only valid when {@link #multi&quot; is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
+     * Only valid when {@link #multi} is `false` and {@link #animate} is `false`.
+     *
      * 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. &lt;b&gt;This is NOT compatible with &quot;animate:true&quot;&lt;/b&gt; (defaults to false).
+     * false to keep the panels in the rendered order.
      */
     activeOnTop : false,
 <span id='Ext-layout-container-Accordion-cfg-multi'>    /**
 </span>     * @cfg {Boolean} multi
-     * Defaults to &lt;code&gt;false&lt;/code&gt;. Set to &lt;code&gt;true&lt;/code&gt; to enable multiple accordion items to be open at once.
+     * Set to &lt;code&gt;true&lt;/code&gt; to enable multiple accordion items to be open at once.
      */
     multi: false,
 
@@ -135,7 +141,7 @@ Ext.define('Ext.layout.container.Accordion', {
 
         me.callParent(arguments);
         if (me.fill) {
-            if (!me.owner.el.dom.style.height) {
+            if (!(me.owner.el.dom.style.height || me.getLayoutTargetSize().height)) {
                 return false;
             }
         } else {
@@ -151,8 +157,7 @@ Ext.define('Ext.layout.container.Accordion', {
             i = 0,
             comp,
             targetSize = me.getLayoutTargetSize(),
-            renderedPanels = [],
-            border;
+            renderedPanels = [];
 
         for (; i &lt; ln; i++) {
             comp = items[i];
@@ -174,7 +179,6 @@ Ext.define('Ext.layout.container.Accordion', {
                 delete comp.hideHeader;
                 comp.collapsible = true;
                 comp.title = comp.title || '&amp;#160;';
-                comp.setBorder(false);
 
                 // Set initial sizes
                 comp.width = targetSize.width;
@@ -187,18 +191,26 @@ Ext.define('Ext.layout.container.Accordion', {
                         comp.collapsed = true;
                     }
                     // Otherwise expand the first item with collapsed explicitly configured as false
-                    else if (comp.collapsed === false) {
+                    else if (comp.hasOwnProperty('collapsed') &amp;&amp; comp.collapsed === false) {
                         comp.flex = 1;
                         me.expandedItem = i;
                     } else {
                         comp.collapsed = true;
                     }
+                    // If we are fitting, then intercept expand/collapse requests.
+                    me.owner.mon(comp, {
+                        show: me.onComponentShow,
+                        beforeexpand: me.onComponentExpand,
+                        beforecollapse: me.onComponentCollapse,
+                        scope: me
+                    });
                 } else {
                     delete comp.flex;
                     comp.animCollapse = me.initialAnimate;
                     comp.autoHeight = true;
                     comp.autoScroll = false;
                 }
+                comp.border = comp.collapsed;
             }
         }
 
@@ -206,15 +218,15 @@ Ext.define('Ext.layout.container.Accordion', {
         if (ln &amp;&amp; me.expandedItem === undefined) {
             me.expandedItem = 0;
             comp = items[0];
-            comp.collapsed = false;
+            comp.collapsed = comp.border = false;
             if (me.fill) {
                 comp.flex = 1;
             }
         }
-        
+
         // Render all Panels.
         me.callParent(arguments);
-                
+
         // Postprocess rendered Panels.
         ln = renderedPanels.length;
         for (i = 0; i &lt; ln; i++) {
@@ -225,24 +237,13 @@ Ext.define('Ext.layout.container.Accordion', {
 
             comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
             comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
-            
-            // If we are fitting, then intercept expand/collapse requests. 
-            if (me.fill) {
-                me.owner.mon(comp, {
-                    show: me.onComponentShow,
-                    beforeexpand: me.onComponentExpand,
-                    beforecollapse: me.onComponentCollapse,
-                    scope: me
-                });
-            }
         }
     },
 
     onLayout: function() {
         var me = this;
-        
-        me.updatePanelClasses();
-                
+
+
         if (me.fill) {
             me.callParent(arguments);
         } else {
@@ -260,24 +261,33 @@ Ext.define('Ext.layout.container.Accordion', {
                 }
             }
         }
-        
+        me.updatePanelClasses();
+
         return me;
     },
-    
+
     updatePanelClasses: function() {
         var children = this.getLayoutItems(),
             ln = children.length,
             siblingCollapsed = true,
             i, child;
-            
+
         for (i = 0; i &lt; ln; i++) {
             child = children[i];
-            if (!siblingCollapsed) {
-                child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
+
+            // Fix for EXTJSIV-3724. Windows only.
+            // Collapsing the Psnel's el to a size which only allows a single hesder to be visible, scrolls the header out of view.
+            if (Ext.isWindows) {
+                child.el.dom.scrollTop = 0;
             }
-            else {
+
+            if (siblingCollapsed) {
                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
             }
+            else {
+                child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
+            }
+
             if (i + 1 == ln &amp;&amp; child.collapsed) {
                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
             }
@@ -287,6 +297,21 @@ Ext.define('Ext.layout.container.Accordion', {
             siblingCollapsed = child.collapsed;
         }
     },
+    
+    animCallback: function(){
+        Ext.Array.forEach(this.toCollapse, function(comp){
+            comp.fireEvent('collapse', comp);
+        });
+        
+        Ext.Array.forEach(this.toExpand, function(comp){
+            comp.fireEvent('expand', comp);
+        });    
+    },
+    
+    setupEvents: function(){
+        this.toCollapse = [];
+        this.toExpand = [];    
+    },
 
     // When a Component expands, adjust the heights of the other Components to be just enough to accommodate
     // their headers.
@@ -298,6 +323,7 @@ Ext.define('Ext.layout.container.Accordion', {
             i = 0,
             comp;
 
+        me.setupEvents();
         for (; i &lt; len; i++) {
             comp = it[i];
             if (comp === toExpand &amp;&amp; comp.collapsed) {
@@ -306,9 +332,14 @@ Ext.define('Ext.layout.container.Accordion', {
                 me.setCollapsed(comp);
             }
         }
-        
+
         me.animate = me.initialAnimate;
-        me.layout();
+        if (me.activeOnTop) {
+            // insert will trigger a layout
+            me.owner.insert(0, toExpand); 
+        } else {
+            me.layout();
+        }
         me.animate = false;
         return false;
     },
@@ -318,6 +349,7 @@ Ext.define('Ext.layout.container.Accordion', {
             toExpand = comp.next() || comp.prev(),
             expanded = me.multi ? me.owner.query('&gt;panel:not([collapsed])') : [];
 
+        me.setupEvents();
         // If we are allowing multi, and the &quot;toCollapse&quot; component is NOT the only expanded Component,
         // then ask the box layout to collapse it to its header.
         if (me.multi) {
@@ -328,7 +360,7 @@ Ext.define('Ext.layout.container.Accordion', {
             if (expanded.length === 1 &amp;&amp; expanded[0] === comp) {
                 me.setExpanded(toExpand);
             }
-            
+
             me.animate = me.initialAnimate;
             me.layout();
             me.animate = false;
@@ -366,7 +398,11 @@ Ext.define('Ext.layout.container.Accordion', {
         comp.el.setHeight(comp.height);
         comp.collapsed = true;
         delete comp.flex;
-        comp.fireEvent('collapse', comp);
+        if (this.initialAnimate) {
+            this.toCollapse.push(comp);
+        } else {
+            comp.fireEvent('collapse', comp);
+        }
         if (comp.collapseTool) {
             comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
         }
@@ -393,7 +429,11 @@ Ext.define('Ext.layout.container.Accordion', {
         comp.flex = 1;
         comp.removeCls(comp.collapsedCls);
         comp.header.removeCls(comp.collapsedHeaderCls);
-        comp.fireEvent('expand', comp);
+         if (this.initialAnimate) {
+            this.toExpand.push(comp);
+        } else {
+            comp.fireEvent('expand', comp);
+        }
         if (comp.collapseTool) {
             comp.collapseTool.setType('collapse-' + comp.collapseDirection);
         }