cmp-foundation-debug.js
资源名称:ext-3.1.0.zip [点击查看]
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:446k
源码类别:
JavaScript
开发平台:
JavaScript
- */
- setActiveItem : function(item){
- this.setActive(item, true);
- },
- // private
- setActive : function(item, expand){
- var ai = this.activeItem;
- item = this.container.getComponent(item);
- if(ai != item){
- if(item.rendered && item.collapsed && expand){
- item.expand();
- }else{
- if(ai){
- ai.fireEvent('deactivate', ai);
- }
- this.activeItem = item;
- item.fireEvent('activate', item);
- }
- }
- }
- });
- Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
- //backwards compat
- Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
- * @class Ext.layout.TableLayout
- * @extends Ext.layout.ContainerLayout
- * <p>This layout allows you to easily render content into an HTML table. The total number of columns can be
- * specified, and rowspan and colspan can be used to create complex layouts within the table.
- * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
- * and should generally not need to be created directly via the new keyword.</p>
- * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
- * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout. In the
- * case of TableLayout, the only valid layout config property is {@link #columns}. However, the items added to a
- * TableLayout can supply the following table-specific config properties:</p>
- * <ul>
- * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
- * <li><b>colspan</b> Applied to the table cell containing the item.</li>
- * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
- * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
- * </ul>
- * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
- * HTML table. You simply add each panel (or "cell") that you want to include along with any span attributes
- * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
- * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
- * total column count in the layoutConfig and start adding panels in their natural order from left to right,
- * top to bottom. The layout will automatically figure out, based on the column count, rowspans and colspans,
- * how to position each panel within the table. Just like with HTML tables, your rowspans and colspans must add
- * up correctly in your overall layout or you'll end up with missing and/or extra cells! Example usage:</p>
- * <pre><code>
- // This code will generate a layout table that is 3 columns by 2 rows
- // with some spanning included. The basic layout will be:
- // +--------+-----------------+
- // | A | B |
- // | |--------+--------|
- // | | C | D |
- // +--------+--------+--------+
- var table = new Ext.Panel({
- title: 'Table Layout',
- layout:'table',
- defaults: {
- // applied to each contained panel
- bodyStyle:'padding:20px'
- },
- layoutConfig: {
- // The total column count must be specified here
- columns: 3
- },
- items: [{
- html: '<p>Cell A content</p>',
- rowspan: 2
- },{
- html: '<p>Cell B content</p>',
- colspan: 2
- },{
- html: '<p>Cell C content</p>',
- cellCls: 'highlight'
- },{
- html: '<p>Cell D content</p>'
- }]
- });
- </code></pre>
- */
- Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
- /**
- * @cfg {Number} columns
- * The total number of columns to create in the table for this layout. If not specified, all Components added to
- * this layout will be rendered into a single row using one column per Component.
- */
- // private
- monitorResize:false,
- targetCls: 'x-table-layout-ct',
- /**
- * @cfg {Object} tableAttrs
- * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
- * used to create the layout's <tt><table></tt> element. Example:</p><pre><code>
- {
- xtype: 'panel',
- layout: 'table',
- layoutConfig: {
- tableAttrs: {
- style: {
- width: '100%'
- }
- },
- columns: 3
- }
- }</code></pre>
- */
- tableAttrs:null,
- // private
- setContainer : function(ct){
- Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
- this.currentRow = 0;
- this.currentColumn = 0;
- this.cells = [];
- },
- // private
- onLayout : function(ct, target){
- var cs = ct.items.items, len = cs.length, c, i;
- if(!this.table){
- this.table = target.createChild(
- Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
- }
- this.renderAll(ct, target);
- },
- // private
- getRow : function(index){
- var row = this.table.tBodies[0].childNodes[index];
- if(!row){
- row = document.createElement('tr');
- this.table.tBodies[0].appendChild(row);
- }
- return row;
- },
- // private
- getNextCell : function(c){
- var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
- var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
- for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
- if(!this.cells[rowIndex]){
- this.cells[rowIndex] = [];
- }
- for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
- this.cells[rowIndex][colIndex] = true;
- }
- }
- var td = document.createElement('td');
- if(c.cellId){
- td.id = c.cellId;
- }
- var cls = 'x-table-layout-cell';
- if(c.cellCls){
- cls += ' ' + c.cellCls;
- }
- td.className = cls;
- if(c.colspan){
- td.colSpan = c.colspan;
- }
- if(c.rowspan){
- td.rowSpan = c.rowspan;
- }
- this.getRow(curRow).appendChild(td);
- return td;
- },
- // private
- getNextNonSpan: function(colIndex, rowIndex){
- var cols = this.columns;
- while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
- if(cols && colIndex >= cols){
- rowIndex++;
- colIndex = 0;
- }else{
- colIndex++;
- }
- }
- return [colIndex, rowIndex];
- },
- // private
- renderItem : function(c, position, target){
- if(c && !c.rendered){
- c.render(this.getNextCell(c));
- this.configureItem(c, position);
- }else if(c && !this.isValidParent(c, target)){
- var container = this.getNextCell(c);
- container.insertBefore(c.getPositionEl().dom, null);
- c.container = Ext.get(container);
- this.configureItem(c, position);
- }
- },
- // private
- isValidParent : function(c, target){
- return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
- }
- /**
- * @property activeItem
- * @hide
- */
- });
- Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
- * @class Ext.layout.AbsoluteLayout
- * @extends Ext.layout.AnchorLayout
- * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
- * ability for x/y positioning using the standard x and y component config options.</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 form = new Ext.form.FormPanel({
- title: 'Absolute Layout',
- layout:'absolute',
- layoutConfig: {
- // layout-specific configs go here
- extraCls: 'x-abs-layout-item',
- },
- baseCls: 'x-plain',
- url:'save-form.php',
- defaultType: 'textfield',
- items: [{
- x: 0,
- y: 5,
- xtype:'label',
- text: 'Send To:'
- },{
- x: 60,
- y: 0,
- name: 'to',
- anchor:'100%' // anchor width by percentage
- },{
- x: 0,
- y: 35,
- xtype:'label',
- text: 'Subject:'
- },{
- x: 60,
- y: 30,
- name: 'subject',
- anchor: '100%' // anchor width by percentage
- },{
- x:0,
- y: 60,
- xtype: 'textarea',
- name: 'msg',
- anchor: '100% 100%' // anchor width and height
- }]
- });
- </code></pre>
- */
- Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
- extraCls: 'x-abs-layout-item',
- onLayout : function(ct, target){
- target.position();
- this.paddingLeft = target.getPadding('l');
- this.paddingTop = target.getPadding('t');
- Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
- },
- // private
- adjustWidthAnchor : function(value, comp){
- return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
- },
- // private
- adjustHeightAnchor : function(value, comp){
- return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
- }
- /**
- * @property activeItem
- * @hide
- */
- });
- Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout; /** * @class Ext.layout.BoxLayout * @extends Ext.layout.ContainerLayout * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p> */ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, { /** * @cfg {Object} defaultMargins * <p>If the individual contained items do not have a <tt>margins</tt> * property specified, the default margins from this property will be * applied to each item.</p> * <br><p>This property may be specified as an object containing margins * to apply in the format:</p><pre><code> { top: (top margin), right: (right margin), bottom: (bottom margin), left: (left margin) }</code></pre> * <p>This property may also be specified as 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> * <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>Defaults to:</p><pre><code> * {top:0, right:0, bottom:0, left:0} * </code></pre> */ defaultMargins : {left:0,top:0,right:0,bottom:0}, /** * @cfg {String} padding * <p>Sets the padding to be applied to all child items managed by this layout.</p> * <p>This property must be specified as a string containing * space-separated, numeric padding values. The order of the sides associated * with each value matches the way CSS processes padding values:</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>Defaults to: <code>"0"</code></p> */ padding : '0', // documented in subclasses pack : 'start', // private monitorResize : true, scrollOffset : 0, extraCls : 'x-box-item', targetCls : 'x-box-layout-ct', innerCls : 'x-box-inner', constructor : function(config){ Ext.layout.BoxLayout.superclass.constructor.call(this, config); if(Ext.isString(this.defaultMargins)){ this.defaultMargins = this.parseMargins(this.defaultMargins); } }, // private 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, last = len-1, cm; if(!this.innerCt){ // the innerCt prevents wrapping and shuffling while // the container is resizing this.innerCt = target.createChild({cls:this.innerCls}); this.padding = this.parseMargins(this.padding); } this.renderAll(ct, this.innerCt); }, // private renderItem : function(c){ if(Ext.isString(c.margins)){ c.margins = this.parseMargins(c.margins); }else if(!c.margins){ c.margins = this.defaultMargins; } Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments); }, // deprecate getTargetSize : function(target){ return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize(true); }, getItems: function(ct){ var items = []; ct.items.each(function(c){ if(c.isVisible()){ items.push(c); } }); return items; } }); /** * @class Ext.layout.VBoxLayout * @extends Ext.layout.BoxLayout * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical * space between child items containing a numeric <code>flex</code> configuration.</p> * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option. */ Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, { /** * @cfg {String} align * Controls how the child items of the container are aligned. Acceptable configuration values for this * property are: * <div class="mdetail-params"><ul> * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally * at the <b>left</b> side of the container</div></li> * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the * <b>mid-width</b> of the container</div></li> * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill * the width of the container</div></li> * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to * the size of the largest item.</div></li> * </ul></div> */ align : 'left', // left, center, stretch, strechmax /** * @cfg {String} pack * Controls how the child items of the container are packed together. Acceptable configuration values * for this property are: * <div class="mdetail-params"><ul> * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at * <b>top</b> side of container</div></li> * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at * <b>mid-height</b> of container</div></li> * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b> * side of container</div></li> * </ul></div> */ /** * @cfg {Number} flex * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b> * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed). */ // private onLayout : function(ct, target){ Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target); var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw, size = target.getViewSize(true), w = size.width, h = size.height - this.scrollOffset, l = this.padding.left, t = this.padding.top, isStart = this.pack == 'start', stretchWidth = w - (this.padding.left + this.padding.right), extraHeight = 0, maxWidth = 0, totalFlex = 0, flexHeight = 0, usedHeight = 0, idx = 0, heights = [], restore = [], c, csLen = cs.length; // Do only width calculations and apply those first, as they can affect height for (i = 0 ; i < csLen; i++) { c = cs[i]; cm = c.margins; margin = cm.top + cm.bottom; maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right); } var innerCtWidth = maxWidth + this.padding.left + this.padding.right; switch(this.align){ case 'stretch': this.innerCt.setSize(w, h); break; case 'stretchmax': case 'left': this.innerCt.setSize(innerCtWidth, h); break; case 'center': this.innerCt.setSize(w = Math.max(w, innerCtWidth), h); break; } var availableWidth = Math.max(0, w - this.padding.left - this.padding.right); // Apply widths for (i = 0 ; i < csLen; i++) { c = cs[i]; cm = c.margins; if(this.align == 'stretch'){ c.setWidth((stretchWidth - (cm.left + cm.right)).constrain( c.minWidth || 0, c.maxWidth || 1000000)); }else if(this.align == 'stretchmax'){ c.setWidth((maxWidth - (cm.left + cm.right)).constrain( c.minWidth || 0, c.maxWidth || 1000000)); }else if(isStart && c.flex){ c.setWidth(); } } // Do height calculations for (i = 0 ; i < csLen; i++) { c = cs[i]; cm = c.margins; totalFlex += c.flex || 0; ch = c.getHeight(); margin = cm.top + cm.bottom; extraHeight += ch + margin; flexHeight += margin + (c.flex ? 0 : ch); } extraHeight = h - extraHeight - this.padding.top - this.padding.bottom; var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight), leftOver = availHeight; for (i = 0 ; i < csLen; i++) { c = cs[i]; if(isStart && c.flex){ ch = Math.floor(availHeight * (c.flex / totalFlex)); leftOver -= ch; heights.push(ch); } } if(this.pack == 'center'){ t += extraHeight ? extraHeight / 2 : 0; }else if(this.pack == 'end'){ t += extraHeight; } idx = 0; // Apply heights for (i = 0 ; i < csLen; i++) { c = cs[i]; cm = c.margins; t += cm.top; aw = availableWidth; cl = l + cm.left // default left pos // Adjust left pos for centering if(this.align == 'center'){ if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){ cl += (diff/2); aw -= diff; } } c.setPosition(cl, t); if(isStart && c.flex){ ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0)); c.setSize(aw, ch); }else{ ch = c.getHeight(); } t += ch + cm.bottom; } } }); Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout; /** * @class Ext.layout.HBoxLayout * @extends Ext.layout.BoxLayout * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal * space between child items containing a numeric <code>flex</code> configuration.</p> * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option. */ Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, { /** * @cfg {String} align * Controls how the child items of the container are aligned. Acceptable configuration values for this * property are: * <div class="mdetail-params"><ul> * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically * at the <b>top</b> of the container</div></li> * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the * <b>middle</b> of the container</div></li> * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill * the height of the container</div></li> * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to * the height of the largest item.</div></li> */ align : 'top', // top, middle, stretch, strechmax /** * @cfg {String} pack * Controls how the child items of the container are packed together. Acceptable configuration values * for this property are: * <div class="mdetail-params"><ul> * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at * <b>left</b> side of container</div></li> * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at * <b>mid-width</b> of container</div></li> * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b> * side of container</div></li> * </ul></div> */ /** * @cfg {Number} flex * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b> * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed). */ // private onLayout : function(ct, target){ Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target); var cs = this.getItems(ct), cm, cw, margin, ch, diff, size = target.getViewSize(true), w = size.width - this.scrollOffset, h = size.height, l = this.padding.left, t = this.padding.top, isStart = this.pack == 'start', isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1, stretchHeight = h - (this.padding.top + this.padding.bottom), extraWidth = 0, maxHeight = 0, totalFlex = 0, flexWidth = 0, usedWidth = 0; Ext.each(cs, function(c){ cm = c.margins; totalFlex += c.flex || 0; cw = c.getWidth(); margin = cm.left + cm.right; extraWidth += cw + margin; flexWidth += margin + (c.flex ? 0 : cw); maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom); }); extraWidth = w - extraWidth - this.padding.left - this.padding.right; var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom; switch(this.align){ case 'stretch': this.innerCt.setSize(w, h); break; case 'stretchmax': case 'top': this.innerCt.setSize(w, innerCtHeight); break; case 'middle': this.innerCt.setSize(w, h = Math.max(h, innerCtHeight)); break; } var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth), leftOver = availWidth, widths = [], restore = [], idx = 0, availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom); Ext.each(cs, function(c){ if(isStart && c.flex){ cw = Math.floor(availWidth * (c.flex / totalFlex)); leftOver -= cw; widths.push(cw); } }); if(this.pack == 'center'){ l += extraWidth ? extraWidth / 2 : 0; }else if(this.pack == 'end'){ l += extraWidth; } Ext.each(cs, function(c){ cm = c.margins; l += cm.left; c.setPosition(l, t + cm.top); if(isStart && c.flex){ cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0)); if(isRestore){ restore.push(c.getHeight()); } c.setSize(cw, availableHeight); }else{ cw = c.getWidth(); } l += cw + cm.right; }); idx = 0; Ext.each(cs, function(c){ cm = c.margins; ch = c.getHeight(); if(isStart && c.flex){ ch = restore[idx++]; } if(this.align == 'stretch'){ c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain( c.minHeight || 0, c.maxHeight || 1000000)); }else if(this.align == 'stretchmax'){ c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain( c.minHeight || 0, c.maxHeight || 1000000)); }else{ if(this.align == 'middle'){ diff = availableHeight - (ch + cm.top + cm.bottom); ch = t + cm.top + (diff/2); if(diff > 0){ c.setPosition(c.x, ch); } } if(isStart && c.flex){ c.setHeight(ch); } } }, this); } }); Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout; /**
- * @class Ext.Viewport
- * @extends Ext.Container
- * <p>A specialized container representing the viewable application area (the browser viewport).</p>
- * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
- * the browser viewport and manages window resizing. There may only be one Viewport created
- * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
- * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
- * method of any of its child Panels may themselves have a layout.</p>
- * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
- * for scrolling if needed using the {@link #autoScroll} config.</p>
- * <p>An example showing a classic application border layout:</p><pre><code>
- new Ext.Viewport({
- layout: 'border',
- items: [{
- region: 'north',
- html: '<h1 class="x-panel-header">Page Title</h1>',
- autoHeight: true,
- border: false,
- margins: '0 0 5 0'
- }, {
- region: 'west',
- collapsible: true,
- title: 'Navigation',
- width: 200
- // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
- }, {
- region: 'south',
- title: 'Title for Panel',
- collapsible: true,
- html: 'Information goes here',
- split: true,
- height: 100,
- minHeight: 100
- }, {
- region: 'east',
- title: 'Title for the Grid Panel',
- collapsible: true,
- split: true,
- width: 200,
- xtype: 'grid',
- // remaining grid configuration not shown ...
- // notice that the GridPanel is added directly as the region
- // it is not "overnested" inside another Panel
- }, {
- region: 'center',
- xtype: 'tabpanel', // TabPanel itself has no title
- items: {
- title: 'Default Tab',
- html: 'The first tab's content. Others may be added dynamically'
- }
- }]
- });
- </code></pre>
- * @constructor
- * Create a new Viewport
- * @param {Object} config The config object
- * @xtype viewport
- */
- Ext.Viewport = Ext.extend(Ext.Container, {
- /*
- * Privatize config options which, if used, would interfere with the
- * correct operation of the Viewport as the sole manager of the
- * layout of the document body.
- */
- /**
- * @cfg {Mixed} applyTo @hide
- */
- /**
- * @cfg {Boolean} allowDomMove @hide
- */
- /**
- * @cfg {Boolean} hideParent @hide
- */
- /**
- * @cfg {Mixed} renderTo @hide
- */
- /**
- * @cfg {Boolean} hideParent @hide
- */
- /**
- * @cfg {Number} height @hide
- */
- /**
- * @cfg {Number} width @hide
- */
- /**
- * @cfg {Boolean} autoHeight @hide
- */
- /**
- * @cfg {Boolean} autoWidth @hide
- */
- /**
- * @cfg {Boolean} deferHeight @hide
- */
- /**
- * @cfg {Boolean} monitorResize @hide
- */
- initComponent : function() {
- Ext.Viewport.superclass.initComponent.call(this);
- document.getElementsByTagName('html')[0].className += ' x-viewport';
- this.el = Ext.getBody();
- this.el.setHeight = Ext.emptyFn;
- this.el.setWidth = Ext.emptyFn;
- this.el.setSize = Ext.emptyFn;
- this.el.dom.scroll = 'no';
- this.allowDomMove = false;
- this.autoWidth = true;
- this.autoHeight = true;
- Ext.EventManager.onWindowResize(this.fireResize, this);
- this.renderTo = this.el;
- },
- fireResize : function(w, h){
- this.onResize(w, h, w, h);
- }
- });
- Ext.reg('viewport', Ext.Viewport);
- /** * @class Ext.Panel * @extends Ext.Container * <p>Panel is a container that has specific functionality and structural components that make * it the perfect building block for application-oriented user interfaces.</p> * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p> * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply 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 Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional * information).</p> * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized * behavior. Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p> * @constructor * @param {Object} config The config object * @xtype panel */ Ext.Panel = Ext.extend(Ext.Container, { /** * The Panel's header {@link Ext.Element Element}. Read-only. * <p>This Element is used to house the {@link #title} and {@link #tools}</p> * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p> * @type Ext.Element * @property header */ /** * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content. * The content may be specified in the {@link #html} config, or it may be loaded using the * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only. * <p>If this is used to load visible HTML elements in either way, then * the Panel may not be used as a Layout for hosting nested Panels.</p> * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout} * then the body Element must not be loaded or changed - it is under the control * of the Panel's Layout. * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p> * @type Ext.Element * @property body */ /** * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only. * @type Ext.Element * @property bwrap */ /** * True if this panel is collapsed. Read-only. * @type Boolean * @property collapsed */ /** * @cfg {Object} bodyCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any * Panel Element.</p> * <p>By default, the Default element in the table below will be used for the html markup to * create a child element with the commensurate Default class name (<code>baseCls</code> will be * replaced by <code>{@link #baseCls}</code>):</p> * <pre> * Panel Default Default Custom Additional Additional * Element element class element class style * ======== ========================== ========= ============== =========== * {@link #header} div {@link #baseCls}+'-header' {@link #headerCfg} headerCssClass headerStyle * {@link #bwrap} div {@link #baseCls}+'-bwrap' {@link #bwrapCfg} bwrapCssClass bwrapStyle * + tbar div {@link #baseCls}+'-tbar' {@link #tbarCfg} tbarCssClass tbarStyle * + {@link #body} div {@link #baseCls}+'-body' {@link #bodyCfg} {@link #bodyCssClass} {@link #bodyStyle} * + bbar div {@link #baseCls}+'-bbar' {@link #bbarCfg} bbarCssClass bbarStyle * + {@link #footer} div {@link #baseCls}+'-footer' {@link #footerCfg} footerCssClass footerStyle * </pre> * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element * to use a different form of markup than is created by default. An example of this might be * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as * a header, or forcing centering of all Panel content by having the body be a <center> * element:</p> * <pre><code> new Ext.Panel({ title: 'Message Title', renderTo: Ext.getBody(), width: 200, height: 130, <b>bodyCfg</b>: { tag: 'center', cls: 'x-panel-body', // Default class not applied if Custom element specified html: 'Message' }, footerCfg: { tag: 'h2', cls: 'x-panel-footer' // same as the Default class html: 'footer html' }, footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass} footerStyle: 'background-color:red' // see {@link #bodyStyle} }); * </code></pre> * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and * styling applied.</p> */ /** * @cfg {Object} headerCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure * of this Panel's {@link #header} Element. See <code>{@link #bodyCfg}</code> also.</p> */ /** * @cfg {Object} bwrapCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure * of this Panel's {@link #bwrap} Element. See <code>{@link #bodyCfg}</code> also.</p> */ /** * @cfg {Object} tbarCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure * of this Panel's {@link #tbar} Element. See <code>{@link #bodyCfg}</code> also.</p> */ /** * @cfg {Object} bbarCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure * of this Panel's {@link #bbar} Element. See <code>{@link #bodyCfg}</code> also.</p> */ /** * @cfg {Object} footerCfg * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure * of this Panel's {@link #footer} Element. See <code>{@link #bodyCfg}</code> also.</p> */ /** * @cfg {Boolean} closable * Panels themselves do not directly support being closed, but some Panel subclasses do (like * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify <code>true</code> * to enable closing in such situations. Defaults to <code>false</code>. */ /** * The Panel's footer {@link Ext.Element Element}. Read-only. * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p> * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p> * @type Ext.Element * @property footer */ /** * @cfg {Mixed} applyTo * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in * the document that specifies some panel-specific structural markup. When <code>applyTo</code> is used, * constituent parts of the panel can be specified by CSS class name within the main element, and the panel * will automatically create those components from that markup. Any required components not specified in the * markup will be autogenerated if necessary.</p> * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p> * <ul><li>baseCls + '-header'</li> * <li>baseCls + '-header-text'</li> * <li>baseCls + '-bwrap'</li> * <li>baseCls + '-tbar'</li> * <li>baseCls + '-body'</li> * <li>baseCls + '-bbar'</li> * <li>baseCls + '-footer'</li></ul> * <p>Using this config, a call to render() is not required. If applyTo is specified, any value passed for * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the * panel's container.</p> */ /** * @cfg {Object/Array} tbar * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render. * To access the top toolbar after render, use {@link #getTopToolbar}.</p> * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form * submission parameters are collected from the DOM tree.</p> */ /** * @cfg {Object/Array} bbar * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render. * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p> * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form * submission parameters are collected from the DOM tree.</p> */ /** @cfg {Object/Array} fbar * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of * {@link Ext.Button Button}s/{@link Ext.Button Button} configs, describing a {@link Ext.Toolbar Toolbar} to be rendered into this Panel's footer element.</p> * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p> * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p> * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example: * <pre><code> var w = new Ext.Window({ height: 250, width: 500, bbar: new Ext.Toolbar({ items: [{ text: 'bbar Left' },'->',{ text: 'bbar Right' }] }), {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->' // to control the alignment of fbar items fbar: [{ text: 'fbar Left' },'->',{ text: 'fbar Right' }] }).show(); * </code></pre> * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form * submission parameters are collected from the DOM tree.</p> */ /** * @cfg {Boolean} header * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating * it. If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not. * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header * will not be rendered. */ /** * @cfg {Boolean} footer * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have * been configured. See <code>{@link #bodyCfg}</code> for an example. */ /** * @cfg {String} title * The title text to be used as innerHTML (html tags are accepted) to display in the panel * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the * <code>{@link #header}</code> element will automatically be created and displayed unless * {@link #header} is explicitly set to <code>false</code>. If you do not want to specify a * <code>title</code> at config time, but you may want one later, you must either specify a non-empty * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container * element will get created. */ /** * @cfg {Array} buttons * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects. * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>, * that width will be applied to the item. */ /** * @cfg {Object/String/Function} autoLoad * A valid url spec according to the Updater {@link Ext.Updater#update} method. * If autoLoad is not null, the panel will attempt to load its contents * immediately upon render.<p> * The URL will become the default URL for this panel's {@link #body} element, * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p> */ /** * @cfg {Boolean} frame * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}). * <p>The template generated for each condition is depicted below:</p><pre><code> * // frame = false <div id="developer-specified-id-goes-here" class="x-panel"> <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:false)</span></div> <div class="x-panel-bwrap"> <div class="x-panel-body"><p>html value goes here</p></div> </div> </div> // frame = true (create 9 elements) <div id="developer-specified-id-goes-here" class="x-panel"> <div class="x-panel-tl"><div class="x-panel-tr"><div class="x-panel-tc"> <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:true)</span></div> </div></div></div> <div class="x-panel-bwrap"> <div class="x-panel-ml"><div class="x-panel-mr"><div class="x-panel-mc"> <div class="x-panel-body"><p>html value goes here</p></div> </div></div></div> <div class="x-panel-bl"><div class="x-panel-br"><div class="x-panel-bc"/> </div></div></div> </div> * </code></pre> */ /** * @cfg {Boolean} border * True to display the borders of the panel's body element, false to hide them (defaults to true). By default, * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false. */ /** * @cfg {Boolean} bodyBorder * True to display an interior border on the body element of the panel, false to hide it (defaults to true). * This only applies when {@link #border} == true. If border == true and bodyBorder == false, the border will display * as a 1px wide inset border, giving the entire body element an inset appearance. */ /** * @cfg {String/Object/Function} bodyCssClass * Additional css class selector to be applied to the {@link #body} element in the format expected by * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}. */ /** * @cfg {String/Object/Function} bodyStyle * Custom CSS styles to be applied to the {@link #body} element in the format expected by * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}. */ /** * @cfg {String} iconCls * The CSS class selector that specifies a background image to be used as the header icon (defaults to ''). * <p>An example of specifying a custom icon class would be something like: * </p><pre><code> // specify the property in the config for the class: ... iconCls: 'my-icon' // css class that specifies background image to be used as the icon image: .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; } </code></pre> */ /** * @cfg {Boolean} collapsible * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into * the header tool button area, false to keep the panel statically sized with no button (defaults to false). */ /** * @cfg {Array} tools * An array of tool button configs to be added to the header tool area. When rendered, each tool is * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i><tool-type></i></code> * <p>Each tool config may contain the following properties: * <div class="mdetail-params"><ul> * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type * of tool to create. By default, this assigns a CSS class of the form <code>x-tool-<i><tool-type></i></code> to the * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below. * The developer may implement custom tools by supplying alternate CSS rules and background images: * <ul> * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><code> toggle</code> (Created by default when {@link #collapsible} is <code>true</code>)</div> * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div> * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div> * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div> * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div> * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div> * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div> * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div> * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div> * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div> * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div> * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div> * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div> * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div> * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div> * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div> * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div> * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div> * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div> * </ul></div></li> * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to * call when clicked. Arguments passed are:<ul> * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li> * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li> * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li> * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li> * </ul></div></li> * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li> * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li> * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or * a config argument to {@link Ext.QuickTip#register}</div></li> * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li> * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying * event listeners in the format of an argument to {@link #addListener}</div></li> * </ul></div> * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these * tools only provide the visual button. Any required functionality must be provided by adding * handlers that implement the necessary behavior.</p> * <p>Example usage:</p> * <pre><code> tools:[{ id:'refresh', qtip: 'Refresh form Data', // hidden:true, handler: function(event, toolEl, panel){ // refresh logic } }, { id:'help', qtip: 'Get Help', handler: function(event, toolEl, panel){ // whatever } }] </code></pre> * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to * a 15x15 image:</p> * <pre><code> .x-tool-help {background-image: url(images/help.png);} .x-tool-help-over {background-image: url(images/help_over.png);} // if using an image sprite: .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;} .x-tool-help-over {background-position:-15px 0;} </code></pre> */ /** * @cfg {Ext.Template/Ext.XTemplate} toolTemplate * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code> new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>')</code></pre> * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array) * as specified in {@link #tools}. In the following example an <a> tag is used to provide a * visual indication when hovering over the tool:</p><pre><code> var win = new Ext.Window({ tools: [{ id: 'download', href: '/MyPdfDoc.pdf' }], toolTemplate: new Ext.XTemplate( '<tpl if="id=='download'">', '<a class="x-tool x-tool-pdf" href="{href}"></a>', '</tpl>', '<tpl if="id!='download'">', '<div class="x-tool x-tool-{id}">&#160;</div>', '</tpl>' ), width:500, height:300, closeAction:'hide' });</code></pre> * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an * appropriate background image, something like:</p> <pre><code> a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;} </code></pre> */ /** * @cfg {Boolean} hideCollapseTool * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>, * <code>false</code> to display it (defaults to <code>false</code>). */ /** * @cfg {Boolean} titleCollapse * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>) * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the * {@link Ext.layout.BorderLayout.Region BorderLayout.Region} * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option. */ /** * @cfg {Mixed} floating * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this * configuration property are:</p><div class="mdetail-params"><ul> * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is * rendered.</div></li> * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic * shimming and shadow).<ul> * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the * panel at negative offsets so that it is hidden.</div> * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div> * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width, * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div> * </ul></div></li> * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used * as the configuration object for the {@link Ext.Layer} that will be created.</div></li> * </ul></div> */ /** * @cfg {Boolean/String} shadow * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>). Note that this option * only applies when <code>{@link #floating} = true</code>. */ /** * @cfg {Number} shadowOffset * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this * option only applies when <code>{@link #floating} = true</code>. */ /** * @cfg {Boolean} shim * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>). * Note that this option only applies when <code>{@link #floating} = true</code>. */ /** * @cfg {Object/Array} keys * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding} * used to assign custom key handling to this panel (defaults to <code>null</code>). */ /** * @cfg {Boolean/Object} draggable * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p> * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which * moves a proxy Element around in place of the Panel's element, but provides no other behaviour * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.: * <pre><code> new Ext.Panel({ title: 'Drag me', x: 100, y: 100, renderTo: Ext.getBody(), floating: true, frame: true, width: 400, height: 200, draggable: { // Config option of Ext.Panel.DD class. // It's a floating Panel, so do not show a placeholder proxy in the original position. insertProxy: false, // Called for each mousemove event while dragging the DD object. onDrag : function(e){ // Record the x,y position of the drag proxy so that we can // position the Panel at end of drag. var pel = this.proxy.getEl(); this.x = pel.getLeft(true); this.y = pel.getTop(true); // Keep the Shadow aligned if there is one. var s = this.panel.getEl().shadow; if (s) { s.realign(this.x, this.y, pel.getWidth(), pel.getHeight()); } }, // Called on the mouseup event. endDrag : function(e){ this.panel.setPosition(this.x, this.y); } } }).show(); </code></pre> */ /** * @cfg {Boolean} disabled * Render this panel disabled (default is <code>false</code>). An important note when using the disabled * config on panels is that IE will often fail to initialize the disabled mask element correectly if * the panel's layout has not yet completed by the time the Panel is disabled during the render process. * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize * the disabled state: * <pre><code> new Ext.Panel({ ... listeners: { 'afterlayout': { fn: function(p){ p.disable(); }, single: true // important, as many layouts can occur } } }); </code></pre> */ /** * @cfg {Boolean} autoHeight * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>). * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code> * can cause issues with scrolling and will not generally work as expected since the panel will take * on the height of its contents rather than the height required by the Ext layout. */ /** * @cfg {String} baseCls * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>). * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling * except for required attributes for Ext layouts to function (e.g. overflow:hidden). * See <code>{@link #unstyled}</code> also.</p> */ baseCls : 'x-panel', /** * @cfg {String} collapsedCls * A CSS class to add to the panel's element after it has been collapsed (defaults to * <code>'x-panel-collapsed'</code>). */ collapsedCls : 'x-panel-collapsed', /** * @cfg {Boolean} maskDisabled * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults * to <code>true</code>). Either way, the panel will always tell its contained elements to disable themselves * when it is disabled, but masking the panel can provide an additional visual cue that the panel is * disabled. */ maskDisabled : true, /** * @cfg {Boolean} animCollapse * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>). */ animCollapse : Ext.enableFx, /** * @cfg {Boolean} headerAsText * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>, * <code>false</code> to hide it (defaults to <code>true</code>). */ headerAsText : true, /** * @cfg {String} buttonAlign * The alignment of any {@link #buttons} added to this panel. Valid values are <code>'right'</code>, * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>). */ buttonAlign : 'right', /** * @cfg {Boolean} collapsed * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to * <code>false</code>). */ collapsed : false, /** * @cfg {Boolean} collapseFirst * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of) * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>). */ collapseFirst : true, /** * @cfg {Number} minButtonWidth * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>) */ minButtonWidth : 75, /** * @cfg {Boolean} unstyled * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden). */ /** * @cfg {String} elements * A comma-delimited list of panel elements to initialize when the panel is rendered. Normally, this list will be * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to * make sure a structural element is rendered even if not specified at config time (for example, you may want * to add a button or toolbar dynamically after the panel has been rendered). Adding those elements to this * list will allocate the required placeholders in the panel when it is rendered. Valid values are<div class="mdetail-params"><ul> * <li><code>header</code></li> * <li><code>tbar</code> (top bar)</li> * <li><code>body</code></li> * <li><code>bbar</code> (bottom bar)</li> * <li><code>footer</code></li> * </ul></div> * Defaults to '<code>body</code>'. */ elements : 'body', /** * @cfg {Boolean} preventBodyReset * Defaults to <code>false</code>. When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code> * will be added to the panel's element, effectively applying css styles suggested by the W3C * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header, * footer, etc.). */ preventBodyReset : false, /** * @cfg {Number/String} padding * A shortcut for setting a padding style on the body element. The value can either be * a number to be applied to all sides, or a normal css string describing padding. * Defaults to <tt>undefined</tt>. * */ padding: undefined, /** @cfg {String} resizeEvent * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>. */ resizeEvent: 'bodyresize', // protected - these could be used to customize the behavior of the window, // but changing them would not be useful without further mofifications and // could lead to unexpected or undesirable results. toolTarget : 'header', collapseEl : 'bwrap', slideAnchor : 't', disabledClass : '', // private, notify box this class will handle heights deferHeight : true, // private expandDefaults: { duration : 0.25 }, // private collapseDefaults : { duration : 0.25 }, // private initComponent : function(){ Ext.Panel.superclass.initComponent.call(this); this.addEvents( /** * @event bodyresize * Fires after the Panel has been resized. * @param {Ext.Panel} p the Panel which has been resized. * @param {Number} width The Panel's new width. * @param {Number} height The Panel's new height. */ 'bodyresize', /** * @event titlechange * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}. * @param {Ext.Panel} p the Panel which has had its title changed. * @param {String} The new title. */ 'titlechange', /** * @event iconchange * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}. * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed. * @param {String} The new icon class. * @param {String} The old icon class. */ 'iconchange', /** * @event collapse * Fires after the Panel has been collapsed. * @param {Ext.Panel} p the Panel that has been collapsed. */ 'collapse', /** * @event expand * Fires after the Panel has been expanded. * @param {Ext.Panel} p The Panel that has been expanded. */ 'expand', /** * @event beforecollapse * Fires before the Panel is collapsed. A handler can return false to cancel the collapse. * @param {Ext.Panel} p the Panel being collapsed. * @param {Boolean} animate True if the collapse is animated, else false. */ 'beforecollapse', /** * @event beforeexpand * Fires before the Panel is expanded. A handler can return false to cancel the expand. * @param {Ext.Panel} p The Panel being expanded. * @param {Boolean} animate True if the expand is animated, else false. */ 'beforeexpand', /** * @event beforeclose * Fires before the Panel is closed. Note that Panels do not directly support being closed, but some * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel. This event only * applies to such subclasses. * A handler can return false to cancel the close. * @param {Ext.Panel} p The Panel being closed. */ 'beforeclose', /** * @event close * Fires after the Panel is closed. Note that Panels do not directly support being closed, but some * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel. * @param {Ext.Panel} p The Panel that has been closed. */ 'close', /** * @event activate * Fires after the Panel has been visually activated. * Note that Panels do not directly support being activated, but some Panel subclasses * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the * activate and deactivate events under the control of the TabPanel. * @param {Ext.Panel} p The Panel that has been activated. */ 'activate', /** * @event deactivate * Fires after the Panel has been visually deactivated. * Note that Panels do not directly support being deactivated, but some Panel subclasses * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the * activate and deactivate events under the control of the TabPanel. * @param {Ext.Panel} p The Panel that has been deactivated. */ 'deactivate' ); if(this.unstyled){ this.baseCls = 'x-plain'; } this.toolbars = []; // shortcuts if(this.tbar){ this.elements += ',tbar'; this.topToolbar = this.createToolbar(this.tbar); delete this.tbar; } if(this.bbar){ this.elements += ',bbar'; this.bottomToolbar = this.createToolbar(this.bbar); delete this.bbar; } if(this.header === true){ this.elements += ',header'; delete this.header; }else if(this.headerCfg || (this.title && this.header !== false)){ this.elements += ',header'; } if(this.footerCfg || this.footer === true){ this.elements += ',footer'; delete this.footer; } if(this.buttons){ this.fbar = this.buttons; delete this.buttons; } if(this.fbar){ this.createFbar(this.fbar); } if(this.autoLoad){ this.on('render', this.doAutoLoad, this, {delay:10}); } }, // private createFbar : function(fbar){ var min = this.minButtonWidth; this.elements += ',footer'; this.fbar = this.createToolbar(fbar, { buttonAlign: this.buttonAlign, toolbarCls: 'x-panel-fbar', enableOverflow: false, defaults: function(c){ return { minWidth: c.minWidth || min }; } }); //@compat addButton and buttons could possibly be removed //@target 4.0 /** * This Panel's Array of buttons as created from the <code>{@link #buttons}</code> * config property. Read only. * @type Array * @property buttons */ this.fbar.items.each(function(c){ c.minWidth = c.minWidth || this.minButtonWidth; }, this); this.buttons = this.fbar.items.items; }, // private createToolbar: function(tb, options){ var result; // Convert array to proper toolbar config if(Ext.isArray(tb)){ tb = { items: tb }; } result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar'); result.ownerCt = this; result.bufferResize = false; this.toolbars.push(result); return result; }, // private createElement : function(name, pnode){ if(this[name]){ pnode.appendChild(this[name].dom); return; } if(name === 'bwrap' || this.elements.indexOf(name) != -1){ if(this[name+'Cfg']){ this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']); }else{ var el = document.createElement('div'); el.className = this[name+'Cls']; this[name] = Ext.get(pnode.appendChild(el)); } if(this[name+'CssClass']){ this[name].addClass(this[name+'CssClass']); } if(this[name+'Style']){ this[name].applyStyles(this[name+'Style']); } } }, // private onRender : function(ct, position){ Ext.Panel.superclass.onRender.call(this, ct, position); this.createClasses(); var el = this.el, d = el.dom, bw, ts; if(this.collapsible && !this.hideCollapseTool){ this.tools = this.tools ? this.tools.slice(0) : []; this.tools[this.collapseFirst?'unshift':'push']({ id: 'toggle', handler : this.toggleCollapse, scope: this }); } if(this.tools){ ts = this.tools; this.elements += (this.header !== false) ? ',header' : ''; } this.tools = {}; el.addClass(this.baseCls); if(d.firstChild){ // existing markup this.header = el.down('.'+this.headerCls); this.bwrap = el.down('.'+this.bwrapCls); var cp = this.bwrap ? this.bwrap : el; this.tbar = cp.down('.'+this.tbarCls); this.body = cp.down('.'+this.bodyCls); this.bbar = cp.down('.'+this.bbarCls); this.footer = cp.down('.'+this.footerCls); this.fromMarkup = true; } if (this.preventBodyReset === true) { el.addClass('x-panel-reset'); } if(this.cls){ el.addClass(this.cls); } if(this.buttons){ this.elements += ',footer'; } // This block allows for maximum flexibility and performance when using existing markup // framing requires special markup if(this.frame){ el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls)); this.createElement('header', d.firstChild.firstChild.firstChild); this.createElement('bwrap', d); // append the mid and bottom frame to the bwrap bw = this.bwrap.dom; var ml = d.childNodes[1], bl = d.childNodes[2]; bw.appendChild(ml); bw.appendChild(bl); var mc = bw.firstChild.firstChild.firstChild; this.createElement('tbar', mc); this.createElement('body', mc); this.createElement('bbar', mc); this.createElement('footer', bw.lastChild.firstChild.firstChild); if(!this.footer){ this.bwrap.dom.lastChild.className += ' x-panel-nofooter'; } /* * Store a reference to this element so: * a) We aren't looking it up all the time * b) The last element is reported incorrectly when using a loadmask */ this.ft = Ext.get(this.bwrap.dom.lastChild); this.mc = Ext.get(mc); }else{ this.createElement('header', d); this.createElement('bwrap', d); // append the mid and bottom frame to the bwrap bw = this.bwrap.dom; this.createElement('tbar', bw); this.createElement('body', bw); this.createElement('bbar', bw); this.createElement('footer', bw); if(!this.header){ this.body.addClass(this.bodyCls + '-noheader'); if(this.tbar){ this.tbar.addClass(this.tbarCls + '-noheader'); } } } if(Ext.isDefined(this.padding)){ this.body.setStyle('padding', this.body.addUnits(this.padding)); } if(this.border === false){ this.el.addClass(this.baseCls + '-noborder'); this.body.addClass(this.bodyCls + '-noborder'); if(this.header){ this.header.addClass(this.headerCls + '-noborder'); } if(this.footer){ this.footer.addClass(this.footerCls + '-noborder'); } if(this.tbar){ this.tbar.addClass(this.tbarCls + '-noborder'); } if(this.bbar){ this.bbar.addClass(this.bbarCls + '-noborder'); } } if(this.bodyBorder === false){ this.body.addClass(this.bodyCls + '-noborder'); } this.bwrap.enableDisplayMode('block'); if(this.header){ this.header.unselectable(); // for tools, we need to wrap any existing header markup if(this.headerAsText){ this.header.dom.innerHTML = '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>'; if(this.iconCls){ this.setIconClass(this.iconCls); } } } if(this.floating){ this.makeFloating(this.floating); } if(this.collapsible && this.titleCollapse && this.header){ this.mon(this.header, 'click', this.toggleCollapse, this); this.header.setStyle('cursor', 'pointer'); } if(ts){ this.addTool.apply(this, ts); } if(this.fbar){ this.footer.addClass('x-panel-btns'); this.fbar.render(this.footer); this.footer.createChild({cls:'x-clear'}); } if(this.tbar && this.topToolbar){ this.topToolbar.render(this.tbar); } if(this.bbar && this.bottomToolbar){ this.bottomToolbar.render(this.bbar); } }, /** * Sets the CSS class that provides the icon image for this panel. This method will replace any existing * icon class if one has already been set and fire the {@link #iconchange} event after completion. * @param {String} cls The new CSS class name */ setIconClass : function(cls){ var old = this.iconCls; this.iconCls = cls; if(this.rendered && this.header){ if(this.frame){ this.header.addClass('x-panel-icon'); this.header.replaceClass(old, this.iconCls); }else{ var hd = this.header, img = hd.child('img.x-panel-inline-icon'); if(img){ Ext.fly(img).replaceClass(old, this.iconCls); }else{ Ext.DomHelper.insertBefore(hd.dom.firstChild, { tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls }); } } } this.fireEvent('iconchange', this, cls, old); }, // private makeFloating : function(cfg){ this.floating = true; this.el = new Ext.Layer(Ext.apply({}, cfg, { shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides', shadowOffset: this.shadowOffset, constrain:false, shim: this.shim === false ? false : undefined }), this.el); }, /** * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel. * @return {Ext.Toolbar} The toolbar */ getTopToolbar : function(){ return this.topToolbar; }, /** * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel. * @return {Ext.Toolbar} The toolbar */ getBottomToolbar : function(){ return this.bottomToolbar; }, /** * Adds a button to this panel. Note that this method must be called prior to rendering. The preferred * approach is to add buttons via the {@link #buttons} config. * @param {String/Object} config A valid {@link Ext.Button} config. A string will become the text for a default * button config, an object will be treated as a button config object. * @param {Function} handler The function to be called on button {@link Ext.Button#click} * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button. * @return {Ext.Button} The button that was added */ addButton : function(config, handler, scope){ if(!this.fbar){ this.createFbar([]); } if(handler){ if(Ext.isString(config)){ config = {text: config}; } config = Ext.apply({ handler: handler, scope: scope }, config) } return this.fbar.add(config); }, // private addTool : function(){ if(!this.rendered){ if(!this.tools){ this.tools = []; } Ext.each(arguments, function(arg){ this.tools.push(arg) }, this); return; } // nowhere to render tools! if(!this[this.toolTarget]){ return; } if(!this.toolTemplate){ // initialize the global tool template on first use var tt = new Ext.Template( '<div class="x-tool x-tool-{id}"> </div>' ); tt.disableFormats = true; tt.compile(); Ext.Panel.prototype.toolTemplate = tt; } for(var i = 0, a = arguments, len = a.length; i < len; i++) { var tc = a[i]; if(!this.tools[tc.id]){ var overCls = 'x-tool-'+tc.id+'-over'; var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true); this.tools[tc.id] = t; t.enableDisplayMode('block'); this.mon(t, 'click', this.createToolHandler(t, tc, overCls, this)); if(tc.on){ this.mon(t, tc.on); } if(tc.hidden){ t.hide(); } if(tc.qtip){ if(Ext.isObject(tc.qtip)){ Ext.QuickTips.register(Ext.apply({ target: t.id }, tc.qtip)); } else { t.dom.qtip = tc.qtip; } } t.addClassOnOver(overCls); } } }, onLayout : function(shallow, force){ if(this.hasLayout && this.toolbars.length > 0){ Ext.each(this.toolbars, function(tb){ tb.doLayout(undefined, force); }); this.syncHeight(); } }, syncHeight : function(){ var h = this.toolbarHeight, bd = this.body, lsh = this.lastSize.height, sz; if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){ return; } if(h != this.getToolbarHeight()){ h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight())); bd.setHeight(h); sz = bd.getSize(); this.toolbarHeight = this.getToolbarHeight(); this.onBodyResize(sz.width, sz.height); } }, // private onShow : function(){ if(this.floating){ return this.el.show(); } Ext.Panel.superclass.onShow.call(this); }, // private onHide : function(){ if(this.floating){ return this.el.hide(); } Ext.Panel.superclass.onHide.call(this); }, // private createToolHandler : function(t, tc, overCls, panel){ return function(e){ t.removeClass(overCls); if(tc.stopEvent !== false){ e.stopEvent(); } if(tc.handler){ tc.handler.call(tc.scope || t, e, t, panel, tc); } }; }, // private afterRender : function(){ if(this.floating && !this.hidden){ this.el.show(); } if(this.title){ this.setTitle(this.title); } if(this.collapsed){ this.collapsed = false; this.collapse(false); } Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last this.initEvents(); }, // private getKeyMap : function(){ if(!this.keyMap){ this.keyMap = new Ext.KeyMap(this.el, this.keys); } return this.keyMap; }, // private initEvents : function(){ if(this.keys){ this.getKeyMap(); } if(this.draggable){ this.initDraggable(); } if(this.toolbars.length > 0){ Ext.each(this.toolbars, function(tb){ tb.doLayout(); tb.on({ scope: this, afterlayout: this.syncHeight, remove: this.syncHeight }); }, this); if(!this.ownerCt){ this.syncHeight(); } } }, // private initDraggable : function(){ /** * <p>If this Panel is configured {@link #draggable}, this property will contain * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p> * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource} * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}. * @type Ext.dd.DragSource. * @property dd */ this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable); }, // private beforeEffect : function(anim){ if(this.floating){ this.el.beforeAction(); } if(anim !== false){ this.el.addClass('x-panel-animated'); } }, // private afterEffect : function(anim){ this.syncShadow(); if(anim !== false){ this.el.removeClass('x-panel-animated'); } }, // private - wraps up an animation param with internal callbacks createEffect : function(a, cb, scope){ var o = { scope:scope, block:true }; if(a === true){ o.callback = cb; return o; }else if(!a.callback){ o.callback = cb; }else { // wrap it up o.callback = function(){ cb.call(scope); Ext.callback(a.callback, a.scope); }; } return Ext.applyIf(o, a); }, /** * Collapses the panel body so that it becomes hidden. Fires the {@link #beforecollapse} event which will * cancel the collapse action if it returns false. * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the * {@link #animCollapse} panel config) * @return {Ext.Panel} this */ collapse : function(animate){ if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){ return; } var doAnim = animate === true || (animate !== false && this.animCollapse); this.beforeEffect(doAnim); this.onCollapse(doAnim, animate); return this; }, // private onCollapse : function(doAnim, animArg){ if(doAnim){ this[this.collapseEl].slideOut(this.slideAnchor, Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this), this.collapseDefaults)); }else{ this[this.collapseEl].hide(); this.afterCollapse(false); } }, // private afterCollapse : function(anim){ this.collapsed = true; this.el.addClass(this.collapsedCls); this.afterEffect(anim); this.fireEvent('collapse', this); }, /** * Expands the panel body so that it becomes visible. Fires the {@link #beforeexpand} event which will * cancel the expand action if it returns false. * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the * {@link #animCollapse} panel config) * @return {Ext.Panel} this */ expand : function(animate){ if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){ return; } var doAnim = animate === true || (animate !== false && this.animCollapse); this.el.removeClass(this.collapsedCls); this.beforeEffect(doAnim); this.onExpand(doAnim, animate); return this; }, // private onExpand : function(doAnim, animArg){ if(doAnim){ this[this.collapseEl].slideIn(this.slideAnchor, Ext.apply(this.createEffect(animArg||true, this.afterExpand, this), this.expandDefaults)); }else{ this[this.collapseEl].show(); this.afterExpand(false); } }, // private afterExpand : function(anim){ this.collapsed = false; this.afterEffect(anim); if(Ext.isDefined(this.deferLayout)){ this.doLayout(true); } this.fireEvent('expand', this); }, /** * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel. * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the * {@link #animCollapse} panel config) * @return {Ext.Panel} this */ toggleCollapse : function(animate){ this[this.collapsed ? 'expand' : 'collapse'](animate); return this; }, // private onDisable : function(){ if(this.rendered && this.maskDisabled){ this.el.mask(); } Ext.Panel.superclass.onDisable.call(this); }, // private onEnable : function(){ if(this.rendered && this.maskDisabled){ this.el.unmask(); } Ext.Panel.superclass.onEnable.call(this); }, // private onResize : function(w, h){ if(Ext.isDefined(w) || Ext.isDefined(h)){ if(!this.collapsed){ // First, set the the Panel's body width. // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match // The Toolbars must not buffer this resize operation because we need to know their heights. if(Ext.isNumber(w)){ this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth())); } else if (w == 'auto') { w = this.body.setWidth('auto').dom.offsetWidth; } else { w = this.body.dom.offsetWidth; } if(this.tbar){ this.tbar.setWidth(w); if(this.topToolbar){ this.topToolbar.setSize(w); } } if(this.bbar){ this.bbar.setWidth(w); if(this.bottomToolbar){ this.bottomToolbar.setSize(w); // The bbar does not move on resize without this. if (Ext.isIE) { this.bbar.setStyle('position', 'static'); this.bbar.setStyle('position', ''); } } } if(this.footer){ this.footer.setWidth(w); if(this.fbar){ this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto'); } } // At this point, the Toolbars must be layed out for getFrameHeight to find a result. if(Ext.isNumber(h)){ h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight())); this.body.setHeight(h); }else if(h == 'auto'){ this.body.setHeight(h); } if(this.disabled && this.el._mask){ this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight()); } }else{ this.queuedBodySize = {width: w, height: h}; if(!this.queuedExpand && this.allowQueuedExpand !== false){ this.queuedExpand = true; this.on('expand', function(){ delete this.queuedExpand; this.onResize(this.queuedBodySize.width, this.queuedBodySize.height); }, this, {single:true}); } } this.onBodyResize(w, h); } this.syncShadow(); Ext.Panel.superclass.onResize.call(this); }, // private onBodyResize: function(w, h){ this.fireEvent('bodyresize', this, w, h); }, // private getToolbarHeight: function(){ var h = 0; if(this.rendered){ Ext.each(this.toolbars, function(tb){ h += tb.getHeight(); }, this); } return h; }, // private adjustBodyHeight : function(h){ return h; }, // private adjustBodyWidth : function(w){ return w; }, // private onPosition : function(){ this.syncShadow(); }, /** * Returns the width in pixels of the framing elements of this panel (not including the body width). To * retrieve the body width see {@link #getInnerWidth}. * @return {Number} The frame width */ getFrameWidth : function(){ var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr'); if(this.frame){ var l = this.bwrap.dom.firstChild; w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r')); w += this.mc.getFrameWidth('lr'); } return w; }, /** * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and * header and footer elements, but not including the body height). To retrieve the body height see {@link #getInnerHeight}. * @return {Number} The frame height */ getFrameHeight : function(){ var h = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb'); h += (this.tbar ? this.tbar.getHeight() : 0) + (this.bbar ? this.bbar.getHeight() : 0); if(this.frame){ h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb'); }else{ h += (this.header ? this.header.getHeight() : 0) + (this.footer ? this.footer.getHeight() : 0); } return h; }, /** * Returns the width in pixels of the body element (not including the width of any framing elements). * For the frame width see {@link #getFrameWidth}. * @return {Number} The body width */ getInnerWidth : function(){ return this.getSize().width - this.getFrameWidth(); }, /** * Returns the height in pixels of the body element (not including the height of any framing elements). * For the frame height see {@link #getFrameHeight}. * @return {Number} The body height */ getInnerHeight : function(){ return this.getSize().height - this.getFrameHeight(); }, // private syncShadow : function(){ if(this.floating){ this.el.sync(true); } }, // private getLayoutTarget : function(){ return this.body; }, // private getContentTarget : function(){ return this.body; }, /** * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p> * <p>In order to be able to set the title, a header element must have been created * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>, * or configuring it with <code><b>{@link #header}: true</b></code>.</p> * @param {String} title The title text to set * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel */ setTitle : function(title, iconCls){ this.title = title; if(this.header && this.headerAsText){ this.header.child('span').update(title); } if(iconCls){ this.setIconClass(iconCls); } this.fireEvent('titlechange', this, title); return this; }, /** * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body. * @return {Ext.Updater} The Updater */ getUpdater : function(){ return this.body.getUpdater(); }, /** * Loads this content panel immediately with content returned from an XHR call. * @param {Object/String/Function} config A config object containing any of the following options: <pre><code> panel.load({ url: 'your-url.php', params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string callback: yourFunction, scope: yourObject, // optional scope for the callback discardUrl: false, nocache: false, text: 'Loading...', timeout: 30, scripts: false }); </code></pre> * The only required property is url. The optional properties nocache, text and scripts * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their * associated property on this panel Updater instance. * @return {Ext.Panel} this */ load : function(){ var um = this.body.getUpdater(); um.update.apply(um, arguments); return this; }, // private beforeDestroy : function(){ Ext.Panel.superclass.beforeDestroy.call(this); if(this.header){ this.header.removeAllListeners(); } if(this.tools){ for(var k in this.tools){ Ext.destroy(this.tools[k]); } } if(Ext.isArray(this.buttons)){ while(this.buttons.length) { Ext.destroy(this.buttons[0]); } } if(this.rendered){ Ext.destroy( this.ft, this.header, this.footer, this.toolbars, this.tbar, this.bbar, this.body, this.mc, this.bwrap ); if (this.fbar) { Ext.destroy( this.fbar, this.fbar.el ); } }else{ Ext.destroy( this.topToolbar, this.bottomToolbar ); } }, // private createClasses : function(){ this.headerCls = this.baseCls + '-header'; this.headerTextCls = this.baseCls + '-header-text'; this.bwrapCls = this.baseCls + '-bwrap'; this.tbarCls = this.baseCls + '-tbar'; this.bodyCls = this.baseCls + '-body'; this.bbarCls = this.baseCls + '-bbar'; this.footerCls = this.baseCls + '-footer'; }, // private createGhost : function(cls, useShim, appendTo){ var el = document.createElement('div'); el.className = 'x-panel-ghost ' + (cls ? cls : ''); if(this.header){ el.appendChild(this.el.dom.firstChild.cloneNode(true)); } Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight()); el.style.width = this.el.dom.offsetWidth + 'px';; if(!appendTo){ this.container.dom.appendChild(el); }else{ Ext.getDom(appendTo).appendChild(el); } if(useShim !== false && this.el.useShim !== false){ var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el); layer.show(); return layer; }else{ return new Ext.Element(el); } }, // private doAutoLoad : function(){ var u = this.body.getUpdater(); if(this.renderer){ u.setRenderer(this.renderer); } u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad}); }, /** * Retrieve a tool by id. * @param {String} id * @return {Object} tool */ getTool : function(id) { return this.tools[id]; } /** * @cfg {String} autoEl @hide */ }); Ext.reg('panel', Ext.Panel); /** * @class Ext.Editor * @extends Ext.Component * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic. * @constructor * Create a new Editor * @param {Object} config The config object * @xtype editor */ Ext.Editor = function(field, config){ if(field.field){ this.field = Ext.create(field.field, 'textfield'); config = Ext.apply({}, field); // copy so we don't disturb original config delete config.field; }else{ this.field = field; } Ext.Editor.superclass.constructor.call(this, config); }; Ext.extend(Ext.Editor, Ext.Component, { /** * @cfg {Ext.form.Field} field * The Field object (or descendant) or config object for field */ /** * @cfg {Boolean} allowBlur * True to {@link #completeEdit complete the editing process} if in edit mode when the * field is blurred. Defaults to <tt>false</tt>. */ /** * @cfg {Boolean/String} autoSize * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only, * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false) */ /** * @cfg {Boolean} revertInvalid * True to automatically revert the field value and cancel the edit when the user completes an edit and the field * validation fails (defaults to true) */ /** * @cfg {Boolean} ignoreNoChange * True to skip the edit completion process (no save, no events fired) if the user completes an edit and * the value has not changed (defaults to false). Applies only to string values - edits for other data types * will never be ignored. */ /** * @cfg {Boolean} hideEl * False to keep the bound element visible while the editor is displayed (defaults to true) */ /** * @cfg {Mixed} value * The data value of the underlying field (defaults to "") */ value : "", /** * @cfg {String} alignment * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?"). */ alignment: "c-c?", /** * @cfg {Array} offsets * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>. */ offsets: [0, 0], /** * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop" * for bottom-right shadow (defaults to "frame") */ shadow : "frame", /** * @cfg {Boolean} constrain True to constrain the editor to the viewport */ constrain : false, /** * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true) */ swallowKeys : true, /** * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>. */ completeOnEnter : true, /** * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>. */ cancelOnEsc : true, /** * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false) */ updateEl : false, initComponent : function(){ Ext.Editor.superclass.initComponent.call(this); this.addEvents( /** * @event beforestartedit * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning * false from the handler of this event. * @param {Editor} this * @param {Ext.Element} boundEl The underlying element bound to this editor * @param {Mixed} value The field value being set */ "beforestartedit", /** * @event startedit * Fires when this editor is displayed * @param {Ext.Element} boundEl The underlying element bound to this editor * @param {Mixed} value The starting field value */ "startedit", /** * @event beforecomplete * Fires after a change has been made to the field, but before the change is reflected in the underlying * field. Saving the change to the field can be canceled by returning false from the handler of this event. * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this * event will not fire since no edit actually occurred. * @param {Editor} this * @param {Mixed} value The current field value * @param {Mixed} startValue The original field value */ "beforecomplete", /** * @event complete * Fires after editing is complete and any changed value has been written to the underlying field. * @param {Editor} this * @param {Mixed} value The current field value * @param {Mixed} startValue The original field value */ "complete", /** * @event canceledit * Fires after editing has been canceled and the editor's value has been reset. * @param {Editor} this * @param {Mixed} value The user-entered field value that was discarded * @param {Mixed} startValue The original field value that was set back into the editor after cancel */ "canceledit", /** * @event specialkey * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check * {@link Ext.EventObject#getKey} to determine which key was pressed. * @param {Ext.form.Field} this * @param {Ext.EventObject} e The event object */ "specialkey" ); }, // private onRender : function(ct, position){ this.el = new Ext.Layer({ shadow: this.shadow, cls: "x-editor", parentEl : ct, shim : this.shim, shadowOffset: this.shadowOffset || 4, id: this.id, constrain: this.constrain }); if(this.zIndex){ this.el.setZIndex(this.zIndex); } this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden"); if(this.field.msgTarget != 'title'){ this.field.msgTarget = 'qtip'; } this.field.inEditor = true; this.mon(this.field, { scope: this, blur: this.onBlur, specialkey: this.onSpecialKey }); if(this.field.grow){ this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1}); } this.field.render(this.el).show(); this.field.getEl().dom.name = ''; if(this.swallowKeys){ this.field.el.swallowEvent([ 'keypress', // *** Opera 'keydown' // *** all other browsers ]); } }, // private onSpecialKey : function(field, e){ var key = e.getKey(), complete = this.completeOnEnter && key == e.ENTER, cancel = this.cancelOnEsc && key == e.ESC; if(complete || cancel){ e.stopEvent(); if(complete){ this.completeEdit(); }else{ this.cancelEdit(); } if(field.triggerBlur){ field.triggerBlur(); } } this.fireEvent('specialkey', field, e); }, /** * Starts the editing process and shows the editor. * @param {Mixed} el The element to edit * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults * to the innerHTML of el. */ startEdit : function(el, value){ if(this.editing){ this.completeEdit(); } this.boundEl = Ext.get(el); var v = value !== undefined ? value : this.boundEl.dom.innerHTML; if(!this.rendered){ this.render(this.parentEl || document.body); } if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){ this.startValue = v; this.field.reset(); this.field.setValue(v); this.realign(true); this.editing = true; this.show(); } }, // private doAutoSize : function(){ if(this.autoSize){ var sz = this.boundEl.getSize(), fs = this.field.getSize(); switch(this.autoSize){ case "width": this.setSize(sz.width, fs.height); break; case "height": this.setSize(fs.width, sz.height); break; case "none": this.setSize(fs.width, fs.height); break; default: this.setSize(sz.width, sz.height); } } }, /** * Sets the height and width of this editor. * @param {Number} width The new width * @param {Number} height The new height */ setSize : function(w, h){ delete this.field.lastSize; this.field.setSize(w, h); if(this.el){ if(Ext.isGecko2 || Ext.isOpera){ // prevent layer scrollbars this.el.setSize(w, h); } this.el.sync(); } }, /** * Realigns the editor to the bound field based on the current alignment config value. * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element. */ realign : function(autoSize){ if(autoSize === true){ this.doAutoSize(); } this.el.alignTo(this.boundEl, this.alignment, this.offsets); }, /** * Ends the editing process, persists the changed value to the underlying field, and hides the editor. * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false) */ completeEdit : function(remainVisible){ if(!this.editing){ return; } var v = this.getValue(); if(!this.field.isValid()){ if(this.revertInvalid !== false){ this.cancelEdit(remainVisible); } return; } if(String(v) === String(this.startValue) && this.ignoreNoChange){ this.hideEdit(remainVisible); return; } if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){ v = this.getValue(); if(this.updateEl && this.boundEl){ this.boundEl.update(v); } this.hideEdit(remainVisible); this.fireEvent("complete", this, v, this.startValue); } }, // private onShow : function(){ this.el.show(); if(this.hideEl !== false){ this.boundEl.hide(); } this.field.show().focus(false, true); this.fireEvent("startedit", this.boundEl, this.startValue); }, /** * Cancels the editing process and hides the editor without persisting any changes. The field value will be * reverted to the original starting value. * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after * cancel (defaults to false) */ cancelEdit : function(remainVisible){ if(this.editing){ var v = this.getValue(); this.setValue(this.startValue); this.hideEdit(remainVisible); this.fireEvent("canceledit", this, v, this.startValue); } }, // private hideEdit: function(remainVisible){ if(remainVisible !== true){ this.editing = false; this.hide(); } }, // private onBlur : function(){ if(this.allowBlur !== true && this.editing){ this.completeEdit(); } }, // private onHide : function(){ if(this.editing){ this.completeEdit(); return; } this.field.blur(); if(this.field.collapse){ this.field.collapse(); } this.el.hide(); if(this.hideEl !== false){ this.boundEl.show(); } }, /** * Sets the data value of the editor * @param {Mixed} value Any valid value supported by the underlying field */ setValue : function(v){ this.field.setValue(v); }, /** * Gets the data value of the editor * @return {Mixed} The data value */ getValue : function(){ return this.field.getValue(); }, beforeDestroy : function(){ Ext.destroyMembers(this, 'field'); delete this.parentEl; delete this.boundEl; } }); Ext.reg('editor', Ext.Editor); /** * @class Ext.ColorPalette * @extends Ext.Component * Simple color palette class for choosing colors. The palette can be rendered to any container.<br /> * Here's an example of typical usage: * <pre><code> var cp = new Ext.ColorPalette({value:'993300'}); // initial selected color cp.render('my-div'); cp.on('select', function(palette, selColor){ // do something with selColor }); </code></pre> * @constructor * Create a new ColorPalette * @param {Object} config The config object * @xtype colorpalette */ Ext.ColorPalette = Ext.extend(Ext.Component, { /** * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component. */ /** * @cfg {String} itemCls * The CSS class to apply to the containing element (defaults to 'x-color-palette') */ itemCls : 'x-color-palette', /** * @cfg {String} value * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that * the hex codes are case-sensitive. */ value : null, /** * @cfg {String} clickEvent * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). * Defaults to <tt>'click'</tt>. */ clickEvent :'click', // private ctype : 'Ext.ColorPalette', /** * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event */ allowReselect : false, /** * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number * of colors with the width setting until the box is symmetrical.</p> * <p>You can override individual colors if needed:</p> * <pre><code> var cp = new Ext.ColorPalette(); cp.colors[0] = 'FF0000'; // change the first box to red </code></pre> Or you can provide a custom array of your own for complete control: <pre><code> var cp = new Ext.ColorPalette(); cp.colors = ['000000', '993300', '333300']; </code></pre> * @type Array */ colors : [ '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333', '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080', 'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696', 'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0', 'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF' ], /** * @cfg {Function} handler * Optional. A function that will handle the select event of this palette. * The handler is passed the following parameters:<div class="mdetail-params"><ul> * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li> * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li> * </ul></div> */ /** * @cfg {Object} scope * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code> * function will be called. Defaults to this ColorPalette instance. */ // private initComponent : function(){ Ext.ColorPalette.superclass.initComponent.call(this); this.addEvents( /** * @event select * Fires when a color is selected * @param {ColorPalette} this * @param {String} color The 6-digit color hex code (without the # symbol) */ 'select' ); if(this.handler){ this.on('select', this.handler, this.scope, true); } }, // private onRender : function(container, position){ this.autoEl = { tag: 'div', cls: this.itemCls }; Ext.ColorPalette.superclass.onRender.call(this, container, position); var t = this.tpl || new Ext.XTemplate( '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>' ); t.overwrite(this.el, this.colors); this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'}); if(this.clickEvent != 'click'){ this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true}); } }, // private afterRender : function(){ Ext.ColorPalette.superclass.afterRender.call(this); if(this.value){ var s = this.value; this.value = null; this.select(s); } }, // private handleClick : function(e, t){ e.preventDefault(); if(!this.disabled){ var c = t.className.match(/(?:^|s)color-(.{6})(?:s|$)/)[1]; this.select(c.toUpperCase()); } }, /** * Selects the specified color in the palette (fires the {@link #select} event) * @param {String} color A valid 6-digit color hex code (# will be stripped if included) */ select : function(color){ color = color.replace('#', ''); if(color != this.value || this.allowReselect){ var el = this.el; if(this.value){ el.child('a.color-'+this.value).removeClass('x-color-palette-sel'); } el.child('a.color-'+color).addClass('x-color-palette-sel'); this.value = color; this.fireEvent('select', this, color); } } /** * @cfg {String} autoEl @hide */ }); Ext.reg('colorpalette', Ext.ColorPalette); /** * @class Ext.DatePicker * @extends Ext.Component * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class * to allow browsing and selection of valid dates.</p> * <p>All the string values documented below may be overridden by including an Ext locale file in * your page.</p> * @constructor * Create a new DatePicker * @param {Object} config The config object * @xtype datepicker */ Ext.DatePicker = Ext.extend(Ext.BoxComponent, { /** * @cfg {String} todayText * The text to display on the button that selects the current date (defaults to <code>'Today'</code>) */ todayText : 'Today', /** * @cfg {String} okText * The text to display on the ok button (defaults to <code>' OK '</code> to give the user extra clicking room) */ okText : ' OK ', /** * @cfg {String} cancelText * The text to display on the cancel button (defaults to <code>'Cancel'</code>) */ cancelText : 'Cancel', /** * @cfg {Function} handler * Optional. A function that will handle the select event of this picker. * The handler is passed the following parameters:<div class="mdetail-params"><ul> * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li> * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li> * </ul></div> */ /** * @cfg {Object} scope * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code> * function will be called. Defaults to this DatePicker instance. */ /** * @cfg {String} todayTip * A string used to format the message for displaying in a tooltip over the button that * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where * the <code>{0}</code> token is replaced by today's date. */ todayTip : '{0} (Spacebar)', /** * @cfg {String} minText * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>) */ minText : 'This date is before the minimum date', /** * @cfg {String} maxText * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>) */ maxText : 'This date is after the maximum date', /** * @cfg {String} format * The default date format string which can be overriden for localization support. The format must be * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>). */ format : 'm/d/y', /** * @cfg {String} disabledDaysText * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>) */ disabledDaysText : 'Disabled', /** * @cfg {String} disabledDatesText * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>) */ disabledDatesText : 'Disabled', /** * @cfg {Array} monthNames * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames) */ monthNames : Date.monthNames, /** * @cfg {Array} dayNames * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames) */ dayNames : Date.dayNames, /** * @cfg {String} nextText * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>) */ nextText : 'Next Month (Control+Right)', /** * @cfg {String} prevText * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>) */ prevText : 'Previous Month (Control+Left)', /** * @cfg {String} monthYearText * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>) */ monthYearText : 'Choose a month (Control+Up/Down to move years)', /** * @cfg {Number} startDay * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday) */ startDay : 0, /** * @cfg {Boolean} showToday * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar * that selects the current date (defaults to <code>true</code>). */ showToday : true, /** * @cfg {Date} minDate * Minimum allowable date (JavaScript date object, defaults to null) */ /** * @cfg {Date} maxDate * Maximum allowable date (JavaScript date object, defaults to null) */ /** * @cfg {Array} disabledDays * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null). */ /** * @cfg {RegExp} disabledDatesRE * JavaScript regular expression used to disable a pattern of dates (defaults to null). The {@link #disabledDates} * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the * disabledDates value. */ /** * @cfg {Array} disabledDates * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular * expression so they are very powerful. Some examples: * <ul> * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li> * <li>['03/08', '09/16'] would disable those days for every year</li> * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li> * <li>['03/../2006'] would disable every day in March 2006</li> * <li>['^03'] would disable every day in every March</li> * </ul> * Note that the format of the dates included in the array should exactly match the {@link #format} config. * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to * escape the dot when restricting dates. For example: ['03\.08\.03']. */ // private // Set by other components to stop the picker focus being updated when the value changes. focusOnSelect: true, // private initComponent : function(){ Ext.DatePicker.superclass.initComponent.call(this); this.value = this.value ? this.value.clearTime(true) : new Date().clearTime(); this.addEvents( /** * @event select * Fires when a date is selected * @param {DatePicker} this DatePicker * @param {Date} date The selected date */ 'select' ); if(this.handler){ this.on('select', this.handler, this.scope || this); } this.initDisabledDays(); }, // private initDisabledDays : function(){ if(!this.disabledDatesRE && this.disabledDates){ var dd = this.disabledDates, len = dd.length - 1, re = '(?:'; Ext.each(dd, function(d, i){ re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i]; if(i != len){ re += '|'; } }, this); this.disabledDatesRE = new RegExp(re + ')'); } }, /** * Replaces any existing disabled dates with new values and refreshes the DatePicker. * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates. */ setDisabledDates : function(dd){ if(Ext.isArray(dd)){ this.disabledDates = dd; this.disabledDatesRE = null; }else{ this.disabledDatesRE = dd; } this.initDisabledDays(); this.update(this.value, true); }, /** * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker. * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config * for details on supported values. */ setDisabledDays : function(dd){ this.disabledDays = dd; this.update(this.value, true); }, /** * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker. * @param {Date} value The minimum date that can be selected */ setMinDate : function(dt){ this.minDate = dt; this.update(this.value, true); }, /** * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker. * @param {Date} value The maximum date that can be selected */ setMaxDate : function(dt){ this.maxDate = dt; this.update(this.value, true); }, /** * Sets the value of the date field * @param {Date} value The date to set */ setValue : function(value){ this.value = value.clearTime(true); this.update(this.value); }, /** * Gets the current selected value of the date field * @return {Date} The selected date */ getValue : function(){ return this.value; }, // private focus : function(){ this.update(this.activeDate); }, // private onEnable: function(initial){ Ext.DatePicker.superclass.onEnable.call(this); this.doDisabled(false); this.update(initial ? this.value : this.activeDate); if(Ext.isIE){ this.el.repaint(); } }, // private onDisable : function(){ Ext.DatePicker.superclass.onDisable.call(this); this.doDisabled(true); if(Ext.isIE && !Ext.isIE8){ /* Really strange problem in IE6/7, when disabled, have to explicitly * repaint each of the nodes to get them to display correctly, simply * calling repaint on the main element doesn't appear to be enough. */ Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){ Ext.fly(el).repaint(); }); } }, // private doDisabled : function(disabled){ this.keyNav.setDisabled(disabled); this.prevRepeater.setDisabled(disabled); this.nextRepeater.setDisabled(disabled); if(this.showToday){ this.todayKeyListener.setDisabled(disabled); this.todayBtn.setDisabled(disabled); } }, // private onRender : function(container, position){ var m = [ '<table cellspacing="0">', '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>', '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'], dn = this.dayNames, i; for(i = 0; i < 7; i++){ var d = this.startDay+i; if(d > 6){ d = d-7; } m.push('<th><span>', dn[d].substr(0,1), '</span></th>'); } m[m.length] = '</tr></thead><tbody><tr>'; for(i = 0; i < 42; i++) { if(i % 7 === 0 && i !== 0){ m[m.length] = '</tr><tr>'; } m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>'; } m.push('</tr></tbody></table></td></tr>', this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '', '</table><div class="x-date-mp"></div>'); var el = document.createElement('div'); el.className = 'x-date-picker'; el.innerHTML = m.join(''); container.dom.insertBefore(el, position); this.el = Ext.get(el); this.eventEl = Ext.get(el.firstChild); this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), { handler: this.showPrevMonth, scope: this, preventDefault:true, stopDefault:true }); this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), { handler: this.showNextMonth, scope: this, preventDefault:true, stopDefault:true }); this.monthPicker = this.el.down('div.x-date-mp'); this.monthPicker.enableDisplayMode('block'); this.keyNav = new Ext.KeyNav(this.eventEl, { 'left' : function(e){ if(e.ctrlKey){ this.showPrevMonth(); }else{ this.update(this.activeDate.add('d', -1)); } }, 'right' : function(e){ if(e.ctrlKey){ this.showNextMonth(); }else{ this.update(this.activeDate.add('d', 1)); } }, 'up' : function(e){ if(e.ctrlKey){ this.showNextYear(); }else{ this.update(this.activeDate.add('d', -7)); } }, 'down' : function(e){ if(e.ctrlKey){ this.showPrevYear(); }else{ this.update(this.activeDate.add('d', 7)); } }, 'pageUp' : function(e){ this.showNextMonth(); }, 'pageDown' : function(e){ this.showPrevMonth(); }, 'enter' : function(e){ e.stopPropagation(); return true; }, scope : this }); this.el.unselectable(); this.cells = this.el.select('table.x-date-inner tbody td'); this.textNodes = this.el.query('table.x-date-inner tbody span'); this.mbtn = new Ext.Button({ text: ' ', tooltip: this.monthYearText, renderTo: this.el.child('td.x-date-middle', true) }); this.mbtn.el.child('em').addClass('x-btn-arrow'); if(this.showToday){ this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this); var today = (new Date()).dateFormat(this.format); this.todayBtn = new Ext.Button({ renderTo: this.el.child('td.x-date-bottom', true), text: String.format(this.todayText, today), tooltip: String.format(this.todayTip, today), handler: this.selectToday, scope: this }); } this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this); this.mon(this.eventEl, 'click', this.handleDateClick, this, {delegate: 'a.x-date-date'}); this.mon(this.mbtn, 'click', this.showMonthPicker, this); this.onEnable(true); }, // private createMonthPicker : function(){ if(!this.monthPicker.dom.firstChild){ var buf = ['<table border="0" cellspacing="0">']; for(var i = 0; i < 6; i++){ buf.push( '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>', '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>', i === 0 ? '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' : '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>' ); } buf.push( '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">', this.okText, '</button><button type="button" class="x-date-mp-cancel">', this.cancelText, '</button></td></tr>', '</table>' ); this.monthPicker.update(buf.join('')); this.mon(this.monthPicker, 'click', this.onMonthClick, this); this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this); this.mpMonths = this.monthPicker.select('td.x-date-mp-month'); this.mpYears = this.monthPicker.select('td.x-date-mp-year'); this.mpMonths.each(function(m, a, i){ i += 1; if((i%2) === 0){ m.dom.xmonth = 5 + Math.round(i * 0.5); }else{ m.dom.xmonth = Math.round((i-1) * 0.5); } }); } }, // private showMonthPicker : function(){ if(!this.disabled){ this.createMonthPicker(); var size = this.el.getSize(); this.monthPicker.setSize(size); this.monthPicker.child('table').setSize(size); this.mpSelMonth = (this.activeDate || this.value).getMonth(); this.updateMPMonth(this.mpSelMonth); this.mpSelYear = (this.activeDate || this.value).getFullYear(); this.updateMPYear(this.mpSelYear); this.monthPicker.slideIn('t', {duration:0.2}); } }, // private updateMPYear : function(y){ this.mpyear = y; var ys = this.mpYears.elements; for(var i = 1; i <= 10; i++){ var td = ys[i-1], y2; if((i%2) === 0){ y2 = y + Math.round(i * 0.5); td.firstChild.innerHTML = y2; td.xyear = y2; }else{ y2 = y - (5-Math.round(i * 0.5)); td.firstChild.innerHTML = y2; td.xyear = y2; } this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel'); } }, // private updateMPMonth : function(sm){ this.mpMonths.each(function(m, a, i){ m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel'); }); }, // private selectMPMonth : function(m){ }, // private onMonthClick : function(e, t){ e.stopEvent(); var el = new Ext.Element(t), pn; if(el.is('button.x-date-mp-cancel')){ this.hideMonthPicker(); } else if(el.is('button.x-date-mp-ok')){ var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()); if(d.getMonth() != this.mpSelMonth){ // 'fix' the JS rolling date conversion if needed d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth(); } this.update(d); this.hideMonthPicker(); } else if((pn = el.up('td.x-date-mp-month', 2))){ this.mpMonths.removeClass('x-date-mp-sel'); pn.addClass('x-date-mp-sel'); this.mpSelMonth = pn.dom.xmonth; } else if((pn = el.up('td.x-date-mp-year', 2))){ this.mpYears.removeClass('x-date-mp-sel'); pn.addClass('x-date-mp-sel'); this.mpSelYear = pn.dom.xyear; } else if(el.is('a.x-date-mp-prev')){ this.updateMPYear(this.mpyear-10); } else if(el.is('a.x-date-mp-next')){ this.updateMPYear(this.mpyear+10); } }, // private onMonthDblClick : function(e, t){ e.stopEvent(); var el = new Ext.Element(t), pn; if((pn = el.up('td.x-date-mp-month', 2))){ this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate())); this.hideMonthPicker(); } else if((pn = el.up('td.x-date-mp-year', 2))){ this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate())); this.hideMonthPicker(); } }, // private hideMonthPicker : function(disableAnim){ if(this.monthPicker){ if(disableAnim === true){ this.monthPicker.hide(); }else{ this.monthPicker.slideOut('t', {duration:0.2}); } } }, // private showPrevMonth : function(e){ this.update(this.activeDate.add('mo', -1)); }, // private showNextMonth : function(e){ this.update(this.activeDate.add('mo', 1)); }, // private showPrevYear : function(){ this.update(this.activeDate.add('y', -1)); }, // private showNextYear : function(){ this.update(this.activeDate.add('y', 1)); }, // private handleMouseWheel : function(e){ e.stopEvent(); if(!this.disabled){ var delta = e.getWheelDelta(); if(delta > 0){ this.showPrevMonth(); } else if(delta < 0){ this.showNextMonth(); } } }, // private handleDateClick : function(e, t){ e.stopEvent(); if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){ this.cancelFocus = this.focusOnSelect === false; this.setValue(new Date(t.dateValue)); delete this.cancelFocus; this.fireEvent('select', this, this.value); } }, // private selectToday : function(){ if(this.todayBtn && !this.todayBtn.disabled){ this.setValue(new Date().clearTime()); this.fireEvent('select', this, this.value); } }, // private update : function(date, forceRefresh){ if(this.rendered){ var vd = this.activeDate, vis = this.isVisible(); this.activeDate = date; if(!forceRefresh && vd && this.el){ var t = date.getTime(); if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){ this.cells.removeClass('x-date-selected'); this.cells.each(function(c){ if(c.dom.firstChild.dateValue == t){ c.addClass('x-date-selected'); if(vis && !this.cancelFocus){ Ext.fly(c.dom.firstChild).focus(50); } return false; } }, this); return; } } var days = date.getDaysInMonth(), firstOfMonth = date.getFirstDateOfMonth(), startingPos = firstOfMonth.getDay()-this.startDay; if(startingPos < 0){ startingPos += 7; } days += startingPos; var pm = date.add('mo', -1), prevStart = pm.getDaysInMonth()-startingPos, cells = this.cells.elements, textEls = this.textNodes, // convert everything to numbers so it's fast day = 86400000, d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(), today = new Date().clearTime().getTime(), sel = date.clearTime(true).getTime(), min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY, max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY, ddMatch = this.disabledDatesRE, ddText = this.disabledDatesText, ddays = this.disabledDays ? this.disabledDays.join('') : false, ddaysText = this.disabledDaysText, format = this.format; if(this.showToday){ var td = new Date().clearTime(), disable = (td < min || td > max || (ddMatch && format && ddMatch.test(td.dateFormat(format))) || (ddays && ddays.indexOf(td.getDay()) != -1)); if(!this.disabled){ this.todayBtn.setDisabled(disable); this.todayKeyListener[disable ? 'disable' : 'enable'](); } } var setCellClass = function(cal, cell){ cell.title = ''; var t = d.getTime(); cell.firstChild.dateValue = t; if(t == today){ cell.className += ' x-date-today'; cell.title = cal.todayText; } if(t == sel){ cell.className += ' x-date-selected'; if(vis){ Ext.fly(cell.firstChild).focus(50); } } // disabling if(t < min) { cell.className = ' x-date-disabled'; cell.title = cal.minText; return; } if(t > max) { cell.className = ' x-date-disabled'; cell.title = cal.maxText; return; } if(ddays){ if(ddays.indexOf(d.getDay()) != -1){ cell.title = ddaysText; cell.className = ' x-date-disabled'; } } if(ddMatch && format){ var fvalue = d.dateFormat(format); if(ddMatch.test(fvalue)){ cell.title = ddText.replace('%0', fvalue); cell.className = ' x-date-disabled'; } } }; var i = 0; for(; i < startingPos; i++) { textEls[i].innerHTML = (++prevStart); d.setDate(d.getDate()+1); cells[i].className = 'x-date-prevday'; setCellClass(this, cells[i]); } for(; i < days; i++){ var intDay = i - startingPos + 1; textEls[i].innerHTML = (intDay); d.setDate(d.getDate()+1); cells[i].className = 'x-date-active'; setCellClass(this, cells[i]); } var extraDays = 0; for(; i < 42; i++) { textEls[i].innerHTML = (++extraDays); d.setDate(d.getDate()+1); cells[i].className = 'x-date-nextday'; setCellClass(this, cells[i]); } this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear()); if(!this.internalRender){ var main = this.el.dom.firstChild, w = main.offsetWidth; this.el.setWidth(w + this.el.getBorderWidth('lr')); Ext.fly(main).setWidth(w); this.internalRender = true; // opera does not respect the auto grow header center column // then, after it gets a width opera refuses to recalculate // without a second pass if(Ext.isOpera && !this.secondPass){ main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px'; this.secondPass = true; this.update.defer(10, this, [date]); } } } }, // private beforeDestroy : function() { if(this.rendered){ Ext.destroy( this.keyNav, this.monthPicker, this.eventEl, this.mbtn, this.nextRepeater, this.prevRepeater, this.cells.el, this.todayBtn ); delete this.textNodes; delete this.cells.elements; } } /** * @cfg {String} autoEl @hide */ }); Ext.reg('datepicker', Ext.DatePicker); /** * @class Ext.LoadMask * A simple utility class for generically masking elements while loading data. If the {@link #store} * config option is specified, the masking will be automatically synchronized with the store's loading * process and the mask element will be cached for reuse. For all other elements, this mask will replace the * element's Updater load indicator and will be destroyed after the initial load. * <p>Example usage:</p> *<pre><code> // Basic mask: var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."}); myMask.show(); </code></pre> * @constructor * Create a new LoadMask * @param {Mixed} el The element or DOM node, or its id * @param {Object} config The config object */ Ext.LoadMask = function(el, config){ this.el = Ext.get(el); Ext.apply(this, config); if(this.store){ this.store.on({ scope: this, beforeload: this.onBeforeLoad, load: this.onLoad, exception: this.onLoad }); this.removeMask = Ext.value(this.removeMask, false); }else{ var um = this.el.getUpdater(); um.showLoadIndicator = false; // disable the default indicator um.on({ scope: this, beforeupdate: this.onBeforeLoad, update: this.onLoad, failure: this.onLoad }); this.removeMask = Ext.value(this.removeMask, true); } }; Ext.LoadMask.prototype = { /** * @cfg {Ext.data.Store} store * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and * hidden on either load sucess, or load fail. */ /** * @cfg {Boolean} removeMask * True to create a single-use mask that is automatically destroyed after loading (useful for page loads), * False to persist the mask element reference for multiple uses (e.g., for paged data widgets). Defaults to false. */ /** * @cfg {String} msg * The text to display in a centered loading message box (defaults to 'Loading...') */ msg : 'Loading...', /** * @cfg {String} msgCls * The CSS class to apply to the loading message element (defaults to "x-mask-loading") */ msgCls : 'x-mask-loading', /** * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false) * @type Boolean */ disabled: false, /** * Disables the mask to prevent it from being displayed */ disable : function(){ this.disabled = true; }, /** * Enables the mask so that it can be displayed */ enable : function(){ this.disabled = false; }, // private onLoad : function(){ this.el.unmask(this.removeMask); }, // private onBeforeLoad : function(){ if(!this.disabled){ this.el.mask(this.msg, this.msgCls); } }, /** * Show this LoadMask over the configured Element. */ show: function(){ this.onBeforeLoad(); }, /** * Hide this LoadMask. */ hide: function(){ this.onLoad(); }, // private destroy : function(){ if(this.store){ this.store.un('beforeload', this.onBeforeLoad, this); this.store.un('load', this.onLoad, this); this.store.un('exception', this.onLoad, this); }else{ var um = this.el.getUpdater(); um.un('beforeupdate', this.onBeforeLoad, this); um.un('update', this.onLoad, this); um.un('failure', this.onLoad, this); } } };/**
- * @class Ext.Slider
- * @extends Ext.BoxComponent
- * Slider which supports vertical or horizontal orientation, keyboard adjustments,
- * configurable snapping, axis clicking and animation. Can be added as an item to
- * any container. Example usage:
- <pre><code>
- new Ext.Slider({
- renderTo: Ext.getBody(),
- width: 200,
- value: 50,
- increment: 10,
- minValue: 0,
- maxValue: 100
- });
- </code></pre>
- */
- Ext.Slider = Ext.extend(Ext.BoxComponent, {
- /**
- * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
- */
- /**
- * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
- */
- vertical: false,
- /**
- * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
- */
- minValue: 0,
- /**
- * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
- */
- maxValue: 100,
- /**
- * @cfg {Number/Boolean} decimalPrecision.
- * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
- * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
- */
- decimalPrecision: 0,
- /**
- * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.
- */
- keyIncrement: 1,
- /**
- * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
- */
- increment: 0,
- // private
- clickRange: [5,15],
- /**
- * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
- */
- clickToChange : true,
- /**
- * @cfg {Boolean} animate Turn on or off animation. Defaults to true
- */
- animate: true,
- /**
- * True while the thumb is in a drag operation
- * @type boolean
- */
- dragging: false,
- // private override
- initComponent : function(){
- if(!Ext.isDefined(this.value)){
- this.value = this.minValue;
- }
- Ext.Slider.superclass.initComponent.call(this);
- this.keyIncrement = Math.max(this.increment, this.keyIncrement);
- this.addEvents(
- /**
- * @event beforechange
- * Fires before the slider value is changed. By returning false from an event handler,
- * you can cancel the event and prevent the slider from changing.
- * @param {Ext.Slider} slider The slider
- * @param {Number} newValue The new value which the slider is being changed to.
- * @param {Number} oldValue The old value which the slider was previously.
- */
- 'beforechange',
- /**
- * @event change
- * Fires when the slider value is changed.
- * @param {Ext.Slider} slider The slider
- * @param {Number} newValue The new value which the slider has been changed to.
- */
- 'change',
- /**
- * @event changecomplete
- * Fires when the slider value is changed by the user and any drag operations have completed.
- * @param {Ext.Slider} slider The slider
- * @param {Number} newValue The new value which the slider has been changed to.
- */
- 'changecomplete',
- /**
- * @event dragstart
- * Fires after a drag operation has started.
- * @param {Ext.Slider} slider The slider
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
- */
- 'dragstart',
- /**
- * @event drag
- * Fires continuously during the drag operation while the mouse is moving.
- * @param {Ext.Slider} slider The slider
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
- */
- 'drag',
- /**
- * @event dragend
- * Fires after the drag operation has completed.
- * @param {Ext.Slider} slider The slider
- * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
- */
- 'dragend'
- );
- if(this.vertical){
- Ext.apply(this, Ext.Slider.Vertical);
- }
- },
- // private override
- onRender : function(){
- this.autoEl = {
- cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
- cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
- };
- Ext.Slider.superclass.onRender.apply(this, arguments);
- this.endEl = this.el.first();
- this.innerEl = this.endEl.first();
- this.thumb = this.innerEl.first();
- this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
- this.focusEl = this.thumb.next();
- this.initEvents();
- },
- // private override
- initEvents : function(){
- this.thumb.addClassOnOver('x-slider-thumb-over');
- this.mon(this.el, {
- scope: this,
- mousedown: this.onMouseDown,
- keydown: this.onKeyDown
- });
- this.focusEl.swallowEvent("click", true);
- this.tracker = new Ext.dd.DragTracker({
- onBeforeStart: this.onBeforeDragStart.createDelegate(this),
- onStart: this.onDragStart.createDelegate(this),
- onDrag: this.onDrag.createDelegate(this),
- onEnd: this.onDragEnd.createDelegate(this),
- tolerance: 3,
- autoStart: 300
- });