/ext-4.0.7/docs/source/Border.html
https://bitbucket.org/srogerf/javascript · HTML · 1130 lines · 1004 code · 126 blank · 0 comment · 0 complexity · 5d4366a9c99954a646446b4ac23f7480 MD5 · raw file
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
- <style type="text/css">
- .highlight { display: block; background-color: #ddd; }
- </style>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-layout-container-Border'>/**
- </span> * This is a multi-pane, application-oriented UI layout style that supports multiple nested panels, automatic bars
- * between regions and built-in {@link Ext.panel.Panel#collapsible expanding and collapsing} of regions.
- *
- * This class is intended to be extended or created via the `layout:'border'` {@link Ext.container.Container#layout}
- * config, and should generally not need to be created directly via the new keyword.
- *
- * @example
- * Ext.create('Ext.panel.Panel', {
- * width: 500,
- * height: 400,
- * title: 'Border Layout',
- * layout: 'border',
- * items: [{
- * title: 'South Region is resizable',
- * region: 'south', // position for region
- * xtype: 'panel',
- * height: 100,
- * split: true, // enable resizing
- * margins: '0 5 5 5'
- * },{
- * // xtype: 'panel' implied by default
- * title: 'West Region is collapsible',
- * region:'west',
- * xtype: 'panel',
- * margins: '5 0 0 5',
- * width: 200,
- * collapsible: true, // make collapsible
- * id: 'west-region-container',
- * layout: 'fit'
- * },{
- * title: 'Center Region',
- * region: 'center', // center region is required, no width/height specified
- * xtype: 'panel',
- * layout: 'fit',
- * margins: '5 5 0 0'
- * }],
- * renderTo: Ext.getBody()
- * });
- *
- * # Notes
- *
- * - Any Container using the Border layout **must** have a child item with `region:'center'`.
- * The child item in the center region will always be resized to fill the remaining space
- * not used by the other regions in the layout.
- *
- * - Any child items with a region of `west` or `east` may be configured with either an initial
- * `width`, or a {@link Ext.layout.container.Box#flex} value, or an initial percentage width
- * **string** (Which is simply divided by 100 and used as a flex value).
- * The 'center' region has a flex value of `1`.
- *
- * - Any child items with a region of `north` or `south` may be configured with either an initial
- * `height`, or a {@link Ext.layout.container.Box#flex} value, or an initial percentage height
- * **string** (Which is simply divided by 100 and used as a flex value).
- * The 'center' region has a flex value of `1`.
- *
- * - The regions of a BorderLayout are **fixed at render time** and thereafter, its child
- * Components may not be removed or added**. To add/remove Components within a BorderLayout,
- * have them wrapped by an additional Container which is directly managed by the BorderLayout.
- * If the region is to be collapsible, the Container used directly by the BorderLayout manager
- * should be a Panel. In the following example a Container (an Ext.panel.Panel) is added to
- * the west region:
- *
- * wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
- * wrc.{@link Ext.container.Container#removeAll removeAll}();
- * wrc.{@link Ext.container.Container#add add}({
- * title: 'Added Panel',
- * html: 'Some content'
- * });
- *
- * - **There is no BorderLayout.Region class in ExtJS 4.0+**
- */
- Ext.define('Ext.layout.container.Border', {
- alias: ['layout.border'],
- extend: 'Ext.layout.container.Container',
- requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
- alternateClassName: 'Ext.layout.BorderLayout',
- targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
- itemCls: Ext.baseCSSPrefix + 'border-item',
- bindToOwnerCtContainer: true,
- percentageRe: /(\d+)%/,
- slideDirection: {
- north: 't',
- south: 'b',
- west: 'l',
- east: 'r'
- },
- constructor: function(config) {
- this.initialConfig = config;
- this.callParent(arguments);
- },
- onLayout: function() {
- var me = this;
- if (!me.borderLayoutInitialized) {
- me.initializeBorderLayout();
- }
- // Delegate this operation to the shadow "V" or "H" box layout, and then down to any embedded layout.
- me.fixHeightConstraints();
- me.shadowLayout.onLayout();
- if (me.embeddedContainer) {
- me.embeddedContainer.layout.onLayout();
- }
- // If the panel was originally configured with collapsed: true, it will have
- // been initialized with a "borderCollapse" flag: Collapse it now before the first layout.
- if (!me.initialCollapsedComplete) {
- Ext.iterate(me.regions, function(name, region){
- if (region.borderCollapse) {
- me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
- }
- });
- me.initialCollapsedComplete = true;
- }
- },
- isValidParent : function(item, target, position) {
- if (!this.borderLayoutInitialized) {
- this.initializeBorderLayout();
- }
- // Delegate this operation to the shadow "V" or "H" box layout.
- return this.shadowLayout.isValidParent(item, target, position);
- },
- beforeLayout: function() {
- if (!this.borderLayoutInitialized) {
- this.initializeBorderLayout();
- }
- // Delegate this operation to the shadow "V" or "H" box layout.
- this.shadowLayout.beforeLayout();
- // note: don't call base because that does a renderItems again
- },
- renderItems: function(items, target) {
- //<debug>
- Ext.Error.raise('This should not be called');
- //</debug>
- },
- renderItem: function(item) {
- //<debug>
- Ext.Error.raise('This should not be called');
- //</debug>
- },
- renderChildren: function() {
- if (!this.borderLayoutInitialized) {
- this.initializeBorderLayout();
- }
- this.shadowLayout.renderChildren();
- },
- /*
- * Gathers items for a layout operation. Injected into child Box layouts through configuration.
- * We must not include child items which are floated over the layout (are primed with a slide out animation)
- */
- getVisibleItems: function() {
- return Ext.ComponentQuery.query(':not([slideOutAnim])', this.callParent(arguments));
- },
- initializeBorderLayout: function() {
- var me = this,
- i = 0,
- items = me.getLayoutItems(),
- ln = items.length,
- regions = (me.regions = {}),
- vBoxItems = [],
- hBoxItems = [],
- horizontalFlex = 0,
- verticalFlex = 0,
- comp, percentage;
- // Map of Splitters for each region
- me.splitters = {};
- // Map of regions
- for (; i < ln; i++) {
- comp = items[i];
- regions[comp.region] = comp;
- // Intercept collapsing to implement showing an alternate Component as a collapsed placeholder
- if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
- // This layout intercepts any initial collapsed state. Panel must not do this itself.
- comp.borderCollapse = comp.collapsed;
- comp.collapsed = false;
- comp.on({
- beforecollapse: me.onBeforeRegionCollapse,
- beforeexpand: me.onBeforeRegionExpand,
- destroy: me.onRegionDestroy,
- scope: me
- });
- me.setupState(comp);
- }
- }
- //<debug>
- if (!regions.center) {
- Ext.Error.raise("You must specify a center region when defining a BorderLayout.");
- }
- //</debug>
- comp = regions.center;
- if (!comp.flex) {
- comp.flex = 1;
- }
- delete comp.width;
- comp.maintainFlex = true;
- // Begin the VBox and HBox item list.
- comp = regions.west;
- if (comp) {
- comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
- hBoxItems.push(comp);
- if (comp.split) {
- hBoxItems.push(me.splitters.west = me.createSplitter(comp));
- }
- percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
- if (percentage) {
- horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
- delete comp.width;
- }
- }
- comp = regions.north;
- if (comp) {
- comp.collapseDirection = Ext.Component.DIRECTION_TOP;
- vBoxItems.push(comp);
- if (comp.split) {
- vBoxItems.push(me.splitters.north = me.createSplitter(comp));
- }
- percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
- if (percentage) {
- verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
- delete comp.height;
- }
- }
- // Decide into which Collection the center region goes.
- if (regions.north || regions.south) {
- if (regions.east || regions.west) {
- // Create the embedded center. Mark it with the region: 'center' property so that it can be identified as the center.
- vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
- xtype: 'container',
- region: 'center',
- id: me.owner.id + '-embedded-center',
- cls: Ext.baseCSSPrefix + 'border-item',
- flex: regions.center.flex,
- maintainFlex: true,
- layout: {
- type: 'hbox',
- align: 'stretch',
- getVisibleItems: me.getVisibleItems
- }
- }));
- hBoxItems.push(regions.center);
- }
- // No east or west: the original center goes straight into the vbox
- else {
- vBoxItems.push(regions.center);
- }
- }
- // If we have no north or south, then the center is part of the HBox items
- else {
- hBoxItems.push(regions.center);
- }
- // Finish off the VBox and HBox item list.
- comp = regions.south;
- if (comp) {
- comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
- if (comp.split) {
- vBoxItems.push(me.splitters.south = me.createSplitter(comp));
- }
- percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
- if (percentage) {
- verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
- delete comp.height;
- }
- vBoxItems.push(comp);
- }
- comp = regions.east;
- if (comp) {
- comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
- if (comp.split) {
- hBoxItems.push(me.splitters.east = me.createSplitter(comp));
- }
- percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
- if (percentage) {
- horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
- delete comp.width;
- }
- hBoxItems.push(comp);
- }
- // Create the injected "items" collections for the Containers.
- // If we have north or south, then the shadow Container will be a VBox.
- // If there are also east or west regions, its center will be a shadow HBox.
- // If there are *only* east or west regions, then the shadow layout will be an HBox (or Fit).
- if (regions.north || regions.south) {
- me.shadowContainer = Ext.create('Ext.container.Container', {
- ownerCt: me.owner,
- el: me.getTarget(),
- layout: Ext.applyIf({
- type: 'vbox',
- align: 'stretch',
- getVisibleItems: me.getVisibleItems
- }, me.initialConfig)
- });
- me.createItems(me.shadowContainer, vBoxItems);
- // Allow the Splitters to orientate themselves
- if (me.splitters.north) {
- me.splitters.north.ownerCt = me.shadowContainer;
- }
- if (me.splitters.south) {
- me.splitters.south.ownerCt = me.shadowContainer;
- }
- // Inject items into the HBox Container if there is one - if there was an east or west.
- if (me.embeddedContainer) {
- me.embeddedContainer.ownerCt = me.shadowContainer;
- me.createItems(me.embeddedContainer, hBoxItems);
- // Allow the Splitters to orientate themselves
- if (me.splitters.east) {
- me.splitters.east.ownerCt = me.embeddedContainer;
- }
- if (me.splitters.west) {
- me.splitters.west.ownerCt = me.embeddedContainer;
- }
- // These spliiters need to be constrained by components one-level below
- // the component in their vobx. We update the min/maxHeight on the helper
- // (embeddedContainer) prior to starting the split/drag. This has to be
- // done on-the-fly to allow min/maxHeight of the E/C/W regions to be set
- // dynamically.
- Ext.each([me.splitters.north, me.splitters.south], function (splitter) {
- if (splitter) {
- splitter.on('beforedragstart', me.fixHeightConstraints, me);
- }
- });
- // The east or west region wanted a percentage
- if (horizontalFlex) {
- regions.center.flex -= horizontalFlex;
- }
- // The north or south region wanted a percentage
- if (verticalFlex) {
- me.embeddedContainer.flex -= verticalFlex;
- }
- } else {
- // The north or south region wanted a percentage
- if (verticalFlex) {
- regions.center.flex -= verticalFlex;
- }
- }
- }
- // If we have no north or south, then there's only one Container, and it's
- // an HBox, or, if only a center region was specified, a Fit.
- else {
- me.shadowContainer = Ext.create('Ext.container.Container', {
- ownerCt: me.owner,
- el: me.getTarget(),
- layout: Ext.applyIf({
- type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
- align: 'stretch'
- }, me.initialConfig)
- });
- me.createItems(me.shadowContainer, hBoxItems);
- // Allow the Splitters to orientate themselves
- if (me.splitters.east) {
- me.splitters.east.ownerCt = me.shadowContainer;
- }
- if (me.splitters.west) {
- me.splitters.west.ownerCt = me.shadowContainer;
- }
- // The east or west region wanted a percentage
- if (horizontalFlex) {
- regions.center.flex -= verticalFlex;
- }
- }
- // Create upward links from the region Components to their shadow ownerCts
- for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
- items[i].shadowOwnerCt = me.shadowContainer;
- }
- if (me.embeddedContainer) {
- for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
- items[i].shadowOwnerCt = me.embeddedContainer;
- }
- }
- // This is the layout that we delegate all operations to
- me.shadowLayout = me.shadowContainer.getLayout();
- me.borderLayoutInitialized = true;
- },
- setupState: function(comp){
- var getState = comp.getState;
- comp.getState = function(){
- // call the original getState
- var state = getState.call(comp) || {},
- region = comp.region;
- state.collapsed = !!comp.collapsed;
- if (region == 'west' || region == 'east') {
- state.width = comp.getWidth();
- } else {
- state.height = comp.getHeight();
- }
- return state;
- };
- comp.addStateEvents(['collapse', 'expand', 'resize']);
- },
- <span id='Ext-layout-container-Border-method-createItems'> /**
- </span> * Create the items collection for our shadow/embedded containers
- * @private
- */
- createItems: function(container, items){
- // Have to inject an items Collection *after* construction.
- // The child items of the shadow layout must retain their original, user-defined ownerCt
- delete container.items;
- container.initItems();
- container.items.addAll(items);
- },
- // Private
- // Create a splitter for a child of the layout.
- createSplitter: function(comp) {
- var me = this,
- interceptCollapse = (comp.collapseMode != 'header'),
- resizer;
- resizer = Ext.create('Ext.resizer.Splitter', {
- hidden: !!comp.hidden,
- collapseTarget: comp,
- performCollapse: !interceptCollapse,
- listeners: interceptCollapse ? {
- click: {
- fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
- element: 'collapseEl'
- }
- } : null
- });
- // Mini collapse means that the splitter is the placeholder Component
- if (comp.collapseMode == 'mini') {
- comp.placeholder = resizer;
- resizer.collapsedCls = comp.collapsedCls;
- }
- // Arrange to hide/show a region's associated splitter when the region is hidden/shown
- comp.on({
- hide: me.onRegionVisibilityChange,
- show: me.onRegionVisibilityChange,
- scope: me
- });
- return resizer;
- },
- // Private
- // Propagates the min/maxHeight values from the inner hbox items to its container.
- fixHeightConstraints: function () {
- var me = this,
- ct = me.embeddedContainer,
- maxHeight = 1e99, minHeight = -1;
- if (!ct) {
- return;
- }
- ct.items.each(function (item) {
- if (Ext.isNumber(item.maxHeight)) {
- maxHeight = Math.max(maxHeight, item.maxHeight);
- }
- if (Ext.isNumber(item.minHeight)) {
- minHeight = Math.max(minHeight, item.minHeight);
- }
- });
- ct.maxHeight = maxHeight;
- ct.minHeight = minHeight;
- },
- // Hide/show a region's associated splitter when the region is hidden/shown
- onRegionVisibilityChange: function(comp){
- this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
- this.layout();
- },
- // Called when a splitter mini-collapse tool is clicked on.
- // The listener is only added if this layout is controlling collapsing,
- // not if the component's collapseMode is 'mini' or 'header'.
- onSplitterCollapseClick: function(comp) {
- if (comp.collapsed) {
- this.onPlaceHolderToolClick(null, null, null, {client: comp});
- } else {
- comp.collapse();
- }
- },
- <span id='Ext-layout-container-Border-method-getPlaceholder'> /**
- </span> * Return the {@link Ext.panel.Panel#placeholder placeholder} Component to which the passed child Panel of the
- * layout will collapse. By default, this will be a {@link Ext.panel.Header Header} component (Docked to the
- * appropriate border). See {@link Ext.panel.Panel#placeholder placeholder}. config to customize this.
- *
- * **Note that this will be a fully instantiated Component, but will only be _rendered_ when the Panel is first
- * collapsed.**
- * @param {Ext.panel.Panel} panel The child Panel of the layout for which to return the {@link
- * Ext.panel.Panel#placeholder placeholder}.
- * @return {Ext.Component} The Panel's {@link Ext.panel.Panel#placeholder placeholder} unless the {@link
- * Ext.panel.Panel#collapseMode collapseMode} is `'header'`, in which case _undefined_ is returned.
- */
- getPlaceholder: function(comp) {
- var me = this,
- placeholder = comp.placeholder,
- shadowContainer = comp.shadowOwnerCt,
- shadowLayout = shadowContainer.layout,
- oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
- horiz = (comp.region == 'north' || comp.region == 'south');
- // No placeholder if the collapse mode is not the Border layout default
- if (comp.collapseMode == 'header') {
- return;
- }
- // Provide a replacement Container with an expand tool
- if (!placeholder) {
- if (comp.collapseMode == 'mini') {
- placeholder = Ext.create('Ext.resizer.Splitter', {
- id: 'collapse-placeholder-' + comp.id,
- collapseTarget: comp,
- performCollapse: false,
- listeners: {
- click: {
- fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
- element: 'collapseEl'
- }
- }
- });
- placeholder.addCls(placeholder.collapsedCls);
- } else {
- placeholder = {
- id: 'collapse-placeholder-' + comp.id,
- margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
- xtype: 'header',
- orientation: horiz ? 'horizontal' : 'vertical',
- title: comp.title,
- textCls: comp.headerTextCls,
- iconCls: comp.iconCls,
- baseCls: comp.baseCls + '-header',
- ui: comp.ui,
- indicateDrag: comp.draggable,
- cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder ' + comp.collapsedCls,
- listeners: comp.floatable ? {
- click: {
- fn: function(e) {
- me.floatCollapsedPanel(e, comp);
- },
- element: 'el'
- }
- } : null
- };
- // Hack for IE6/7/IEQuirks's inability to display an inline-block
- if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
- placeholder.width = 25;
- }
- if (!comp.hideCollapseTool) {
- placeholder[horiz ? 'tools' : 'items'] = [{
- xtype: 'tool',
- client: comp,
- type: 'expand-' + oppositeDirection,
- handler: me.onPlaceHolderToolClick,
- scope: me
- }];
- }
- }
- placeholder = me.owner.createComponent(placeholder);
- if (comp.isXType('panel')) {
- comp.on({
- titlechange: me.onRegionTitleChange,
- iconchange: me.onRegionIconChange,
- scope: me
- });
- }
- }
- // The collapsed Component holds a reference to its placeholder and vice versa
- comp.placeholder = placeholder;
- placeholder.comp = comp;
- return placeholder;
- },
- <span id='Ext-layout-container-Border-method-onRegionTitleChange'> /**
- </span> * @private
- * Update the placeholder title when panel title has been set or changed.
- */
- onRegionTitleChange: function(comp, newTitle) {
- comp.placeholder.setTitle(newTitle);
- },
- <span id='Ext-layout-container-Border-method-onRegionIconChange'> /**
- </span> * @private
- * Update the placeholder iconCls when panel iconCls has been set or changed.
- */
- onRegionIconChange: function(comp, newIconCls) {
- comp.placeholder.setIconCls(newIconCls);
- },
- <span id='Ext-layout-container-Border-method-calculateChildBox'> /**
- </span> * @private
- * Calculates the size and positioning of the passed child item. Must be present because Panel's expand,
- * when configured with a flex, calls this method on its ownerCt's layout.
- * @param {Ext.Component} child The child Component to calculate the box for
- * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
- */
- calculateChildBox: function(comp) {
- var me = this;
- if (me.shadowContainer.items.contains(comp)) {
- return me.shadowContainer.layout.calculateChildBox(comp);
- }
- else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
- return me.embeddedContainer.layout.calculateChildBox(comp);
- }
- },
- <span id='Ext-layout-container-Border-method-onBeforeRegionCollapse'> /**
- </span> * @private
- * Intercepts the Panel's own collapse event and perform's substitution of the Panel
- * with a placeholder Header orientated in the appropriate dimension.
- * @param comp The Panel being collapsed.
- * @param direction
- * @param animate
- * @returns {Boolean} false to inhibit the Panel from performing its own collapse.
- */
- onBeforeRegionCollapse: function(comp, direction, animate) {
- if (comp.collapsedChangingLayout) {
- //<debug warn>
- if (Ext.global.console && Ext.global.console.warn) {
- Ext.global.console.warn(Ext.getDisplayName(arguments.callee), 'aborted because the collapsed state is in the middle of changing');
- }
- //</debug>
- return false;
- }
- comp.collapsedChangingLayout = true;
- var me = this,
- compEl = comp.el,
- width,
- miniCollapse = comp.collapseMode == 'mini',
- shadowContainer = comp.shadowOwnerCt,
- shadowLayout = shadowContainer.layout,
- placeholder = comp.placeholder,
- sl = me.owner.suspendLayout,
- scsl = shadowContainer.suspendLayout,
- isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); // Flag to keep the placeholder non-adjacent to any Splitter
- // Do not trigger a layout during transition to collapsed Component
- me.owner.suspendLayout = true;
- shadowContainer.suspendLayout = true;
- // Prevent upward notifications from downstream layouts
- shadowLayout.layoutBusy = true;
- if (shadowContainer.componentLayout) {
- shadowContainer.componentLayout.layoutBusy = true;
- }
- me.shadowContainer.layout.layoutBusy = true;
- me.layoutBusy = true;
- me.owner.componentLayout.layoutBusy = true;
- // Provide a replacement Container with an expand tool
- if (!placeholder) {
- placeholder = me.getPlaceholder(comp);
- }
- // placeholder already in place; show it.
- if (placeholder.shadowOwnerCt === shadowContainer) {
- placeholder.show();
- }
- // Insert the collapsed placeholder Component into the appropriate Box layout shadow Container
- // It must go next to its client Component, but non-adjacent to the splitter so splitter can find its collapse client.
- // Inject an ownerCt value pointing to the owner, border layout Container as the user will expect.
- else {
- shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
- placeholder.shadowOwnerCt = shadowContainer;
- placeholder.ownerCt = me.owner;
- }
- // Flag the collapsing Component as hidden and show the placeholder.
- // This causes the shadow Box layout's calculateChildBoxes to calculate the correct new arrangement.
- // We hide or slideOut the Component's element
- comp.hidden = true;
- if (!placeholder.rendered) {
- shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
- // The inserted placeholder does not have the proper size, so copy the width
- // for N/S or the height for E/W from the component. This fixes EXTJSIV-1562
- // without recursive layouts. This is only an issue initially. After this time,
- // placeholder will have the correct width/height set by the layout (which has
- // already happened when we get here initially).
- if (comp.region == 'north' || comp.region == 'south') {
- placeholder.setCalculatedSize(comp.getWidth());
- } else {
- placeholder.setCalculatedSize(undefined, comp.getHeight());
- }
- }
- // Jobs to be done after the collapse has been done
- function afterCollapse() {
- // Reinstate automatic laying out.
- me.owner.suspendLayout = sl;
- shadowContainer.suspendLayout = scsl;
- delete shadowLayout.layoutBusy;
- if (shadowContainer.componentLayout) {
- delete shadowContainer.componentLayout.layoutBusy;
- }
- delete me.shadowContainer.layout.layoutBusy;
- delete me.layoutBusy;
- delete me.owner.componentLayout.layoutBusy;
- delete comp.collapsedChangingLayout;
- // Fire the collapse event: The Panel has in fact been collapsed, but by substitution of an alternative Component
- comp.collapsed = true;
- comp.fireEvent('collapse', comp);
- }
- /*
- * Set everything to the new positions. Note that we
- * only want to animate the collapse if it wasn't configured
- * initially with collapsed: true
- */
- if (comp.animCollapse && me.initialCollapsedComplete) {
- shadowLayout.layout();
- compEl.dom.style.zIndex = 100;
- // If we're mini-collapsing, the placholder is a Splitter. We don't want it to "bounce in"
- if (!miniCollapse) {
- placeholder.el.hide();
- }
- compEl.slideOut(me.slideDirection[comp.region], {
- duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
- listeners: {
- afteranimate: function() {
- compEl.show().setLeftTop(-10000, -10000);
- compEl.dom.style.zIndex = '';
- // If we're mini-collapsing, the placholder is a Splitter. We don't want it to "bounce in"
- if (!miniCollapse) {
- placeholder.el.slideIn(me.slideDirection[comp.region], {
- easing: 'linear',
- duration: 100
- });
- }
- afterCollapse();
- }
- }
- });
- } else {
- compEl.setLeftTop(-10000, -10000);
- shadowLayout.layout();
- afterCollapse();
- }
- return false;
- },
- // Hijack the expand operation to remove the placeholder and slide the region back in.
- onBeforeRegionExpand: function(comp, animate) {
- // We don't check for comp.collapsedChangingLayout here because onPlaceHolderToolClick does it
- this.onPlaceHolderToolClick(null, null, null, {client: comp, shouldFireBeforeexpand: false});
- return false;
- },
- // Called when the collapsed placeholder is clicked to reinstate a "collapsed" (in reality hidden) Panel.
- onPlaceHolderToolClick: function(e, target, owner, tool) {
- var me = this,
- comp = tool.client,
- // Hide the placeholder unless it was the Component's preexisting splitter
- hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
- compEl = comp.el,
- toCompBox,
- placeholder = comp.placeholder,
- placeholderEl = placeholder.el,
- shadowContainer = comp.shadowOwnerCt,
- shadowLayout = shadowContainer.layout,
- curSize,
- sl = me.owner.suspendLayout,
- scsl = shadowContainer.suspendLayout,
- isFloating;
- if (comp.collapsedChangingLayout) {
- //<debug warn>
- if (Ext.global.console && Ext.global.console.warn) {
- Ext.global.console.warn(Ext.getDisplayName(arguments.callee), 'aborted because the collapsed state is in the middle of changing');
- }
- //</debug>
- return false;
- }
- if (tool.shouldFireBeforeexpand !== false && comp.fireEvent('beforeexpand', comp, true) === false) {
- return false;
- }
- comp.collapsedChangingLayout = true;
- // If the slide in is still going, stop it.
- // This will either leave the Component in its fully floated state (which is processed below)
- // or in its collapsed state. Either way, we expand it..
- if (comp.getActiveAnimation()) {
- comp.stopAnimation();
- }
- // If the Component is fully floated when they click the placeholder Tool,
- // it will be primed with a slide out animation object... so delete that
- // and remove the mouseout listeners
- if (comp.slideOutAnim) {
- // Remove mouse leave monitors
- compEl.un(comp.panelMouseMon);
- placeholderEl.un(comp.placeholderMouseMon);
- delete comp.slideOutAnim;
- delete comp.panelMouseMon;
- delete comp.placeholderMouseMon;
- // If the Panel was floated and primed with a slideOut animation, we don't want to animate its layout operation.
- isFloating = true;
- }
- // Do not trigger a layout during transition to expanded Component
- me.owner.suspendLayout = true;
- shadowContainer.suspendLayout = true;
- // Prevent upward notifications from downstream layouts
- shadowLayout.layoutBusy = true;
- if (shadowContainer.componentLayout) {
- shadowContainer.componentLayout.layoutBusy = true;
- }
- me.shadowContainer.layout.layoutBusy = true;
- me.layoutBusy = true;
- me.owner.componentLayout.layoutBusy = true;
- // Unset the hidden and collapsed flags set in onBeforeRegionCollapse. The shadowLayout will now take it into account
- // Find where the shadow Box layout plans to put the expanding Component.
- comp.hidden = false;
- comp.collapsed = false;
- if (hidePlaceholder) {
- placeholder.hidden = true;
- }
- toCompBox = shadowLayout.calculateChildBox(comp);
- // Show the collapse tool in case it was hidden by the slide-in
- if (comp.collapseTool) {
- comp.collapseTool.show();
- }
- // If we're going to animate, we need to hide the component before moving it back into position
- if (comp.animCollapse && !isFloating) {
- compEl.setStyle('visibility', 'hidden');
- }
- compEl.setLeftTop(toCompBox.left, toCompBox.top);
- // Equalize the size of the expanding Component prior to animation
- // in case the layout area has changed size during the time it was collapsed.
- curSize = comp.getSize();
- if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
- me.setItemSize(comp, toCompBox.width, toCompBox.height);
- }
- // Jobs to be done after the expand has been done
- function afterExpand() {
- // Reinstate automatic laying out.
- me.owner.suspendLayout = sl;
- shadowContainer.suspendLayout = scsl;
- delete shadowLayout.layoutBusy;
- if (shadowContainer.componentLayout) {
- delete shadowContainer.componentLayout.layoutBusy;
- }
- delete me.shadowContainer.layout.layoutBusy;
- delete me.layoutBusy;
- delete me.owner.componentLayout.layoutBusy;
- delete comp.collapsedChangingLayout;
- // In case it was floated out and they clicked the re-expand tool
- comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
- // Fire the expand event: The Panel has in fact been expanded, but by removal of an alternative Component
- comp.fireEvent('expand', comp);
- }
- // Hide the placeholder
- if (hidePlaceholder) {
- placeholder.el.hide();
- }
- // Slide the expanding Component to its new position.
- // When that is done, layout the layout.
- if (comp.animCollapse && !isFloating) {
- compEl.dom.style.zIndex = 100;
- compEl.slideIn(me.slideDirection[comp.region], {
- duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
- listeners: {
- afteranimate: function() {
- compEl.dom.style.zIndex = '';
- comp.hidden = false;
- shadowLayout.onLayout();
- afterExpand();
- }
- }
- });
- } else {
- shadowLayout.onLayout();
- afterExpand();
- }
- },
- floatCollapsedPanel: function(e, comp) {
- if (comp.floatable === false) {
- return;
- }
- var me = this,
- compEl = comp.el,
- placeholder = comp.placeholder,
- placeholderEl = placeholder.el,
- shadowContainer = comp.shadowOwnerCt,
- shadowLayout = shadowContainer.layout,
- placeholderBox = shadowLayout.getChildBox(placeholder),
- scsl = shadowContainer.suspendLayout,
- curSize, toCompBox, compAnim;
- // Ignore clicks on tools.
- if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
- return;
- }
- // It's *being* animated, ignore the click.
- // Possible future enhancement: Stop and *reverse* the current active Fx.
- if (compEl.getActiveAnimation()) {
- return;
- }
- // If the Component is already fully floated when they click the placeholder,
- // it will be primed with a slide out animation object... so slide it out.
- if (comp.slideOutAnim) {
- me.slideOutFloatedComponent(comp);
- return;
- }
- // Function to be called when the mouse leaves the floated Panel
- // Slide out when the mouse leaves the region bounded by the slid Component and its placeholder.
- function onMouseLeaveFloated(e) {
- var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
- // If mouse is not within slide Region, slide it out
- if (!slideRegion.contains(e.getPoint())) {
- me.slideOutFloatedComponent(comp);
- }
- }
- // Monitor for mouseouting of the placeholder. Hide it if they exit for half a second or more
- comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
- // Do not trigger a layout during slide out of the Component
- shadowContainer.suspendLayout = true;
- // Prevent upward notifications from downstream layouts
- me.layoutBusy = true;
- me.owner.componentLayout.layoutBusy = true;
- // The collapse tool is hidden while slid.
- // It is re-shown on expand.
- if (comp.collapseTool) {
- comp.collapseTool.hide();
- }
- // Set flags so that the layout will calculate the boxes for what we want
- comp.hidden = false;
- comp.collapsed = false;
- placeholder.hidden = true;
- // Recalculate new arrangement of the Component being floated.
- toCompBox = shadowLayout.calculateChildBox(comp);
- placeholder.hidden = false;
- // Component to appear just after the placeholder, whatever "after" means in the context of the shadow Box layout.
- if (comp.region == 'north' || comp.region == 'west') {
- toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
- } else {
- toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
- }
- compEl.setStyle('visibility', 'hidden');
- compEl.setLeftTop(toCompBox.left, toCompBox.top);
- // Equalize the size of the expanding Component prior to animation
- // in case the layout area has changed size during the time it was collapsed.
- curSize = comp.getSize();
- if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
- me.setItemSize(comp, toCompBox.width, toCompBox.height);
- }
- // This animation slides the collapsed Component's el out to just beyond its placeholder
- compAnim = {
- listeners: {
- afteranimate: function() {
- shadowContainer.suspendLayout = scsl;
- delete me.layoutBusy;
- delete me.owner.componentLayout.layoutBusy;
- // Prime the Component with an Anim config object to slide it back out
- compAnim.listeners = {
- afterAnimate: function() {
- compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
- // Reinstate the correct, current state after slide out animation finishes
- comp.hidden = true;
- comp.collapsed = true;
- delete comp.slideOutAnim;
- delete comp.panelMouseMon;
- delete comp.placeholderMouseMon;
- }
- };
- comp.slideOutAnim = compAnim;
- }
- },
- duration: 500
- };
- // Give the element the correct class which places it at a high z-index
- compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
- // Begin the slide in
- compEl.slideIn(me.slideDirection[comp.region], compAnim);
- // Monitor for mouseouting of the slid area. Hide it if they exit for half a second or more
- comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
- },
- slideOutFloatedComponent: function(comp) {
- var compEl = comp.el,
- slideOutAnim;
- // Remove mouse leave monitors
- compEl.un(comp.panelMouseMon);
- comp.placeholder.el.un(comp.placeholderMouseMon);
- // Slide the Component out
- compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
- delete comp.slideOutAnim;
- delete comp.panelMouseMon;
- delete comp.placeholderMouseMon;
- },
- /*
- * @private
- * Ensure any collapsed placeholder Component is destroyed along with its region.
- * Can't do this in onDestroy because they may remove a Component and use it elsewhere.
- */
- onRegionDestroy: function(comp) {
- var placeholder = comp.placeholder;
- if (placeholder) {
- delete placeholder.ownerCt;
- placeholder.destroy();
- }
- },
- /*
- * @private
- * Ensure any shadow Containers are destroyed.
- * Ensure we don't keep references to Components.
- */
- onDestroy: function() {
- var me = this,
- shadowContainer = me.shadowContainer,
- embeddedContainer = me.embeddedContainer;
- if (shadowContainer) {
- delete shadowContainer.ownerCt;
- Ext.destroy(shadowContainer);
- }
- if (embeddedContainer) {
- delete embeddedContainer.ownerCt;
- Ext.destroy(embeddedContainer);
- }
- delete me.regions;
- delete me.splitters;
- delete me.shadowContainer;
- delete me.embeddedContainer;
- me.callParent(arguments);
- }
- });
- </pre>
- </body>
- </html>