4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-panel-Panel'>/**
19 </span> * @class Ext.panel.Panel
20 * @extends Ext.panel.AbstractPanel
21 * <p>Panel is a container that has specific functionality and structural components that make
22 * it the perfect building block for application-oriented user interfaces.</p>
23 * <p>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.</p>
25 * <p>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&#39;s built-in <code><b>{@link Ext.container.Container#layout layout}</b></code> 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 <b>does not apply any sizing</b>
31 * {@img Ext.panel.Panel/panel.png Panel components}
32 * <p>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).</p>
35 * <p>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}.</p>
38 * <p><b>Note:</b> By default, the <code>{@link #closable close}</code> header tool <i>destroys</i> 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 <b>unusable</b>. To enable the close
40 * tool to simply <i>hide</i> a Panel for later re-use, configure the Panel with <b><code>{@link #closeAction closeAction: 'hide'}</code></b>.</p>
41 * <p>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&#39;s how to do it:<pre><code>
44 Ext.create('Ext.panel.Panel', {
47 html: '&lt;p&gt;World!&lt;/p&gt;',
48 renderTo: document.body
50 </code></pre></p>
51 * <p>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:<pre><code>
52 var filterPanel = Ext.create('Ext.panel.Panel', {
53 bodyPadding: 5, // Don&#39;t want content to crunch against the borders
57 fieldLabel: 'Start date'
60 fieldLabel: 'End date'
63 </code></pre></p>
64 * <p>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.</p>
66 * <p>Panels will often use specific {@link #layout}s to provide an application with shape and structure by containing and arranging child
67 * Components: <pre><code>
68 var resultsPanel = Ext.create('Ext.panel.Panel', {
72 renderTo: document.body,
74 type: 'vbox', // Arrange child items vertically
75 align: 'stretch', // Each takes up full width
78 items: [{ // Results grid specified as a config object with an xtype of 'grid'
80 columns: [{header: 'Column One'}], // One header just for show. There&#39;s no data,
81 store: Ext.create('Ext.data.ArrayStore', {}), // A dummy empty data store
82 flex: 1 // Use 1/3 of Container&#39;s height (hint to Box layout)
84 xtype: 'splitter' // A splitter between the two child items
85 }, { // Details Panel specified as a config object (no xtype defaults to 'panel').
89 fieldLabel: 'Data item',
91 }], // An array of form fields
92 flex: 2 // Use 2/3 of Container&#39;s height (hint to Box layout)
95 </code></pre>
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 <code>flex</code> value to distribute available space proportionately.</p>
100 * <p>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.</p>
102 * <p>Using these techniques, as long as the <b>layout</b> is chosen and configured correctly, an application may have any level of
103 * nested containment, all dynamically sized according to configuration, the user&#39;s preference and available browser size.</p>
105 Ext.define('Ext.panel.Panel', {
106 extend: 'Ext.panel.AbstractPanel',
113 'Ext.layout.component.Dock',
116 alias: 'widget.panel',
117 alternateClassName: 'Ext.Panel',
119 <span id='Ext-panel-Panel-cfg-collapsedCls'> /**
120 </span> * @cfg {String} collapsedCls
121 * A CSS class to add to the panel&#39;s element after it has been collapsed (defaults to
122 * <code>'collapsed'</code>).
124 collapsedCls: 'collapsed',
126 <span id='Ext-panel-Panel-cfg-animCollapse'> /**
127 </span> * @cfg {Boolean} animCollapse
128 * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
129 * animation (defaults to <code>true</code> if the {@link Ext.fx.Anim} class is available, otherwise <code>false</code>).
130 * May also be specified as the animation duration in milliseconds.
132 animCollapse: Ext.enableFx,
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 <tt>75</tt>). If set, this will
137 * be used as the default value for the <tt>{@link Ext.button.Button#minWidth}</tt> config of
138 * each Button added to the <b>footer toolbar</b> 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.
144 <span id='Ext-panel-Panel-cfg-collapsed'> /**
145 </span> * @cfg {Boolean} collapsed
146 * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
147 * <code>false</code>).
151 <span id='Ext-panel-Panel-cfg-collapseFirst'> /**
152 </span> * @cfg {Boolean} collapseFirst
153 * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
154 * any other tools in the panel&#39;s title bar, <code>false</code> to render it last (defaults to <code>true</code>).
158 <span id='Ext-panel-Panel-cfg-hideCollapseTool'> /**
159 </span> * @cfg {Boolean} hideCollapseTool
160 * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
161 * <code>false</code> to display it (defaults to <code>false</code>).
163 hideCollapseTool: false,
165 <span id='Ext-panel-Panel-cfg-titleCollapse'> /**
166 </span> * @cfg {Boolean} titleCollapse
167 * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
168 * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
169 * (defaults to <code>false</code>)).
171 titleCollapse: false,
173 <span id='Ext-panel-Panel-cfg-collapseMode'> /**
174 </span> * @cfg {String} collapseMode
175 * <p><b>Important: this config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
176 * <p>When <i>not</i> a direct child item of a {@link Ext.layout.container.Border border layout}, then the Panel&#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.</p>
178 * <p>When a child item of a {@link Ext.layout.container.Border border layout}, this config has two options:
179 * <div class="mdetail-params"><ul>
180 * <li><b><code>undefined/omitted</code></b><div class="sub-desc">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.</div></li>
182 * <li><b><code>header</code></b> : <div class="sub-desc">The Panel collapses to leave its header visible as when not inside a {@link Ext.layout.container.Border border layout}.</div></li>
183 * </ul></div></p>
186 <span id='Ext-panel-Panel-cfg-placeholder'> /**
187 </span> * @cfg {Mixed} placeholder
188 * <p><b>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 <code>'header'</code> {@link #collapseMode}.</b></p>
190 * <p><b>Optional.</b> 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.</p>
195 <span id='Ext-panel-Panel-cfg-floatable'> /**
196 </span> * @cfg {Boolean} floatable
197 * <p><b>Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
198 * <tt>true</tt> to allow clicking a collapsed Panel&#39;s {@link #placeholder} to display the Panel floated
199 * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
200 * clicking the expand button to see it again (defaults to <tt>true</tt>).
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.
210 <span id='Ext-panel-Panel-cfg-collapsible'> /**
211 </span> * @cfg {Boolean} collapsible
212 * <p>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).</p>
214 * See {@link #collapseMode} and {@link #collapseDirection}
218 <span id='Ext-panel-Panel-cfg-collapseDirection'> /**
219 </span> * @cfg {Boolean} collapseDirection
220 * <p>The direction to collapse the Panel when the toggle button is clicked.</p>
221 * <p>Defaults to the {@link #headerPosition}</p>
222 * <p><b>Important: This config is <u>ignored</u> for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
223 * <p>Specify as <code>'top'</code>, <code>'bottom'</code>, <code>'left'</code> or <code>'right'</code>.</p>
226 <span id='Ext-panel-Panel-cfg-closable'> /**
227 </span> * @cfg {Boolean} closable
228 * <p>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 <code>false</code>).</p>
230 * <p>By default, when close is requested by clicking the close button in the header, the {@link #close}
231 * method will be called. This will <i>{@link Ext.Component#destroy destroy}</i> the Panel and its content
232 * meaning that it may not be reused.</p>
233 * <p>To make closing a Panel <i>hide</i> the Panel so that it may be reused, set
234 * {@link #closeAction} to 'hide'.</p>
238 <span id='Ext-panel-Panel-cfg-closeAction'> /**
239 </span> * @cfg {String} closeAction
240 * <p>The action to take when the close header tool is clicked:
241 * <div class="mdetail-params"><ul>
242 * <li><b><code>'{@link #destroy}'</code></b> : <b>Default</b><div class="sub-desc">
243 * {@link #destroy remove} the window from the DOM and {@link Ext.Component#destroy destroy}
244 * it and all descendant Components. The window will <b>not</b> be available to be
245 * redisplayed via the {@link #show} method.
246 * </div></li>
247 * <li><b><code>'{@link #hide}'</code></b> : <div class="sub-desc">
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 * </div></li>
251 * </ul></div>
252 * <p><b>Note:</b> This behavior has changed! setting *does* affect the {@link #close} method
253 * which will invoke the approriate closeAction.
255 closeAction: 'destroy',
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 * <pre><code>
263 var panel = new Ext.panel.Panel({
268 text: 'Docked to the top'
271 });</pre></code>
274 <span id='Ext-panel-Panel-cfg-preventHeader'> /**
275 </span> * @cfg {Boolean} preventHeader Prevent a Header from being created and shown. Defaults to false.
277 preventHeader: false,
279 <span id='Ext-panel-Panel-cfg-headerPosition'> /**
280 </span> * @cfg {String} headerPosition Specify as <code>'top'</code>, <code>'bottom'</code>, <code>'left'</code> or <code>'right'</code>. Defaults to <code>'top'</code>.
282 headerPosition: 'top',
284 <span id='Ext-panel-Panel-cfg-frame'> /**
285 </span> * @cfg {Boolean} frame
286 * True to apply a frame to the panel.
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).
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 * <p>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.</p>
304 * <p>Example usage:</p>
305 * <pre><code>
308 qtip: 'Refresh form Data',
310 handler: function(event, toolEl, panel){
317 handler: function(event, toolEl, panel){
321 </code></pre>
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`.
331 initComponent: function() {
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.
342 "beforeexpand",
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<ul>
349 * <li>Ext.Component.DIRECTION_TOP</li>
350 * <li>Ext.Component.DIRECTION_RIGHT</li>
351 * <li>Ext.Component.DIRECTION_BOTTOM</li>
352 * <li>Ext.Component.DIRECTION_LEFT</li></ul>
353 * @param {Boolean} animate True if the collapse is animated, else false.
355 "beforecollapse",
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.
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.
369 "collapse",
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.
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.
390 // Save state on these two events.
391 this.addStateEvents('expand', 'collapse');
398 me.setUI(me.ui + '-framed');
403 me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
405 // Backwards compatibility
409 setBorder: function(border) {
411 // method = (border === false || border === 0) ? 'addClsWithUI' : 'removeClsWithUI';
413 // me.callParent(arguments);
415 // if (me.collapsed) {
416 // me[method](me.collapsedCls + '-noborder');
420 // me.header.setBorder(border);
421 // if (me.collapsed) {
422 // me.header[method](me.collapsedCls + '-noborder');
426 this.callParent(arguments);
429 beforeDestroy: function() {
437 initAria: function() {
439 this.initHeaderAria();
442 initHeaderAria: function() {
446 if (el && header) {
447 el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
451 getHeader: function() {
455 <span id='Ext-panel-Panel-method-setTitle'> /**
456 </span> * Set a title for the panel&#39;s header. See {@link Ext.panel.Header#title}.
457 * @param {String} newTitle
459 setTitle: function(newTitle) {
461 oldTitle = this.title;
465 me.header.setTitle(newTitle);
471 me.reExpander.setTitle(newTitle);
473 me.fireEvent('titlechange', me, newTitle, oldTitle);
476 <span id='Ext-panel-Panel-method-setIconCls'> /**
477 </span> * Set the iconCls for the panel&#39;s header. See {@link Ext.panel.Header#iconCls}.
478 * @param {String} newIconCls
480 setIconCls: function(newIconCls) {
482 oldIconCls = me.iconCls;
484 me.iconCls = newIconCls;
485 var header = me.header;
487 header.setIconCls(newIconCls);
489 me.fireEvent('iconchange', me, newIconCls, oldIconCls);
492 bridgeToolbars: function() {
496 minButtonWidth = me.minButtonWidth;
498 function initToolbar (toolbar, pos, useButtonAlign) {
499 if (Ext.isArray(toolbar)) {
505 else if (!toolbar.xtype) {
506 toolbar.xtype = 'toolbar';
509 if (pos == 'left' || pos == 'right') {
510 toolbar.vertical = true;
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'
523 // Short-hand toolbars (tbar, bbar and fbar plus new lbar and rbar):
525 <span id='Ext-panel-Panel-cfg-buttonAlign'> /**
526 </span> * @cfg {String} buttonAlign
527 * <p>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).</p>
529 * <p><b>NOTE:</b> 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.</p>
534 <span id='Ext-panel-Panel-cfg-tbar'> /**
535 </span> * @cfg {Object/Array} tbar
537 Convenience method. Short for 'Top Bar'.
540 { xtype: 'button', text: 'Button 1' }
549 { xtype: 'button', text: 'Button 1' }
556 me.addDocked(initToolbar(me.tbar, 'top'));
560 <span id='Ext-panel-Panel-cfg-bbar'> /**
561 </span> * @cfg {Object/Array} bbar
563 Convenience method. Short for 'Bottom Bar'.
566 { xtype: 'button', text: 'Button 1' }
575 { xtype: 'button', text: 'Button 1' }
582 me.addDocked(initToolbar(me.bbar, 'bottom'));
586 <span id='Ext-panel-Panel-cfg-buttons'> /**
587 </span> * @cfg {Object/Array} buttons
589 Convenience method used for adding buttons docked to the bottom of the panel. This is a
590 synonym for the {@link #fbar} config.
602 defaults: {minWidth: {@link #minButtonWidth}},
604 { xtype: 'component', flex: 1 },
605 { xtype: 'button', text: 'Button 1' }
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.
615 me.fbar = me.buttons;
619 <span id='Ext-panel-Panel-cfg-fbar'> /**
620 </span> * @cfg {Object/Array} fbar
622 Convenience method used for adding items to the bottom of the panel. Short for Footer Bar.
625 { type: 'button', text: 'Button 1' }
634 defaults: {minWidth: {@link #minButtonWidth}},
636 { xtype: 'component', flex: 1 },
637 { xtype: 'button', text: 'Button 1' }
641 The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
642 each of the buttons in the fbar.
647 fbar = initToolbar(me.fbar, 'bottom', true); // only we useButtonAlign
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 && config.isXType('button'))) &&
656 !('minWidth' in defaults)) {
657 defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
667 <span id='Ext-panel-Panel-cfg-lbar'> /**
668 </span> * @cfg {Object/Array} lbar
670 * Convenience method. Short for 'Left Bar' (left-docked, vertical toolbar).
673 * { xtype: 'button', text: 'Button 1' }
682 * { xtype: 'button', text: 'Button 1' }
689 me.addDocked(initToolbar(me.lbar, 'left'));
693 <span id='Ext-panel-Panel-cfg-rbar'> /**
694 </span> * @cfg {Object/Array} rbar
696 * Convenience method. Short for 'Right Bar' (right-docked, vertical toolbar).
699 * { xtype: 'button', text: 'Button 1' }
708 * { xtype: 'button', text: 'Button 1' }
715 me.addDocked(initToolbar(me.rbar, 'right'));
720 <span id='Ext-panel-Panel-method-initTools'> /**
722 * Tools are a Panel-specific capabilty.
723 * Panel uses initTools. Subclasses may contribute tools by implementing addTools.
725 initTools: function() {
728 me.tools = me.tools || [];
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 && !(me.hideCollapseTool || me.header === false)) {
733 me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
734 me.collapseTool = me.expandTool = me.createComponent({
736 type: 'collapse-' + me.collapseDirection,
737 expandType: me.getOppositeDirection(me.collapseDirection),
738 handler: me.toggleCollapse,
742 // Prepend collapse tool is configured to do so.
743 if (me.collapseFirst) {
744 me.tools.unshift(me.collapseTool);
748 // Add subclass-specific tools.
751 // Make Panel closable.
753 me.addClsWithUI('closable');
756 handler: Ext.Function.bind(me.close, this, [])
760 // Append collapse tool if needed.
761 if (me.collapseTool && !me.collapseFirst) {
762 me.tools.push(me.collapseTool);
766 <span id='Ext-panel-Panel-property-addTools'> /**
768 * Template method to be implemented in subclasses to add their tools after the collapsible tool.
770 addTools: Ext.emptyFn,
772 <span id='Ext-panel-Panel-method-close'> /**
773 </span> * <p>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.<p>
776 * <p><b>Note:</b> 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}.</p>
781 if (this.fireEvent('beforeclose', this) !== false) {
787 doClose: function() {
788 this.fireEvent('close', this);
789 this[this.closeAction]();
792 onRender: function(ct, position) {
796 // Add class-specific header tools.
797 // Panel adds collapsible and closable.
800 // Dock the header/title
803 // Call to super after adding the header, to prevent an unnecessary re-layout
804 me.callParent(arguments);
807 afterRender: function() {
809 me.callParent(arguments);
811 me.collapsed = false;
812 me.collapse(null, false, true);
816 <span id='Ext-panel-Panel-method-updateHeader'> /**
817 </span> * Create, hide, or show the header component as appropriate based on the current config.
819 * @param {Boolean} force True to force the header to be created
821 updateHeader: function(force) {
827 if (!me.preventHeader && (force || title || (tools && tools.length))) {
829 header = me.header = Ext.create('Ext.panel.Header', {
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',
838 indicateDrag: me.draggable,
840 frame : me.frame && me.frameHeader,
841 ignoreParentFrame : me.frame || me.overlapHeader,
842 ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
843 listeners : me.collapsible && me.titleCollapse ? {
844 click: me.toggleCollapse,
848 me.addDocked(header, 0);
850 // Reference the Header's tool array.
851 // Header injects named references.
852 me.tools = header.tools;
862 setUI: function(ui) {
865 me.callParent(arguments);
873 getContentTarget: function() {
877 getTargetEl: function() {
878 return this.body || this.frameBody || this.el;
881 addTool: function(tool) {
882 this.tools.push(tool);
883 var header = this.header;
885 header.addTool(tool);
890 getOppositeDirection: function(d) {
891 var c = Ext.Component;
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;
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<ul>
909 * <li>Ext.Component.DIRECTION_TOP</li>
910 * <li>Ext.Component.DIRECTION_RIGHT</li>
911 * <li>Ext.Component.DIRECTION_BOTTOM</li>
912 * <li>Ext.Component.DIRECTION_LEFT</li></ul>
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
917 collapse: function(direction, animate, /* private - passed if called at render time */ internal) {
920 height = me.getHeight(),
921 width = me.getWidth(),
924 dockedItems = me.dockedItems.items,
925 dockedItemCount = dockedItems.length,
939 afteranimate: me.afterCollapse,
942 duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
945 reExpanderOrientation,
952 direction = me.collapseDirection;
955 // If internal (Called because of initial collapsed state), then no animation, and no events.
958 } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
962 reExpanderDock = direction;
963 me.expandDirection = me.getOppositeDirection(direction);
965 // Track docked items which we hide during collapsed state
966 me.hiddenDocked = [];
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';
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 < dockedItemCount; i++) {
981 comp = dockedItems[i];
982 if (comp.isVisible()) {
983 if (comp.isHeader && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
986 me.hiddenDocked.push(comp);
991 if (direction == Ext.Component.DIRECTION_BOTTOM) {
992 pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
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';
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 < dockedItemCount; i++) {
1009 comp = dockedItems[i];
1010 if (comp.isVisible()) {
1011 if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
1014 me.hiddenDocked.push(comp);
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;
1026 throw('Panel collapse must be passed a valid Component collapse direction');
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);
1035 // Disable toggle tool during animated collapse
1036 if (animate && me.collapseTool) {
1037 me.collapseTool.disable();
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');
1046 // We found a header: Measure it to find the collapse-to size.
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 && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
1052 reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
1055 frameInfo = reExpander.getFrameInfo();
1058 newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
1061 reExpander.removeClsWithUI(me.collapsedCls);
1062 reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
1063 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
1064 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
1067 // No header: Render and insert a temporary one, and then measure it.
1070 hideMode: 'offsets',
1073 orientation: reExpanderOrientation,
1074 dock: reExpanderDock,
1075 textCls: me.headerTextCls,
1076 iconCls: me.iconCls,
1077 baseCls: me.baseCls + '-header',
1079 frame: me.frame && 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',
1085 if (!me.hideCollapseTool) {
1086 reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
1088 type: 'expand-' + me.expandDirection,
1089 handler: me.toggleCollapse,
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);
1100 // Insert the new docked item
1101 me.insertDocked(0, reExpander);
1104 me.reExpander = reExpander;
1105 me.reExpander.addClsWithUI(me.collapsedCls);
1106 me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
1107 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
1108 me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
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);
1118 // Animate to the new size
1119 anim.to[collapseDimension] = newSize;
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);
1129 me.collapseMemento.capture(['width', 'height', 'minWidth', 'minHeight']);
1131 // Remove any flex config before we attempt to collapse.
1132 me.savedFlex = me.flex;
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);
1144 me.afterCollapse(false, internal);
1149 afterCollapse: function(animated, internal) {
1152 l = me.hiddenDocked.length;
1154 me.collapseMemento.restore(['minWidth', 'minHeight']);
1157 for (; i < l; i++) {
1158 me.hiddenDocked[i].hide();
1160 if (me.reExpander) {
1161 me.reExpander.updateFrame();
1162 me.reExpander.show();
1164 me.collapsed = true;
1167 me.doComponentLayout();
1171 me.resizer.disable();
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');
1178 me.collapseMemento.restore('height');
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);
1186 me.fireEvent('collapse', me);
1189 // Re-enable the toggle tool after an animated collapse
1190 if (animated && me.collapseTool) {
1191 me.collapseTool.enable();
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
1202 expand: function(animate) {
1204 if (!me.collapsed || me.fireEvent('beforeexpand', me, animate) === false) {
1209 l = me.hiddenDocked.length,
1210 direction = me.expandDirection,
1211 height = me.getHeight(),
1212 width = me.getWidth(),
1215 // Disable toggle tool during animated expand
1216 if (animate && me.collapseTool) {
1217 me.collapseTool.disable();
1220 // Show any docked items that we hid on collapse
1221 // And hide the injected reExpander Header
1222 for (; i < l; i++) {
1223 me.hiddenDocked[i].hidden = false;
1224 me.hiddenDocked[i].el.show();
1226 if (me.reExpander) {
1227 if (me.reExpander.temporary) {
1228 me.reExpander.hide();
1230 me.reExpander.removeClsWithUI(me.collapsedCls);
1231 me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
1232 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
1233 me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
1235 me.reExpander.updateFrame();
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);
1244 // Unset the flag before the potential call to calculateChildBox to calculate our newly flexed size
1245 me.collapsed = false;
1247 // Collapsed means body element was hidden
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');
1264 afteranimate: me.afterExpand,
1269 if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
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();
1276 // Must size back down to collapsed for the animation.
1277 me.setCalculatedSize(me.width, anim.from.height);
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;
1286 // Else, restore to saved height
1288 anim.to.height = me.expandedSize;
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);
1297 } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
1299 // If autoWidth, measure the width now we have shown the body element.
1301 me.setCalculatedSize(null, me.height);
1302 anim.to.width = me.getWidth();
1304 // Must size back down to collapsed for the animation.
1305 me.setCalculatedSize(anim.from.width, me.height);
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;
1314 // Else, restore to saved width
1316 anim.to.width = me.expandedSize;
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);
1330 me.setCalculatedSize(anim.to.width, anim.to.height);
1332 me.setLeft(anim.to.x);
1335 me.setTop(anim.to.y);
1337 me.afterExpand(false);
1343 afterExpand: function(animated) {
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
1350 me.collapseMemento.restoreAll();
1353 me.setAutoScroll(me.initialConfig.autoScroll);
1355 // Restored to a calculated flex. Delete the set width and height properties so that flex works from now on.
1357 me.flex = me.savedFlex;
1358 delete me.savedFlex;
1363 // Reinstate layout out after Panel has re-expanded
1364 delete me.suspendLayout;
1365 if (animated && 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);
1372 me.resizer.enable();
1375 me.fireEvent('expand', me);
1377 // Re-enable the toggle tool after an animated expand
1378 if (animated && me.collapseTool) {
1379 me.collapseTool.enable();
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
1387 toggleCollapse: function() {
1388 if (this.collapsed) {
1389 this.expand(this.animCollapse);
1391 this.collapse(this.collapseDirection, this.animCollapse);
1397 getKeyMap : function(){
1399 this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
1405 initDraggable : function(){
1406 <span id='Ext-panel-Panel-property-dd'> /**
1407 </span> * <p>If this Panel is configured {@link #draggable}, this property will contain
1408 * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
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.
1414 this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
1417 // private - helper function for ghost
1418 ghostTools : function() {
1420 origTools = this.initialConfig.tools;
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.
1441 // private - used for dragging
1442 ghost: function(cls) {
1444 ghostPanel = me.ghostPanel,
1448 ghostPanel = Ext.create('Ext.panel.Panel', {
1449 renderTo: document.body,
1453 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
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 ||'')
1464 me.ghostPanel = ghostPanel;
1466 ghostPanel.floatParent = me.floatParent;
1468 ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
1470 ghostPanel.toFront();
1472 ghostPanel.el.show();
1473 ghostPanel.setPosition(box.x, box.y);
1474 ghostPanel.setSize(box.width, box.height);
1476 if (me.floatingItems) {
1477 me.floatingItems.hide();
1483 unghost: function(show, matchPosition) {
1485 if (!me.ghostPanel) {
1488 if (show !== false) {
1490 if (matchPosition !== false) {
1491 me.setPosition(me.ghostPanel.getPosition());
1493 if (me.floatingItems) {
1494 me.floatingItems.show();
1496 Ext.defer(me.focus, 10, me);
1498 me.ghostPanel.el.hide();
1501 initResizable: function(resizable) {
1502 if (this.collapsed) {
1503 resizable.disabled = true;
1505 this.callParent([resizable]);