Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Panel3.html
1 <!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-panel.Panel-method-constructor'><span id='Ext-panel.Panel'>/**
2 </span></span> * @class Ext.panel.Panel
3  * @extends Ext.panel.AbstractPanel
4  * &lt;p&gt;Panel is a container that has specific functionality and structural components that make
5  * it the perfect building block for application-oriented user interfaces.&lt;/p&gt;
6  * &lt;p&gt;Panels are, by virtue of their inheritance from {@link Ext.container.Container}, capable
7  * of being configured with a {@link Ext.container.Container#layout layout}, and containing child Components.&lt;/p&gt;
8  * &lt;p&gt;When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.container.Container#add adding} Components
9  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
10  * those child elements need to be sized using one of Ext&amp;#39;s built-in &lt;code&gt;&lt;b&gt;{@link Ext.container.Container#layout layout}&lt;/b&gt;&lt;/code&gt; schemes. By
11  * default, Panels use the {@link Ext.layout.container.Auto Auto} scheme. This simply renders
12  * child components, appending them one after the other inside the Container, and &lt;b&gt;does not apply any sizing&lt;/b&gt;
13  * at all.&lt;/p&gt;
14  * {@img Ext.panel.Panel/panel.png Panel components}
15  * &lt;p&gt;A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
16  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
17  * information).&lt;/p&gt;
18  * &lt;p&gt;Panel also provides built-in {@link #collapsible collapsible, expandable} and {@link #closable} behavior.
19  * Panels can be easily dropped into any {@link Ext.container.Container Container} or layout, and the
20  * layout and rendering pipeline is {@link Ext.container.Container#add completely managed by the framework}.&lt;/p&gt;
21  * &lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; By default, the &lt;code&gt;{@link #closable close}&lt;/code&gt; header tool &lt;i&gt;destroys&lt;/i&gt; the Panel resulting in removal of the Panel
22  * and the destruction of any descendant Components. This makes the Panel object, and all its descendants &lt;b&gt;unusable&lt;/b&gt;. To enable the close
23  * tool to simply &lt;i&gt;hide&lt;/i&gt; a Panel for later re-use, configure the Panel with &lt;b&gt;&lt;code&gt;{@link #closeAction closeAction: 'hide'}&lt;/code&gt;&lt;/b&gt;.&lt;/p&gt;
24  * &lt;p&gt;Usually, Panels are used as constituents within an application, in which case, they would be used as child items of Containers,
25  * and would themselves use Ext.Components as child {@link #items}. However to illustrate simply rendering a Panel into the document,
26  * here&amp;#39;s how to do it:&lt;pre&gt;&lt;code&gt;
27 Ext.create('Ext.panel.Panel', {
28     title: 'Hello',
29     width: 200,
30     html: '&amp;lt;p&amp;gt;World!&amp;lt;/p&amp;gt;',
31     renderTo: document.body
32 });
33 &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
34  * &lt;p&gt;A more realistic scenario is a Panel created to house input fields which will not be rendered, but used as a constituent part of a Container:&lt;pre&gt;&lt;code&gt;
35 var filterPanel = Ext.create('Ext.panel.Panel', {
36     bodyPadding: 5,  // Don&amp;#39;t want content to crunch against the borders
37     title: 'Filters',
38     items: [{
39         xtype: 'datefield',
40         fieldLabel: 'Start date'
41     }, {
42         xtype: 'datefield',
43         fieldLabel: 'End date'
44     }]
45 });
46 &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
47  * &lt;p&gt;Note that the Panel above is not configured to render into the document, nor is it configured with a size or position. In a real world scenario,
48  * the Container into which the Panel is added will use a {@link #layout} to render, size and position its child Components.&lt;/p&gt;
49  * &lt;p&gt;Panels will often use specific {@link #layout}s to provide an application with shape and structure by containing and arranging child
50  * Components: &lt;pre&gt;&lt;code&gt;
51 var resultsPanel = Ext.create('Ext.panel.Panel', {
52     title: 'Results',
53     width: 600,
54     height: 400,
55     renderTo: document.body,
56     layout: {
57         type: 'vbox',       // Arrange child items vertically
58         align: 'stretch',    // Each takes up full width
59         padding: 5
60     },
61     items: [{               // Results grid specified as a config object with an xtype of 'grid'
62         xtype: 'grid',
63         columns: [{header: 'Column One'}],            // One header just for show. There&amp;#39;s no data,
64         store: Ext.create('Ext.data.ArrayStore', {}), // A dummy empty data store
65         flex: 1                                       // Use 1/3 of Container&amp;#39;s height (hint to Box layout)
66     }, {
67         xtype: 'splitter'   // A splitter between the two child items
68     }, {                    // Details Panel specified as a config object (no xtype defaults to 'panel').
69         title: 'Details',
70         bodyPadding: 5,
71         items: [{
72             fieldLabel: 'Data item',
73             xtype: 'textfield'
74         }], // An array of form fields
75         flex: 2             // Use 2/3 of Container&amp;#39;s height (hint to Box layout)
76     }]
77 });
78 &lt;/code&gt;&lt;/pre&gt;
79  * The example illustrates one possible method of displaying search results. The Panel contains a grid with the resulting data arranged
80  * in rows. Each selected row may be displayed in detail in the Panel below. The {@link Ext.layout.container.VBox vbox} layout is used
81  * to arrange the two vertically. It is configured to stretch child items horizontally to full width. Child items may either be configured
82  * with a numeric height, or with a &lt;code&gt;flex&lt;/code&gt; value to distribute available space proportionately.&lt;/p&gt;
83  * &lt;p&gt;This Panel itself may be a child item of, for exaple, a {@link Ext.tab.Panel} which will size its child items to fit within its
84  * content area.&lt;/p&gt;
85  * &lt;p&gt;Using these techniques, as long as the &lt;b&gt;layout&lt;/b&gt; is chosen and configured correctly, an application may have any level of
86  * nested containment, all dynamically sized according to configuration, the user&amp;#39;s preference and available browser size.&lt;/p&gt;
87  * @constructor
88  * @param {Object} config The config object
89  * @xtype panel
90  */
91 Ext.define('Ext.panel.Panel', {
92     extend: 'Ext.panel.AbstractPanel',
93     requires: [
94         'Ext.panel.Header',
95         'Ext.fx.Anim',
96         'Ext.util.KeyMap',
97         'Ext.panel.DD',
98         'Ext.XTemplate',
99         'Ext.layout.component.Dock'
100     ],
101     alias: 'widget.panel',
102     alternateClassName: 'Ext.Panel',
103
104 <span id='Ext-panel.Panel-cfg-collapsedCls'>    /**
105 </span>     * @cfg {String} collapsedCls
106      * A CSS class to add to the panel&amp;#39;s element after it has been collapsed (defaults to
107      * &lt;code&gt;'collapsed'&lt;/code&gt;).
108      */
109     collapsedCls: 'collapsed',
110
111 <span id='Ext-panel.Panel-cfg-animCollapse'>    /**
112 </span>     * @cfg {Boolean} animCollapse
113      * &lt;code&gt;true&lt;/code&gt; to animate the transition when the panel is collapsed, &lt;code&gt;false&lt;/code&gt; to skip the
114      * animation (defaults to &lt;code&gt;true&lt;/code&gt; if the {@link Ext.fx.Anim} class is available, otherwise &lt;code&gt;false&lt;/code&gt;).
115      * May also be specified as the animation duration in milliseconds.
116      */
117     animCollapse: Ext.enableFx,
118
119 <span id='Ext-panel.Panel-cfg-minButtonWidth'>    /**
120 </span>     * @cfg {Number} minButtonWidth
121      * Minimum width of all footer toolbar buttons in pixels (defaults to &lt;tt&gt;75&lt;/tt&gt;). If set, this will
122      * be used as the default value for the &lt;tt&gt;{@link Ext.button.Button#minWidth}&lt;/tt&gt; config of
123      * each Button added to the &lt;b&gt;footer toolbar&lt;/b&gt; via the {@link #fbar} or {@link #buttons} configurations.
124      * It will be ignored for buttons that have a minWidth configured some other way, e.g. in their own config
125      * object or via the {@link Ext.container.Container#config-defaults defaults} of their parent container.
126      */
127     minButtonWidth: 75,
128
129 <span id='Ext-panel.Panel-cfg-collapsed'>    /**
130 </span>     * @cfg {Boolean} collapsed
131      * &lt;code&gt;true&lt;/code&gt; to render the panel collapsed, &lt;code&gt;false&lt;/code&gt; to render it expanded (defaults to
132      * &lt;code&gt;false&lt;/code&gt;).
133      */
134     collapsed: false,
135
136 <span id='Ext-panel.Panel-cfg-collapseFirst'>    /**
137 </span>     * @cfg {Boolean} collapseFirst
138      * &lt;code&gt;true&lt;/code&gt; to make sure the collapse/expand toggle button always renders first (to the left of)
139      * any other tools in the panel&amp;#39;s title bar, &lt;code&gt;false&lt;/code&gt; to render it last (defaults to &lt;code&gt;true&lt;/code&gt;).
140      */
141     collapseFirst: true,
142
143 <span id='Ext-panel.Panel-cfg-hideCollapseTool'>    /**
144 </span>     * @cfg {Boolean} hideCollapseTool
145      * &lt;code&gt;true&lt;/code&gt; to hide the expand/collapse toggle button when &lt;code&gt;{@link #collapsible} == true&lt;/code&gt;,
146      * &lt;code&gt;false&lt;/code&gt; to display it (defaults to &lt;code&gt;false&lt;/code&gt;).
147      */
148     hideCollapseTool: false,
149
150 <span id='Ext-panel.Panel-cfg-titleCollapse'>    /**
151 </span>     * @cfg {Boolean} titleCollapse
152      * &lt;code&gt;true&lt;/code&gt; to allow expanding and collapsing the panel (when &lt;code&gt;{@link #collapsible} = true&lt;/code&gt;)
153      * by clicking anywhere in the header bar, &lt;code&gt;false&lt;/code&gt;) to allow it only by clicking to tool button
154      * (defaults to &lt;code&gt;false&lt;/code&gt;)).
155      */
156     titleCollapse: false,
157
158 <span id='Ext-panel.Panel-cfg-collapseMode'>    /**
159 </span>     * @cfg {String} collapseMode
160      * &lt;p&gt;&lt;b&gt;Important: this config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.&lt;/b&gt;&lt;/p&gt;
161      * &lt;p&gt;When &lt;i&gt;not&lt;/i&gt; a direct child item of a {@link Ext.layout.container.Border border layout}, then the Panel&amp;#39;s header remains visible, and the body is collapsed to zero dimensions.
162      * If the Panel has no header, then a new header (orientated correctly depending on the {@link #collapseDirection}) will be inserted to show a the title and a re-expand tool.&lt;/p&gt;
163      * &lt;p&gt;When a child item of a {@link Ext.layout.container.Border border layout}, this config has two options:
164      * &lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
165      * &lt;li&gt;&lt;b&gt;&lt;code&gt;undefined/omitted&lt;/code&gt;&lt;/b&gt;&lt;div class=&quot;sub-desc&quot;&gt;When collapsed, a placeholder {@link Ext.panel.Header Header} is injected into the layout to represent the Panel
166      * and to provide a UI with a Tool to allow the user to re-expand the Panel.&lt;/div&gt;&lt;/li&gt;
167      * &lt;li&gt;&lt;b&gt;&lt;code&gt;header&lt;/code&gt;&lt;/b&gt; : &lt;div class=&quot;sub-desc&quot;&gt;The Panel collapses to leave its header visible as when not inside a {@link Ext.layout.container.Border border layout}.&lt;/div&gt;&lt;/li&gt;
168      * &lt;/ul&gt;&lt;/div&gt;&lt;/p&gt;
169      */
170
171 <span id='Ext-panel.Panel-cfg-placeholder'>    /**
172 </span>     * @cfg {Mixed} placeholder
173      * &lt;p&gt;&lt;b&gt;Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}
174      * when not using the &lt;code&gt;'header'&lt;/code&gt; {@link #collapseMode}.&lt;/b&gt;&lt;/p&gt;
175      * &lt;p&gt;&lt;b&gt;Optional.&lt;/b&gt; A Component (or config object for a Component) to show in place of this Panel when this Panel is collapsed by a
176      * {@link Ext.layout.container.Border border layout}. Defaults to a generated {@link Ext.panel.Header Header}
177      * containing a {@link Ext.panel.Tool Tool} to re-expand the Panel.&lt;/p&gt;
178      */
179
180 <span id='Ext-panel.Panel-cfg-floatable'>    /**
181 </span>     * @cfg {Boolean} floatable
182      * &lt;p&gt;&lt;b&gt;Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.&lt;/b&gt;&lt;/p&gt;
183      * &lt;tt&gt;true&lt;/tt&gt; to allow clicking a collapsed Panel&amp;#39;s {@link #placeholder} to display the Panel floated
184      * above the layout, &lt;tt&gt;false&lt;/tt&gt; to force the user to fully expand a collapsed region by
185      * clicking the expand button to see it again (defaults to &lt;tt&gt;true&lt;/tt&gt;).
186      */
187     floatable: true,
188
189 <span id='Ext-panel.Panel-cfg-collapsible'>    /**
190 </span>     * @cfg {Boolean} collapsible
191      * &lt;p&gt;True to make the panel collapsible and have an expand/collapse toggle Tool added into
192      * the header tool button area. False to keep the panel sized either statically, or by an owning layout manager, with no toggle Tool (defaults to false).&lt;/p&gt;
193      * See {@link #collapseMode} and {@link #collapseDirection}
194      */
195     collapsible: false,
196
197 <span id='Ext-panel.Panel-cfg-collapseDirection'>    /**
198 </span>     * @cfg {Boolean} collapseDirection
199      * &lt;p&gt;The direction to collapse the Panel when the toggle button is clicked.&lt;/p&gt;
200      * &lt;p&gt;Defaults to the {@link #headerPosition}&lt;/p&gt;
201      * &lt;p&gt;&lt;b&gt;Important: This config is &lt;u&gt;ignored&lt;/u&gt; for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.&lt;/b&gt;&lt;/p&gt;
202      * &lt;p&gt;Specify as &lt;code&gt;'top'&lt;/code&gt;, &lt;code&gt;'bottom'&lt;/code&gt;, &lt;code&gt;'left'&lt;/code&gt; or &lt;code&gt;'right'&lt;/code&gt;.&lt;/p&gt;
203      */
204
205 <span id='Ext-panel.Panel-cfg-closable'>    /**
206 </span>     * @cfg {Boolean} closable
207      * &lt;p&gt;True to display the 'close' tool button and allow the user to close the window, false to
208      * hide the button and disallow closing the window (defaults to &lt;code&gt;false&lt;/code&gt;).&lt;/p&gt;
209      * &lt;p&gt;By default, when close is requested by clicking the close button in the header, the {@link #close}
210      * method will be called. This will &lt;i&gt;{@link Ext.Component#destroy destroy}&lt;/i&gt; the Panel and its content
211      * meaning that it may not be reused.&lt;/p&gt;
212      * &lt;p&gt;To make closing a Panel &lt;i&gt;hide&lt;/i&gt; the Panel so that it may be reused, set
213      * {@link #closeAction} to 'hide'.&lt;/p&gt;
214      */
215     closable: false,
216
217 <span id='Ext-panel.Panel-cfg-closeAction'>    /**
218 </span>     * @cfg {String} closeAction
219      * &lt;p&gt;The action to take when the close header tool is clicked:
220      * &lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
221      * &lt;li&gt;&lt;b&gt;&lt;code&gt;'{@link #destroy}'&lt;/code&gt;&lt;/b&gt; : &lt;b&gt;Default&lt;/b&gt;&lt;div class=&quot;sub-desc&quot;&gt;
222      * {@link #destroy remove} the window from the DOM and {@link Ext.Component#destroy destroy}
223      * it and all descendant Components. The window will &lt;b&gt;not&lt;/b&gt; be available to be
224      * redisplayed via the {@link #show} method.
225      * &lt;/div&gt;&lt;/li&gt;
226      * &lt;li&gt;&lt;b&gt;&lt;code&gt;'{@link #hide}'&lt;/code&gt;&lt;/b&gt; : &lt;div class=&quot;sub-desc&quot;&gt;
227      * {@link #hide} the window by setting visibility to hidden and applying negative offsets.
228      * The window will be available to be redisplayed via the {@link #show} method.
229      * &lt;/div&gt;&lt;/li&gt;
230      * &lt;/ul&gt;&lt;/div&gt;
231      * &lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; This behavior has changed! setting *does* affect the {@link #close} method
232      * which will invoke the approriate closeAction.
233      */
234     closeAction: 'destroy',
235
236 <span id='Ext-panel.Panel-cfg-dockedItems'>    /**
237 </span>     * @cfg {Object/Array} dockedItems
238      * A component or series of components to be added as docked items to this panel.
239      * The docked items can be docked to either the top, right, left or bottom of a panel.
240      * This is typically used for things like toolbars or tab bars:
241      * &lt;pre&gt;&lt;code&gt;
242 var panel = new Ext.panel.Panel({
243     dockedItems: [{
244         xtype: 'toolbar',
245         dock: 'top',
246         items: [{
247             text: 'Docked to the top'
248         }]
249     }]
250 });&lt;/pre&gt;&lt;/code&gt;
251      */
252
253 <span id='Ext-panel.Panel-cfg-preventHeader'>    /**
254 </span>      * @cfg {Boolean} preventHeader Prevent a Header from being created and shown. Defaults to false.
255       */
256     preventHeader: false,
257
258 <span id='Ext-panel.Panel-cfg-headerPosition'>     /**
259 </span>      * @cfg {String} headerPosition Specify as &lt;code&gt;'top'&lt;/code&gt;, &lt;code&gt;'bottom'&lt;/code&gt;, &lt;code&gt;'left'&lt;/code&gt; or &lt;code&gt;'right'&lt;/code&gt;. Defaults to &lt;code&gt;'top'&lt;/code&gt;.
260       */
261     headerPosition: 'top',
262
263 <span id='Ext-panel.Panel-cfg-frame'>     /**
264 </span>     * @cfg {Boolean} frame
265      * True to apply a frame to the panel.
266      */
267     frame: false,
268
269 <span id='Ext-panel.Panel-cfg-frameHeader'>    /**
270 </span>     * @cfg {Boolean} frameHeader
271      * True to apply a frame to the panel panels header (if 'frame' is true).
272      */
273     frameHeader: true,
274
275 <span id='Ext-panel.Panel-cfg-tools'>    /**
276 </span>     * @cfg {Array} tools
277      * An array of {@link Ext.panel.Tool} configs/instances to be added to the header tool area. The tools are stored as child
278      * components of the header container. They can be accessed using {@link #down} and {#query}, as well as the other
279      * component methods. The toggle tool is automatically created if {@link #collapsible} is set to true.
280      * &lt;p&gt;Note that, apart from the toggle tool which is provided when a panel is collapsible, these
281      * tools only provide the visual button. Any required functionality must be provided by adding
282      * handlers that implement the necessary behavior.&lt;/p&gt;
283      * &lt;p&gt;Example usage:&lt;/p&gt;
284      * &lt;pre&gt;&lt;code&gt;
285 tools:[{
286     type:'refresh',
287     qtip: 'Refresh form Data',
288     // hidden:true,
289     handler: function(event, toolEl, panel){
290         // refresh logic
291     }
292 },
293 {
294     type:'help',
295     qtip: 'Get Help',
296     handler: function(event, toolEl, panel){
297         // show help here
298     }
299 }]
300 &lt;/code&gt;&lt;/pre&gt;
301      */
302
303
304     initComponent: function() {
305         var me = this,
306             cls;
307
308         me.addEvents(
309 <span id='Ext-panel.Panel-event-titlechange'>        /**
310 </span>         * @event titlechange
311          * Fires after the Panel title has been set or changed.
312          * @param {Ext.panel.Panel} p the Panel which has been resized.
313          * @param {String} newTitle The new title.
314          * @param {String} oldTitle The previous panel title.
315          */
316             'titlechange',
317 <span id='Ext-panel.Panel-event-iconchange'>        /**
318 </span>         * @event iconchange
319          * Fires after the Panel iconCls has been set or changed.
320          * @param {Ext.panel.Panel} p the Panel which has been resized.
321          * @param {String} newIconCls The new iconCls.
322          * @param {String} oldIconCls The previous panel iconCls.
323          */
324             'iconchange'
325         );
326
327         if (me.unstyled) {
328             me.setUI('plain');
329         }
330
331         if (me.frame) {
332             me.setUI('default-framed');
333         }
334
335         me.callParent();
336
337         me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
338
339         // Backwards compatibility
340         me.bridgeToolbars();
341     },
342
343     setBorder: function(border) {
344         // var me     = this,
345         //     method = (border === false || border === 0) ? 'addClsWithUI' : 'removeClsWithUI';
346         // 
347         // me.callParent(arguments);
348         // 
349         // if (me.collapsed) {
350         //     me[method](me.collapsedCls + '-noborder');
351         // }
352         // 
353         // if (me.header) {
354         //     me.header.setBorder(border);
355         //     if (me.collapsed) {
356         //         me.header[method](me.collapsedCls + '-noborder');
357         //     }
358         // }
359         
360         this.callParent(arguments);
361     },
362
363     beforeDestroy: function() {
364         Ext.destroy(
365             this.ghostPanel,
366             this.dd
367         );
368         this.callParent();
369     },
370
371     initAria: function() {
372         this.callParent();
373         this.initHeaderAria();
374     },
375
376     initHeaderAria: function() {
377         var me = this,
378             el = me.el,
379             header = me.header;
380         if (el &amp;&amp; header) {
381             el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
382         }
383     },
384
385     getHeader: function() {
386         return this.header;
387     },
388
389 <span id='Ext-panel.Panel-method-setTitle'>    /**
390 </span>     * Set a title for the panel&amp;#39;s header. See {@link Ext.panel.Header#title}.
391      * @param {String} newTitle
392      */
393     setTitle: function(newTitle) {
394         var me = this,
395         oldTitle = this.title;
396
397         me.title = newTitle;
398         if (me.header) {
399             me.header.setTitle(newTitle);
400         } else {
401             me.updateHeader();
402         }
403
404         if (me.reExpander) {
405             me.reExpander.setTitle(newTitle);
406         }
407         me.fireEvent('titlechange', me, newTitle, oldTitle);
408     },
409
410 <span id='Ext-panel.Panel-method-setIconCls'>    /**
411 </span>     * Set the iconCls for the panel&amp;#39;s header. See {@link Ext.panel.Header#iconCls}.
412      * @param {String} newIconCls
413      */
414     setIconCls: function(newIconCls) {
415         var me = this,
416             oldIconCls = me.iconCls;
417
418         me.iconCls = newIconCls;
419         var header = me.header;
420         if (header) {
421             header.setIconCls(newIconCls);
422         }
423         me.fireEvent('iconchange', me, newIconCls, oldIconCls);
424     },
425
426     bridgeToolbars: function() {
427         var me = this,
428             fbar,
429             fbarDefaults,
430             minButtonWidth = me.minButtonWidth;
431
432         function initToolbar (toolbar, pos) {
433             if (Ext.isArray(toolbar)) {
434                 toolbar = {
435                     xtype: 'toolbar',
436                     items: toolbar
437                 };
438             }
439             else if (!toolbar.xtype) {
440                 toolbar.xtype = 'toolbar';
441             }
442             toolbar.dock = pos;
443             if (pos == 'left' || pos == 'right') {
444                 toolbar.vertical = true;
445             }
446             return toolbar;
447         }
448
449         // Backwards compatibility
450
451 <span id='Ext-panel.Panel-cfg-tbar'>        /**
452 </span>         * @cfg {Object/Array} tbar
453
454 Convenience method. Short for 'Top Bar'.
455
456     tbar: [
457       { xtype: 'button', text: 'Button 1' }
458     ]
459
460 is equivalent to
461
462     dockedItems: [{
463         xtype: 'toolbar',
464         dock: 'top',
465         items: [
466             { xtype: 'button', text: 'Button 1' }
467         ]
468     }]
469
470          * @markdown
471          */
472         if (me.tbar) {
473             me.addDocked(initToolbar(me.tbar, 'top'));
474             me.tbar = null;
475         }
476
477 <span id='Ext-panel.Panel-cfg-bbar'>        /**
478 </span>         * @cfg {Object/Array} bbar
479
480 Convenience method. Short for 'Bottom Bar'.
481
482     bbar: [
483       { xtype: 'button', text: 'Button 1' }
484     ]
485
486 is equivalent to
487
488     dockedItems: [{
489         xtype: 'toolbar',
490         dock: 'bottom',
491         items: [
492             { xtype: 'button', text: 'Button 1' }
493         ]
494     }]
495
496          * @markdown
497          */
498         if (me.bbar) {
499             me.addDocked(initToolbar(me.bbar, 'bottom'));
500             me.bbar = null;
501         }
502
503 <span id='Ext-panel.Panel-cfg-buttons'>        /**
504 </span>         * @cfg {Object/Array} buttons
505
506 Convenience method used for adding buttons docked to the bottom right of the panel. This is a
507 synonym for the {@link #fbar} config.
508
509     buttons: [
510       { text: 'Button 1' }
511     ]
512
513 is equivalent to
514
515     dockedItems: [{
516         xtype: 'toolbar',
517         dock: 'bottom',
518         defaults: {minWidth: {@link #minButtonWidth}},
519         items: [
520             { xtype: 'component', flex: 1 },
521             { xtype: 'button', text: 'Button 1' }
522         ]
523     }]
524
525 The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
526 each of the buttons in the buttons toolbar.
527
528          * @markdown
529          */
530         if (me.buttons) {
531             me.fbar = me.buttons;
532             me.buttons = null;
533         }
534
535 <span id='Ext-panel.Panel-cfg-fbar'>        /**
536 </span>         * @cfg {Object/Array} fbar
537
538 Convenience method used for adding items to the bottom right of the panel. Short for Footer Bar.
539
540     fbar: [
541       { type: 'button', text: 'Button 1' }
542     ]
543
544 is equivalent to
545
546     dockedItems: [{
547         xtype: 'toolbar',
548         dock: 'bottom',
549         defaults: {minWidth: {@link #minButtonWidth}},
550         items: [
551             { xtype: 'component', flex: 1 },
552             { xtype: 'button', text: 'Button 1' }
553         ]
554     }]
555
556 The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
557 each of the buttons in the fbar.
558
559          * @markdown
560          */
561         if (me.fbar) {
562             fbar = initToolbar(me.fbar, 'bottom');
563             fbar.ui = 'footer';
564
565             // Apply the minButtonWidth config to buttons in the toolbar
566             if (minButtonWidth) {
567                 fbarDefaults = fbar.defaults;
568                 fbar.defaults = function(config) {
569                     var defaults = fbarDefaults || {};
570                     if ((!config.xtype || config.xtype === 'button' || (config.isComponent &amp;&amp; config.isXType('button'))) &amp;&amp;
571                             !('minWidth' in defaults)) {
572                         defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
573                     }
574                     return defaults;
575                 };
576             }
577
578             fbar = me.addDocked(fbar)[0];
579             fbar.insert(0, {
580                 flex: 1,
581                 xtype: 'component',
582                 focusable: false
583             });
584             me.fbar = null;
585         }
586
587 <span id='Ext-panel.Panel-cfg-lbar'>        /**
588 </span>         * @cfg {Object/Array} lbar
589          *
590          * Convenience method. Short for 'Left Bar' (left-docked, vertical toolbar).
591          *
592          *    lbar: [
593          *      { xtype: 'button', text: 'Button 1' }
594          *    ]
595          *
596          * is equivalent to
597          *
598          *    dockedItems: [{
599          *        xtype: 'toolbar',
600          *        dock: 'left',
601          *        items: [
602          *            { xtype: 'button', text: 'Button 1' }
603          *        ]
604          *    }]
605          *
606          * @markdown
607          */
608         if (me.lbar) {
609             me.addDocked(initToolbar(me.lbar, 'left'));
610             me.lbar = null;
611         }
612
613 <span id='Ext-panel.Panel-cfg-rbar'>        /**
614 </span>         * @cfg {Object/Array} rbar
615          *
616          * Convenience method. Short for 'Right Bar' (right-docked, vertical toolbar).
617          *
618          *    rbar: [
619          *      { xtype: 'button', text: 'Button 1' }
620          *    ]
621          *
622          * is equivalent to
623          *
624          *    dockedItems: [{
625          *        xtype: 'toolbar',
626          *        dock: 'right',
627          *        items: [
628          *            { xtype: 'button', text: 'Button 1' }
629          *        ]
630          *    }]
631          *
632          * @markdown
633          */
634         if (me.rbar) {
635             me.addDocked(initToolbar(me.rbar, 'right'));
636             me.rbar = null;
637         }
638     },
639
640 <span id='Ext-panel.Panel-method-initTools'>    /**
641 </span>     * @private
642      * Tools are a Panel-specific capabilty.
643      * Panel uses initTools. Subclasses may contribute tools by implementing addTools.
644      */
645     initTools: function() {
646         var me = this;
647
648         me.tools = me.tools || [];
649
650         // Add a collapse tool unless configured to not show a collapse tool
651         // or to not even show a header.
652         if (me.collapsible &amp;&amp; !(me.hideCollapseTool || me.header === false)) {
653             me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
654             me.collapseTool = me.expandTool = me.createComponent({
655                 xtype: 'tool',
656                 type: 'collapse-' + me.collapseDirection,
657                 expandType: me.getOppositeDirection(me.collapseDirection),
658                 handler: me.toggleCollapse,
659                 scope: me
660             });
661
662             // Prepend collapse tool is configured to do so.
663             if (me.collapseFirst) {
664                 me.tools.unshift(me.collapseTool);
665             }
666         }
667
668         // Add subclass-specific tools.
669         me.addTools();
670
671         // Make Panel closable.
672         if (me.closable) {
673             me.addClsWithUI('closable');
674             me.addTool({
675                 type: 'close',
676                 handler: Ext.Function.bind(me.close, this, [])
677             });
678         }
679
680         // Append collapse tool if needed.
681         if (me.collapseTool &amp;&amp; !me.collapseFirst) {
682             me.tools.push(me.collapseTool);
683         }
684     },
685
686 <span id='Ext-panel.Panel-property-addTools'>    /**
687 </span>     * @private
688      * Template method to be implemented in subclasses to add their tools after the collapsible tool.
689      */
690     addTools: Ext.emptyFn,
691
692 <span id='Ext-panel.Panel-method-close'>    /**
693 </span>     * &lt;p&gt;Closes the Panel. By default, this method, removes it from the DOM, {@link Ext.Component#destroy destroy}s
694      * the Panel object and all its descendant Components. The {@link #beforeclose beforeclose}
695      * event is fired before the close happens and will cancel the close action if it returns false.&lt;p&gt;
696      * &lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; This method is not affected by the {@link #closeAction} setting which
697      * only affects the action triggered when clicking the {@link #closable 'close' tool in the header}.
698      * To hide the Panel without destroying it, call {@link #hide}.&lt;/p&gt;
699      */
700     close: function() {
701         if (this.fireEvent('beforeclose', this) !== false) {
702             this.doClose();
703         }
704     },
705
706     // private
707     doClose: function() {
708         this.fireEvent('close', this);
709         this[this.closeAction]();
710     },
711
712     onRender: function(ct, position) {
713         var me = this,
714             topContainer;
715
716         // Add class-specific header tools.
717         // Panel adds collapsible and closable.
718         me.initTools();
719
720         // Dock the header/title
721         me.updateHeader();
722
723         // If initially collapsed, collapsed flag must indicate true current state at this point.
724         // Do collapse after the first time the Panel's structure has been laid out.
725         if (me.collapsed) {
726             me.collapsed = false;
727             topContainer = me.findLayoutController();
728             if (!me.hidden &amp;&amp; topContainer) {
729                 topContainer.on({
730                     afterlayout: function() {
731                         me.collapse(null, false, true);
732                     },
733                     single: true
734                 });
735             } else {
736                 me.afterComponentLayout = function() {
737                     delete me.afterComponentLayout;
738                     Ext.getClass(me).prototype.afterComponentLayout.apply(me, arguments);
739                     me.collapse(null, false, true);
740                 };
741             }
742         }
743
744         // Call to super after adding the header, to prevent an unnecessary re-layout
745         me.callParent(arguments);
746     },
747
748 <span id='Ext-panel.Panel-method-updateHeader'>    /**
749 </span>     * Create, hide, or show the header component as appropriate based on the current config.
750      * @private
751      * @param {Boolean} force True to force the the header to be created
752      */
753     updateHeader: function(force) {
754         var me = this,
755             header = me.header,
756             title = me.title,
757             tools = me.tools;
758
759         if (!me.preventHeader &amp;&amp; (force || title || (tools &amp;&amp; tools.length))) {
760             if (!header) {
761                 header = me.header = Ext.create('Ext.panel.Header', {
762                     title       : title,
763                     orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
764                     dock        : me.headerPosition || 'top',
765                     textCls     : me.headerTextCls,
766                     iconCls     : me.iconCls,
767                     baseCls     : me.baseCls + '-header',
768                     tools       : tools,
769                     ui          : me.ui,
770                     indicateDrag: me.draggable,
771                     border      : me.border,
772                     frame       : me.frame &amp;&amp; me.frameHeader,
773                     ignoreParentFrame : me.frame || me.overlapHeader,
774                     ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
775                     listeners   : me.collapsible &amp;&amp; me.titleCollapse ? {
776                         click: me.toggleCollapse,
777                         scope: me
778                     } : null
779                 });
780                 me.addDocked(header, 0);
781
782                 // Reference the Header's tool array.
783                 // Header injects named references.
784                 me.tools = header.tools;
785             }
786             header.show();
787             me.initHeaderAria();
788         } else if (header) {
789             header.hide();
790         }
791     },
792
793     // inherit docs
794     setUI: function(ui) {
795         var me = this;
796
797         me.callParent(arguments);
798
799         if (me.header) {
800             me.header.setUI(ui);
801         }
802     },
803
804     // private
805     getContentTarget: function() {
806         return this.body;
807     },
808
809     getTargetEl: function() {
810         return this.body || this.frameBody || this.el;
811     },
812
813     addTool: function(tool) {
814         this.tools.push(tool);
815         var header = this.header;
816         if (header) {
817             header.addTool(tool);
818         }
819         this.updateHeader();
820     },
821
822     getOppositeDirection: function(d) {
823         var c = Ext.Component;
824         switch (d) {
825             case c.DIRECTION_TOP:
826                 return c.DIRECTION_BOTTOM;
827             case c.DIRECTION_RIGHT:
828                 return c.DIRECTION_LEFT;
829             case c.DIRECTION_BOTTOM:
830                 return c.DIRECTION_TOP;
831             case c.DIRECTION_LEFT:
832                 return c.DIRECTION_RIGHT;
833         }
834     },
835
836 <span id='Ext-panel.Panel-method-collapse'>    /**
837 </span>     * Collapses the panel body so that the body becomes hidden. Docked Components parallel to the
838      * border towards which the collapse takes place will remain visible.  Fires the {@link #beforecollapse} event which will
839      * cancel the collapse action if it returns false.
840      * @param {Number} direction. The direction to collapse towards. Must be one of&lt;ul&gt;
841      * &lt;li&gt;Ext.Component.DIRECTION_TOP&lt;/li&gt;
842      * &lt;li&gt;Ext.Component.DIRECTION_RIGHT&lt;/li&gt;
843      * &lt;li&gt;Ext.Component.DIRECTION_BOTTOM&lt;/li&gt;
844      * &lt;li&gt;Ext.Component.DIRECTION_LEFT&lt;/li&gt;&lt;/ul&gt;
845      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
846      * {@link #animCollapse} panel config)
847      * @return {Ext.panel.Panel} this
848      */
849     collapse: function(direction, animate, /* private - passed if called at render time */ internal) {
850         var me = this,
851             c = Ext.Component,
852             height = me.getHeight(),
853             width = me.getWidth(),
854             frameInfo,
855             newSize = 0,
856             dockedItems = me.dockedItems.items,
857             dockedItemCount = dockedItems.length,
858             i = 0,
859             comp,
860             pos,
861             anim = {
862                 from: {
863                     height: height,
864                     width: width
865                 },
866                 to: {
867                     height: height,
868                     width: width
869                 },
870                 listeners: {
871                     afteranimate: me.afterCollapse,
872                     scope: me
873                 },
874                 duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
875             },
876             reExpander,
877             reExpanderOrientation,
878             reExpanderDock,
879             getDimension,
880             setDimension,
881             collapseDimension;
882
883         if (!direction) {
884             direction = me.collapseDirection;
885         }
886
887         // If internal (Called because of initial collapsed state), then no animation, and no events.
888         if (internal) {
889             animate = false;
890         } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
891             return false;
892         }
893
894         reExpanderDock = direction;
895         me.expandDirection = me.getOppositeDirection(direction);
896
897         // Track docked items which we hide during collapsed state
898         me.hiddenDocked = [];
899
900         switch (direction) {
901             case c.DIRECTION_TOP:
902             case c.DIRECTION_BOTTOM:
903                 me.expandedSize = me.getHeight();
904                 reExpanderOrientation = 'horizontal';
905                 collapseDimension = 'height';
906                 getDimension = 'getHeight';
907                 setDimension = 'setHeight';
908
909                 // Collect the height of the visible header.
910                 // Hide all docked items except the header.
911                 // Hide *ALL* docked items if we're going to end up hiding the whole Panel anyway
912                 for (; i &lt; dockedItemCount; i++) {
913                     comp = dockedItems[i];
914                     if (comp.isVisible()) {
915                         if (comp.isHeader &amp;&amp; (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
916                             reExpander = comp;
917                         } else {
918                             me.hiddenDocked.push(comp);
919                         }
920                     }
921                 }
922
923                 if (direction == Ext.Component.DIRECTION_BOTTOM) {
924                     pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
925                     anim.from.top = pos;
926                 }
927                 break;
928
929             case c.DIRECTION_LEFT:
930             case c.DIRECTION_RIGHT:
931                 me.expandedSize = me.getWidth();
932                 reExpanderOrientation = 'vertical';
933                 collapseDimension = 'width';
934                 getDimension = 'getWidth';
935                 setDimension = 'setWidth';
936
937                 // Collect the height of the visible header.
938                 // Hide all docked items except the header.
939                 // Hide *ALL* docked items if we're going to end up hiding the whole Panel anyway
940                 for (; i &lt; dockedItemCount; i++) {
941                     comp = dockedItems[i];
942                     if (comp.isVisible()) {
943                         if (comp.isHeader &amp;&amp; (comp.dock == 'left' || comp.dock == 'right')) {
944                             reExpander = comp;
945                         } else {
946                             me.hiddenDocked.push(comp);
947                         }
948                     }
949                 }
950
951                 if (direction == Ext.Component.DIRECTION_RIGHT) {
952                     pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
953                     anim.from.left = pos;
954                 }
955                 break;
956
957             default:
958                 throw('Panel collapse must be passed a valid Component collapse direction');
959         }
960
961         // No scrollbars when we shrink this Panel
962         // And no laying out of any children... we're effectively *hiding* the body
963         me.setAutoScroll(false);
964         me.suspendLayout = true;
965         me.body.setVisibilityMode(Ext.core.Element.DISPLAY);
966
967         // Disable toggle tool during animated collapse
968         if (animate &amp;&amp; me.collapseTool) {
969             me.collapseTool.disable();
970         }
971
972         // Add the collapsed class now, so that collapsed CSS rules are applied before measurements are taken.
973         me.addClsWithUI(me.collapsedCls);
974         // if (me.border === false) {
975         //     me.addClsWithUI(me.collapsedCls + '-noborder');
976         // }
977
978         // We found a header: Measure it to find the collapse-to size.
979         if (reExpander) {
980             //we must add the collapsed cls to the header and then remove to get the proper height
981             reExpander.addClsWithUI(me.collapsedCls);
982             reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
983             if (me.border &amp;&amp; (!me.frame || (me.frame &amp;&amp; Ext.supports.CSS3BorderRadius))) {
984                 reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
985             }
986
987             frameInfo = reExpander.getFrameInfo();
988                         
989             //get the size
990             newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
991
992             //and remove
993             reExpander.removeClsWithUI(me.collapsedCls);
994             reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);              
995             if (me.border &amp;&amp; (!me.frame || (me.frame &amp;&amp; Ext.supports.CSS3BorderRadius))) {
996                 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
997             }
998         }
999         // No header: Render and insert a temporary one, and then measure it.
1000         else {
1001             reExpander = {
1002                 hideMode: 'offsets',
1003                 temporary: true,
1004                 title: me.title,
1005                 orientation: reExpanderOrientation,
1006                 dock: reExpanderDock,
1007                 textCls: me.headerTextCls,
1008                 iconCls: me.iconCls,
1009                 baseCls: me.baseCls + '-header',
1010                 ui: me.ui,
1011                 frame: me.frame &amp;&amp; me.frameHeader,
1012                 ignoreParentFrame: me.frame || me.overlapHeader,
1013                 indicateDrag: me.draggable,
1014                 cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
1015                 renderTo: me.el
1016             };
1017             reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
1018                 xtype: 'tool',
1019                 type: 'expand-' + me.expandDirection,
1020                 handler: me.toggleCollapse,
1021                 scope: me
1022             }];
1023
1024             // Capture the size of the re-expander.
1025             // For vertical headers in IE6 and IE7, this will be sized by a CSS rule in _panel.scss
1026             reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
1027             newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
1028             reExpander.hide();
1029
1030             // Insert the new docked item
1031             me.insertDocked(0, reExpander);
1032         }
1033
1034         me.reExpander = reExpander;
1035         me.reExpander.addClsWithUI(me.collapsedCls);
1036         me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
1037         if (me.border &amp;&amp; (!me.frame || (me.frame &amp;&amp; Ext.supports.CSS3BorderRadius))) {
1038             me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
1039         }
1040
1041         // If collapsing right or down, we'll be also animating the left or top.
1042         if (direction == Ext.Component.DIRECTION_RIGHT) {
1043             anim.to.left = pos + (width - newSize);
1044         } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
1045             anim.to.top = pos + (height - newSize);
1046         }
1047
1048         // Animate to the new size
1049         anim.to[collapseDimension] = newSize;
1050
1051         // Remove any flex config before we attempt to collapse.
1052         me.savedFlex = me.flex;
1053         me.savedMinWidth = me.minWidth;
1054         me.savedMinHeight = me.minHeight;
1055         me.minWidth = 0;
1056         me.minHeight = 0;
1057         delete me.flex;
1058
1059         if (animate) {
1060             me.animate(anim);
1061         } else {
1062             me.setSize(anim.to.width, anim.to.height);
1063             if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
1064                 me.setPosition(anim.to.left, anim.to.top);
1065             }
1066             me.afterCollapse(false, internal);
1067         }
1068         return me;
1069     },
1070
1071     afterCollapse: function(animated, internal) {
1072         var me = this,
1073             i = 0,
1074             l = me.hiddenDocked.length;
1075
1076         me.minWidth = me.savedMinWidth;
1077         me.minHeight = me.savedMinHeight;
1078
1079         me.body.hide();
1080         for (; i &lt; l; i++) {
1081             me.hiddenDocked[i].hide();
1082         }
1083         if (me.reExpander) {
1084             me.reExpander.updateFrame();
1085             me.reExpander.show();
1086         }
1087         me.collapsed = true;
1088
1089         if (!internal) {
1090             me.doComponentLayout();
1091         }
1092
1093         if (me.resizer) {
1094             me.resizer.disable();
1095         }
1096
1097         // If me Panel was configured with a collapse tool in its header, flip it's type
1098         if (me.collapseTool) {
1099             me.collapseTool.setType('expand-' + me.expandDirection);
1100         }
1101         if (!internal) {
1102             me.fireEvent('collapse', me);
1103         }
1104
1105         // Re-enable the toggle tool after an animated collapse
1106         if (animated &amp;&amp; me.collapseTool) {
1107             me.collapseTool.enable();
1108         }
1109     },
1110
1111 <span id='Ext-panel.Panel-method-expand'>    /**
1112 </span>     * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
1113      * cancel the expand action if it returns false.
1114      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
1115      * {@link #animCollapse} panel config)
1116      * @return {Ext.panel.Panel} this
1117      */
1118     expand: function(animate) {
1119         if (!this.collapsed || this.fireEvent('beforeexpand', this, animate) === false) {
1120             return false;
1121         }
1122         var me = this,
1123             i = 0,
1124             l = me.hiddenDocked.length,
1125             direction = me.expandDirection,
1126             height = me.getHeight(),
1127             width = me.getWidth(),
1128             pos, anim, satisfyJSLint;
1129
1130         // Disable toggle tool during animated expand
1131         if (animate &amp;&amp; me.collapseTool) {
1132             me.collapseTool.disable();
1133         }
1134
1135         // Show any docked items that we hid on collapse
1136         // And hide the injected reExpander Header
1137         for (; i &lt; l; i++) {
1138             me.hiddenDocked[i].hidden = false;
1139             me.hiddenDocked[i].el.show();
1140         }
1141         if (me.reExpander) {
1142             if (me.reExpander.temporary) {
1143                 me.reExpander.hide();
1144             } else {
1145                 me.reExpander.removeClsWithUI(me.collapsedCls);
1146                 me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
1147                 if (me.border &amp;&amp; (!me.frame || (me.frame &amp;&amp; Ext.supports.CSS3BorderRadius))) {
1148                     me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
1149                 }
1150                 me.reExpander.updateFrame();
1151             }
1152         }
1153
1154         // If me Panel was configured with a collapse tool in its header, flip it's type
1155         if (me.collapseTool) {
1156             me.collapseTool.setType('collapse-' + me.collapseDirection);
1157         }
1158
1159         // Unset the flag before the potential call to calculateChildBox to calculate our newly flexed size
1160         me.collapsed = false;
1161
1162         // Collapsed means body element was hidden
1163         me.body.show();
1164
1165         // Remove any collapsed styling before any animation begins
1166         me.removeClsWithUI(me.collapsedCls);
1167         // if (me.border === false) {
1168         //     me.removeClsWithUI(me.collapsedCls + '-noborder');
1169         // }
1170
1171         anim = {
1172             to: {
1173             },
1174             from: {
1175                 height: height,
1176                 width: width
1177             },
1178             listeners: {
1179                 afteranimate: me.afterExpand,
1180                 scope: me
1181             }
1182         };
1183
1184         if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
1185
1186             // If autoHeight, measure the height now we have shown the body element.
1187             if (me.autoHeight) {
1188                 me.setCalculatedSize(me.width, null);
1189                 anim.to.height = me.getHeight();
1190
1191                 // Must size back down to collapsed for the animation.
1192                 me.setCalculatedSize(me.width, anim.from.height);
1193             }
1194             // If we were flexed, then we can't just restore to the saved size.
1195             // We must restore to the currently correct, flexed size, so we much ask the Box layout what that is.
1196             else if (me.savedFlex) {
1197                 me.flex = me.savedFlex;
1198                 anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
1199                 delete me.flex;
1200             }
1201             // Else, restore to saved height
1202             else {
1203                 anim.to.height = me.expandedSize;
1204             }
1205
1206             // top needs animating upwards
1207             if (direction == Ext.Component.DIRECTION_TOP) {
1208                 pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
1209                 anim.from.top = pos;
1210                 anim.to.top = pos - (anim.to.height - height);
1211             }
1212         } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
1213
1214             // If autoWidth, measure the width now we have shown the body element.
1215             if (me.autoWidth) {
1216                 me.setCalculatedSize(null, me.height);
1217                 anim.to.width = me.getWidth();
1218
1219                 // Must size back down to collapsed for the animation.
1220                 me.setCalculatedSize(anim.from.width, me.height);
1221             }
1222             // If we were flexed, then we can't just restore to the saved size.
1223             // We must restore to the currently correct, flexed size, so we much ask the Box layout what that is.
1224             else if (me.savedFlex) {
1225                 me.flex = me.savedFlex;
1226                 anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
1227                 delete me.flex;
1228             }
1229             // Else, restore to saved width
1230             else {
1231                 anim.to.width = me.expandedSize;
1232             }
1233
1234             // left needs animating leftwards
1235             if (direction == Ext.Component.DIRECTION_LEFT) {
1236                 pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
1237                 anim.from.left = pos;
1238                 anim.to.left = pos - (anim.to.width - width);
1239             }
1240         }
1241
1242         if (animate) {
1243             me.animate(anim);
1244         } else {
1245             me.setSize(anim.to.width, anim.to.height);
1246             if (anim.to.x) {
1247                 me.setLeft(anim.to.x);
1248             }
1249             if (anim.to.y) {
1250                 me.setTop(anim.to.y);
1251             }
1252             me.afterExpand(false);
1253         }
1254
1255         return me;
1256     },
1257
1258     afterExpand: function(animated) {
1259         var me = this;
1260         me.setAutoScroll(me.initialConfig.autoScroll);
1261
1262         // Restored to a calculated flex. Delete the set width and height properties so that flex works from now on.
1263         if (me.savedFlex) {
1264             me.flex = me.savedFlex;
1265             delete me.savedFlex;
1266             delete me.width;
1267             delete me.height;
1268         }
1269
1270         // Reinstate layout out after Panel has re-expanded
1271         delete me.suspendLayout;
1272         if (animated &amp;&amp; me.ownerCt) {
1273             me.ownerCt.doLayout();
1274         }
1275
1276         if (me.resizer) {
1277             me.resizer.enable();
1278         }
1279
1280         me.fireEvent('expand', me);
1281
1282         // Re-enable the toggle tool after an animated expand
1283         if (animated &amp;&amp; me.collapseTool) {
1284             me.collapseTool.enable();
1285         }
1286     },
1287
1288 <span id='Ext-panel.Panel-method-toggleCollapse'>    /**
1289 </span>     * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
1290      * @return {Ext.panel.Panel} this
1291      */
1292     toggleCollapse: function() {
1293         if (this.collapsed) {
1294             this.expand(this.animCollapse);
1295         } else {
1296             this.collapse(this.collapseDirection, this.animCollapse);
1297         }
1298         return this;
1299     },
1300
1301     // private
1302     getKeyMap : function(){
1303         if(!this.keyMap){
1304             this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
1305         }
1306         return this.keyMap;
1307     },
1308
1309     // private
1310     initDraggable : function(){
1311 <span id='Ext-panel.Panel-property-dd'>        /**
1312 </span>         * &lt;p&gt;If this Panel is configured {@link #draggable}, this property will contain
1313          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.&lt;/p&gt;
1314          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
1315          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
1316          * @type Ext.dd.DragSource.
1317          * @property dd
1318          */
1319         this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
1320     },
1321
1322     // private - helper function for ghost
1323     ghostTools : function() {
1324         var tools = [],
1325             origTools = this.initialConfig.tools;
1326
1327         if (origTools) {
1328             Ext.each(origTools, function(tool) {
1329                 // Some tools can be full components, and copying them into the ghost
1330                 // actually removes them from the owning panel. You could also potentially
1331                 // end up with duplicate DOM ids as well. To avoid any issues we just make
1332                 // a simple bare-minimum clone of each tool for ghosting purposes.
1333                 tools.push({
1334                     type: tool.type
1335                 });
1336             });
1337         }
1338         else {
1339             tools = [{
1340                 type: 'placeholder'
1341             }];
1342         }
1343         return tools;
1344     },
1345
1346     // private - used for dragging
1347     ghost: function(cls) {
1348         var me = this,
1349             ghostPanel = me.ghostPanel,
1350             box = me.getBox();
1351
1352         if (!ghostPanel) {
1353             ghostPanel = Ext.create('Ext.panel.Panel', {
1354                 renderTo: document.body,
1355                 floating: {
1356                     shadow: false
1357                 },
1358                 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
1359                 title: me.title,
1360                 overlapHeader: me.overlapHeader,
1361                 headerPosition: me.headerPosition,
1362                 width: me.getWidth(),
1363                 height: me.getHeight(),
1364                 iconCls: me.iconCls,
1365                 baseCls: me.baseCls,
1366                 tools: me.ghostTools(),
1367                 cls: me.baseCls + '-ghost ' + (cls ||'')
1368             });
1369             me.ghostPanel = ghostPanel;
1370         }
1371         ghostPanel.floatParent = me.floatParent;
1372         if (me.floating) {
1373             ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
1374         } else {
1375             ghostPanel.toFront();
1376         }
1377         ghostPanel.el.show();
1378         ghostPanel.setPosition(box.x, box.y);
1379         ghostPanel.setSize(box.width, box.height);
1380         me.el.hide();
1381         if (me.floatingItems) {
1382             me.floatingItems.hide();
1383         }
1384         return ghostPanel;
1385     },
1386
1387     // private
1388     unghost: function(show, matchPosition) {
1389         var me = this;
1390         if (!me.ghostPanel) {
1391             return;
1392         }
1393         if (show !== false) {
1394             me.el.show();
1395             if (matchPosition !== false) {
1396                 me.setPosition(me.ghostPanel.getPosition());
1397             }
1398             if (me.floatingItems) {
1399                 me.floatingItems.show();
1400             }
1401             Ext.defer(me.focus, 10, me);
1402         }
1403         me.ghostPanel.el.hide();
1404     },
1405
1406     initResizable: function(resizable) {
1407         if (this.collapsed) {
1408             resizable.disabled = true;
1409         }
1410         this.callParent([resizable]);
1411     }
1412 });
1413 </pre></pre></body></html>