4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-layout-container-Accordion'>/**
19 </span> * @class Ext.layout.container.Accordion
20 * @extends Ext.layout.container.VBox
21 * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
22 * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
23 * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.panel.Panel</b> may be used in an accordion layout Container.</p>
24 * {@img Ext.layout.container.Accordion/Ext.layout.container.Accordion.png Ext.layout.container.Accordion container layout}
25 * <p>Example usage:</p>
26 * <pre><code>
27 Ext.create('Ext.panel.Panel', {
28 title: 'Accordion Layout',
33 // applied to each contained panel
34 bodyStyle: 'padding:15px'
37 // layout-specific configs go here
44 html: 'Panel content!'
47 html: 'Panel content!'
50 html: 'Panel content!'
52 renderTo: Ext.getBody()
54 </code></pre>
56 Ext.define('Ext.layout.container.Accordion', {
57 extend: 'Ext.layout.container.VBox',
58 alias: ['layout.accordion'],
59 alternateClassName: 'Ext.layout.AccordionLayout',
63 <span id='Ext-layout-container-Accordion-cfg-fill'> /**
64 </span> * @cfg {Boolean} fill
65 * True to adjust the active item's height to fill the available space in the container, false to use the
66 * item's current height, or auto height if not explicitly set (defaults to true).
69 <span id='Ext-layout-container-Accordion-cfg-autoWidth'> /**
70 </span> * @cfg {Boolean} autoWidth
71 * <p><b>This config is ignored in ExtJS 4.x.</b></p>
72 * Child Panels have their width actively managed to fit within the accordion's width.
75 <span id='Ext-layout-container-Accordion-cfg-titleCollapse'> /**
76 </span> * @cfg {Boolean} titleCollapse
77 * <p><b>Not implemented in PR2.</b></p>
78 * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
79 * expand/collapse only when the toggle tool button is clicked (defaults to true). When set to false,
80 * {@link #hideCollapseTool} should be false also.
83 <span id='Ext-layout-container-Accordion-cfg-hideCollapseTool'> /**
84 </span> * @cfg {Boolean} hideCollapseTool
85 * True to hide the contained Panels' collapse/expand toggle buttons, false to display them (defaults to false).
86 * When set to true, {@link #titleCollapse} is automatically set to <code>true</code>.
88 hideCollapseTool : false,
89 <span id='Ext-layout-container-Accordion-cfg-collapseFirst'> /**
90 </span> * @cfg {Boolean} collapseFirst
91 * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
92 * in the contained Panels' title bars, false to render it last (defaults to false).
94 collapseFirst : false,
95 <span id='Ext-layout-container-Accordion-cfg-animate'> /**
96 </span> * @cfg {Boolean} animate
97 * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
98 * close directly with no animation (defaults to <code>true</code>). Note: The layout performs animated collapsing
99 * and expanding, <i>not</i> the child Panels.
102 <span id='Ext-layout-container-Accordion-cfg-activeOnTop'> /**
103 </span> * @cfg {Boolean} activeOnTop
104 * <p><b>Not implemented in PR4.</b></p>
105 * <p>Only valid when {@link #multi" is <code>false</code>.</p>
106 * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
107 * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
110 <span id='Ext-layout-container-Accordion-cfg-multi'> /**
111 </span> * @cfg {Boolean} multi
112 * Defaults to <code>false</code>. Set to <code>true</code> to enable multiple accordion items to be open at once.
116 constructor: function() {
119 me.callParent(arguments);
121 // animate flag must be false during initial render phase so we don't get animations.
122 me.initialAnimate = me.animate;
125 // Child Panels are not absolutely positioned if we are not filling, so use a different itemCls.
126 if (me.fill === false) {
127 me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
131 // Cannot lay out a fitting accordion before we have been allocated a height.
132 // So during render phase, layout will not be performed.
133 beforeLayout: function() {
136 me.callParent(arguments);
138 if (!me.owner.el.dom.style.height || !me.getLayoutTargetSize().height) {
142 me.owner.componentLayout.monitorChildren = false;
144 me.owner.setAutoScroll(true);
148 renderItems : function(items, target) {
153 targetSize = me.getLayoutTargetSize(),
157 for (; i < ln; i++) {
159 if (!comp.rendered) {
160 renderedPanels.push(comp);
162 // Set up initial properties for Panels in an accordion.
163 if (me.collapseFirst) {
164 comp.collapseFirst = me.collapseFirst;
166 if (me.hideCollapseTool) {
167 comp.hideCollapseTool = me.hideCollapseTool;
168 comp.titleCollapse = true;
170 else if (me.titleCollapse) {
171 comp.titleCollapse = me.titleCollapse;
174 delete comp.hideHeader;
175 comp.collapsible = true;
176 comp.title = comp.title || '&#160;';
179 comp.width = targetSize.width;
184 // If there is an expanded item, all others must be rendered collapsed.
185 if (me.expandedItem !== undefined) {
186 comp.collapsed = true;
188 // Otherwise expand the first item with collapsed explicitly configured as false
189 else if (comp.hasOwnProperty('collapsed') && comp.collapsed === false) {
193 comp.collapsed = true;
195 // If we are fitting, then intercept expand/collapse requests.
197 show: me.onComponentShow,
198 beforeexpand: me.onComponentExpand,
199 beforecollapse: me.onComponentCollapse,
204 comp.animCollapse = me.initialAnimate;
205 comp.autoHeight = true;
206 comp.autoScroll = false;
211 // If no collapsed:false Panels found, make the first one expanded.
212 if (ln && me.expandedItem === undefined) {
215 comp.collapsed = false;
221 // Render all Panels.
222 me.callParent(arguments);
224 // Postprocess rendered Panels.
225 ln = renderedPanels.length;
226 for (i = 0; i < ln; i++) {
227 comp = renderedPanels[i];
229 // Delete the dimension property so that our align: 'stretch' processing manages the width from here
232 comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
233 comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
237 onLayout: function() {
242 me.callParent(arguments);
244 var targetSize = me.getLayoutTargetSize(),
245 items = me.getVisibleItems(),
249 for (; i < len; i++) {
251 if (comp.collapsed) {
252 items[i].setWidth(targetSize.width);
254 items[i].setSize(null, null);
258 me.updatePanelClasses();
263 updatePanelClasses: function() {
264 var children = this.getLayoutItems(),
265 ln = children.length,
266 siblingCollapsed = true,
269 for (i = 0; i < ln; i++) {
272 if (siblingCollapsed) {
273 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
276 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
279 if (i + 1 == ln && child.collapsed) {
280 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
283 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
285 siblingCollapsed = child.collapsed;
289 // When a Component expands, adjust the heights of the other Components to be just enough to accommodate
291 // The expanded Component receives the only flex value, and so gets all remaining space.
292 onComponentExpand: function(toExpand) {
294 it = me.owner.items.items,
299 for (; i < len; i++) {
301 if (comp === toExpand && comp.collapsed) {
302 me.setExpanded(comp);
303 } else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
304 me.setCollapsed(comp);
308 me.animate = me.initialAnimate;
314 onComponentCollapse: function(comp) {
316 toExpand = comp.next() || comp.prev(),
317 expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
319 // If we are allowing multi, and the "toCollapse" component is NOT the only expanded Component,
320 // then ask the box layout to collapse it to its header.
322 me.setCollapsed(comp);
324 // If the collapsing Panel is the only expanded one, expand the following Component.
325 // All this is handling fill: true, so there must be at least one expanded,
326 if (expanded.length === 1 && expanded[0] === comp) {
327 me.setExpanded(toExpand);
330 me.animate = me.initialAnimate;
334 // Not allowing multi: expand the next sibling if possible, prev sibling if we collapsed the last
336 me.onComponentExpand(toExpand);
341 onComponentShow: function(comp) {
342 // Showing a Component means that you want to see it, so expand it.
343 this.onComponentExpand(comp);
346 setCollapsed: function(comp) {
347 var otherDocks = comp.getDockedItems(),
349 len = otherDocks.length,
352 // Hide all docked items except the header
353 comp.hiddenDocked = [];
354 for (; i < len; i++) {
355 dockItem = otherDocks[i];
356 if ((dockItem !== comp.header) && !dockItem.hidden) {
357 dockItem.hidden = true;
358 comp.hiddenDocked.push(dockItem);
361 comp.addCls(comp.collapsedCls);
362 comp.header.addCls(comp.collapsedHeaderCls);
363 comp.height = comp.header.getHeight();
364 comp.el.setHeight(comp.height);
365 comp.collapsed = true;
367 comp.fireEvent('collapse', comp);
368 if (comp.collapseTool) {
369 comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
373 setExpanded: function(comp) {
374 var otherDocks = comp.hiddenDocked,
375 len = otherDocks ? otherDocks.length : 0,
378 // Show temporarily hidden docked items
379 for (; i < len; i++) {
380 otherDocks[i].show();
383 // If it was an initial native collapse which hides the body
384 if (!comp.body.isVisible()) {
387 delete comp.collapsed;
389 delete comp.componentLayout.lastComponentSize;
390 comp.suspendLayout = false;
392 comp.removeCls(comp.collapsedCls);
393 comp.header.removeCls(comp.collapsedHeaderCls);
394 comp.fireEvent('expand', comp);
395 if (comp.collapseTool) {
396 comp.collapseTool.setType('collapse-' + comp.collapseDirection);
398 comp.setAutoScroll(comp.initialConfig.autoScroll);