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