Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Accordion.html
diff --git a/docs/source/Accordion.html b/docs/source/Accordion.html
new file mode 100644 (file)
index 0000000..2b43997
--- /dev/null
@@ -0,0 +1,385 @@
+<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><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;
+ */
+Ext.define('Ext.layout.container.Accordion', {
+    extend: 'Ext.layout.container.VBox',
+    alias: ['layout.accordion'],
+    alternateClassName: 'Ext.layout.AccordionLayout',
+    
+    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).
+     */
+    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.
+     */
+    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,
+     * {@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).
+     * 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).
+     */
+    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
+     * 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;
+     * 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).
+     */
+    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.
+     */
+    multi: false,
+
+    constructor: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        // animate flag must be false during initial render phase so we don't get animations.
+        me.initialAnimate = me.animate;
+        me.animate = false;
+
+        // Child Panels are not absolutely positioned if we are not filling, so use a different itemCls.
+        if (me.fill === false) {
+            me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
+        }
+    },
+
+    // Cannot lay out a fitting accordion before we have been allocated a height.
+    // So during render phase, layout will not be performed.
+    beforeLayout: function() {
+        var me = this;
+
+        me.callParent(arguments);
+        if (me.fill) {
+            if (!me.owner.el.dom.style.height) {
+                return false;
+            }
+        } else {
+            me.owner.componentLayout.monitorChildren = false;
+            me.autoSize = true;
+            me.owner.setAutoScroll(true);
+        }
+    },
+
+    renderItems : function(items, target) {
+        var me = this,
+            ln = items.length,
+            i = 0,
+            comp,
+            targetSize = me.getLayoutTargetSize(),
+            renderedPanels = [],
+            border;
+
+        for (; i &lt; ln; i++) {
+            comp = items[i];
+            if (!comp.rendered) {
+                renderedPanels.push(comp);
+
+                // Set up initial properties for Panels in an accordion.
+                if (me.collapseFirst) {
+                    comp.collapseFirst = me.collapseFirst;
+                }
+                if (me.hideCollapseTool) {
+                    comp.hideCollapseTool = me.hideCollapseTool;
+                    comp.titleCollapse = true;
+                }
+                else if (me.titleCollapse) {
+                    comp.titleCollapse = me.titleCollapse;
+                }
+
+                delete comp.hideHeader;
+                comp.collapsible = true;
+                comp.title = comp.title || '&amp;#160;';
+                comp.setBorder(false);
+
+                // Set initial sizes
+                comp.width = targetSize.width;
+                if (me.fill) {
+                    delete comp.height;
+                    delete comp.flex;
+
+                    // If there is an expanded item, all others must be rendered collapsed.
+                    if (me.expandedItem !== undefined) {
+                        comp.collapsed = true;
+                    }
+                    // Otherwise expand the first item with collapsed explicitly configured as false
+                    else if (comp.collapsed === false) {
+                        comp.flex = 1;
+                        me.expandedItem = i;
+                    } else {
+                        comp.collapsed = true;
+                    }
+                } else {
+                    delete comp.flex;
+                    comp.animCollapse = me.initialAnimate;
+                    comp.autoHeight = true;
+                    comp.autoScroll = false;
+                }
+            }
+        }
+
+        // If no collapsed:false Panels found, make the first one expanded.
+        if (ln &amp;&amp; me.expandedItem === undefined) {
+            me.expandedItem = 0;
+            comp = items[0];
+            comp.collapsed = 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++) {
+            comp = renderedPanels[i];
+
+            // Delete the dimension property so that our align: 'stretch' processing manages the width from here
+            delete comp.width;
+
+            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 {
+            var targetSize = me.getLayoutTargetSize(),
+                items = me.getVisibleItems(),
+                len = items.length,
+                i = 0, comp;
+
+            for (; i &lt; len; i++) {
+                comp = items[i];
+                if (comp.collapsed) {
+                    items[i].setWidth(targetSize.width);
+                } else {
+                    items[i].setSize(null, null);
+                }
+            }
+        }
+        
+        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');
+            }
+            else {
+                child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
+            }
+            if (i + 1 == ln &amp;&amp; child.collapsed) {
+                child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
+            }
+            else {
+                child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
+            }
+            siblingCollapsed = child.collapsed;
+        }
+    },
+
+    // When a Component expands, adjust the heights of the other Components to be just enough to accommodate
+    // their headers.
+    // The expanded Component receives the only flex value, and so gets all remaining space.
+    onComponentExpand: function(toExpand) {
+        var me = this,
+            it = me.owner.items.items,
+            len = it.length,
+            i = 0,
+            comp;
+
+        for (; i &lt; len; i++) {
+            comp = it[i];
+            if (comp === toExpand &amp;&amp; comp.collapsed) {
+                me.setExpanded(comp);
+            } else if (!me.multi &amp;&amp; (comp.rendered &amp;&amp; comp.header.rendered &amp;&amp; comp !== toExpand &amp;&amp; !comp.collapsed)) {
+                me.setCollapsed(comp);
+            }
+        }
+        
+        me.animate = me.initialAnimate;
+        me.layout();
+        me.animate = false;
+        return false;
+    },
+
+    onComponentCollapse: function(comp) {
+        var me = this,
+            toExpand = comp.next() || comp.prev(),
+            expanded = me.multi ? me.owner.query('&gt;panel:not([collapsed])') : [];
+
+        // 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) {
+            me.setCollapsed(comp);
+
+            // If the collapsing Panel is the only expanded one, expand the following Component.
+            // All this is handling fill: true, so there must be at least one expanded,
+            if (expanded.length === 1 &amp;&amp; expanded[0] === comp) {
+                me.setExpanded(toExpand);
+            }
+            
+            me.animate = me.initialAnimate;
+            me.layout();
+            me.animate = false;
+        }
+        // Not allowing multi: expand the next sibling if possible, prev sibling if we collapsed the last
+        else if (toExpand) {
+            me.onComponentExpand(toExpand);
+        }
+        return false;
+    },
+
+    onComponentShow: function(comp) {
+        // Showing a Component means that you want to see it, so expand it.
+        this.onComponentExpand(comp);
+    },
+
+    setCollapsed: function(comp) {
+        var otherDocks = comp.getDockedItems(),
+            dockItem,
+            len = otherDocks.length,
+            i = 0;
+
+        // Hide all docked items except the header
+        comp.hiddenDocked = [];
+        for (; i &lt; len; i++) {
+            dockItem = otherDocks[i];
+            if ((dockItem !== comp.header) &amp;&amp; !dockItem.hidden) {
+                dockItem.hidden = true;
+                comp.hiddenDocked.push(dockItem);
+            }
+        }
+        comp.addCls(comp.collapsedCls);
+        comp.header.addCls(comp.collapsedHeaderCls);
+        comp.height = comp.header.getHeight();
+        comp.el.setHeight(comp.height);
+        comp.collapsed = true;
+        delete comp.flex;
+        comp.fireEvent('collapse', comp);
+        if (comp.collapseTool) {
+            comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
+        }
+    },
+
+    setExpanded: function(comp) {
+        var otherDocks = comp.hiddenDocked,
+            len = otherDocks ? otherDocks.length : 0,
+            i = 0;
+
+        // Show temporarily hidden docked items
+        for (; i &lt; len; i++) {
+            otherDocks[i].hidden = false;
+        }
+
+        // If it was an initial native collapse which hides the body
+        if (!comp.body.isVisible()) {
+            comp.body.show();
+        }
+        delete comp.collapsed;
+        delete comp.height;
+        delete comp.componentLayout.lastComponentSize;
+        comp.suspendLayout = false;
+        comp.flex = 1;
+        comp.removeCls(comp.collapsedCls);
+        comp.header.removeCls(comp.collapsedHeaderCls);
+        comp.fireEvent('expand', comp);
+        if (comp.collapseTool) {
+            comp.collapseTool.setType('collapse-' + comp.collapseDirection);
+        }
+        comp.setAutoScroll(comp.initialConfig.autoScroll);
+    }
+});</pre></pre></body></html>
\ No newline at end of file