cmp-foundation-debug.js
资源名称:ext-3.1.0.zip [点击查看]
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:446k
源码类别:
JavaScript
开发平台:
JavaScript
- * @param {Function} onComplete A function to be invoked when resizing is complete
- */
- setElementSize : function(s, newSize, onComplete){
- if(s.orientation == Ext.SplitBar.HORIZONTAL){
- if(!s.animate){
- s.resizingEl.setWidth(newSize);
- if(onComplete){
- onComplete(s, newSize);
- }
- }else{
- s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
- }
- }else{
- if(!s.animate){
- s.resizingEl.setHeight(newSize);
- if(onComplete){
- onComplete(s, newSize);
- }
- }else{
- s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
- }
- }
- }
- };
- /**
- *@class Ext.SplitBar.AbsoluteLayoutAdapter
- * @extends Ext.SplitBar.BasicLayoutAdapter
- * Adapter that moves the splitter element to align with the resized sizing element.
- * Used with an absolute positioned SplitBar.
- * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
- * document.body, make sure you assign an id to the body element.
- */
- Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
- this.basic = new Ext.SplitBar.BasicLayoutAdapter();
- this.container = Ext.get(container);
- };
- Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
- init : function(s){
- this.basic.init(s);
- },
- getElementSize : function(s){
- return this.basic.getElementSize(s);
- },
- setElementSize : function(s, newSize, onComplete){
- this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
- },
- moveSplitter : function(s){
- var yes = Ext.SplitBar;
- switch(s.placement){
- case yes.LEFT:
- s.el.setX(s.resizingEl.getRight());
- break;
- case yes.RIGHT:
- s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
- break;
- case yes.TOP:
- s.el.setY(s.resizingEl.getBottom());
- break;
- case yes.BOTTOM:
- s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
- break;
- }
- }
- };
- /**
- * Orientation constant - Create a vertical SplitBar
- * @static
- * @type Number
- */
- Ext.SplitBar.VERTICAL = 1;
- /**
- * Orientation constant - Create a horizontal SplitBar
- * @static
- * @type Number
- */
- Ext.SplitBar.HORIZONTAL = 2;
- /**
- * Placement constant - The resizing element is to the left of the splitter element
- * @static
- * @type Number
- */
- Ext.SplitBar.LEFT = 1;
- /**
- * Placement constant - The resizing element is to the right of the splitter element
- * @static
- * @type Number
- */
- Ext.SplitBar.RIGHT = 2;
- /**
- * Placement constant - The resizing element is positioned above the splitter element
- * @static
- * @type Number
- */
- Ext.SplitBar.TOP = 3;
- /**
- * Placement constant - The resizing element is positioned under splitter element
- * @static
- * @type Number
- */
- Ext.SplitBar.BOTTOM = 4;
- /** * @class Ext.Container * @extends Ext.BoxComponent * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the * basic behavior of containing items, namely adding, inserting and removing items.</p> * * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}. * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight * Container to be encapsulated by an HTML element to your specifications by using the * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels} * for example.</p> * * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly * create one using the <b><code>'container'</code></b> xtype:<pre><code> // explicitly create a Container var embeddedColumns = new Ext.Container({ autoEl: 'div', // This is the default layout: 'column', defaults: { // implicitly create Container by specifying xtype xtype: 'container', autoEl: 'div', // This is the default. layout: 'form', columnWidth: 0.5, style: { padding: '10px' } }, // The two items below will be Ext.Containers, each encapsulated by a <DIV> element. items: [{ items: { xtype: 'datefield', name: 'startDate', fieldLabel: 'Start date' } }, { items: { xtype: 'datefield', name: 'endDate', fieldLabel: 'End date' } }] });</code></pre></p> * * <p><u><b>Layout</b></u></p> * <p>Container classes delegate the rendering of child Components to a layout * manager class which must be configured into the Container using the * <code><b>{@link #layout}</b></code> configuration property.</p> * <p>When either specifying child <code>{@link #items}</code> of a Container, * or dynamically {@link #add adding} Components to a Container, remember to * consider how you wish the Container to arrange those child elements, and * whether those child elements need to be sized using one of Ext's built-in * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only * renders child components, appending them one after the other inside the * Container, and <b>does not apply any sizing</b> at all.</p> * <p>A common mistake is when a developer neglects to specify a * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code> * has been specified). If a Container is left to use the default * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its * child components will be resized, or changed in any way when the Container * is resized.</p> * <p>Certain layout managers allow dynamic addition of child components. * Those that do include {@link Ext.layout.CardLayout}, * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and * {@link Ext.layout.TableLayout}. For example:<pre><code> // Create the GridPanel. var myNewGrid = new Ext.grid.GridPanel({ store: myStore, columns: myColumnModel, title: 'Results', // the title becomes the title of the tab }); myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout} myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid); * </code></pre></p> * <p>The example above adds a newly created GridPanel to a TabPanel. Note that * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which * means all its child items are sized to {@link Ext.layout.FitLayout fit} * exactly into its client area. * <p><b><u>Overnesting is a common problem</u></b>. * An example of overnesting occurs when a GridPanel is added to a TabPanel * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a * Component which can be added directly to a Container. If the wrapping Panel * has no <code><b>{@link #layout}</b></code> configuration, then the overnested * GridPanel will not be sized as expected.<p> * * <p><u><b>Adding via remote configuration</b></u></p> * * <p>A server side script can be used to add Components which are generated dynamically on the server. * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server * based on certain parameters: * </p><pre><code> // execute an Ajax request to invoke server side script: Ext.Ajax.request({ url: 'gen-invoice-grid.php', // send additional parameters to instruct server script params: { startDate: Ext.getCmp('start-date').getValue(), endDate: Ext.getCmp('end-date').getValue() }, // process the response object to add it to the TabPanel: success: function(xhr) { var newComponent = eval(xhr.responseText); // see discussion below myTabPanel.add(newComponent); // add the component to the TabPanel myTabPanel.setActiveTab(newComponent); }, failure: function() { Ext.Msg.alert("Grid create failed", "Server communication failure"); } }); </code></pre> * <p>The server script needs to return an executable Javascript statement which, when processed * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype}, * or an instantiated Component. The server might return this for example:</p><pre><code> (function() { function formatDate(value){ return value ? value.dateFormat('M d, Y') : ''; }; var store = new Ext.data.Store({ url: 'get-invoice-data.php', baseParams: { startDate: '01/01/2008', endDate: '01/31/2008' }, reader: new Ext.data.JsonReader({ record: 'transaction', idProperty: 'id', totalRecords: 'total' }, [ 'customer', 'invNo', {name: 'date', type: 'date', dateFormat: 'm/d/Y'}, {name: 'value', type: 'float'} ]) }); var grid = new Ext.grid.GridPanel({ title: 'Invoice Report', bbar: new Ext.PagingToolbar(store), store: store, columns: [ {header: "Customer", width: 250, dataIndex: 'customer', sortable: true}, {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true}, {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true}, {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true} ], }); store.load(); return grid; // return instantiated component })(); </code></pre> * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function * runs, and returns the instantiated grid component.</p> * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for * the Store, the metadata to allow generation of the Record layout, and the ColumnModel * can all be generated into the code since these are all known on the server.</p> * * @xtype container */ Ext.Container = Ext.extend(Ext.BoxComponent, { /** * @cfg {Boolean} monitorResize * True to automatically monitor window resize events to handle anything that is sensitive to the current size * of the viewport. This value is typically managed by the chosen <code>{@link #layout}</code> and should not need * to be set manually. */ /** * @cfg {String/Object} layout * <p><b>*Important</b>: In order for child items to be correctly sized and * positioned, typically a layout manager <b>must</b> be specified through * the <code>layout</code> configuration option.</p> * <br><p>The sizing and positioning of child {@link items} is the responsibility of * the Container's layout manager which creates and manages the type of layout * you have in mind. For example:</p><pre><code> new Ext.Window({ width:300, height: 300, layout: 'fit', // explicitly set layout manager: override the default (layout:'auto') items: [{ title: 'Panel inside a Window' }] }).show(); * </code></pre> * <p>If the {@link #layout} configuration is not explicitly specified for * a general purpose container (e.g. Container or Panel) the * {@link Ext.layout.ContainerLayout default layout manager} will be used * which does nothing but render child components sequentially into the * Container (no sizing or positioning will be performed in this situation). * Some container classes implicitly specify a default layout * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific * purpose classes internally specify/manage their internal layout (e.g. * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p> * <br><p><b><code>layout</code></b> may be specified as either as an Object or * as a String:</p><div><ul class="mdetail-params"> * * <li><u>Specify as an Object</u></li> * <div><ul class="mdetail-params"> * <li>Example usage:</li> <pre><code> layout: { type: 'vbox', padding: '5', align: 'left' } </code></pre> * * <li><code><b>type</b></code></li> * <br/><p>The layout type to be used for this container. If not specified, * a default {@link Ext.layout.ContainerLayout} will be created and used.</p> * <br/><p>Valid layout <code>type</code> values are:</p> * <div class="sub-desc"><ul class="mdetail-params"> * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li> * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li> * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li> * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> <b>Default</b></li> * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li> * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li> * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li> * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li> * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li> * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li> * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li> * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li> * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li> * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li> * </ul></div> * * <li>Layout specific configuration properties</li> * <br/><p>Additional layout specific configuration properties may also be * specified. For complete details regarding the valid config options for * each layout type, see the layout class corresponding to the <code>type</code> * specified.</p> * * </ul></div> * * <li><u>Specify as a String</u></li> * <div><ul class="mdetail-params"> * <li>Example usage:</li> <pre><code> layout: 'vbox', layoutConfig: { padding: '5', align: 'left' } </code></pre> * <li><code><b>layout</b></code></li> * <br/><p>The layout <code>type</code> to be used for this container (see list * of valid layout type values above).</p><br/> * <li><code><b>{@link #layoutConfig}</b></code></li> * <br/><p>Additional layout specific configuration properties. For complete * details regarding the valid config options for each layout type, see the * layout class corresponding to the <code>layout</code> specified.</p> * </ul></div></ul></div> */ /** * @cfg {Object} layoutConfig * This is a config object containing properties specific to the chosen * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b> * has been specified as a <i>string</i>.</p> */ /** * @cfg {Boolean/Number} bufferResize * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>. */ bufferResize: 50, /** * @cfg {String/Number} activeItem * A string component id or the numeric index of the component that should be initially activated within the * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first * item in the container's collection). activeItem only applies to layout styles that can display * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}. */ /** * @cfg {Object/Array} items * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre> * <p>A single item, or an array of child Components to be added to this container, * for example:</p> * <pre><code> // specifying a single item items: {...}, layout: 'fit', // specify a layout! // specifying multiple items items: [{...}, {...}], layout: 'anchor', // specify a layout! * </code></pre> * <p>Each item may be:</p> * <div><ul class="mdetail-params"> * <li>any type of object based on {@link Ext.Component}</li> * <li>a fully instanciated object or</li> * <li>an object literal that:</li> * <div><ul class="mdetail-params"> * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li> * <li>the {@link Ext.Component#xtype} specified is associated with the Component * desired and should be chosen from one of the available xtypes as listed * in {@link Ext.Component}.</li> * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly * specified, the {@link #defaultType} for that Container is used.</li> * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully * instanciated Component object</li> * </ul></div></ul></div> * <p><b>Notes</b>:</p> * <div><ul class="mdetail-params"> * <li>Ext uses lazy rendering. Child Components will only be rendered * should it become necessary. Items are automatically laid out when they are first * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li> * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/ * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li> * </ul></div> */ /** * @cfg {Object|Function} defaults * <p>This option is a means of applying default settings to all added items whether added through the {@link #items} * config or via the {@link #add} or {@link #insert} methods.</p> * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are * applied conditionally so as not to override existing properties in the item.</p> * <p>If the defaults option is specified as a function, then the function will be called using this Container as the * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object * from that call is then applied to the item as default properties.</p> * <p>For example, to automatically apply padding to the body of each of a set of * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p> * <p>Usage:</p><pre><code> defaults: { // defaults are applied to items, not the container autoScroll:true }, items: [ { xtype: 'panel', // defaults <b>do not</b> have precedence over id: 'panel1', // options in config objects, so the defaults autoScroll: false // will not be applied here, panel1 will be autoScroll:false }, new Ext.Panel({ // defaults <b>do</b> have precedence over options id: 'panel2', // options in components, so the defaults autoScroll: false // will be applied here, panel2 will be autoScroll:true. }) ] * </code></pre> */ /** @cfg {Boolean} autoDestroy * If true the container will automatically destroy any contained component that is removed from it, else * destruction must be handled manually (defaults to true). */ autoDestroy : true, /** @cfg {Boolean} forceLayout * If true the container will force a layout initially even if hidden or collapsed. This option * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false). */ forceLayout: false, /** @cfg {Boolean} hideBorders * True to hide the borders of each contained component, false to defer to the component's existing * border settings (defaults to false). */ /** @cfg {String} defaultType * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p> * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>, * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p> */ defaultType : 'panel', /** @cfg {String} resizeEvent * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>. */ resizeEvent: 'resize', /** * @cfg {Array} bubbleEvents * <p>An array of events that, when fired, should be bubbled to any parent container. * See {@link Ext.util.Observable#enableBubble}. * Defaults to <code>['add', 'remove']</code>. */ bubbleEvents: ['add', 'remove'], // private initComponent : function(){ Ext.Container.superclass.initComponent.call(this); this.addEvents( /** * @event afterlayout * Fires when the components in this container are arranged by the associated layout manager. * @param {Ext.Container} this * @param {ContainerLayout} layout The ContainerLayout implementation for this container */ 'afterlayout', /** * @event beforeadd * Fires before any {@link Ext.Component} is added or inserted into the container. * A handler can return false to cancel the add. * @param {Ext.Container} this * @param {Ext.Component} component The component being added * @param {Number} index The index at which the component will be added to the container's items collection */ 'beforeadd', /** * @event beforeremove * Fires before any {@link Ext.Component} is removed from the container. A handler can return * false to cancel the remove. * @param {Ext.Container} this * @param {Ext.Component} component The component being removed */ 'beforeremove', /** * @event add * @bubbles * Fires after any {@link Ext.Component} is added or inserted into the container. * @param {Ext.Container} this * @param {Ext.Component} component The component that was added * @param {Number} index The index at which the component was added to the container's items collection */ 'add', /** * @event remove * @bubbles * Fires after any {@link Ext.Component} is removed from the container. * @param {Ext.Container} this * @param {Ext.Component} component The component that was removed */ 'remove' ); this.enableBubble(this.bubbleEvents); /** * The collection of components in this container as a {@link Ext.util.MixedCollection} * @type MixedCollection * @property items */ var items = this.items; if(items){ delete this.items; this.add(items); } }, // private initItems : function(){ if(!this.items){ this.items = new Ext.util.MixedCollection(false, this.getComponentId); this.getLayout(); // initialize the layout } }, // private setLayout : function(layout){ if(this.layout && this.layout != layout){ this.layout.setContainer(null); } this.initItems(); this.layout = layout; layout.setContainer(this); }, afterRender: function(){ this.layoutDone = false; if(!this.layout){ this.layout = 'auto'; } if(Ext.isObject(this.layout) && !this.layout.layout){ this.layoutConfig = this.layout; this.layout = this.layoutConfig.type; } if(Ext.isString(this.layout)){ this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig); } this.setLayout(this.layout); // BoxComponent's afterRender will set the size. // This will will trigger a layout if the layout is configured to monitor resize Ext.Container.superclass.afterRender.call(this); if(Ext.isDefined(this.activeItem)){ var item = this.activeItem; delete this.activeItem; this.layout.setActiveItem(item); } // If we have no ownerCt and the BoxComponent's sizing did not trigger a layout, force a layout if(!this.ownerCt && !this.layoutDone){ this.doLayout(false, true); } if(this.monitorResize === true){ Ext.EventManager.onWindowResize(this.doLayout, this, [false]); } }, /** * <p>Returns the Element to be used to contain the child Components of this Container.</p> * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but * if there is a more complex structure to a Container, this may be overridden to return * the element into which the {@link #layout layout} renders child Components.</p> * @return {Ext.Element} The Element to render child Components into. */ getLayoutTarget : function(){ return this.el; }, // private - used as the key lookup function for the items collection getComponentId : function(comp){ return comp.getItemId(); }, /** * <p>Adds {@link Ext.Component Component}(s) to this Container.</p> * <br><p><b>Description</b></u> : * <div><ul class="mdetail-params"> * <li>Fires the {@link #beforeadd} event before adding</li> * <li>The Container's {@link #defaults default config values} will be applied * accordingly (see <code>{@link #defaults}</code> for details).</li> * <li>Fires the {@link #add} event after the component has been added.</li> * </ul></div> * <br><p><b>Notes</b></u> : * <div><ul class="mdetail-params"> * <li>If the Container is <i>already rendered</i> when <code>add</code> * is called, you may need to call {@link #doLayout} to refresh the view which causes * any unrendered child Components to be rendered. This is required so that you can * <code>add</code> multiple child components if needed while only refreshing the layout * once. For example:<pre><code> var tb = new {@link Ext.Toolbar}(); tb.render(document.body); // toolbar is rendered tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button') tb.add({text:'Button 2'}); tb.{@link #doLayout}(); // refresh the layout * </code></pre></li> * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager * may not be removed or added. See the Notes for {@link Ext.layout.BorderLayout BorderLayout} * for more details.</li> * </ul></div> * @param {Object/Array} component * <p>Either a single component or an Array of components to add. See * <code>{@link #items}</code> for additional information.</p> * @param {Object} (Optional) component_2 * @param {Object} (Optional) component_n * @return {Ext.Component} component The Component (or config object) that was added. */ add : function(comp){ this.initItems(); var args = arguments.length > 1; if(args || Ext.isArray(comp)){ var result = []; Ext.each(args ? arguments : comp, function(c){ result.push(this.add(c)); }, this); return result; } var c = this.lookupComponent(this.applyDefaults(comp)); var index = this.items.length; if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){ this.items.add(c); // *onAdded c.onAdded(this, index); this.onAdd(c); this.fireEvent('add', this, c, index); } return c; }, onAdd : function(c){ // Empty template method }, // private onAdded : function(container, pos) { //overridden here so we can cascade down, not worth creating a template method. this.ownerCt = container; this.initRef(); //initialize references for child items this.cascade(function(c){ c.initRef(); }); this.fireEvent('added', this, container, pos); }, /** * Inserts a Component into this Container at a specified index. Fires the * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the * Component has been inserted. * @param {Number} index The index at which the Component will be inserted * into the Container's items collection * @param {Ext.Component} component The child Component to insert.<br><br> * Ext uses lazy rendering, and will only render the inserted Component should * it become necessary.<br><br> * A Component config object may be passed in order to avoid the overhead of * constructing a real Component object if lazy rendering might mean that the * inserted Component will not be rendered immediately. To take advantage of * this 'lazy instantiation', set the {@link Ext.Component#xtype} config * property to the registered type of the Component wanted.<br><br> * For a list of all available xtypes, see {@link Ext.Component}. * @return {Ext.Component} component The Component (or config object) that was * inserted with the Container's default config values applied. */ insert : function(index, comp){ this.initItems(); var a = arguments, len = a.length; if(len > 2){ var result = []; for(var i = len-1; i >= 1; --i) { result.push(this.insert(index, a[i])); } return result; } var c = this.lookupComponent(this.applyDefaults(comp)); index = Math.min(index, this.items.length); if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){ if(c.ownerCt == this){ this.items.remove(c); } this.items.insert(index, c); c.onAdded(this, index); this.onAdd(c); this.fireEvent('add', this, c, index); } return c; }, // private applyDefaults : function(c){ var d = this.defaults; if(d){ if(Ext.isFunction(d)){ d = d.call(this, c); } if(Ext.isString(c)){ c = Ext.ComponentMgr.get(c); Ext.apply(c, d); }else if(!c.events){ Ext.applyIf(c, d); }else{ Ext.apply(c, d); } } return c; }, // private onBeforeAdd : function(item){ if(item.ownerCt){ item.ownerCt.remove(item, false); } if(this.hideBorders === true){ item.border = (item.border === true); } }, /** * Removes a component from this container. Fires the {@link #beforeremove} event before removing, then fires * the {@link #remove} event after the component has been removed. * @param {Component/String} component The component reference or id to remove. * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function. * Defaults to the value of this Container's {@link #autoDestroy} config. * @return {Ext.Component} component The Component that was removed. */ remove : function(comp, autoDestroy){ this.initItems(); var c = this.getComponent(comp); if(c && this.fireEvent('beforeremove', this, c) !== false){ this.doRemove(c, autoDestroy); this.fireEvent('remove', this, c); } return c; }, onRemove: function(c){ // Empty template method }, // private doRemove: function(c, autoDestroy){ if(this.layout && this.rendered){ this.layout.onRemove(c); } this.items.remove(c); c.onRemoved(); this.onRemove(c); if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){ c.destroy(); } }, /** * Removes all components from this container. * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function. * Defaults to the value of this Container's {@link #autoDestroy} config. * @return {Array} Array of the destroyed components */ removeAll: function(autoDestroy){ this.initItems(); var item, rem = [], items = []; this.items.each(function(i){ rem.push(i); }); for (var i = 0, len = rem.length; i < len; ++i){ item = rem[i]; this.remove(item, autoDestroy); if(item.ownerCt !== this){ items.push(item); } } return items; }, /** * Examines this container's <code>{@link #items}</code> <b>property</b> * and gets a direct child component of this container. * @param {String/Number} comp This parameter may be any of the following: * <div><ul class="mdetail-params"> * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code> * or <code>{@link Ext.Component#id id}</code> of the child component </li> * <li>a <b><code>Number</code></b> : representing the position of the child component * within the <code>{@link #items}</code> <b>property</b></li> * </ul></div> * <p>For additional information see {@link Ext.util.MixedCollection#get}. * @return Ext.Component The component (if found). */ getComponent : function(comp){ if(Ext.isObject(comp)){ comp = comp.getItemId(); } return this.items.get(comp); }, // private lookupComponent : function(comp){ if(Ext.isString(comp)){ return Ext.ComponentMgr.get(comp); }else if(!comp.events){ return this.createComponent(comp); } return comp; }, // private createComponent : function(config, defaultType){ // add in ownerCt at creation time but then immediately // remove so that onBeforeAdd can handle it var c = config.render ? config : Ext.create(Ext.apply({ ownerCt: this }, config), defaultType || this.defaultType); delete c.ownerCt; return c; }, /** * We can only lay out if there is a view area in which to layout. * display:none on the layout target, *or any of its parent elements* will mean it has no view area. */ canLayout: function() { var el = this.getLayoutTarget(), vs; return !!(el && (vs = el.dom.offsetWidth || el.dom.offsetHeight)); }, /** * Force this container's layout to be recalculated. A call to this function is required after adding a new component * to an already rendered container, or possibly after changing sizing/position properties of child components. * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer) * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden. * @return {Ext.Container} this */ doLayout: function(shallow, force){ var rendered = this.rendered, forceLayout = force || this.forceLayout, cs, i, len, c; this.layoutDone = true; if(!this.canLayout() || this.collapsed){ this.deferLayout = this.deferLayout || !shallow; if(!forceLayout){ return; } shallow = shallow && !this.deferLayout; } else { delete this.deferLayout; } cs = (shallow !== true && this.items) ? this.items.items : []; // Inhibit child Containers from relaying on resize since we are about to to explicitly call doLayout on them all! for(i = 0, len = cs.length; i < len; i++){ if ((c = cs[i]).layout) { c.suspendLayoutResize = true; } } // Tell the layout manager to ensure all child items are rendered, and sized according to their rules. // Will not cause the child items to relayout. if(rendered && this.layout){ this.layout.layout(); } // Explicitly lay out all child items for(i = 0; i < len; i++){ if((c = cs[i]).doLayout){ c.doLayout(false, forceLayout); } } if(rendered){ this.onLayout(shallow, forceLayout); } // Initial layout completed this.hasLayout = true; delete this.forceLayout; // Re-enable child layouts relaying on resize. for(i = 0; i < len; i++){ if ((c = cs[i]).layout) { delete c.suspendLayoutResize; } } }, //private onLayout : Ext.emptyFn, onResize: function(adjWidth, adjHeight, rawWidth, rawHeight){ Ext.Container.superclass.onResize.apply(this, arguments); if ((this.rendered && this.layout && this.layout.monitorResize) && !this.suspendLayoutResize) { this.layout.onResize(); } }, // private hasLayoutPending: function(){ // Traverse hierarchy to see if any parent container has a pending layout. var pending = this.layoutPending; this.ownerCt.bubble(function(c){ return !(pending = c.layoutPending); }); return pending; }, onShow : function(){ Ext.Container.superclass.onShow.call(this); if(Ext.isDefined(this.deferLayout)){ this.doLayout(true); } }, /** * Returns the layout currently in use by the container. If the container does not currently have a layout * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout. * @return {ContainerLayout} layout The container's layout */ getLayout : function(){ if(!this.layout){ var layout = new Ext.layout.ContainerLayout(this.layoutConfig); this.setLayout(layout); } return this.layout; }, // private beforeDestroy : function(){ var c; if(this.items){ while(c = this.items.first()){ this.doRemove(c, true); } } if(this.monitorResize){ Ext.EventManager.removeResizeListener(this.doLayout, this); } Ext.destroy(this.layout); Ext.Container.superclass.beforeDestroy.call(this); }, /** * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of * function call will be the scope provided or the current component. The arguments to the function * will be the args provided or the current component. If the function returns false at any point, * the bubble is stopped. * @param {Function} fn The function to call * @param {Object} scope (optional) The scope of the function (defaults to current node) * @param {Array} args (optional) The args to call the function with (default to passing the current component) * @return {Ext.Container} this */ bubble : function(fn, scope, args){ var p = this; while(p){ if(fn.apply(scope || p, args || [p]) === false){ break; } p = p.ownerCt; } return this; }, /** * Cascades down the component/container heirarchy from this component (called first), calling the specified function with * each component. The scope (<i>this</i>) of * function call will be the scope provided or the current component. The arguments to the function * will be the args provided or the current component. If the function returns false at any point, * the cascade is stopped on that branch. * @param {Function} fn The function to call * @param {Object} scope (optional) The scope of the function (defaults to current component) * @param {Array} args (optional) The args to call the function with (defaults to passing the current component) * @return {Ext.Container} this */ cascade : function(fn, scope, args){ if(fn.apply(scope || this, args || [this]) !== false){ if(this.items){ var cs = this.items.items; for(var i = 0, len = cs.length; i < len; i++){ if(cs[i].cascade){ cs[i].cascade(fn, scope, args); }else{ fn.apply(scope || cs[i], args || [cs[i]]); } } } } return this; }, /** * Find a component under this container at any level by id * @param {String} id * @return Ext.Component */ findById : function(id){ var m, ct = this; this.cascade(function(c){ if(ct != c && c.id === id){ m = c; return false; } }); return m || null; }, /** * Find a component under this container at any level by xtype or class * @param {String/Class} xtype The xtype string for a component, or the class of the component directly * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is * the default), or true to check whether this Component is directly of the specified xtype. * @return {Array} Array of Ext.Components */ findByType : function(xtype, shallow){ return this.findBy(function(c){ return c.isXType(xtype, shallow); }); }, /** * Find a component under this container at any level by property * @param {String} prop * @param {String} value * @return {Array} Array of Ext.Components */ find : function(prop, value){ return this.findBy(function(c){ return c[prop] === value; }); }, /** * Find a component under this container at any level by a custom function. If the passed function returns * true, the component will be included in the results. The passed function is called with the arguments (component, this container). * @param {Function} fn The function to call * @param {Object} scope (optional) * @return {Array} Array of Ext.Components */ findBy : function(fn, scope){ var m = [], ct = this; this.cascade(function(c){ if(ct != c && fn.call(scope || c, c, ct) === true){ m.push(c); } }); return m; }, /** * Get a component contained by this container (alias for items.get(key)) * @param {String/Number} key The index or id of the component * @return {Ext.Component} Ext.Component */ get : function(key){ return this.items.get(key); } }); Ext.Container.LAYOUTS = {}; Ext.reg('container', Ext.Container); /** * @class Ext.layout.ContainerLayout * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout * classes in Ext. It simply renders all child Components into the Container, performing no sizing or * positioning services. To utilize a layout that provides sizing and positioning of child Components, * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p> * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt> * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p> */ Ext.layout.ContainerLayout = Ext.extend(Object, { /** * @cfg {String} extraCls * <p>An optional extra CSS class that will be added to the container. This can be useful for adding * customized styles to the container or any of its children using standard CSS rules. See * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p> * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes * which assign a value by default: * <div class="mdetail-params"><ul> * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li> * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li> * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li> * </ul></div> * To configure the above Classes with an extra CSS class append to the default. For example, * for ColumnLayout:<pre><code> * extraCls: 'x-column custom-class' * </code></pre> * </p> */ /** * @cfg {Boolean} renderHidden * True to hide each contained item on render (defaults to false). */ /** * A reference to the {@link Ext.Component} that is active. For example, <pre><code> * if(myPanel.layout.activeItem.id == 'item-1') { ... } * </code></pre> * <tt>activeItem</tt> only applies to layout styles that can display items one at a time * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} * and {@link Ext.layout.FitLayout}). Read-only. Related to {@link Ext.Container#activeItem}. * @type {Ext.Component} * @property activeItem */ // private monitorResize:false, // private activeItem : null, constructor : function(config){ Ext.apply(this, config); }, // private layout : function(){ var target = this.container.getLayoutTarget(); if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){ target.addClass(this.targetCls) } this.onLayout(this.container, target); this.container.fireEvent('afterlayout', this.container, this); this.hasLayout = true; }, // private onLayout : function(ct, target){ this.renderAll(ct, target); }, // private isValidParent : function(c, target){ return target && c.getPositionEl().dom.parentNode == (target.dom || target); }, // private renderAll : function(ct, target){ var items = ct.items.items; for(var i = 0, len = items.length; i < len; i++) { var c = items[i]; if(c && (!c.rendered || !this.isValidParent(c, target))){ this.renderItem(c, i, target); } } }, // private renderItem : function(c, position, target){ if(c && !c.rendered){ c.render(target, position); this.configureItem(c, position); }else if(c && !this.isValidParent(c, target)){ if(Ext.isNumber(position)){ position = target.dom.childNodes[position]; } target.dom.insertBefore(c.getPositionEl().dom, position || null); c.container = target; this.configureItem(c, position); } }, // private configureItem: function(c, position){ if(this.extraCls){ var t = c.getPositionEl ? c.getPositionEl() : c; t.addClass(this.extraCls); } // If we are forcing a layout, do so *before* we hide so elements have height/width if(c.doLayout && this.forceLayout){ c.doLayout(false, true); } if (this.renderHidden && c != this.activeItem) { c.hide(); } }, onRemove: function(c){ if(this.activeItem == c){ delete this.activeItem; } if(c.rendered && this.extraCls){ var t = c.getPositionEl ? c.getPositionEl() : c; t.removeClass(this.extraCls); } }, // private onResize: function(){ var ct = this.container, b = ct.bufferResize; if (ct.collapsed){ return; } // Not having an ownerCt negates the buffering: floating and top level // Containers (Viewport, Window, ToolTip, Menu) need to lay out ASAP. if (b && ct.ownerCt) { // If we do NOT already have a layout pending from an ancestor, schedule one. // If there is a layout pending, we do nothing here. // buffering to be deprecated soon if (!ct.hasLayoutPending()){ if(!this.resizeTask){ this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this); this.resizeBuffer = Ext.isNumber(b) ? b : 50; } ct.layoutPending = true; this.resizeTask.delay(this.resizeBuffer); } }else{ ct.doLayout(false, this.forceLayout); } }, // private runLayout: function(){ var ct = this.container; ct.doLayout(); delete ct.layoutPending; }, // private setContainer : function(ct){ // No longer use events to handle resize. Instead this will be handled through a direct function call. /* if(this.monitorResize && ct != this.container){ var old = this.container; if(old){ old.un(old.resizeEvent, this.onResize, this); } if(ct){ ct.on(ct.resizeEvent, this.onResize, this); } } */ this.container = ct; }, // private parseMargins : function(v){ if(Ext.isNumber(v)){ v = v.toString(); } var ms = v.split(' '); var len = ms.length; if(len == 1){ ms[1] = ms[0]; ms[2] = ms[0]; ms[3] = ms[0]; } if(len == 2){ ms[2] = ms[0]; ms[3] = ms[1]; } if(len == 3){ ms[3] = ms[1]; } return { top:parseInt(ms[0], 10) || 0, right:parseInt(ms[1], 10) || 0, bottom:parseInt(ms[2], 10) || 0, left:parseInt(ms[3], 10) || 0 }; }, /** * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped, * labeled and styled form Field. A default Template is supplied, but this may be * overriden to create custom field structures. The template processes values returned from * {@link Ext.layout.FormLayout#getTemplateArgs}. * @property fieldTpl * @type Ext.Template */ fieldTpl: (function() { var t = new Ext.Template( '<div class="x-form-item {itemCls}" tabIndex="-1">', '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>', '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">', '</div><div class="{clearCls}"></div>', '</div>' ); t.disableFormats = true; return t.compile(); })(), /* * Destroys this layout. This is a template method that is empty by default, but should be implemented * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes. * @protected */ destroy : function(){ if(!Ext.isEmpty(this.targetCls)){ var target = this.container.getLayoutTarget(); if(target){ target.removeClass(this.targetCls); } } } }); Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout; /**
- * @class Ext.layout.FitLayout
- * @extends Ext.layout.ContainerLayout
- * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
- * container. This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
- * config, and should generally not need to be created directly via the new keyword.</p>
- * <p>FitLayout does not have any direct config options (other than inherited ones). To fit a panel to a container
- * using FitLayout, simply set layout:'fit' on the container and add a single panel to it. If the container has
- * multiple panels, only the first one will be displayed. Example usage:</p>
- * <pre><code>
- var p = new Ext.Panel({
- title: 'Fit Layout',
- layout:'fit',
- items: {
- title: 'Inner Panel',
- html: '<p>This is the inner panel content</p>',
- border: false
- }
- });
- </code></pre>
- */
- Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
- // private
- monitorResize:true,
- // private
- onLayout : function(ct, target){
- Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
- if(!this.container.collapsed){
- this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize(true));
- }
- },
- // private
- setItemSize : function(item, size){
- if(item && size.height > 0){ // display none?
- item.setSize(size);
- }
- }
- });
- Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
- * @class Ext.layout.CardLayout
- * @extends Ext.layout.FitLayout
- * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
- * visible at any given time. This layout style is most commonly used for wizards, tab implementations, etc.
- * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
- * and should generally not need to be created directly via the new keyword.</p>
- * <p>The CardLayout's focal method is {@link #setActiveItem}. Since only one panel is displayed at a time,
- * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
- * the next panel to display. The layout itself does not provide a user interface for handling this navigation,
- * so that functionality must be provided by the developer.</p>
- * <p>In the following example, a simplistic wizard setup is demonstrated. A button bar is added
- * to the footer of the containing panel to provide navigation buttons. The buttons will be handled by a
- * common navigation routine -- for this example, the implementation of that routine has been ommitted since
- * it can be any type of custom logic. Note that other uses of a CardLayout (like a tab control) would require a
- * completely different implementation. For serious implementations, a better approach would be to extend
- * CardLayout to provide the custom functionality needed. Example usage:</p>
- * <pre><code>
- var navHandler = function(direction){
- // This routine could contain business logic required to manage the navigation steps.
- // It would call setActiveItem as needed, manage navigation button state, handle any
- // branching logic that might be required, handle alternate actions like cancellation
- // or finalization, etc. A complete wizard implementation could get pretty
- // sophisticated depending on the complexity required, and should probably be
- // done as a subclass of CardLayout in a real-world implementation.
- };
- var card = new Ext.Panel({
- title: 'Example Wizard',
- layout:'card',
- activeItem: 0, // make sure the active item is set on the container config!
- bodyStyle: 'padding:15px',
- defaults: {
- // applied to each contained panel
- border:false
- },
- // just an example of one possible navigation scheme, using buttons
- bbar: [
- {
- id: 'move-prev',
- text: 'Back',
- handler: navHandler.createDelegate(this, [-1]),
- disabled: true
- },
- '->', // greedy spacer so that the buttons are aligned to each side
- {
- id: 'move-next',
- text: 'Next',
- handler: navHandler.createDelegate(this, [1])
- }
- ],
- // the panels (or "cards") within the layout
- items: [{
- id: 'card-0',
- html: '<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>'
- },{
- id: 'card-1',
- html: '<p>Step 2 of 3</p>'
- },{
- id: 'card-2',
- html: '<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>'
- }]
- });
- </code></pre>
- */
- Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
- /**
- * @cfg {Boolean} deferredRender
- * True to render each contained item at the time it becomes active, false to render all contained items
- * as soon as the layout is rendered (defaults to false). If there is a significant amount of content or
- * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
- * true might improve performance.
- */
- deferredRender : false,
- /**
- * @cfg {Boolean} layoutOnCardChange
- * True to force a layout of the active item when the active card is changed. Defaults to false.
- */
- layoutOnCardChange : false,
- /**
- * @cfg {Boolean} renderHidden @hide
- */
- // private
- renderHidden : true,
- constructor: function(config){
- Ext.layout.CardLayout.superclass.constructor.call(this, config);
- // this.forceLayout = (this.deferredRender === false);
- },
- /**
- * Sets the active (visible) item in the layout.
- * @param {String/Number} item The string component id or numeric index of the item to activate
- */
- setActiveItem : function(item){
- var ai = this.activeItem;
- item = this.container.getComponent(item);
- if(ai != item){
- if(ai){
- ai.hide();
- ai.fireEvent('deactivate', ai);
- }
- var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
- this.activeItem = item;
- if(item){
- item.show();
- }
- this.layout();
- if(item && layout){
- item.doLayout();
- }
- item.fireEvent('activate', item);
- }
- },
- // private
- renderAll : function(ct, target){
- if(this.deferredRender){
- this.renderItem(this.activeItem, undefined, target);
- }else{
- Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
- }
- }
- });
- Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/** * @class Ext.layout.AnchorLayout * @extends Ext.layout.ContainerLayout * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions. * If the container is resized, all anchored items are automatically rerendered according to their * <b><tt>{@link #anchor}</tt></b> rules.</p> * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout} * config, and should generally not need to be created directly via the new keyword.</p> * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default, * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>. * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring * logic if necessary. For example:</p> * <pre><code> var viewport = new Ext.Viewport({ layout:'anchor', anchorSize: {width:800, height:600}, items:[{ title:'Item 1', html:'Content 1', width:800, anchor:'right 20%' },{ title:'Item 2', html:'Content 2', width:300, anchor:'50% 30%' },{ title:'Item 3', html:'Content 3', width:600, anchor:'-100 50%' }] }); * </code></pre> */ Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, { /** * @cfg {String} anchor * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/> * * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt> * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%'). * The following types of anchor values are supported:<div class="mdetail-params"><ul> * * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc"> * The first anchor is the percentage width that the item should take up within the container, and the * second is the percentage height. For example:<pre><code> // two values specified anchor: '100% 50%' // render item complete width of the container and // 1/2 height of the container // one value specified anchor: '100%' // the width value; the height will default to auto * </code></pre></div></li> * * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc"> * This is a raw adjustment where the first anchor is the offset from the right edge of the container, * and the second is the offset from the bottom edge. For example:<pre><code> // two values specified anchor: '-50 -100' // render item the complete width of the container // minus 50 pixels and // the complete height minus 100 pixels. // one value specified anchor: '-50' // anchor value is assumed to be the right offset value // bottom offset will default to 0 * </code></pre></div></li> * * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt> * (or <tt>'b'</tt>).<div class="sub-desc"> * Either the container must have a fixed size or an anchorSize config value defined at render time in * order for these to have any effect.</div></li> * * <li><b>Mixed</b> : <div class="sub-desc"> * Anchor values can also be mixed as needed. For example, to render the width offset from the container * right edge by 50 pixels and 75% of the container's height use: * <pre><code> anchor: '-50 75%' * </code></pre></div></li> * * * </ul></div> */ // private monitorResize:true, // private // deprecate getAnchorViewSize : function(ct, target){ return target.dom == document.body ? target.getViewSize(true) : target.getStyleSize(); }, // private onLayout : function(ct, target){ Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target); var size = target.getViewSize(true); var w = size.width, h = size.height; if(w < 20 && h < 20){ return; } // find the container anchoring size var aw, ah; if(ct.anchorSize){ if(typeof ct.anchorSize == 'number'){ aw = ct.anchorSize; }else{ aw = ct.anchorSize.width; ah = ct.anchorSize.height; } }else{ aw = ct.initialConfig.width; ah = ct.initialConfig.height; } var cs = ct.items.items, len = cs.length, i, c, a, cw, ch, el, vs; for(i = 0; i < len; i++){ c = cs[i]; el = c.getPositionEl(); if(c.anchor){ a = c.anchorSpec; if(!a){ // cache all anchor values vs = c.anchor.split(' '); c.anchorSpec = a = { right: this.parseAnchor(vs[0], c.initialConfig.width, aw), bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah) }; } cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined; ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined; if(cw || ch){ c.setSize(cw || undefined, ch || undefined); } } } }, // private parseAnchor : function(a, start, cstart){ if(a && a != 'none'){ var last; if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor var diff = cstart - start; return function(v){ if(v !== last){ last = v; return v - diff; } } }else if(a.indexOf('%') != -1){ var ratio = parseFloat(a.replace('%', ''))*.01; // percentage return function(v){ if(v !== last){ last = v; return Math.floor(v*ratio); } } }else{ a = parseInt(a, 10); if(!isNaN(a)){ // simple offset adjustment return function(v){ if(v !== last){ last = v; return v + a; } } } } } return false; }, // private adjustWidthAnchor : function(value, comp){ return value; }, // private adjustHeightAnchor : function(value, comp){ return value; } /** * @property activeItem * @hide */ }); Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout; /**
- * @class Ext.layout.ColumnLayout
- * @extends Ext.layout.ContainerLayout
- * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
- * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
- * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
- * and should generally not need to be created directly via the new keyword.</p>
- * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
- * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it. The
- * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
- * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
- * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
- * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
- * less than 1 (e.g., .25).</p>
- * <p>The basic rules for specifying column widths are pretty simple. The logic makes two passes through the
- * set of contained panels. During the first layout pass, all panels that either have a fixed width or none
- * specified (auto) are skipped, but their widths are subtracted from the overall container width. During the second
- * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
- * the total <b>remaining</b> container width. In other words, percentage width panels are designed to fill the space
- * left over by all the fixed-width and/or auto-width panels. Because of this, while you can specify any number of columns
- * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
- * layout may not render as expected. Example usage:</p>
- * <pre><code>
- // All columns are percentages -- they must add up to 1
- var p = new Ext.Panel({
- title: 'Column Layout - Percentage Only',
- layout:'column',
- items: [{
- title: 'Column 1',
- columnWidth: .25
- },{
- title: 'Column 2',
- columnWidth: .6
- },{
- title: 'Column 3',
- columnWidth: .15
- }]
- });
- // Mix of width and columnWidth -- all columnWidth values must add up
- // to 1. The first column will take up exactly 120px, and the last two
- // columns will fill the remaining container width.
- var p = new Ext.Panel({
- title: 'Column Layout - Mixed',
- layout:'column',
- items: [{
- title: 'Column 1',
- width: 120
- },{
- title: 'Column 2',
- columnWidth: .8
- },{
- title: 'Column 3',
- columnWidth: .2
- }]
- });
- </code></pre>
- */
- Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
- // private
- monitorResize:true,
- extraCls: 'x-column',
- scrollOffset : 0,
- // private
- targetCls: 'x-column-layout-ct',
- isValidParent : function(c, target){
- return c.getPositionEl().dom.parentNode == this.innerCt.dom;
- },
- // private
- onLayout : function(ct, target){
- var cs = ct.items.items, len = cs.length, c, i;
- if(!this.innerCt){
- // the innerCt prevents wrapping and shuffling while
- // the container is resizing
- this.innerCt = target.createChild({cls:'x-column-inner'});
- this.innerCt.createChild({cls:'x-clear'});
- }
- this.renderAll(ct, this.innerCt);
- var size = target.getViewSize(true);
- if(size.width < 1 && size.height < 1){ // display none?
- return;
- }
- var w = size.width - this.scrollOffset,
- h = size.height,
- pw = w;
- this.innerCt.setWidth(w);
- // some columns can be percentages while others are fixed
- // so we need to make 2 passes
- for(i = 0; i < len; i++){
- c = cs[i];
- if(!c.columnWidth){
- pw -= (c.getSize().width + c.getPositionEl().getMargins('lr'));
- }
- }
- pw = pw < 0 ? 0 : pw;
- for(i = 0; i < len; i++){
- c = cs[i];
- if(c.columnWidth){
- c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));
- }
- }
- }
- /**
- * @property activeItem
- * @hide
- */
- });
- Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/** * @class Ext.layout.BorderLayout * @extends Ext.layout.ContainerLayout * <p>This is a multi-pane, application-oriented UI layout style that supports multiple * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p> * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt> * {@link Ext.Container#layout} config, and should generally not need to be created directly * via the new keyword.</p> * <p>BorderLayout does not have any direct config options (other than inherited ones). * All configuration options available for customizing the BorderLayout are at the * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion} * levels.</p> * <p>Example usage:</p> * <pre><code> var myBorderPanel = new Ext.Panel({ {@link Ext.Component#renderTo renderTo}: document.body, {@link Ext.BoxComponent#width width}: 700, {@link Ext.BoxComponent#height height}: 500, {@link Ext.Panel#title title}: 'Border Layout', {@link Ext.Container#layout layout}: 'border', {@link Ext.Container#items items}: [{ {@link Ext.Panel#title title}: 'South Region is resizable', {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south', // position for region {@link Ext.BoxComponent#height height}: 100, {@link Ext.layout.BorderLayout.Region#split split}: true, // enable resizing {@link Ext.SplitBar#minSize minSize}: 75, // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50} {@link Ext.SplitBar#maxSize maxSize}: 150, {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5' },{ // xtype: 'panel' implied by default {@link Ext.Panel#title title}: 'West Region is collapsible', {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west', {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5', {@link Ext.BoxComponent#width width}: 200, {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true, // make collapsible {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed {@link Ext.Component#id id}: 'west-region-container', {@link Ext.Container#layout layout}: 'fit', {@link Ext.Panel#unstyled unstyled}: true },{ {@link Ext.Panel#title title}: 'Center Region', {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center', // center region is required, no width/height specified {@link Ext.Component#xtype xtype}: 'container', {@link Ext.Container#layout layout}: 'fit', {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0' }] }); </code></pre> * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul> * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>. * 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.</li> * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined * (an integer representing the number of pixels that the region should take up).</li> * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li> * <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 * 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) * is added to the west region: * <div style="margin-left:16px"><pre><code> wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container'); wrc.{@link Ext.Panel#removeAll removeAll}(); wrc.{@link Ext.Container#add add}({ title: 'Added Panel', html: 'Some content' }); wrc.{@link Ext.Container#doLayout doLayout}(); * </code></pre></div> * </li> * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}: * <div style="margin-left:16px"><pre><code> wr = myBorderPanel.layout.west; * </code></pre></div> * </li> * </ul></div> */ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, { // private monitorResize:true, // private rendered : false, targetCls: 'x-border-layout-ct', // private onLayout : function(ct, target){ var collapsed; if(!this.rendered){ var items = ct.items.items; collapsed = []; for(var i = 0, len = items.length; i < len; i++) { var c = items[i]; var pos = c.region; if(c.collapsed){ collapsed.push(c); } c.collapsed = false; if(!c.rendered){ c.render(target, i); c.getPositionEl().addClass('x-border-panel'); } this[pos] = pos != 'center' && c.split ? new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) : new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos); this[pos].render(target, c); } this.rendered = true; } var size = target.getViewSize(false); if(size.width < 20 || size.height < 20){ // display none? if(collapsed){ this.restoreCollapsed = collapsed; } return; }else if(this.restoreCollapsed){ collapsed = this.restoreCollapsed; delete this.restoreCollapsed; } var w = size.width, h = size.height; var centerW = w, centerH = h, centerY = 0, centerX = 0; var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center; if(!c && Ext.layout.BorderLayout.WARN !== false){ throw 'No center region defined in BorderLayout ' + ct.id; } if(n && n.isVisible()){ var b = n.getSize(); var m = n.getMargins(); b.width = w - (m.left+m.right); b.x = m.left; b.y = m.top; centerY = b.height + b.y + m.bottom; centerH -= centerY; n.applyLayout(b); } if(s && s.isVisible()){ var b = s.getSize(); var m = s.getMargins(); b.width = w - (m.left+m.right); b.x = m.left; var totalHeight = (b.height + m.top + m.bottom); b.y = h - totalHeight + m.top; centerH -= totalHeight; s.applyLayout(b); } if(west && west.isVisible()){ var b = west.getSize(); var m = west.getMargins(); b.height = centerH - (m.top+m.bottom); b.x = m.left; b.y = centerY + m.top; var totalWidth = (b.width + m.left + m.right); centerX += totalWidth; centerW -= totalWidth; west.applyLayout(b); } if(e && e.isVisible()){ var b = e.getSize(); var m = e.getMargins(); b.height = centerH - (m.top+m.bottom); var totalWidth = (b.width + m.left + m.right); b.x = w - totalWidth + m.left; b.y = centerY + m.top; centerW -= totalWidth; e.applyLayout(b); } if(c){ var m = c.getMargins(); var centerBox = { x: centerX + m.left, y: centerY + m.top, width: centerW - (m.left+m.right), height: centerH - (m.top+m.bottom) }; c.applyLayout(centerBox); } if(collapsed){ for(var i = 0, len = collapsed.length; i < len; i++){ collapsed[i].collapse(false); } } if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue target.repaint(); } }, destroy: function() { var r = ['north', 'south', 'east', 'west']; for (var i = 0; i < r.length; i++) { var region = this[r[i]]; if(region){ if(region.destroy){ region.destroy(); }else if (region.split){ region.split.destroy(true); } } } Ext.layout.BorderLayout.superclass.destroy.call(this); } /** * @property activeItem * @hide */ }); /** * @class Ext.layout.BorderLayout.Region * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer * within the layout. Each region has its own {@link Ext.layout.ContainerLayout layout} that is * independent of other regions and the containing BorderLayout, and can be any of the * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p> * <p>Region size is managed automatically and cannot be changed by the user -- for * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p> * @constructor * Create a new Region. * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region. * @param {Object} config The configuration options * @param {String} position The region position. Valid values are: <tt>north</tt>, <tt>south</tt>, * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>. Every {@link Ext.layout.BorderLayout BorderLayout} * <b>must have a center region</b> for the primary content -- all other regions are optional. */ Ext.layout.BorderLayout.Region = function(layout, config, pos){ Ext.apply(this, config); this.layout = layout; this.position = pos; this.state = {}; if(typeof this.margins == 'string'){ this.margins = this.layout.parseMargins(this.margins); } this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins); if(this.collapsible){ if(typeof this.cmargins == 'string'){ this.cmargins = this.layout.parseMargins(this.cmargins); } if(this.collapseMode == 'mini' && !this.cmargins){ this.cmargins = {left:0,top:0,right:0,bottom:0}; }else{ this.cmargins = Ext.applyIf(this.cmargins || {}, pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins); } } }; Ext.layout.BorderLayout.Region.prototype = { /** * @cfg {Boolean} animFloat * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated * panel that will close again once the user mouses out of that panel (or clicks out if * <tt>{@link #autoHide} = false</tt>). Setting <tt>{@link #animFloat} = false</tt> will * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>). */ /** * @cfg {Boolean} autoHide * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated * panel. If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses * out of the panel. If <tt>autoHide = false</tt>, the panel will continue to display until the * user clicks outside of the panel (defaults to <tt>true</tt>). */ /** * @cfg {String} collapseMode * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul> * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible} * regions are collapsed by clicking the expand/collapse tool button that renders into the region's * title bar.</div></li> * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode. * </div></li> * </ul></div></p> * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode = * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible} * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p> * <p>See also <tt>{@link #cmargins}</tt>.</p> */ /** * @cfg {Object} margins * An object containing margins to apply to the region when in the expanded state in the * format:<pre><code> { top: (top margin), right: (right margin), bottom: (bottom margin), left: (left margin) }</code></pre> * <p>May also be a string containing space-separated, numeric margin values. The order of the * sides associated with each value matches the way CSS processes margin values:</p> * <p><div class="mdetail-params"><ul> * <li>If there is only one value, it applies to all sides.</li> * <li>If there are two values, the top and bottom borders are set to the first value and the * right and left are set to the second.</li> * <li>If there are three values, the top is set to the first value, the left and right are set * to the second, and the bottom is set to the third.</li> * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li> * </ul></div></p> * <p>Defaults to:</p><pre><code> * {top:0, right:0, bottom:0, left:0} * </code></pre> */ /** * @cfg {Object} cmargins * An object containing margins to apply to the region when in the collapsed state in the * format:<pre><code> { top: (top margin), right: (right margin), bottom: (bottom margin), left: (left margin) }</code></pre> * <p>May also be a string containing space-separated, numeric margin values. The order of the * sides associated with each value matches the way CSS processes margin values.</p> * <p><ul> * <li>If there is only one value, it applies to all sides.</li> * <li>If there are two values, the top and bottom borders are set to the first value and the * right and left are set to the second.</li> * <li>If there are three values, the top is set to the first value, the left and right are set * to the second, and the bottom is set to the third.</li> * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li> * </ul></p> */ /** * @cfg {Boolean} collapsible * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>). If * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title * bar of the region, otherwise the button will not be shown.</p> * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>. */ collapsible : false, /** * @cfg {Boolean} split * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to * resize the regions dynamically. Defaults to <tt>false</tt> creating a * {@link Ext.layout.BorderLayout.Region Region}.</p><br> * <p><b>Notes</b>:</p><div class="mdetail-params"><ul> * <li>this configuration option is ignored if <tt>region='center'</tt></li> * <li>when <tt>split == true</tt>, it is common to specify a * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li> * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space * for the collapse tool</tt></li> * </ul></div> */ split:false, /** * @cfg {Boolean} floatable * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by * clicking the expand button to see it again (defaults to <tt>true</tt>). */ floatable: true, /** * @cfg {Number} minWidth * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>). * <tt>maxWidth</tt> may also be specified.</p><br> * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p> */ minWidth:50, /** * @cfg {Number} minHeight * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>) * <tt>maxHeight</tt> may also be specified.</p><br> * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p> */ minHeight:50, // private defaultMargins : {left:0,top:0,right:0,bottom:0}, // private defaultNSCMargins : {left:5,top:5,right:5,bottom:5}, // private defaultEWCMargins : {left:5,top:0,right:5,bottom:0}, floatingZIndex: 100, /** * True if this region is collapsed. Read-only. * @type Boolean * @property */ isCollapsed : false, /** * This region's panel. Read-only. * @type Ext.Panel * @property panel */ /** * This region's layout. Read-only. * @type Layout * @property layout */ /** * This region's layout position (north, south, east, west or center). Read-only. * @type String * @property position */ // private render : function(ct, p){ this.panel = p; p.el.enableDisplayMode(); this.targetEl = ct; this.el = p.el; var gs = p.getState, ps = this.position; p.getState = function(){ return Ext.apply(gs.call(p) || {}, this.state); }.createDelegate(this); if(ps != 'center'){ p.allowQueuedExpand = false; p.on({ beforecollapse: this.beforeCollapse, collapse: this.onCollapse, beforeexpand: this.beforeExpand, expand: this.onExpand, hide: this.onHide, show: this.onShow, scope: this }); if(this.collapsible || this.floatable){ p.collapseEl = 'el'; p.slideAnchor = this.getSlideAnchor(); } if(p.tools && p.tools.toggle){ p.tools.toggle.addClass('x-tool-collapse-'+ps); p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over'); } } }, // private getCollapsedEl : function(){ if(!this.collapsedEl){ if(!this.toolTemplate){ var tt = new Ext.Template( '<div class="x-tool x-tool-{id}"> </div>' ); tt.disableFormats = true; tt.compile(); Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt; } this.collapsedEl = this.targetEl.createChild({ cls: "x-layout-collapsed x-layout-collapsed-"+this.position, id: this.panel.id + '-xcollapsed' }); this.collapsedEl.enableDisplayMode('block'); if(this.collapseMode == 'mini'){ this.collapsedEl.addClass('x-layout-cmini-'+this.position); this.miniCollapsedEl = this.collapsedEl.createChild({ cls: "x-layout-mini x-layout-mini-"+this.position, html: " " }); this.miniCollapsedEl.addClassOnOver('x-layout-mini-over'); this.collapsedEl.addClassOnOver("x-layout-collapsed-over"); this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true}); }else { if(this.collapsible !== false && !this.hideCollapseTool) { var t = this.toolTemplate.append( this.collapsedEl.dom, {id:'expand-'+this.position}, true); t.addClassOnOver('x-tool-expand-'+this.position+'-over'); t.on('click', this.onExpandClick, this, {stopEvent:true}); } if(this.floatable !== false || this.titleCollapse){ this.collapsedEl.addClassOnOver("x-layout-collapsed-over"); this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this); } } } return this.collapsedEl; }, // private onExpandClick : function(e){ if(this.isSlid){ this.panel.expand(false); }else{ this.panel.expand(); } }, // private onCollapseClick : function(e){ this.panel.collapse(); }, // private beforeCollapse : function(p, animate){ this.lastAnim = animate; if(this.splitEl){ this.splitEl.hide(); } this.getCollapsedEl().show(); var el = this.panel.getEl(); this.originalZIndex = el.getStyle('z-index'); el.setStyle('z-index', 100); this.isCollapsed = true; this.layout.layout(); }, // private onCollapse : function(animate){ this.panel.el.setStyle('z-index', 1); if(this.lastAnim === false || this.panel.animCollapse === false){ this.getCollapsedEl().dom.style.visibility = 'visible'; }else{ this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2}); } this.state.collapsed = true; this.panel.saveState(); }, // private beforeExpand : function(animate){ if(this.isSlid){ this.afterSlideIn(); } var c = this.getCollapsedEl(); this.el.show(); if(this.position == 'east' || this.position == 'west'){ this.panel.setSize(undefined, c.getHeight()); }else{ this.panel.setSize(c.getWidth(), undefined); } c.hide(); c.dom.style.visibility = 'hidden'; this.panel.el.setStyle('z-index', this.floatingZIndex); }, // private onExpand : function(){ this.isCollapsed = false; if(this.splitEl){ this.splitEl.show(); } this.layout.layout(); this.panel.el.setStyle('z-index', this.originalZIndex); this.state.collapsed = false; this.panel.saveState(); }, // private collapseClick : function(e){ if(this.isSlid){ e.stopPropagation(); this.slideIn(); }else{ e.stopPropagation(); this.slideOut(); } }, // private onHide : function(){ if(this.isCollapsed){ this.getCollapsedEl().hide(); }else if(this.splitEl){ this.splitEl.hide(); } }, // private onShow : function(){ if(this.isCollapsed){ this.getCollapsedEl().show(); }else if(this.splitEl){ this.splitEl.show(); } }, /** * True if this region is currently visible, else false. * @return {Boolean} */ isVisible : function(){ return !this.panel.hidden; }, /** * Returns the current margins for this region. If the region is collapsed, the * {@link #cmargins} (collapsed margins) value will be returned, otherwise the * {@link #margins} value will be returned. * @return {Object} An object containing the element's margins: <tt>{left: (left * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt> */ getMargins : function(){ return this.isCollapsed && this.cmargins ? this.cmargins : this.margins; }, /** * Returns the current size of this region. If the region is collapsed, the size of the * collapsedEl will be returned, otherwise the size of the region's panel will be returned. * @return {Object} An object containing the element's size: <tt>{width: (element width), * height: (element height)}</tt> */ getSize : function(){ return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize(); }, /** * Sets the specified panel as the container element for this region. * @param {Ext.Panel} panel The new panel */ setPanel : function(panel){ this.panel = panel; }, /** * Returns the minimum allowable width for this region. * @return {Number} The minimum width */ getMinWidth: function(){ return this.minWidth; }, /** * Returns the minimum allowable height for this region. * @return {Number} The minimum height */ getMinHeight: function(){ return this.minHeight; }, // private applyLayoutCollapsed : function(box){ var ce = this.getCollapsedEl(); ce.setLeftTop(box.x, box.y); ce.setSize(box.width, box.height); }, // private applyLayout : function(box){ if(this.isCollapsed){ this.applyLayoutCollapsed(box); }else{ this.panel.setPosition(box.x, box.y); this.panel.setSize(box.width, box.height); } }, // private beforeSlide: function(){ this.panel.beforeEffect(); }, // private afterSlide : function(){ this.panel.afterEffect(); }, // private initAutoHide : function(){ if(this.autoHide !== false){ if(!this.autoHideHd){ var st = new Ext.util.DelayedTask(this.slideIn, this); this.autoHideHd = { "mouseout": function(e){ if(!e.within(this.el, true)){ st.delay(500); } }, "mouseover" : function(e){ st.cancel(); }, scope : this }; } this.el.on(this.autoHideHd); this.collapsedEl.on(this.autoHideHd); } }, // private clearAutoHide : function(){ if(this.autoHide !== false){ this.el.un("mouseout", this.autoHideHd.mouseout); this.el.un("mouseover", this.autoHideHd.mouseover); this.collapsedEl.un("mouseout", this.autoHideHd.mouseout); this.collapsedEl.un("mouseover", this.autoHideHd.mouseover); } }, // private clearMonitor : function(){ Ext.getDoc().un("click", this.slideInIf, this); }, /** * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout * are clicked, or the mouse exits the Region. */ slideOut : function(){ if(this.isSlid || this.el.hasActiveFx()){ return; } this.isSlid = true; var ts = this.panel.tools; if(ts && ts.toggle){ ts.toggle.hide(); } this.el.show(); if(this.position == 'east' || this.position == 'west'){ this.panel.setSize(undefined, this.collapsedEl.getHeight()); }else{ this.panel.setSize(this.collapsedEl.getWidth(), undefined); } this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top]; this.el.alignTo(this.collapsedEl, this.getCollapseAnchor()); this.el.setStyle("z-index", this.floatingZIndex+2); this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating'); if(this.animFloat !== false){ this.beforeSlide(); this.el.slideIn(this.getSlideAnchor(), { callback: function(){ this.afterSlide(); this.initAutoHide(); Ext.getDoc().on("click", this.slideInIf, this); }, scope: this, block: true }); }else{ this.initAutoHide(); Ext.getDoc().on("click", this.slideInIf, this); } }, // private afterSlideIn : function(){ this.clearAutoHide(); this.isSlid = false; this.clearMonitor(); this.el.setStyle("z-index", ""); this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed'); this.el.dom.style.left = this.restoreLT[0]; this.el.dom.style.top = this.restoreLT[1]; var ts = this.panel.tools; if(ts && ts.toggle){ ts.toggle.show(); } }, /** * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides * this region back into its collapsed state. */ slideIn : function(cb){ if(!this.isSlid || this.el.hasActiveFx()){ Ext.callback(cb); return; } this.isSlid = false; if(this.animFloat !== false){ this.beforeSlide(); this.el.slideOut(this.getSlideAnchor(), { callback: function(){ this.el.hide(); this.afterSlide(); this.afterSlideIn(); Ext.callback(cb); }, scope: this, block: true }); }else{ this.el.hide(); this.afterSlideIn(); } }, // private slideInIf : function(e){ if(!e.within(this.el)){ this.slideIn(); } }, // private anchors : { "west" : "left", "east" : "right", "north" : "top", "south" : "bottom" }, // private sanchors : { "west" : "l", "east" : "r", "north" : "t", "south" : "b" }, // private canchors : { "west" : "tl-tr", "east" : "tr-tl", "north" : "tl-bl", "south" : "bl-tl" }, // private getAnchor : function(){ return this.anchors[this.position]; }, // private getCollapseAnchor : function(){ return this.canchors[this.position]; }, // private getSlideAnchor : function(){ return this.sanchors[this.position]; }, // private getAlignAdj : function(){ var cm = this.cmargins; switch(this.position){ case "west": return [0, 0]; break; case "east": return [0, 0]; break; case "north": return [0, 0]; break; case "south": return [0, 0]; break; } }, // private getExpandAdj : function(){ var c = this.collapsedEl, cm = this.cmargins; switch(this.position){ case "west": return [-(cm.right+c.getWidth()+cm.left), 0]; break; case "east": return [cm.right+c.getWidth()+cm.left, 0]; break; case "north": return [0, -(cm.top+cm.bottom+c.getHeight())]; break; case "south": return [0, cm.top+cm.bottom+c.getHeight()]; break; } }, destroy : function(){ Ext.destroy(this.miniCollapsedEl, this.collapsedEl); } }; /** * @class Ext.layout.BorderLayout.SplitRegion * @extends Ext.layout.BorderLayout.Region * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that * has a built-in {@link Ext.SplitBar} for user resizing of regions. The movement of the split bar * is configurable to move either {@link #tickSize smooth or incrementally}.</p> * @constructor * Create a new SplitRegion. * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region. * @param {Object} config The configuration options * @param {String} position The region position. Valid values are: north, south, east, west and center. Every * BorderLayout must have a center region for the primary content -- all other regions are optional. */ Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){ Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos); // prevent switch this.applyLayout = this.applyFns[pos]; }; Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, { /** * @cfg {Number} tickSize * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}. * By default, the {@link Ext.SplitBar SplitBar} moves smoothly. */ /** * @cfg {String} splitTip * The tooltip to display when the user hovers over a * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar * (defaults to <tt>"Drag to resize."</tt>). Only applies if * <tt>{@link #useSplitTips} = true</tt>. */ splitTip : "Drag to resize.", /** * @cfg {String} collapsibleSplitTip * The tooltip to display when the user hovers over a * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar * (defaults to "Drag to resize. Double click to hide."). Only applies if * <tt>{@link #useSplitTips} = true</tt>. */ collapsibleSplitTip : "Drag to resize. Double click to hide.", /** * @cfg {Boolean} useSplitTips * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar * (defaults to <tt>false</tt>). The tooltip text will be the value of either * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate. */ useSplitTips : false, // private splitSettings : { north : { orientation: Ext.SplitBar.VERTICAL, placement: Ext.SplitBar.TOP, maxFn : 'getVMaxSize', minProp: 'minHeight', maxProp: 'maxHeight' }, south : { orientation: Ext.SplitBar.VERTICAL, placement: Ext.SplitBar.BOTTOM, maxFn : 'getVMaxSize', minProp: 'minHeight', maxProp: 'maxHeight' }, east : { orientation: Ext.SplitBar.HORIZONTAL, placement: Ext.SplitBar.RIGHT, maxFn : 'getHMaxSize', minProp: 'minWidth', maxProp: 'maxWidth' }, west : { orientation: Ext.SplitBar.HORIZONTAL, placement: Ext.SplitBar.LEFT, maxFn : 'getHMaxSize', minProp: 'minWidth', maxProp: 'maxWidth' } }, // private applyFns : { west : function(box){ if(this.isCollapsed){ return this.applyLayoutCollapsed(box); } var sd = this.splitEl.dom, s = sd.style; this.panel.setPosition(box.x, box.y); var sw = sd.offsetWidth; s.left = (box.x+box.width-sw)+'px'; s.top = (box.y)+'px'; s.height = Math.max(0, box.height)+'px'; this.panel.setSize(box.width-sw, box.height); }, east : function(box){ if(this.isCollapsed){ return this.applyLayoutCollapsed(box); } var sd = this.splitEl.dom, s = sd.style; var sw = sd.offsetWidth; this.panel.setPosition(box.x+sw, box.y); s.left = (box.x)+'px'; s.top = (box.y)+'px'; s.height = Math.max(0, box.height)+'px'; this.panel.setSize(box.width-sw, box.height); }, north : function(box){ if(this.isCollapsed){ return this.applyLayoutCollapsed(box); } var sd = this.splitEl.dom, s = sd.style; var sh = sd.offsetHeight; this.panel.setPosition(box.x, box.y); s.left = (box.x)+'px'; s.top = (box.y+box.height-sh)+'px'; s.width = Math.max(0, box.width)+'px'; this.panel.setSize(box.width, box.height-sh); }, south : function(box){ if(this.isCollapsed){ return this.applyLayoutCollapsed(box); } var sd = this.splitEl.dom, s = sd.style; var sh = sd.offsetHeight; this.panel.setPosition(box.x, box.y+sh); s.left = (box.x)+'px'; s.top = (box.y)+'px'; s.width = Math.max(0, box.width)+'px'; this.panel.setSize(box.width, box.height-sh); } }, // private render : function(ct, p){ Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p); var ps = this.position; this.splitEl = ct.createChild({ cls: "x-layout-split x-layout-split-"+ps, html: " ", id: this.panel.id + '-xsplit' }); if(this.collapseMode == 'mini'){ this.miniSplitEl = this.splitEl.createChild({ cls: "x-layout-mini x-layout-mini-"+ps, html: " " }); this.miniSplitEl.addClassOnOver('x-layout-mini-over'); this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true}); } var s = this.splitSettings[ps]; this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation); this.split.tickSize = this.tickSize; this.split.placement = s.placement; this.split.getMaximumSize = this[s.maxFn].createDelegate(this); this.split.minSize = this.minSize || this[s.minProp]; this.split.on("beforeapply", this.onSplitMove, this); this.split.useShim = this.useShim === true; this.maxSize = this.maxSize || this[s.maxProp]; if(p.hidden){ this.splitEl.hide(); } if(this.useSplitTips){ this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip; } if(this.collapsible){ this.splitEl.on("dblclick", this.onCollapseClick, this); } }, //docs inherit from superclass getSize : function(){ if(this.isCollapsed){ return this.collapsedEl.getSize(); } var s = this.panel.getSize(); if(this.position == 'north' || this.position == 'south'){ s.height += this.splitEl.dom.offsetHeight; }else{ s.width += this.splitEl.dom.offsetWidth; } return s; }, // private getHMaxSize : function(){ var cmax = this.maxSize || 10000; var center = this.layout.center; return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth()); }, // private getVMaxSize : function(){ var cmax = this.maxSize || 10000; var center = this.layout.center; return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight()); }, // private onSplitMove : function(split, newSize){ var s = this.panel.getSize(); this.lastSplitSize = newSize; if(this.position == 'north' || this.position == 'south'){ this.panel.setSize(s.width, newSize); this.state.height = newSize; }else{ this.panel.setSize(newSize, s.height); this.state.width = newSize; } this.layout.layout(); this.panel.saveState(); return false; }, /** * Returns a reference to the split bar in use by this region. * @return {Ext.SplitBar} The split bar */ getSplitBar : function(){ return this.split; }, // inherit docs destroy : function() { Ext.destroy(this.miniSplitEl, this.split, this.splitEl); Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this); } }); Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/** * @class Ext.layout.FormLayout * @extends Ext.layout.AnchorLayout * <p>This layout manager is specifically designed for rendering and managing child Components of * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of * {@link Ext.form.Field Field}s.</p> * * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt> * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p> * * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel} * (which is configured with FormLayout as its layout class by default) since it also provides built-in * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p> * * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g. * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following * layout-specific config properties:<div class="mdetail-params"><ul> * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li> * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li> * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li> * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li> * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li> * </ul></div></p> * * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option: * <div class="mdetail-params"><ul> * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li> * </ul></div></p> * * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured * in this way may be configured with the following options which affect the way the FormLayout renders them: * <div class="mdetail-params"><ul> * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li> * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li> * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li> * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li> * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li> * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li> * </ul></div></p> * * <p>Example usage:</p> * <pre><code> // Required if showing validation messages Ext.QuickTips.init(); // While you can create a basic Panel with layout:'form', practically // you should usually use a FormPanel to also get its form functionality // since it already creates a FormLayout internally. var form = new Ext.form.FormPanel({ title: 'Form Layout', bodyStyle: 'padding:15px', width: 350, defaultType: 'textfield', defaults: { // applied to each contained item width: 230, msgTarget: 'side' }, items: [{ fieldLabel: 'First Name', name: 'first', allowBlank: false, {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config },{ fieldLabel: 'Last Name', name: 'last' },{ fieldLabel: 'Email', name: 'email', vtype:'email' }, { xtype: 'textarea', hideLabel: true, // override hideLabels layout config name: 'msg', anchor: '100% -53' } ], buttons: [ {text: 'Save'}, {text: 'Cancel'} ], layoutConfig: { {@link #labelSeparator}: '~' // superseded by assignment below }, // config options applicable to container when layout='form': hideLabels: false, labelAlign: 'left', // or 'right' or 'top' {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value labelWidth: 65, // defaults to 100 labelPad: 8 // defaults to 5, must specify labelWidth to be honored }); </code></pre> */ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, { /** * @cfg {String} labelSeparator * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}. Configuration * of this property at the <b>container</b> level takes precedence. */ labelSeparator : ':', /** * Read only. The CSS style specification string added to field labels in this layout if not * otherwise {@link Ext.Component#labelStyle specified by each contained field}. * @type String * @property labelStyle */ /** * @cfg {Boolean} trackLabels * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>. */ trackLabels: false, onRemove: function(c){ Ext.layout.FormLayout.superclass.onRemove.call(this, c); if(this.trackLabels){ c.un('show', this.onFieldShow, this); c.un('hide', this.onFieldHide, this); } // check for itemCt, since we may be removing a fieldset or something similar var el = c.getPositionEl(), ct = c.getItemCt && c.getItemCt(); if(c.rendered && ct){ if (el && el.dom) { el.insertAfter(ct); } Ext.destroy(ct); Ext.destroyMembers(c, 'label', 'itemCt'); if(c.customItemCt){ Ext.destroyMembers(c, 'getItemCt', 'customItemCt'); } } }, // private setContainer : function(ct){ Ext.layout.FormLayout.superclass.setContainer.call(this, ct); if(ct.labelAlign){ ct.addClass('x-form-label-'+ct.labelAlign); } if(ct.hideLabels){ Ext.apply(this, { labelStyle: 'display:none', elementStyle: 'padding-left:0;', labelAdjust: 0 }); }else{ this.labelSeparator = ct.labelSeparator || this.labelSeparator; ct.labelWidth = ct.labelWidth || 100; if(Ext.isNumber(ct.labelWidth)){ var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5; Ext.apply(this, { labelAdjust: ct.labelWidth + pad, labelStyle: 'width:' + ct.labelWidth + 'px;', elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px' }); } if(ct.labelAlign == 'top'){ Ext.apply(this, { labelStyle: 'width:auto;', labelAdjust: 0, elementStyle: 'padding-left:0;' }); } } }, // private isHide: function(c){ return c.hideLabel || this.container.hideLabels; }, onFieldShow: function(c){ c.getItemCt().removeClass('x-hide-' + c.hideMode); }, onFieldHide: function(c){ c.getItemCt().addClass('x-hide-' + c.hideMode); }, //private getLabelStyle: function(s){ var ls = '', items = [this.labelStyle, s]; for (var i = 0, len = items.length; i < len; ++i){ if (items[i]){ ls += items[i]; if (ls.substr(-1, 1) != ';'){ ls += ';' } } } return ls; }, /** * @cfg {Ext.Template} fieldTpl * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code> new Ext.Template( '<div class="x-form-item {itemCls}" tabIndex="-1">', '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>', '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">', '</div><div class="{clearCls}"></div>', '</div>' ); </code></pre> * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p> * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul> * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt> * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt> * supplied at the container level.</div></li> * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li> * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc"> * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li> * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this * field (defaults to <tt>''</tt>)</div></li> * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after * the text of the label for this field (defaults to a colon <tt>':'</tt> or the * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li> * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li> * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li> * </ul></div> * <p>Also see <tt>{@link #getTemplateArgs}</tt></p> */ // private renderItem : function(c, position, target){ if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){ var args = this.getTemplateArgs(c); if(Ext.isNumber(position)){ position = target.dom.childNodes[position] || null; } if(position){ c.itemCt = this.fieldTpl.insertBefore(position, args, true); }else{ c.itemCt = this.fieldTpl.append(target, args, true); } if(!c.getItemCt){ // Non form fields don't have getItemCt, apply it here // This will get cleaned up in onRemove Ext.apply(c, { getItemCt: function(){ return c.itemCt; }, customItemCt: true }); } c.label = c.getItemCt().child('label.x-form-item-label'); if(!c.rendered){ c.render('x-form-el-' + c.id); }else if(!this.isValidParent(c, target)){ Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl()); } if(this.trackLabels){ if(c.hidden){ this.onFieldHide(c); } c.on({ scope: this, show: this.onFieldShow, hide: this.onFieldHide }); } this.configureItem(c); }else { Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments); } }, /** * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p> * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl} * to create a correctly wrapped, labeled and styled form Field. This may be overriden to * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul> * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt> * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt> * supplied at the container level.</div></li> * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li> * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc"> * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li> * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this * field (defaults to <tt>''</tt>)</div></li> * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after * the text of the label for this field (defaults to a colon <tt>':'</tt> or the * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li> * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li> * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li> * </ul></div> * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered. * @return An object hash containing the properties required to render the Field. */ getTemplateArgs: function(field) { var noLabelSep = !field.fieldLabel || field.hideLabel; return { id: field.id, label: field.fieldLabel, labelStyle: this.getLabelStyle(field.labelStyle), elementStyle: this.elementStyle||'', labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator), itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''), clearCls: field.clearCls || 'x-form-clear-left' }; }, // private adjustWidthAnchor: function(value, c){ if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){ var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict); return value - this.labelAdjust + (adjust ? -3 : 0); } return value; }, adjustHeightAnchor : function(value, c){ if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){ return value - c.label.getHeight(); } return value; }, // private isValidParent : function(c, target){ return target && this.container.getEl().contains(c.getPositionEl()); } /** * @property activeItem * @hide */ }); Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout; /**
- * @class Ext.layout.AccordionLayout
- * @extends Ext.layout.FitLayout
- * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
- * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
- * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
- * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
- * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
- * <p>Example usage:</p>
- * <pre><code>
- var accordion = new Ext.Panel({
- title: 'Accordion Layout',
- layout:'accordion',
- defaults: {
- // applied to each contained panel
- bodyStyle: 'padding:15px'
- },
- layoutConfig: {
- // layout-specific configs go here
- titleCollapse: false,
- animate: true,
- activeOnTop: true
- },
- items: [{
- title: 'Panel 1',
- html: '<p>Panel content!</p>'
- },{
- title: 'Panel 2',
- html: '<p>Panel content!</p>'
- },{
- title: 'Panel 3',
- html: '<p>Panel content!</p>'
- }]
- });
- </code></pre>
- */
- Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
- /**
- * @cfg {Boolean} fill
- * True to adjust the active item's height to fill the available space in the container, false to use the
- * item's current height, or auto height if not explicitly set (defaults to true).
- */
- fill : true,
- /**
- * @cfg {Boolean} autoWidth
- * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
- * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
- * layouts if they have auto width, so in such cases this config should be set to false.
- */
- autoWidth : true,
- /**
- * @cfg {Boolean} titleCollapse
- * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
- * expand/collapse only when the toggle tool button is clicked (defaults to true). When set to false,
- * {@link #hideCollapseTool} should be false also.
- */
- titleCollapse : true,
- /**
- * @cfg {Boolean} hideCollapseTool
- * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
- * When set to true, {@link #titleCollapse} should be true also.
- */
- hideCollapseTool : false,
- /**
- * @cfg {Boolean} collapseFirst
- * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
- * in the contained panels' title bars, false to render it last (defaults to false).
- */
- collapseFirst : false,
- /**
- * @cfg {Boolean} animate
- * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
- * close directly with no animation (defaults to false). Note: to defer to the specific config setting of each
- * contained panel for this property, set this to undefined at the layout level.
- */
- animate : false,
- /**
- * @cfg {Boolean} sequence
- * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
- */
- sequence : false,
- /**
- * @cfg {Boolean} activeOnTop
- * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
- * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
- */
- activeOnTop : false,
- renderItem : function(c){
- if(this.animate === false){
- c.animCollapse = false;
- }
- c.collapsible = true;
- if(this.autoWidth){
- c.autoWidth = true;
- }
- if(this.titleCollapse){
- c.titleCollapse = true;
- }
- if(this.hideCollapseTool){
- c.hideCollapseTool = true;
- }
- if(this.collapseFirst !== undefined){
- c.collapseFirst = this.collapseFirst;
- }
- if(!this.activeItem && !c.collapsed){
- this.setActiveItem(c, true);
- }else if(this.activeItem && this.activeItem != c){
- c.collapsed = true;
- }
- Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
- c.header.addClass('x-accordion-hd');
- c.on('beforeexpand', this.beforeExpand, this);
- },
- onRemove: function(c){
- Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
- if(c.rendered){
- c.header.removeClass('x-accordion-hd');
- }
- c.un('beforeexpand', this.beforeExpand, this);
- },
- // private
- beforeExpand : function(p, anim){
- var ai = this.activeItem;
- if(ai){
- if(this.sequence){
- delete this.activeItem;
- if (!ai.collapsed){
- ai.collapse({callback:function(){
- p.expand(anim || true);
- }, scope: this});
- return false;
- }
- }else{
- ai.collapse(this.animate);
- }
- }
- this.setActive(p);
- if(this.activeOnTop){
- p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
- }
- this.layout();
- },
- // private
- setItemSize : function(item, size){
- if(this.fill && item){
- var hh = 0;
- this.container.items.each(function(p){
- if(p != item){
- hh += p.header.getHeight();
- }
- });
- size.height -= hh;
- item.setSize(size);
- }
- },
- /**
- * Sets the active (expanded) item in the layout.
- * @param {String/Number} item The string component id or numeric index of the item to activate