1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-layout.container.Border'>/**
2 </span> * @class Ext.layout.container.Border
3 * @extends Ext.layout.container.Container
4 * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5 * nested panels, automatic bars between regions and built-in
6 * {@link Ext.panel.Panel#collapsible expanding and collapsing} of regions.</p>
7 * <p>This class is intended to be extended or created via the <code>layout:'border'</code>
8 * {@link Ext.container.Container#layout} config, and should generally not need to be created directly
9 * via the new keyword.</p>
10 * {@img Ext.layout.container.Border/Ext.layout.container.Border.png Ext.layout.container.Border container layout}
11 * <p>Example usage:</p>
12 * <pre><code>
13 Ext.create('Ext.panel.Panel', {
16 title: 'Border Layout',
19 title: 'South Region is resizable',
20 region: 'south', // position for region
23 split: true, // enable resizing
26 // xtype: 'panel' implied by default
27 title: 'West Region is collapsible',
32 collapsible: true, // make collapsible
33 id: 'west-region-container',
36 title: 'Center Region',
37 region: 'center', // center region is required, no width/height specified
42 renderTo: Ext.getBody()
44 </code></pre>
45 * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
46 * <li>Any Container using the Border layout <b>must</b> have a child item with <code>region:'center'</code>.
47 * The child item in the center region will always be resized to fill the remaining space not used by
48 * the other regions in the layout.</li>
49 * <li>Any child items with a region of <code>west</code> or <code>east</code> may be configured with either
50 * an initial <code>width</code>, or a {@link Ext.layout.container.Box#flex} value, or an initial percentage width <b>string</b> (Which is simply divided by 100 and used as a flex value). The 'center' region has a flex value of <code>1</code>.</li>
51 * <li>Any child items with a region of <code>north</code> or <code>south</code> may be configured with either
52 * an initial <code>height</code>, or a {@link Ext.layout.container.Box#flex} value, or an initial percentage height <b>string</b> (Which is simply divided by 100 and used as a flex value). The 'center' region has a flex value of <code>1</code>.</li>
53 * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>.To add/remove
54 * Components within a BorderLayout, have them wrapped by an additional Container which is directly
55 * managed by the BorderLayout. If the region is to be collapsible, the Container used directly
56 * by the BorderLayout manager should be a Panel. In the following example a Container (an Ext.panel.Panel)
57 * is added to the west region:<pre><code>
58 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
59 wrc.{@link Ext.container.Container#removeAll removeAll}();
60 wrc.{@link Ext.container.Container#add add}({
64 * </code></pre>
66 * <li><b>There is no BorderLayout.Region class in ExtJS 4.0+</b></li>
67 * </ul></div>
69 Ext.define('Ext.layout.container.Border', {
71 alias: ['layout.border'],
72 extend: 'Ext.layout.container.Container',
73 requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
74 alternateClassName: 'Ext.layout.BorderLayout',
76 targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
78 itemCls: Ext.baseCSSPrefix + 'border-item',
80 bindToOwnerCtContainer: true,
84 percentageRe: /(\d+)%/,
93 constructor: function(config) {
94 this.initialConfig = config;
95 this.callParent(arguments);
98 onLayout: function() {
100 if (!me.borderLayoutInitialized) {
101 me.initializeBorderLayout();
104 // Delegate this operation to the shadow "V" or "H" box layout, and then down to any embedded layout.
105 me.shadowLayout.onLayout();
106 if (me.embeddedContainer) {
107 me.embeddedContainer.layout.onLayout();
110 // If the panel was originally configured with collapsed: true, it will have
111 // been initialized with a "borderCollapse" flag: Collapse it now before the first layout.
112 if (!me.initialCollapsedComplete) {
113 Ext.iterate(me.regions, function(name, region){
114 if (region.borderCollapse) {
115 me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
118 me.initialCollapsedComplete = true;
122 isValidParent : function(item, target, position) {
123 if (!this.borderLayoutInitialized) {
124 this.initializeBorderLayout();
127 // Delegate this operation to the shadow "V" or "H" box layout.
128 return this.shadowLayout.isValidParent(item, target, position);
131 beforeLayout: function() {
132 if (!this.borderLayoutInitialized) {
133 this.initializeBorderLayout();
136 // Delegate this operation to the shadow "V" or "H" box layout.
137 this.shadowLayout.beforeLayout();
140 renderItems: function(items, target) {
142 Ext.Error.raise('This should not be called');
146 renderItem: function(item) {
148 Ext.Error.raise('This should not be called');
152 initializeBorderLayout: function() {
155 items = me.getLayoutItems(),
157 regions = (me.regions = {}),
164 // Map of Splitters for each region
168 for (; i < ln; i++) {
170 regions[comp.region] = comp;
172 // Intercept collapsing to implement showing an alternate Component as a collapsed placeholder
173 if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
175 // This layout intercepts any initial collapsed state. Panel must not do this itself.
176 comp.borderCollapse = comp.collapsed;
177 delete comp.collapsed;
180 beforecollapse: me.onBeforeRegionCollapse,
181 beforeexpand: me.onBeforeRegionExpand,
182 destroy: me.onRegionDestroy,
189 if (!regions.center) {
190 Ext.Error.raise("You must specify a center region when defining a BorderLayout.");
193 comp = regions.center;
198 comp.maintainFlex = true;
200 // Begin the VBox and HBox item list.
203 comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
204 hBoxItems.push(comp);
206 hBoxItems.push(me.splitters.west = me.createSplitter(comp));
208 percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
210 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
214 comp = regions.north;
216 comp.collapseDirection = Ext.Component.DIRECTION_TOP;
217 vBoxItems.push(comp);
219 vBoxItems.push(me.splitters.north = me.createSplitter(comp));
221 percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
223 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
228 // Decide into which Collection the center region goes.
229 if (regions.north || regions.south) {
230 if (regions.east || regions.west) {
232 // Create the embedded center. Mark it with the region: 'center' property so that it can be identified as the center.
233 vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
236 id: me.owner.id + '-embedded-center',
237 cls: Ext.baseCSSPrefix + 'border-item',
238 flex: regions.center.flex,
245 hBoxItems.push(regions.center);
247 // No east or west: the original center goes straight into the vbox
249 vBoxItems.push(regions.center);
252 // If we have no north or south, then the center is part of the HBox items
254 hBoxItems.push(regions.center);
257 // Finish off the VBox and HBox item list.
258 comp = regions.south;
260 comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
262 vBoxItems.push(me.splitters.south = me.createSplitter(comp));
264 percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
266 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
269 vBoxItems.push(comp);
273 comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
275 hBoxItems.push(me.splitters.east = me.createSplitter(comp));
277 percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
279 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
282 hBoxItems.push(comp);
285 // Create the injected "items" collections for the Containers.
286 // If we have north or south, then the shadow Container will be a VBox.
287 // If there are also east or west regions, its center will be a shadow HBox.
288 // If there are *only* east or west regions, then the shadow layout will be an HBox (or Fit).
289 if (regions.north || regions.south) {
291 me.shadowContainer = Ext.create('Ext.container.Container', {
294 layout: Ext.applyIf({
299 me.createItems(me.shadowContainer, vBoxItems);
301 // Allow the Splitters to orientate themselves
302 if (me.splitters.north) {
303 me.splitters.north.ownerCt = me.shadowContainer;
305 if (me.splitters.south) {
306 me.splitters.south.ownerCt = me.shadowContainer;
309 // Inject items into the HBox Container if there is one - if there was an east or west.
310 if (me.embeddedContainer) {
311 me.embeddedContainer.ownerCt = me.shadowContainer;
312 me.createItems(me.embeddedContainer, hBoxItems);
314 // Allow the Splitters to orientate themselves
315 if (me.splitters.east) {
316 me.splitters.east.ownerCt = me.embeddedContainer;
318 if (me.splitters.west) {
319 me.splitters.west.ownerCt = me.embeddedContainer;
322 // The east or west region wanted a percentage
323 if (horizontalFlex) {
324 regions.center.flex -= horizontalFlex;
326 // The north or south region wanted a percentage
328 me.embeddedContainer.flex -= verticalFlex;
331 // The north or south region wanted a percentage
333 regions.center.flex -= verticalFlex;
337 // If we have no north or south, then there's only one Container, and it's
338 // an HBox, or, if only a center region was specified, a Fit.
340 me.shadowContainer = Ext.create('Ext.container.Container', {
343 layout: Ext.applyIf({
344 type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
348 me.createItems(me.shadowContainer, hBoxItems);
350 // Allow the Splitters to orientate themselves
351 if (me.splitters.east) {
352 me.splitters.east.ownerCt = me.shadowContainer;
354 if (me.splitters.west) {
355 me.splitters.west.ownerCt = me.shadowContainer;
358 // The east or west region wanted a percentage
359 if (horizontalFlex) {
360 regions.center.flex -= verticalFlex;
364 // Create upward links from the region Components to their shadow ownerCts
365 for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
366 items[i].shadowOwnerCt = me.shadowContainer;
368 if (me.embeddedContainer) {
369 for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
370 items[i].shadowOwnerCt = me.embeddedContainer;
374 // This is the layout that we delegate all operations to
375 me.shadowLayout = me.shadowContainer.getLayout();
377 me.borderLayoutInitialized = true;
381 setupState: function(comp){
382 var getState = comp.getState;
383 comp.getState = function(){
384 // call the original getState
385 var state = getState.call(comp) || {},
386 region = comp.region;
388 state.collapsed = !!comp.collapsed;
389 if (region == 'west' || region == 'east') {
390 state.width = comp.getWidth();
392 state.height = comp.getHeight();
396 comp.addStateEvents(['collapse', 'expand', 'resize']);
399 <span id='Ext-layout.container.Border-method-createItems'> /**
400 </span> * Create the items collection for our shadow/embedded containers
403 createItems: function(container, items){
404 // Have to inject an items Collection *after* construction.
405 // The child items of the shadow layout must retain their original, user-defined ownerCt
406 delete container.items;
407 container.initItems();
408 container.items.addAll(items);
412 // Create a splitter for a child of the layout.
413 createSplitter: function(comp) {
415 interceptCollapse = (comp.collapseMode != 'header'),
418 resizer = Ext.create('Ext.resizer.Splitter', {
419 hidden: !!comp.hidden,
420 collapseTarget: comp,
421 performCollapse: !interceptCollapse,
422 listeners: interceptCollapse ? {
424 fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
425 element: 'collapseEl'
430 // Mini collapse means that the splitter is the placeholder Component
431 if (comp.collapseMode == 'mini') {
432 comp.placeholder = resizer;
435 // Arrange to hide/show a region's associated splitter when the region is hidden/shown
437 hide: me.onRegionVisibilityChange,
438 show: me.onRegionVisibilityChange,
444 // Hide/show a region's associated splitter when the region is hidden/shown
445 onRegionVisibilityChange: function(comp){
446 this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
450 // Called when a splitter mini-collapse tool is clicked on.
451 // The listener is only added if this layout is controlling collapsing,
452 // not if the component's collapseMode is 'mini' or 'header'.
453 onSplitterCollapseClick: function(comp) {
454 if (comp.collapsed) {
455 this.onPlaceHolderToolClick(null, null, null, {client: comp});
461 <span id='Ext-layout.container.Border-method-getPlaceholder'> /**
462 </span> * <p>Return the {@link Ext.panel.Panel#placeholder placeholder} Component to which the passed child Panel of the layout will collapse.
463 * By default, this will be a {@link Ext.panel.Header Header} component (Docked to the appropriate border). See {@link Ext.panel.Panel#placeholder placeholder}.
464 * config to customize this.</p>
465 * <p><b>Note that this will be a fully instantiated Component, but will only be <i>rendered</i> when the Panel is first collapsed.</b></p>
466 * @param {Panel} panel The child Panel of the layout for which to return the {@link Ext.panel.Panel#placeholder placeholder}.
467 * @returns {Component} The Panel's {@link Ext.panel.Panel#placeholder placeholder} unless the {@link Ext.panel.Panel#collapseMode collapseMode} is
468 * <code>'header'</code>, in which case <i>undefined</i> is returned.
470 getPlaceholder: function(comp) {
472 placeholder = comp.placeholder,
473 shadowContainer = comp.shadowOwnerCt,
474 shadowLayout = shadowContainer.layout,
475 oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
476 horiz = (comp.region == 'north' || comp.region == 'south');
478 // No placeholder if the collapse mode is not the Border layout default
479 if (comp.collapseMode == 'header') {
483 // Provide a replacement Container with an expand tool
485 if (comp.collapseMode == 'mini') {
486 placeholder = Ext.create('Ext.resizer.Splitter', {
487 id: 'collapse-placeholder-' + comp.id,
488 collapseTarget: comp,
489 performCollapse: false,
492 fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
493 element: 'collapseEl'
497 placeholder.addCls(placeholder.collapsedCls);
500 id: 'collapse-placeholder-' + comp.id,
501 margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
503 orientation: horiz ? 'horizontal' : 'vertical',
505 textCls: comp.headerTextCls,
506 iconCls: comp.iconCls,
507 baseCls: comp.baseCls + '-header',
509 indicateDrag: comp.draggable,
510 cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder',
511 listeners: comp.floatable ? {
514 me.floatCollapsedPanel(e, comp);
520 // Hack for IE6/7/IEQuirks's inability to display an inline-block
521 if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
522 placeholder.width = 25;
524 placeholder[horiz ? 'tools' : 'items'] = [{
527 type: 'expand-' + oppositeDirection,
528 handler: me.onPlaceHolderToolClick,
532 placeholder = me.owner.createComponent(placeholder);
533 if (comp.isXType('panel')) {
535 titlechange: me.onRegionTitleChange,
536 iconchange: me.onRegionIconChange,
542 // The collapsed Component holds a reference to its placeholder and vice versa
543 comp.placeholder = placeholder;
544 placeholder.comp = comp;
549 <span id='Ext-layout.container.Border-method-onRegionTitleChange'> /**
551 * Update the placeholder title when panel title has been set or changed.
553 onRegionTitleChange: function(comp, newTitle) {
554 comp.placeholder.setTitle(newTitle);
557 <span id='Ext-layout.container.Border-method-onRegionIconChange'> /**
559 * Update the placeholder iconCls when panel iconCls has been set or changed.
561 onRegionIconChange: function(comp, newIconCls) {
562 comp.placeholder.setIconCls(newIconCls);
565 <span id='Ext-layout.container.Border-method-calculateChildBox'> /**
567 * Calculates the size and positioning of the passed child item. Must be present because Panel's expand,
568 * when configured with a flex, calls this method on its ownerCt's layout.
569 * @param {Component} child The child Component to calculate the box for
570 * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
572 calculateChildBox: function(comp) {
574 if (me.shadowContainer.items.contains(comp)) {
575 return me.shadowContainer.layout.calculateChildBox(comp);
577 else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
578 return me.embeddedContainer.layout.calculateChildBox(comp);
582 <span id='Ext-layout.container.Border-method-onBeforeRegionCollapse'> /**
584 * Intercepts the Panel's own collapse event and perform's substitution of the Panel
585 * with a placeholder Header orientated in the appropriate dimension.
586 * @param comp The Panel being collapsed.
589 * @returns {Boolean} false to inhibit the Panel from performing its own collapse.
591 onBeforeRegionCollapse: function(comp, direction, animate) {
594 miniCollapse = comp.collapseMode == 'mini',
595 shadowContainer = comp.shadowOwnerCt,
596 shadowLayout = shadowContainer.layout,
597 placeholder = comp.placeholder,
599 targetSize = shadowLayout.getLayoutTargetSize(),
600 sl = me.owner.suspendLayout,
601 scsl = shadowContainer.suspendLayout,
602 isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); // Flag to keep the placeholder non-adjacent to any Splitter
604 // Do not trigger a layout during transition to collapsed Component
605 me.owner.suspendLayout = true;
606 shadowContainer.suspendLayout = true;
608 // Prevent upward notifications from downstream layouts
609 shadowLayout.layoutBusy = true;
610 if (shadowContainer.componentLayout) {
611 shadowContainer.componentLayout.layoutBusy = true;
613 me.shadowContainer.layout.layoutBusy = true;
614 me.layoutBusy = true;
615 me.owner.componentLayout.layoutBusy = true;
617 // Provide a replacement Container with an expand tool
619 placeholder = me.getPlaceholder(comp);
622 // placeholder already in place; show it.
623 if (placeholder.shadowOwnerCt === shadowContainer) {
626 // Insert the collapsed placeholder Component into the appropriate Box layout shadow Container
627 // It must go next to its client Component, but non-adjacent to the splitter so splitter can find its collapse client.
628 // Inject an ownerCt value pointing to the owner, border layout Container as the user will expect.
630 shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
631 placeholder.shadowOwnerCt = shadowContainer;
632 placeholder.ownerCt = me.owner;
635 // Flag the collapsing Component as hidden and show the placeholder.
636 // This causes the shadow Box layout's calculateChildBoxes to calculate the correct new arrangement.
637 // We hide or slideOut the Component's element
640 if (!placeholder.rendered) {
641 shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
644 // Jobs to be done after the collapse has been done
645 function afterCollapse() {
647 // Reinstate automatic laying out.
648 me.owner.suspendLayout = sl;
649 shadowContainer.suspendLayout = scsl;
650 delete shadowLayout.layoutBusy;
651 if (shadowContainer.componentLayout) {
652 delete shadowContainer.componentLayout.layoutBusy;
654 delete me.shadowContainer.layout.layoutBusy;
655 delete me.layoutBusy;
656 delete me.owner.componentLayout.layoutBusy;
658 // Fire the collapse event: The Panel has in fact been collapsed, but by substitution of an alternative Component
659 comp.collapsed = true;
660 comp.fireEvent('collapse', comp);
664 * Set everything to the new positions. Note that we
665 * only want to animate the collapse if it wasn't configured
666 * initially with collapsed: true
668 if (comp.animCollapse && me.initialCollapsedComplete) {
669 shadowLayout.layout();
670 compEl.dom.style.zIndex = 100;
672 // If we're mini-collapsing, the placholder is a Splitter. We don't want it to "bounce in"
674 placeholder.el.hide();
676 compEl.slideOut(me.slideDirection[comp.region], {
677 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
679 afteranimate: function() {
680 compEl.show().setLeftTop(-10000, -10000);
681 compEl.dom.style.zIndex = '';
683 // If we're mini-collapsing, the placholder is a Splitter. We don't want it to "bounce in"
685 placeholder.el.slideIn(me.slideDirection[comp.region], {
695 compEl.setLeftTop(-10000, -10000);
696 shadowLayout.layout();
699 // Horrible workaround for https://sencha.jira.com/browse/EXTJSIV-1562
701 placeholder.setCalculatedSize(placeholder.el.getWidth());
708 // Hijack the expand operation to remove the placeholder and slide the region back in.
709 onBeforeRegionExpand: function(comp, animate) {
710 this.onPlaceHolderToolClick(null, null, null, {client: comp});
714 // Called when the collapsed placeholder is clicked to reinstate a "collapsed" (in reality hidden) Panel.
715 onPlaceHolderToolClick: function(e, target, owner, tool) {
719 // Hide the placeholder unless it was the Component's preexisting splitter
720 hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
723 placeholder = comp.placeholder,
724 placeholderEl = placeholder.el,
725 shadowContainer = comp.shadowOwnerCt,
726 shadowLayout = shadowContainer.layout,
728 sl = me.owner.suspendLayout,
729 scsl = shadowContainer.suspendLayout,
732 // If the slide in is still going, stop it.
733 // This will either leave the Component in its fully floated state (which is processed below)
734 // or in its collapsed state. Either way, we expand it..
735 if (comp.getActiveAnimation()) {
736 comp.stopAnimation();
739 // If the Component is fully floated when they click the placeholder Tool,
740 // it will be primed with a slide out animation object... so delete that
741 // and remove the mouseout listeners
742 if (comp.slideOutAnim) {
743 // Remove mouse leave monitors
744 compEl.un(comp.panelMouseMon);
745 placeholderEl.un(comp.placeholderMouseMon);
747 delete comp.slideOutAnim;
748 delete comp.panelMouseMon;
749 delete comp.placeholderMouseMon;
751 // If the Panel was floated and primed with a slideOut animation, we don't want to animate its layout operation.
755 // Do not trigger a layout during transition to expanded Component
756 me.owner.suspendLayout = true;
757 shadowContainer.suspendLayout = true;
759 // Prevent upward notifications from downstream layouts
760 shadowLayout.layoutBusy = true;
761 if (shadowContainer.componentLayout) {
762 shadowContainer.componentLayout.layoutBusy = true;
764 me.shadowContainer.layout.layoutBusy = true;
765 me.layoutBusy = true;
766 me.owner.componentLayout.layoutBusy = true;
768 // Unset the hidden and collapsed flags set in onBeforeRegionCollapse. The shadowLayout will now take it into account
769 // Find where the shadow Box layout plans to put the expanding Component.
771 comp.collapsed = false;
772 if (hidePlaceholder) {
773 placeholder.hidden = true;
775 toCompBox = shadowLayout.calculateChildBox(comp);
777 // Show the collapse tool in case it was hidden by the slide-in
778 if (comp.collapseTool) {
779 comp.collapseTool.show();
782 // If we're going to animate, we need to hide the component before moving it back into position
783 if (comp.animCollapse && !isFloating) {
784 compEl.setStyle('visibility', 'hidden');
786 compEl.setLeftTop(toCompBox.left, toCompBox.top);
788 // Equalize the size of the expanding Component prior to animation
789 // in case the layout area has changed size during the time it was collapsed.
790 curSize = comp.getSize();
791 if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
792 me.setItemSize(comp, toCompBox.width, toCompBox.height);
795 // Jobs to be done after the expand has been done
796 function afterExpand() {
797 // Reinstate automatic laying out.
798 me.owner.suspendLayout = sl;
799 shadowContainer.suspendLayout = scsl;
800 delete shadowLayout.layoutBusy;
801 if (shadowContainer.componentLayout) {
802 delete shadowContainer.componentLayout.layoutBusy;
804 delete me.shadowContainer.layout.layoutBusy;
805 delete me.layoutBusy;
806 delete me.owner.componentLayout.layoutBusy;
808 // In case it was floated out and they clicked the re-expand tool
809 comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
811 // Fire the expand event: The Panel has in fact been expanded, but by removal of an alternative Component
812 comp.fireEvent('expand', comp);
815 // Hide the placeholder
816 if (hidePlaceholder) {
817 placeholder.el.hide();
820 // Slide the expanding Component to its new position.
821 // When that is done, layout the layout.
822 if (comp.animCollapse && !isFloating) {
823 compEl.dom.style.zIndex = 100;
824 compEl.slideIn(me.slideDirection[comp.region], {
825 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
827 afteranimate: function() {
828 compEl.dom.style.zIndex = '';
830 shadowLayout.onLayout();
836 shadowLayout.onLayout();
841 floatCollapsedPanel: function(e, comp) {
843 if (comp.floatable === false) {
849 placeholder = comp.placeholder,
850 placeholderEl = placeholder.el,
851 shadowContainer = comp.shadowOwnerCt,
852 shadowLayout = shadowContainer.layout,
853 placeholderBox = shadowLayout.getChildBox(placeholder),
854 scsl = shadowContainer.suspendLayout,
855 curSize, toCompBox, compAnim;
857 // Ignore clicks on tools.
858 if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
862 // It's *being* animated, ignore the click.
863 // Possible future enhancement: Stop and *reverse* the current active Fx.
864 if (compEl.getActiveAnimation()) {
868 // If the Component is already fully floated when they click the placeholder,
869 // it will be primed with a slide out animation object... so slide it out.
870 if (comp.slideOutAnim) {
871 me.slideOutFloatedComponent(comp);
875 // Function to be called when the mouse leaves the floated Panel
876 // Slide out when the mouse leaves the region bounded by the slid Component and its placeholder.
877 function onMouseLeaveFloated(e) {
878 var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
880 // If mouse is not within slide Region, slide it out
881 if (!slideRegion.contains(e.getPoint())) {
882 me.slideOutFloatedComponent(comp);
886 // Monitor for mouseouting of the placeholder. Hide it if they exit for half a second or more
887 comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
889 // Do not trigger a layout during slide out of the Component
890 shadowContainer.suspendLayout = true;
892 // Prevent upward notifications from downstream layouts
893 me.layoutBusy = true;
894 me.owner.componentLayout.layoutBusy = true;
896 // The collapse tool is hidden while slid.
897 // It is re-shown on expand.
898 if (comp.collapseTool) {
899 comp.collapseTool.hide();
902 // Set flags so that the layout will calculate the boxes for what we want
904 comp.collapsed = false;
905 placeholder.hidden = true;
907 // Recalculate new arrangement of the Component being floated.
908 toCompBox = shadowLayout.calculateChildBox(comp);
909 placeholder.hidden = false;
911 // Component to appear just after the placeholder, whatever "after" means in the context of the shadow Box layout.
912 if (comp.region == 'north' || comp.region == 'west') {
913 toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
915 toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
917 compEl.setStyle('visibility', 'hidden');
918 compEl.setLeftTop(toCompBox.left, toCompBox.top);
920 // Equalize the size of the expanding Component prior to animation
921 // in case the layout area has changed size during the time it was collapsed.
922 curSize = comp.getSize();
923 if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
924 me.setItemSize(comp, toCompBox.width, toCompBox.height);
927 // This animation slides the collapsed Component's el out to just beyond its placeholder
930 afteranimate: function() {
931 shadowContainer.suspendLayout = scsl;
932 delete me.layoutBusy;
933 delete me.owner.componentLayout.layoutBusy;
935 // Prime the Component with an Anim config object to slide it back out
936 compAnim.listeners = {
937 afterAnimate: function() {
938 compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
940 // Reinstate the correct, current state after slide out animation finishes
942 comp.collapsed = true;
943 delete comp.slideOutAnim;
944 delete comp.panelMouseMon;
945 delete comp.placeholderMouseMon;
948 comp.slideOutAnim = compAnim;
954 // Give the element the correct class which places it at a high z-index
955 compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
957 // Begin the slide in
958 compEl.slideIn(me.slideDirection[comp.region], compAnim);
960 // Monitor for mouseouting of the slid area. Hide it if they exit for half a second or more
961 comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
965 slideOutFloatedComponent: function(comp) {
966 var compEl = comp.el,
969 // Remove mouse leave monitors
970 compEl.un(comp.panelMouseMon);
971 comp.placeholder.el.un(comp.placeholderMouseMon);
973 // Slide the Component out
974 compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
976 delete comp.slideOutAnim;
977 delete comp.panelMouseMon;
978 delete comp.placeholderMouseMon;
983 * Ensure any collapsed placeholder Component is destroyed along with its region.
984 * Can't do this in onDestroy because they may remove a Component and use it elsewhere.
986 onRegionDestroy: function(comp) {
987 var placeholder = comp.placeholder;
989 delete placeholder.ownerCt;
990 placeholder.destroy();
996 * Ensure any shadow Containers are destroyed.
997 * Ensure we don't keep references to Components.
999 onDestroy: function() {
1001 shadowContainer = me.shadowContainer,
1002 embeddedContainer = me.embeddedContainer;
1004 if (shadowContainer) {
1005 delete shadowContainer.ownerCt;
1006 Ext.destroy(shadowContainer);
1009 if (embeddedContainer) {
1010 delete embeddedContainer.ownerCt;
1011 Ext.destroy(embeddedContainer);
1014 delete me.splitters;
1015 delete me.shadowContainer;
1016 delete me.embeddedContainer;
1017 me.callParent(arguments);
1020 </pre></pre></body></html>