ux-all-debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:193k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.0.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ Ext.ns('Ext.ux.grid'); /**  * @class Ext.ux.grid.BufferView  * @extends Ext.grid.GridView  * A custom GridView which renders rows on an as-needed basis.  */ Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, { /**  * @cfg {Number} rowHeight  * The height of a row in the grid.  */ rowHeight: 19, /**  * @cfg {Number} borderHeight  * The combined height of border-top and border-bottom of a row.  */ borderHeight: 2, /**  * @cfg {Boolean/Number} scrollDelay  * The number of milliseconds before rendering rows out of the visible  * viewing area. Defaults to 100. Rows will render immediately with a config  * of false.  */ scrollDelay: 100, /**  * @cfg {Number} cacheSize  * The number of rows to look forward and backwards from the currently viewable  * area.  The cache applies only to rows that have been rendered already.  */ cacheSize: 20, /**  * @cfg {Number} cleanDelay  * The number of milliseconds to buffer cleaning of extra rows not in the  * cache.  */ cleanDelay: 500, initTemplates : function(){ Ext.ux.grid.BufferView.superclass.initTemplates.call(this); var ts = this.templates; // empty div to act as a place holder for a row         ts.rowHolder = new Ext.Template(         '<div class="x-grid3-row {alt}" style="{tstyle}"></div>' ); ts.rowHolder.disableFormats = true; ts.rowHolder.compile(); ts.rowBody = new Ext.Template(         '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<tbody><tr>{cells}</tr>', (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''), '</tbody></table>' ); ts.rowBody.disableFormats = true; ts.rowBody.compile(); }, getStyleRowHeight : function(){ return Ext.isBorderBox ? (this.rowHeight + this.borderHeight) : this.rowHeight; }, getCalculatedRowHeight : function(){ return this.rowHeight + this.borderHeight; }, getVisibleRowCount : function(){ var rh = this.getCalculatedRowHeight(); var visibleHeight = this.scroller.dom.clientHeight; return (visibleHeight < 1) ? 0 : Math.ceil(visibleHeight / rh); }, getVisibleRows: function(){ var count = this.getVisibleRowCount(); var sc = this.scroller.dom.scrollTop; var start = (sc == 0 ? 0 : Math.floor(sc/this.getCalculatedRowHeight())-1); return { first: Math.max(start, 0), last: Math.min(start + count + 2, this.ds.getCount()-1) }; }, doRender : function(cs, rs, ds, startRow, colCount, stripe, onlyBody){ var ts = this.templates, ct = ts.cell, rt = ts.row, rb = ts.rowBody, last = colCount-1; var rh = this.getStyleRowHeight(); var vr = this.getVisibleRows(); var tstyle = 'width:'+this.getTotalWidth()+';height:'+rh+'px;'; // buffers var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r; for (var j = 0, len = rs.length; j < len; j++) { r = rs[j]; cb = []; var rowIndex = (j+startRow); var visible = rowIndex >= vr.first && rowIndex <= vr.last; if (visible) { for (var i = 0; i < colCount; i++) { c = cs[i]; p.id = c.id; p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : ''); p.attr = p.cellAttr = ""; p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds); p.style = c.style; if (p.value == undefined || p.value === "") { p.value = "&#160;"; } if (r.dirty && typeof r.modified[c.name] !== 'undefined') { p.css += ' x-grid3-dirty-cell'; } cb[cb.length] = ct.apply(p); } } var alt = []; if(stripe && ((rowIndex+1) % 2 == 0)){     alt[0] = "x-grid3-row-alt"; } if(r.dirty){     alt[1] = " x-grid3-dirty-row"; } rp.cols = colCount; if(this.getRowClass){     alt[2] = this.getRowClass(r, rowIndex, rp, ds); } rp.alt = alt.join(" "); rp.cells = cb.join(""); buf[buf.length] =  !visible ? ts.rowHolder.apply(rp) : (onlyBody ? rb.apply(rp) : rt.apply(rp)); } return buf.join(""); }, isRowRendered: function(index){ var row = this.getRow(index); return row && row.childNodes.length > 0; }, syncScroll: function(){ Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments); this.update(); }, // a (optionally) buffered method to update contents of gridview update: function(){ if (this.scrollDelay) { if (!this.renderTask) { this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this); } this.renderTask.delay(this.scrollDelay); }else{ this.doUpdate(); } }, doUpdate: function(){ if (this.getVisibleRowCount() > 0) { var g = this.grid, cm = g.colModel, ds = g.store;         var cs = this.getColumnData();         var vr = this.getVisibleRows(); for (var i = vr.first; i <= vr.last; i++) { // if row is NOT rendered and is visible, render it if(!this.isRowRendered(i)){ var html = this.doRender(cs, [ds.getAt(i)], ds, i, cm.getColumnCount(), g.stripeRows, true); this.getRow(i).innerHTML = html; } } this.clean(); } }, // a buffered method to clean rows clean : function(){ if(!this.cleanTask){ this.cleanTask = new Ext.util.DelayedTask(this.doClean, this); } this.cleanTask.delay(this.cleanDelay); }, doClean: function(){ if (this.getVisibleRowCount() > 0) { var vr = this.getVisibleRows(); vr.first -= this.cacheSize; vr.last += this.cacheSize; var i = 0, rows = this.getRows(); // if first is less than 0, all rows have been rendered // so lets clean the end... if(vr.first <= 0){ i = vr.last + 1; } for(var len = this.ds.getCount(); i < len; i++){ // if current row is outside of first and last and // has content, update the innerHTML to nothing if ((i < vr.first || i > vr.last) && rows[i].innerHTML) { rows[i].innerHTML = ''; } } } }, layout: function(){ Ext.ux.grid.BufferView.superclass.layout.call(this); this.update(); } }); // We are adding these custom layouts to a namespace that does not // exist by default in Ext, so we have to add the namespace first: Ext.ns('Ext.ux.layout'); /**  * @class Ext.ux.layout.CenterLayout  * @extends Ext.layout.FitLayout  * <p>This is a very simple layout style used to center contents within a container.  This layout works within  * nested containers and can also be used as expected as a Viewport layout to center the page layout.</p>  * <p>As a subclass of FitLayout, CenterLayout expects to have a single child panel of the container that uses  * the layout.  The layout does not require any config options, although the child panel contained within the  * layout must provide a fixed or percentage width.  The child panel's height will fit to the container by  * default, but you can specify <tt>autoHeight:true</tt> to allow it to autosize based on its content height.  * Example usage:</p>  * <pre><code> // The content panel is centered in the container var p = new Ext.Panel({     title: 'Center Layout',     layout: 'ux.center',     items: [{         title: 'Centered Content',         width: '75%',         html: 'Some content'     }] }); // If you leave the title blank and specify no border // you'll create a non-visual, structural panel just // for centering the contents in the main container. var p = new Ext.Panel({     layout: 'ux.center',     border: false,     items: [{         title: 'Centered Content',         width: 300,         autoHeight: true,         html: 'Some content'     }] }); </code></pre>  */ Ext.ux.layout.CenterLayout = Ext.extend(Ext.layout.FitLayout, { // private     setItemSize : function(item, size){         this.container.addClass('ux-layout-center');         item.addClass('ux-layout-center-item');         if(item && size.height > 0){             if(item.width){                 size.width = item.width;             }             item.setSize(size);         }     } }); Ext.Container.LAYOUTS['ux.center'] = Ext.ux.layout.CenterLayout; Ext.ns('Ext.ux.grid');
  2. /**
  3.  * @class Ext.ux.grid.CheckColumn
  4.  * @extends Object
  5.  * GridPanel plugin to add a column with check boxes to a grid.
  6.  * <p>Example usage:</p>
  7.  * <pre><code>
  8. // create the column
  9. var checkColumn = new Ext.grid.CheckColumn({
  10.    header: 'Indoor?',
  11.    dataIndex: 'indoor',
  12.    id: 'check',
  13.    width: 55
  14. });
  15. // add the column to the column model
  16. var cm = new Ext.grid.ColumnModel([{
  17.        header: 'Foo',
  18.        ...
  19.     },
  20.     checkColumn
  21. ]);
  22. // create the grid
  23. var grid = new Ext.grid.EditorGridPanel({
  24.     ...
  25.     cm: cm,
  26.     plugins: [checkColumn], // include plugin
  27.     ...
  28. });
  29.  * </code></pre>
  30.  * In addition to storing a Boolean value within the record data, this
  31.  * class toggles a css class between <tt>'x-grid3-check-col'</tt> and
  32.  * <tt>'x-grid3-check-col-on'</tt> to alter the background image used for
  33.  * a column.
  34.  */
  35. Ext.ux.grid.CheckColumn = function(config){
  36.     Ext.apply(this, config);
  37.     if(!this.id){
  38.         this.id = Ext.id();
  39.     }
  40.     this.renderer = this.renderer.createDelegate(this);
  41. };
  42. Ext.ux.grid.CheckColumn.prototype ={
  43.     init : function(grid){
  44.         this.grid = grid;
  45.         this.grid.on('render', function(){
  46.             var view = this.grid.getView();
  47.             view.mainBody.on('mousedown', this.onMouseDown, this);
  48.         }, this);
  49.     },
  50.     onMouseDown : function(e, t){
  51.         if(t.className && t.className.indexOf('x-grid3-cc-'+this.id) != -1){
  52.             e.stopEvent();
  53.             var index = this.grid.getView().findRowIndex(t);
  54.             var record = this.grid.store.getAt(index);
  55.             record.set(this.dataIndex, !record.data[this.dataIndex]);
  56.         }
  57.     },
  58.     renderer : function(v, p, record){
  59.         p.css += ' x-grid3-check-col-td'; 
  60.         return '<div class="x-grid3-check-col'+(v?'-on':'')+' x-grid3-cc-'+this.id+'">&#160;</div>';
  61.     }
  62. };
  63. // register ptype
  64. Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn);
  65. // backwards compat
  66. Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn;Ext.ns('Ext.ux.tree');
  67. /**
  68.  * @class Ext.ux.tree.ColumnTree
  69.  * @extends Ext.tree.TreePanel
  70.  * 
  71.  * @xtype columntree
  72.  */
  73. Ext.ux.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
  74.     lines : false,
  75.     borderWidth : Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
  76.     cls : 'x-column-tree',
  77.     onRender : function(){
  78.         Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
  79.         this.headers = this.header.createChild({cls:'x-tree-headers'});
  80.         var cols = this.columns, c;
  81.         var totalWidth = 0;
  82.         var scrollOffset = 19; // similar to Ext.grid.GridView default
  83.         for(var i = 0, len = cols.length; i < len; i++){
  84.              c = cols[i];
  85.              totalWidth += c.width;
  86.              this.headers.createChild({
  87.                  cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
  88.                  cn: {
  89.                      cls:'x-tree-hd-text',
  90.                      html: c.header
  91.                  },
  92.                  style:'width:'+(c.width-this.borderWidth)+'px;'
  93.              });
  94.         }
  95.         this.headers.createChild({cls:'x-clear'});
  96.         // prevent floats from wrapping when clipped
  97.         this.headers.setWidth(totalWidth+scrollOffset);
  98.         this.innerCt.setWidth(totalWidth);
  99.     }
  100. });
  101. Ext.reg('columntree', Ext.ux.tree.ColumnTree);
  102. //backwards compat
  103. Ext.tree.ColumnTree = Ext.ux.tree.ColumnTree;
  104. /**
  105.  * @class Ext.ux.tree.ColumnNodeUI
  106.  * @extends Ext.tree.TreeNodeUI
  107.  */
  108. Ext.ux.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
  109.     focus: Ext.emptyFn, // prevent odd scrolling behavior
  110.     renderElements : function(n, a, targetNode, bulkRender){
  111.         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
  112.         var t = n.getOwnerTree();
  113.         var cols = t.columns;
  114.         var bw = t.borderWidth;
  115.         var c = cols[0];
  116.         var buf = [
  117.              '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
  118.                 '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
  119.                     '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
  120.                     '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
  121.                     '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
  122.                     '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
  123.                     a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
  124.                     '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
  125.                 "</div>"];
  126.          for(var i = 1, len = cols.length; i < len; i++){
  127.              c = cols[i];
  128.              buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
  129.                         '<div class="x-tree-col-text">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
  130.                       "</div>");
  131.          }
  132.          buf.push(
  133.             '<div class="x-clear"></div></div>',
  134.             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
  135.             "</li>");
  136.         if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
  137.             this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
  138.                                 n.nextSibling.ui.getEl(), buf.join(""));
  139.         }else{
  140.             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
  141.         }
  142.         this.elNode = this.wrap.childNodes[0];
  143.         this.ctNode = this.wrap.childNodes[1];
  144.         var cs = this.elNode.firstChild.childNodes;
  145.         this.indentNode = cs[0];
  146.         this.ecNode = cs[1];
  147.         this.iconNode = cs[2];
  148.         this.anchor = cs[3];
  149.         this.textNode = cs[3].firstChild;
  150.     }
  151. });
  152. //backwards compat
  153. Ext.tree.ColumnNodeUI = Ext.ux.tree.ColumnNodeUI;
  154. /**
  155.  * @class Ext.DataView.LabelEditor
  156.  * @extends Ext.Editor
  157.  * 
  158.  */
  159. Ext.DataView.LabelEditor = Ext.extend(Ext.Editor, {
  160.     alignment: "tl-tl",
  161.     hideEl : false,
  162.     cls: "x-small-editor",
  163.     shim: false,
  164.     completeOnEnter: true,
  165.     cancelOnEsc: true,
  166.     labelSelector: 'span.x-editable',
  167.     
  168.     constructor: function(cfg, field){
  169.         Ext.DataView.LabelEditor.superclass.constructor.call(this,
  170.             field || new Ext.form.TextField({
  171.                 allowBlank: false,
  172.                 growMin:90,
  173.                 growMax:240,
  174.                 grow:true,
  175.                 selectOnFocus:true
  176.             }), cfg
  177.         );
  178.     },
  179.     
  180.     init : function(view){
  181.         this.view = view;
  182.         view.on('render', this.initEditor, this);
  183.         this.on('complete', this.onSave, this);
  184.     },
  185.     initEditor : function(){
  186.         this.view.on({
  187.             scope: this,
  188.             containerclick: this.doBlur,
  189.             click: this.doBlur
  190.         });
  191.         this.view.getEl().on('mousedown', this.onMouseDown, this, {delegate: this.labelSelector});
  192.     },
  193.     
  194.     doBlur: function(){
  195.         if(this.editing){
  196.             this.field.blur();
  197.         }
  198.     },
  199.     onMouseDown : function(e, target){
  200.         if(!e.ctrlKey && !e.shiftKey){
  201.             var item = this.view.findItemFromChild(target);
  202.             e.stopEvent();
  203.             var record = this.view.store.getAt(this.view.indexOf(item));
  204.             this.startEdit(target, record.data[this.dataIndex]);
  205.             this.activeRecord = record;
  206.         }else{
  207.             e.preventDefault();
  208.         }
  209.     },
  210.     onSave : function(ed, value){
  211.         this.activeRecord.set(this.dataIndex, value);
  212.     }
  213. });
  214. Ext.DataView.DragSelector = function(cfg){
  215.     cfg = cfg || {};
  216.     var view, proxy, tracker;
  217.     var rs, bodyRegion, dragRegion = new Ext.lib.Region(0,0,0,0);
  218.     var dragSafe = cfg.dragSafe === true;
  219.     this.init = function(dataView){
  220.         view = dataView;
  221.         view.on('render', onRender);
  222.     };
  223.     function fillRegions(){
  224.         rs = [];
  225.         view.all.each(function(el){
  226.             rs[rs.length] = el.getRegion();
  227.         });
  228.         bodyRegion = view.el.getRegion();
  229.     }
  230.     function cancelClick(){
  231.         return false;
  232.     }
  233.     function onBeforeStart(e){
  234.         return !dragSafe || e.target == view.el.dom;
  235.     }
  236.     function onStart(e){
  237.         view.on('containerclick', cancelClick, view, {single:true});
  238.         if(!proxy){
  239.             proxy = view.el.createChild({cls:'x-view-selector'});
  240.         }else{
  241.             proxy.setDisplayed('block');
  242.         }
  243.         fillRegions();
  244.         view.clearSelections();
  245.     }
  246.     function onDrag(e){
  247.         var startXY = tracker.startXY;
  248.         var xy = tracker.getXY();
  249.         var x = Math.min(startXY[0], xy[0]);
  250.         var y = Math.min(startXY[1], xy[1]);
  251.         var w = Math.abs(startXY[0] - xy[0]);
  252.         var h = Math.abs(startXY[1] - xy[1]);
  253.         dragRegion.left = x;
  254.         dragRegion.top = y;
  255.         dragRegion.right = x+w;
  256.         dragRegion.bottom = y+h;
  257.         dragRegion.constrainTo(bodyRegion);
  258.         proxy.setRegion(dragRegion);
  259.         for(var i = 0, len = rs.length; i < len; i++){
  260.             var r = rs[i], sel = dragRegion.intersect(r);
  261.             if(sel && !r.selected){
  262.                 r.selected = true;
  263.                 view.select(i, true);
  264.             }else if(!sel && r.selected){
  265.                 r.selected = false;
  266.                 view.deselect(i);
  267.             }
  268.         }
  269.     }
  270.     function onEnd(e){
  271.         if (!Ext.isIE) {
  272.             view.un('containerclick', cancelClick, view);    
  273.         }        
  274.         if(proxy){
  275.             proxy.setDisplayed(false);
  276.         }
  277.     }
  278.     function onRender(view){
  279.         tracker = new Ext.dd.DragTracker({
  280.             onBeforeStart: onBeforeStart,
  281.             onStart: onStart,
  282.             onDrag: onDrag,
  283.             onEnd: onEnd
  284.         });
  285.         tracker.initEl(view.el);
  286.     }
  287. };Ext.ns('Ext.ux.form'); /**  * @class Ext.ux.form.FileUploadField  * @extends Ext.form.TextField  * Creates a file upload field.  * @xtype fileuploadfield  */ Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField,  {     /**      * @cfg {String} buttonText The button text to display on the upload button (defaults to      * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text      * value will be used instead if available.      */     buttonText: 'Browse...',     /**      * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible      * text field (defaults to false).  If true, all inherited TextField members will still be available.      */     buttonOnly: false,     /**      * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field      * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.      */     buttonOffset: 3,     /**      * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.      */     // private     readOnly: true,     /**      * @hide      * @method autoSize      */     autoSize: Ext.emptyFn,     // private     initComponent: function(){         Ext.ux.form.FileUploadField.superclass.initComponent.call(this);         this.addEvents(             /**              * @event fileselected              * Fires when the underlying file input field's value has changed from the user              * selecting a new file from the system file selection dialog.              * @param {Ext.ux.form.FileUploadField} this              * @param {String} value The file value returned by the underlying file input field              */             'fileselected'         );     },     // private     onRender : function(ct, position){         Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);         this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});         this.el.addClass('x-form-file-text');         this.el.dom.removeAttribute('name');         this.fileInput = this.wrap.createChild({             id: this.getFileInputId(),             name: this.name||this.getId(),             cls: 'x-form-file',             tag: 'input',             type: 'file',             size: 1         });         var btnCfg = Ext.applyIf(this.buttonCfg || {}, {             text: this.buttonText         });         this.button = new Ext.Button(Ext.apply(btnCfg, {             renderTo: this.wrap,             cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')         }));         if(this.buttonOnly){             this.el.hide();             this.wrap.setWidth(this.button.getEl().getWidth());         }         this.fileInput.on('change', function(){             var v = this.fileInput.dom.value;             this.setValue(v);             this.fireEvent('fileselected', this, v);         }, this);     },     // private     getFileInputId: function(){         return this.id + '-file';     },     // private     onResize : function(w, h){         Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);         this.wrap.setWidth(w);         if(!this.buttonOnly){             var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;             this.el.setWidth(w);         }     },     // private     onDestroy: function(){         Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);         Ext.destroy(this.fileInput, this.button, this.wrap);     },     // private     preFocus : Ext.emptyFn,     // private     getResizeEl : function(){         return this.wrap;     },     // private     getPositionEl : function(){         return this.wrap;     },     // private     alignErrorIcon : function(){         this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);     } }); Ext.reg('fileuploadfield', Ext.ux.form.FileUploadField); // backwards compat Ext.form.FileUploadField = Ext.ux.form.FileUploadField; (function(){
  288. Ext.ns('Ext.a11y');
  289. Ext.a11y.Frame = Ext.extend(Object, {
  290.     initialized: false,
  291.     
  292.     constructor: function(size, color){
  293.         this.setSize(size || 1);
  294.         this.setColor(color || '15428B');
  295.     },
  296.     
  297.     init: function(){
  298.         if (!this.initialized) {
  299.             this.sides = [];
  300.             
  301.             var s, i;
  302.             
  303.             this.ct = Ext.DomHelper.append(document.body, {
  304.                 cls: 'x-a11y-focusframe'
  305.             }, true);
  306.             
  307.             for (i = 0; i < 4; i++) {
  308.                 s = Ext.DomHelper.append(this.ct, {
  309.                     cls: 'x-a11y-focusframe-side',
  310.                     style: 'background-color: #' + this.color
  311.                 }, true);
  312.                 s.visibilityMode = Ext.Element.DISPLAY;
  313.                 this.sides.push(s);
  314.             }
  315.             
  316.             this.frameTask = new Ext.util.DelayedTask(function(el){
  317.                 var newEl = Ext.get(el);
  318.                 if (newEl != this.curEl) {
  319.                     var w = newEl.getWidth();
  320.                     var h = newEl.getHeight();
  321.                     this.sides[0].show().setSize(w, this.size).anchorTo(el, 'tl', [0, -1]);
  322.                     this.sides[2].show().setSize(w, this.size).anchorTo(el, 'bl', [0, -1]);
  323.                     this.sides[1].show().setSize(this.size, h).anchorTo(el, 'tr', [-1, 0]);
  324.                     this.sides[3].show().setSize(this.size, h).anchorTo(el, 'tl', [-1, 0]);
  325.                     this.curEl = newEl;
  326.                 }
  327.             }, this);
  328.             
  329.             this.unframeTask = new Ext.util.DelayedTask(function(){
  330.                 if (this.initialized) {
  331.                     this.sides[0].hide();
  332.                     this.sides[1].hide();
  333.                     this.sides[2].hide();
  334.                     this.sides[3].hide();
  335.                     this.curEl = null;
  336.                 }
  337.             }, this);
  338.             this.initialized = true;
  339.         }
  340.     },
  341.     
  342.     frame: function(el){
  343.         this.init();
  344.         this.unframeTask.cancel();
  345.         this.frameTask.delay(2, false, false, [el]);
  346.     },
  347.     
  348.     unframe: function(){
  349.         this.init();
  350.         this.unframeTask.delay(2);
  351.     },
  352.     
  353.     setSize: function(size){
  354.         this.size = size;
  355.     },
  356.     
  357.     setColor: function(color){
  358.         this.color = color;
  359.     }
  360. });
  361. Ext.a11y.FocusFrame = new Ext.a11y.Frame(2, '15428B');
  362. Ext.a11y.RelayFrame = new Ext.a11y.Frame(1, '6B8CBF');
  363. Ext.a11y.Focusable = Ext.extend(Ext.util.Observable, {
  364.     constructor: function(el, relayTo, noFrame, frameEl){
  365.         Ext.a11y.Focusable.superclass.constructor.call(this);
  366.         
  367.         this.addEvents('focus', 'blur', 'left', 'right', 'up', 'down', 'esc', 'enter', 'space');
  368.         
  369.         if (el instanceof Ext.Component) {
  370.             this.el = el.el;
  371.             this.setComponent(el);
  372.         }
  373.         else {
  374.             this.el = Ext.get(el);
  375.             this.setComponent(null);
  376.         }
  377.         
  378.         this.setRelayTo(relayTo)
  379.         this.setNoFrame(noFrame);
  380.         this.setFrameEl(frameEl);
  381.         
  382.         this.init();
  383.         
  384.         Ext.a11y.FocusMgr.register(this);
  385.     },
  386.     
  387.     init: function(){
  388.         this.el.dom.tabIndex = '1';
  389.         this.el.addClass('x-a11y-focusable');
  390.         this.el.on({
  391.             focus: this.onFocus,
  392.             blur: this.onBlur,
  393.             keydown: this.onKeyDown,
  394.             scope: this
  395.         });
  396.     },
  397.     
  398.     setRelayTo: function(relayTo){
  399.         this.relayTo = relayTo ? Ext.a11y.FocusMgr.get(relayTo) : null;
  400.     },
  401.     
  402.     setNoFrame: function(noFrame){
  403.         this.noFrame = (noFrame === true) ? true : false;
  404.     },
  405.     
  406.     setFrameEl: function(frameEl){
  407.         this.frameEl = frameEl && Ext.get(frameEl) || this.el;
  408.     },
  409.     
  410.     setComponent: function(cmp){
  411.         this.component = cmp || null;
  412.     },
  413.     
  414.     onKeyDown: function(e, t){
  415.         var k = e.getKey(), SK = Ext.a11y.Focusable.SpecialKeys, ret, tf;
  416.         
  417.         tf = (t !== this.el.dom) ? Ext.a11y.FocusMgr.get(t, true) : this;
  418.         if (!tf) {
  419.             // this can happen when you are on a focused item within a panel body
  420.             // that is not a Ext.a11y.Focusable
  421.             tf = Ext.a11y.FocusMgr.get(Ext.fly(t).parent('.x-a11y-focusable'));
  422.         }
  423.         
  424.         if (SK[k] !== undefined) {
  425.             ret = this.fireEvent(SK[k], e, t, tf, this);
  426.         }
  427.         if (ret === false || this.fireEvent('keydown', e, t, tf, this) === false) {
  428.             e.stopEvent();
  429.         }
  430.     },
  431.     
  432.     focus: function(){
  433.         this.el.dom.focus();
  434.     },
  435.     
  436.     blur: function(){
  437.         this.el.dom.blur();
  438.     },
  439.     
  440.     onFocus: function(e, t){
  441.         this.el.addClass('x-a11y-focused');
  442.         if (this.relayTo) {
  443.             this.relayTo.el.addClass('x-a11y-focused-relay');
  444.             if (!this.relayTo.noFrame) {
  445.                 Ext.a11y.FocusFrame.frame(this.relayTo.frameEl);
  446.             }
  447.             if (!this.noFrame) {
  448.                 Ext.a11y.RelayFrame.frame(this.frameEl);
  449.             }
  450.         }
  451.         else {
  452.             if (!this.noFrame) {
  453.                 Ext.a11y.FocusFrame.frame(this.frameEl);
  454.             }
  455.         }
  456.         
  457.         this.fireEvent('focus', e, t, this);
  458.     },
  459.     
  460.     onBlur: function(e, t){
  461.         if (this.relayTo) {
  462.             this.relayTo.el.removeClass('x-a11y-focused-relay');
  463.             Ext.a11y.RelayFrame.unframe();
  464.         }
  465.         this.el.removeClass('x-a11y-focused');
  466.         Ext.a11y.FocusFrame.unframe();
  467.         this.fireEvent('blur', e, t, this);
  468.     },
  469.     
  470.     destroy: function(){
  471.         this.el.un('keydown', this.onKeyDown);
  472.         this.el.un('focus', this.onFocus);
  473.         this.el.un('blur', this.onBlur);
  474.         this.el.removeClass('x-a11y-focusable');
  475.         this.el.removeClass('x-a11y-focused');
  476.         if (this.relayTo) {
  477.             this.relayTo.el.removeClass('x-a11y-focused-relay');
  478.         }
  479.     }
  480. });
  481. Ext.a11y.FocusItem = Ext.extend(Object, {
  482.     constructor: function(el, enableTabbing){
  483.         Ext.a11y.FocusItem.superclass.constructor.call(this);
  484.         
  485.         this.el = Ext.get(el);
  486.         this.fi = new Ext.a11y.Focusable(el);
  487.         this.fi.setComponent(this);
  488.         
  489.         this.fi.on('tab', this.onTab, this);
  490.         
  491.         this.enableTabbing = enableTabbing === true ? true : false;
  492.     },
  493.     
  494.     getEnterItem: function(){
  495.         if (this.enableTabbing) {
  496.             var items = this.getFocusItems();
  497.             if (items && items.length) {
  498.                 return items[0];
  499.             }
  500.         }
  501.     },
  502.     
  503.     getFocusItems: function(){
  504.         if (this.enableTabbing) {
  505.             return this.el.query('a, button, input, select');
  506.         }
  507.         return null;
  508.     },
  509.     
  510.     onTab: function(e, t){
  511.         var items = this.getFocusItems(), i;
  512.         
  513.         if (items && items.length && (i = items.indexOf(t)) !== -1) {
  514.             if (e.shiftKey && i > 0) {
  515.                 e.stopEvent();
  516.                 items[i - 1].focus();
  517.                 Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
  518.                 return;
  519.             }
  520.             else 
  521.                 if (!e.shiftKey && i < items.length - 1) {
  522.                     e.stopEvent();
  523.                     items[i + 1].focus();
  524.                     Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
  525.                     return;
  526.                 }
  527.         }
  528.     },
  529.     
  530.     focus: function(){
  531.         if (this.enableTabbing) {
  532.             var items = this.getFocusItems();
  533.             if (items && items.length) {
  534.                 items[0].focus();
  535.                 Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
  536.                 return;
  537.             }
  538.         }
  539.         this.fi.focus();
  540.     },
  541.     
  542.     blur: function(){
  543.         this.fi.blur();
  544.     }
  545. });
  546. Ext.a11y.FocusMgr = function(){
  547.     var all = new Ext.util.MixedCollection();
  548.     
  549.     return {
  550.         register: function(f){
  551.             all.add(f.el && Ext.id(f.el), f);
  552.         },
  553.         
  554.         unregister: function(f){
  555.             all.remove(f);
  556.         },
  557.         
  558.         get: function(el, noCreate){
  559.             return all.get(Ext.id(el)) || (noCreate ? false : new Ext.a11y.Focusable(el));
  560.         },
  561.         
  562.         all: all
  563.     }
  564. }();
  565. Ext.a11y.Focusable.SpecialKeys = {};
  566. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.LEFT] = 'left';
  567. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.RIGHT] = 'right';
  568. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.DOWN] = 'down';
  569. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.UP] = 'up';
  570. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ESC] = 'esc';
  571. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ENTER] = 'enter';
  572. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.SPACE] = 'space';
  573. Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.TAB] = 'tab';
  574. // we use the new observeClass method to fire our new initFocus method on components
  575. Ext.util.Observable.observeClass(Ext.Component);
  576. Ext.Component.on('render', function(cmp){
  577.     cmp.initFocus();
  578.     cmp.initARIA();
  579. });
  580. Ext.override(Ext.Component, {
  581.     initFocus: Ext.emptyFn,
  582.     initARIA: Ext.emptyFn
  583. });
  584. Ext.override(Ext.Container, {
  585.     isFocusable: true,
  586.     noFocus: false,
  587.     
  588.     // private
  589.     initFocus: function(){
  590.         if (!this.fi && !this.noFocus) {
  591.             this.fi = new Ext.a11y.Focusable(this);
  592.         }
  593.         this.mon(this.fi, {
  594.             focus: this.onFocus,
  595.             blur: this.onBlur,
  596.             tab: this.onTab,
  597.             enter: this.onEnter,
  598.             esc: this.onEsc,
  599.             scope: this
  600.         });
  601.         
  602.         if (this.hidden) {
  603.             this.isFocusable = false;
  604.         }
  605.         
  606.         this.on('show', function(){
  607.             this.isFocusable = true;
  608.         }, this);
  609.         this.on('hide', function(){
  610.             this.isFocusable = false;
  611.         }, this);
  612.     },
  613.     
  614.     focus: function(){
  615.         this.fi.focus();
  616.     },
  617.     
  618.     blur: function(){
  619.         this.fi.blur();
  620.     },
  621.     
  622.     enter: function(){
  623.         var eitem = this.getEnterItem();
  624.         if (eitem) {
  625.             eitem.focus();
  626.         }
  627.     },
  628.     
  629.     onFocus: Ext.emptyFn,
  630.     onBlur: Ext.emptyFn,
  631.     
  632.     onTab: function(e, t, tf){
  633.         var rf = tf.relayTo || tf;
  634.         if (rf.component && rf.component !== this) {
  635.             e.stopEvent();
  636.             var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);
  637.             item.focus();
  638.         }
  639.     },
  640.     
  641.     onEnter: function(e, t, tf){
  642.         // check to see if enter is pressed while "on" the panel
  643.         if (tf.component && tf.component === this) {
  644.             e.stopEvent();
  645.             this.enter();
  646.         }
  647.         e.stopPropagation();
  648.     },
  649.     
  650.     onEsc: function(e, t){
  651.         e.preventDefault();
  652.         
  653.         // check to see if esc is pressed while "inside" the panel
  654.         // or while "on" the panel
  655.         if (t === this.el.dom) {
  656.             // "on" the panel, check if this panel has an owner panel and focus that
  657.             // we dont stop the event in this case so that this same check will be
  658.             // done for this ownerCt
  659.             if (this.ownerCt) {
  660.                 this.ownerCt.focus();
  661.             }
  662.         }
  663.         else {
  664.             // we were inside the panel when esc was pressed,
  665.             // so go back "on" the panel
  666.             if (this.ownerCt && this.ownerCt.isFocusable) {
  667.                 var si = this.ownerCt.getFocusItems();
  668.                 
  669.                 if (si && si.getCount() > 1) {
  670.                     e.stopEvent();
  671.                 }
  672.             }
  673.             this.focus();
  674.         }
  675.     },
  676.     
  677.     getFocusItems: function(){
  678.         return this.items &&
  679.         this.items.filterBy(function(o){
  680.             return o.isFocusable;
  681.         }) ||
  682.         null;
  683.     },
  684.     
  685.     getEnterItem: function(){
  686.         var ci = this.getFocusItems(), length = ci ? ci.getCount() : 0;
  687.         
  688.         if (length === 1) {
  689.             return ci.first().getEnterItem && ci.first().getEnterItem() || ci.first();
  690.         }
  691.         else 
  692.             if (length > 1) {
  693.                 return ci.first();
  694.             }
  695.     },
  696.     
  697.     getNextFocus: function(current){
  698.         var items = this.getFocusItems(), next = current, i = items.indexOf(current), length = items.getCount();
  699.         
  700.         if (i === length - 1) {
  701.             next = items.first();
  702.         }
  703.         else {
  704.             next = items.get(i + 1);
  705.         }
  706.         return next;
  707.     },
  708.     
  709.     getPreviousFocus: function(current){
  710.         var items = this.getFocusItems(), prev = current, i = items.indexOf(current), length = items.getCount();
  711.         
  712.         if (i === 0) {
  713.             prev = items.last();
  714.         }
  715.         else {
  716.             prev = items.get(i - 1);
  717.         }
  718.         return prev;
  719.     },
  720.     
  721.     getFocusable : function() {
  722.         return this.fi;
  723.     }
  724. });
  725. Ext.override(Ext.Panel, {
  726.     /**
  727.      * @cfg {Boolean} enableTabbing <tt>true</tt> to enable tabbing. Default is <tt>false</tt>.
  728.      */        
  729.     getFocusItems: function(){
  730.         // items gets all the items inside the body
  731.         var items = Ext.Panel.superclass.getFocusItems.call(this), bodyFocus = null;
  732.         
  733.         if (!items) {
  734.             items = new Ext.util.MixedCollection();
  735.             this.bodyFocus = this.bodyFocus || new Ext.a11y.FocusItem(this.body, this.enableTabbing);
  736.             items.add('body', this.bodyFocus);
  737.         }
  738.         // but panels can also have tbar, bbar, fbar
  739.         if (this.tbar && this.topToolbar) {
  740.             items.insert(0, this.topToolbar);
  741.         }
  742.         if (this.bbar && this.bottomToolbar) {
  743.             items.add(this.bottomToolbar);
  744.         }
  745.         if (this.fbar) {
  746.             items.add(this.fbar);
  747.         }
  748.         
  749.         return items;
  750.     }
  751. });
  752. Ext.override(Ext.TabPanel, {
  753.     // private
  754.     initFocus: function(){
  755.         Ext.TabPanel.superclass.initFocus.call(this);
  756.         this.mon(this.fi, {
  757.             left: this.onLeft,
  758.             right: this.onRight,
  759.             scope: this
  760.         });
  761.     },
  762.     
  763.     onLeft: function(e){
  764.         if (!this.activeTab) {
  765.             return;
  766.         }
  767.         e.stopEvent();
  768.         var prev = this.items.itemAt(this.items.indexOf(this.activeTab) - 1);
  769.         if (prev) {
  770.             this.setActiveTab(prev);
  771.         }
  772.         return false;
  773.     },
  774.     
  775.     onRight: function(e){
  776.         if (!this.activeTab) {
  777.             return;
  778.         }
  779.         e.stopEvent();
  780.         var next = this.items.itemAt(this.items.indexOf(this.activeTab) + 1);
  781.         if (next) {
  782.             this.setActiveTab(next);
  783.         }
  784.         return false;
  785.     }
  786. });
  787. Ext.override(Ext.tree.TreeNodeUI, {
  788.     // private
  789.     focus: function(){
  790.         this.node.getOwnerTree().bodyFocus.focus();
  791.     }
  792. });
  793. Ext.override(Ext.tree.TreePanel, {
  794.     // private
  795.     afterRender : function(){
  796.         Ext.tree.TreePanel.superclass.afterRender.call(this);
  797.         this.root.render();
  798.         if(!this.rootVisible){
  799.             this.root.renderChildren();
  800.         }
  801.         this.bodyFocus = new Ext.a11y.FocusItem(this.body.down('.x-tree-root-ct'));
  802.         this.bodyFocus.fi.setFrameEl(this.body);
  803.     } 
  804. });
  805. Ext.override(Ext.grid.GridPanel, {
  806.     initFocus: function(){
  807.         Ext.grid.GridPanel.superclass.initFocus.call(this);
  808.         this.bodyFocus = new Ext.a11y.FocusItem(this.view.focusEl);
  809.         this.bodyFocus.fi.setFrameEl(this.body);
  810.     }
  811. });
  812. Ext.override(Ext.Button, {
  813.     isFocusable: true,
  814.     noFocus: false,
  815.     
  816.     initFocus: function(){
  817.         Ext.Button.superclass.initFocus.call(this);
  818.         this.fi = this.fi || new Ext.a11y.Focusable(this.btnEl, null, null, this.el);
  819.         this.fi.setComponent(this);
  820.         
  821.         this.mon(this.fi, {
  822.             focus: this.onFocus,
  823.             blur: this.onBlur,
  824.             scope: this
  825.         });
  826.         
  827.         if (this.menu) {
  828.             this.mon(this.fi, 'down', this.showMenu, this);
  829.             this.on('menuhide', this.focus, this);
  830.         }
  831.         
  832.         if (this.hidden) {
  833.             this.isFocusable = false;
  834.         }
  835.         
  836.         this.on('show', function(){
  837.             this.isFocusable = true;
  838.         }, this);
  839.         this.on('hide', function(){
  840.             this.isFocusable = false;
  841.         }, this);
  842.     },
  843.     
  844.     focus: function(){
  845.         this.fi.focus();
  846.     },
  847.     
  848.     blur: function(){
  849.         this.fi.blur();
  850.     },
  851.     
  852.     onFocus: function(){
  853.         if (!this.disabled) {
  854.             this.el.addClass("x-btn-focus");
  855.         }
  856.     },
  857.     
  858.     onBlur: function(){
  859.         this.el.removeClass("x-btn-focus");
  860.     }
  861. });
  862. Ext.override(Ext.Toolbar, {
  863.     initFocus: function(){
  864.         Ext.Toolbar.superclass.initFocus.call(this);
  865.         this.mon(this.fi, {
  866.             left: this.onLeft,
  867.             right: this.onRight,
  868.             scope: this
  869.         });
  870.         
  871.         this.on('focus', this.onButtonFocus, this, {
  872.             stopEvent: true
  873.         });
  874.     },
  875.     
  876.     addItem: function(item){
  877.         Ext.Toolbar.superclass.add.apply(this, arguments);
  878.         if (item.rendered && item.fi !== undefined) {
  879.             item.fi.setRelayTo(this.el);
  880.             this.relayEvents(item.fi, ['focus']);
  881.         }
  882.         else {
  883.             item.on('render', function(){
  884.                 if (item.fi !== undefined) {
  885.                     item.fi.setRelayTo(this.el);
  886.                     this.relayEvents(item.fi, ['focus']);
  887.                 }
  888.             }, this, {
  889.                 single: true
  890.             });
  891.         }
  892.         return item;
  893.     },
  894.     
  895.     onFocus: function(){
  896.         var items = this.getFocusItems();
  897.         if (items && items.getCount() > 0) {
  898.             if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {
  899.                 this.lastFocus.focus();
  900.             }
  901.             else {
  902.                 items.first().focus();
  903.             }
  904.         }
  905.     },
  906.     
  907.     onButtonFocus: function(e, t, tf){
  908.         this.lastFocus = tf.component || null;
  909.     },
  910.     
  911.     onLeft: function(e, t, tf){
  912.         e.stopEvent();
  913.         this.getPreviousFocus(tf.component).focus();
  914.     },
  915.     
  916.     onRight: function(e, t, tf){
  917.         e.stopEvent();
  918.         this.getNextFocus(tf.component).focus();
  919.     },
  920.     
  921.     getEnterItem: Ext.emptyFn,
  922.     onTab: Ext.emptyFn,
  923.     onEsc: Ext.emptyFn
  924. });
  925. Ext.override(Ext.menu.BaseItem, {
  926.     initFocus: function(){
  927.         this.fi = new Ext.a11y.Focusable(this, this.parentMenu && this.parentMenu.el || null, true);
  928.     }
  929. });
  930. Ext.override(Ext.menu.Menu, {
  931.     initFocus: function(){
  932.         this.fi = new Ext.a11y.Focusable(this);
  933.         this.focusEl = this.fi;
  934.     }
  935. });
  936. Ext.a11y.WindowMgr = new Ext.WindowGroup();
  937. Ext.apply(Ext.WindowMgr, {
  938.     bringToFront: function(win){
  939.         Ext.a11y.WindowMgr.bringToFront.call(this, win);
  940.         if (win.modal) {
  941.             win.enter();
  942.         }
  943.         else {
  944.             win.focus();
  945.         }
  946.     }
  947. });
  948. Ext.override(Ext.Window, {
  949.     initFocus: function(){
  950.         Ext.Window.superclass.initFocus.call(this);
  951.         this.on('beforehide', function(){
  952.             Ext.a11y.RelayFrame.unframe();
  953.             Ext.a11y.FocusFrame.unframe();
  954.         });
  955.     }
  956. });
  957. Ext.override(Ext.form.Field, {
  958.     isFocusable: true,
  959.     noFocus: false,
  960.     
  961.     initFocus: function(){
  962.         this.fi = this.fi || new Ext.a11y.Focusable(this, null, true);
  963.         
  964.         Ext.form.Field.superclass.initFocus.call(this);
  965.         
  966.         if (this.hidden) {
  967.             this.isFocusable = false;
  968.         }
  969.         
  970.         this.on('show', function(){
  971.             this.isFocusable = true;
  972.         }, this);
  973.         this.on('hide', function(){
  974.             this.isFocusable = false;
  975.         }, this);
  976.     }
  977. });
  978. Ext.override(Ext.FormPanel, {
  979.     initFocus: function(){
  980.         Ext.FormPanel.superclass.initFocus.call(this);
  981.         this.on('focus', this.onFieldFocus, this, {
  982.             stopEvent: true
  983.         });
  984.     },
  985.     
  986.     // private
  987.     createForm: function(){
  988.         delete this.initialConfig.listeners;
  989.         var form = new Ext.form.BasicForm(null, this.initialConfig);
  990.         form.afterMethod('add', this.formItemAdd, this);
  991.         return form;
  992.     },
  993.     
  994.     formItemAdd: function(item){
  995.         item.on('render', function(field){
  996.             field.fi.setRelayTo(this.el);
  997.             this.relayEvents(field.fi, ['focus']);
  998.         }, this, {
  999.             single: true
  1000.         });
  1001.     },
  1002.     
  1003.     onFocus: function(){
  1004.         var items = this.getFocusItems();
  1005.         if (items && items.getCount() > 0) {
  1006.             if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {
  1007.                 this.lastFocus.focus();
  1008.             }
  1009.             else {
  1010.                 items.first().focus();
  1011.             }
  1012.         }
  1013.     },
  1014.     
  1015.     onFieldFocus: function(e, t, tf){
  1016.         this.lastFocus = tf.component || null;
  1017.     },
  1018.     
  1019.     onTab: function(e, t, tf){
  1020.         if (tf.relayTo.component === this) {
  1021.             var item = e.shiftKey ? this.getPreviousFocus(tf.component) : this.getNextFocus(tf.component);
  1022.             
  1023.             if (item) {
  1024.                 ev.stopEvent();
  1025.                 item.focus();
  1026.                 return;
  1027.             }
  1028.         }
  1029.         Ext.FormPanel.superclass.onTab.apply(this, arguments);
  1030.     },
  1031.     
  1032.     getNextFocus: function(current){
  1033.         var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();
  1034.         
  1035.         return (i < length - 1) ? items.get(i + 1) : false;
  1036.     },
  1037.     
  1038.     getPreviousFocus: function(current){
  1039.         var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();
  1040.         
  1041.         return (i > 0) ? items.get(i - 1) : false;
  1042.     }
  1043. });
  1044. Ext.override(Ext.Viewport, {
  1045.     initFocus: function(){
  1046.         Ext.Viewport.superclass.initFocus.apply(this);
  1047.         this.mon(Ext.get(document), 'focus', this.focus, this);
  1048.         this.mon(Ext.get(document), 'blur', this.blur, this);
  1049.         this.fi.setNoFrame(true);
  1050.     },
  1051.     
  1052.     onTab: function(e, t, tf, f){
  1053.         e.stopEvent();
  1054.         
  1055.         if (tf === f) {
  1056.             items = this.getFocusItems();
  1057.             if (items && items.getCount() > 0) {
  1058.                 items.first().focus();
  1059.             }
  1060.         }
  1061.         else {
  1062.             var rf = tf.relayTo || tf;
  1063.             var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);
  1064.             item.focus();
  1065.         }
  1066.     }
  1067. });
  1068.     
  1069. })();/**
  1070.  * @class Ext.ux.GMapPanel
  1071.  * @extends Ext.Panel
  1072.  * @author Shea Frederick
  1073.  */
  1074. Ext.ux.GMapPanel = Ext.extend(Ext.Panel, {
  1075.     initComponent : function(){
  1076.         
  1077.         var defConfig = {
  1078.             plain: true,
  1079.             zoomLevel: 3,
  1080.             yaw: 180,
  1081.             pitch: 0,
  1082.             zoom: 0,
  1083.             gmapType: 'map',
  1084.             border: false
  1085.         };
  1086.         
  1087.         Ext.applyIf(this,defConfig);
  1088.         
  1089.         Ext.ux.GMapPanel.superclass.initComponent.call(this);        
  1090.     },
  1091.     afterRender : function(){
  1092.         
  1093.         var wh = this.ownerCt.getSize();
  1094.         Ext.applyIf(this, wh);
  1095.         
  1096.         Ext.ux.GMapPanel.superclass.afterRender.call(this);    
  1097.         
  1098.         if (this.gmapType === 'map'){
  1099.             this.gmap = new GMap2(this.body.dom);
  1100.         }
  1101.         
  1102.         if (this.gmapType === 'panorama'){
  1103.             this.gmap = new GStreetviewPanorama(this.body.dom);
  1104.         }
  1105.         
  1106.         if (typeof this.addControl == 'object' && this.gmapType === 'map') {
  1107.             this.gmap.addControl(this.addControl);
  1108.         }
  1109.         
  1110.         if (typeof this.setCenter === 'object') {
  1111.             if (typeof this.setCenter.geoCodeAddr === 'string'){
  1112.                 this.geoCodeLookup(this.setCenter.geoCodeAddr);
  1113.             }else{
  1114.                 if (this.gmapType === 'map'){
  1115.                     var point = new GLatLng(this.setCenter.lat,this.setCenter.lng);
  1116.                     this.gmap.setCenter(point, this.zoomLevel);    
  1117.                 }
  1118.                 if (typeof this.setCenter.marker === 'object' && typeof point === 'object'){
  1119.                     this.addMarker(point,this.setCenter.marker,this.setCenter.marker.clear);
  1120.                 }
  1121.             }
  1122.             if (this.gmapType === 'panorama'){
  1123.                 this.gmap.setLocationAndPOV(new GLatLng(this.setCenter.lat,this.setCenter.lng), {yaw: this.yaw, pitch: this.pitch, zoom: this.zoom});
  1124.             }
  1125.         }
  1126.         GEvent.bind(this.gmap, 'load', this, function(){
  1127.             this.onMapReady();
  1128.         });
  1129.     },
  1130.     onMapReady : function(){
  1131.         this.addMarkers(this.markers);
  1132.         this.addMapControls();
  1133.         this.addOptions();  
  1134.     },
  1135.     onResize : function(w, h){
  1136.         if (typeof this.getMap() == 'object') {
  1137.             this.gmap.checkResize();
  1138.         }
  1139.         
  1140.         Ext.ux.GMapPanel.superclass.onResize.call(this, w, h);
  1141.     },
  1142.     setSize : function(width, height, animate){
  1143.         
  1144.         if (typeof this.getMap() == 'object') {
  1145.             this.gmap.checkResize();
  1146.         }
  1147.         
  1148.         Ext.ux.GMapPanel.superclass.setSize.call(this, width, height, animate);
  1149.         
  1150.     },
  1151.     getMap : function(){
  1152.         
  1153.         return this.gmap;
  1154.         
  1155.     },
  1156.     getCenter : function(){
  1157.         
  1158.         return this.getMap().getCenter();
  1159.         
  1160.     },
  1161.     getCenterLatLng : function(){
  1162.         
  1163.         var ll = this.getCenter();
  1164.         return {lat: ll.lat(), lng: ll.lng()};
  1165.         
  1166.     },
  1167.     addMarkers : function(markers) {
  1168.         
  1169.         if (Ext.isArray(markers)){
  1170.             for (var i = 0; i < markers.length; i++) {
  1171.                 var mkr_point = new GLatLng(markers[i].lat,markers[i].lng);
  1172.                 this.addMarker(mkr_point,markers[i].marker,false,markers[i].setCenter, markers[i].listeners);
  1173.             }
  1174.         }
  1175.         
  1176.     },
  1177.     addMarker : function(point, marker, clear, center, listeners){
  1178.         
  1179.         Ext.applyIf(marker,G_DEFAULT_ICON);
  1180.         if (clear === true){
  1181.             this.getMap().clearOverlays();
  1182.         }
  1183.         if (center === true) {
  1184.             this.getMap().setCenter(point, this.zoomLevel);
  1185.         }
  1186.         var mark = new GMarker(point,marker);
  1187.         if (typeof listeners === 'object'){
  1188.             for (evt in listeners) {
  1189.                 GEvent.bind(mark, evt, this, listeners[evt]);
  1190.             }
  1191.         }
  1192.         this.getMap().addOverlay(mark);
  1193.     },
  1194.     addMapControls : function(){
  1195.         
  1196.         if (this.gmapType === 'map') {
  1197.             if (Ext.isArray(this.mapControls)) {
  1198.                 for(i=0;i<this.mapControls.length;i++){
  1199.                     this.addMapControl(this.mapControls[i]);
  1200.                 }
  1201.             }else if(typeof this.mapControls === 'string'){
  1202.                 this.addMapControl(this.mapControls);
  1203.             }else if(typeof this.mapControls === 'object'){
  1204.                 this.getMap().addControl(this.mapControls);
  1205.             }
  1206.         }
  1207.         
  1208.     },
  1209.     addMapControl : function(mc){
  1210.         
  1211.         var mcf = window[mc];
  1212.         if (typeof mcf === 'function') {
  1213.             this.getMap().addControl(new mcf());
  1214.         }    
  1215.         
  1216.     },
  1217.     addOptions : function(){
  1218.         
  1219.         if (Ext.isArray(this.mapConfOpts)) {
  1220.             var mc;
  1221.             for(i=0;i<this.mapConfOpts.length;i++){
  1222.                 this.addOption(this.mapConfOpts[i]);
  1223.             }
  1224.         }else if(typeof this.mapConfOpts === 'string'){
  1225.             this.addOption(this.mapConfOpts);
  1226.         }        
  1227.         
  1228.     },
  1229.     addOption : function(mc){
  1230.         
  1231.         var mcf = this.getMap()[mc];
  1232.         if (typeof mcf === 'function') {
  1233.             this.getMap()[mc]();
  1234.         }    
  1235.         
  1236.     },
  1237.     geoCodeLookup : function(addr) {
  1238.         
  1239.         this.geocoder = new GClientGeocoder();
  1240.         this.geocoder.getLocations(addr, this.addAddressToMap.createDelegate(this));
  1241.         
  1242.     },
  1243.     addAddressToMap : function(response) {
  1244.         
  1245.         if (!response || response.Status.code != 200) {
  1246.             Ext.MessageBox.alert('Error', 'Code '+response.Status.code+' Error Returned');
  1247.         }else{
  1248.             place = response.Placemark[0];
  1249.             addressinfo = place.AddressDetails;
  1250.             accuracy = addressinfo.Accuracy;
  1251.             if (accuracy === 0) {
  1252.                 Ext.MessageBox.alert('Unable to Locate Address', 'Unable to Locate the Address you provided');
  1253.             }else{
  1254.                 if (accuracy < 7) {
  1255.                     Ext.MessageBox.alert('Address Accuracy', 'The address provided has a low accuracy.<br><br>Level '+accuracy+' Accuracy (8 = Exact Match, 1 = Vague Match)');
  1256.                 }else{
  1257.                     point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
  1258.                     if (typeof this.setCenter.marker === 'object' && typeof point === 'object'){
  1259.                         this.addMarker(point,this.setCenter.marker,this.setCenter.marker.clear,true, this.setCenter.listeners);
  1260.                     }
  1261.                 }
  1262.             }
  1263.         }
  1264.         
  1265.     }
  1266.  
  1267. });
  1268. Ext.reg('gmappanel', Ext.ux.GMapPanel); Ext.ns('Ext.ux.grid');
  1269. /**
  1270.  * @class Ext.ux.grid.GroupSummary
  1271.  * @extends Ext.util.Observable
  1272.  * A GridPanel plugin that enables dynamic column calculations and a dynamically
  1273.  * updated grouped summary row.
  1274.  */
  1275. Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, {
  1276.     /**
  1277.      * @cfg {Function} summaryRenderer Renderer example:<pre><code>
  1278. summaryRenderer: function(v, params, data){
  1279.     return ((v === 0 || v > 1) ? '(' + v +' Tasks)' : '(1 Task)');
  1280. },
  1281.      * </code></pre>
  1282.      */
  1283.     /**
  1284.      * @cfg {String} summaryType (Optional) The type of
  1285.      * calculation to be used for the column.  For options available see
  1286.      * {@link #Calculations}.
  1287.      */
  1288.     constructor : function(config){
  1289.         Ext.apply(this, config);
  1290.         Ext.ux.grid.GroupSummary.superclass.constructor.call(this);
  1291.     },
  1292.     init : function(grid){
  1293.         this.grid = grid;
  1294.         this.cm = grid.getColumnModel();
  1295.         this.view = grid.getView();
  1296.         var v = this.view;
  1297.         v.doGroupEnd = this.doGroupEnd.createDelegate(this);
  1298.         v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
  1299.         v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
  1300.         v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);
  1301.         v.afterMethod('onUpdate', this.doUpdate, this);
  1302.         v.afterMethod('onRemove', this.doRemove, this);
  1303.         if(!this.rowTpl){
  1304.             this.rowTpl = new Ext.Template(
  1305.                 '<div class="x-grid3-summary-row" style="{tstyle}">',
  1306.                 '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
  1307.                     '<tbody><tr>{cells}</tr></tbody>',
  1308.                 '</table></div>'
  1309.             );
  1310.             this.rowTpl.disableFormats = true;
  1311.         }
  1312.         this.rowTpl.compile();
  1313.         if(!this.cellTpl){
  1314.             this.cellTpl = new Ext.Template(
  1315.                 '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
  1316.                 '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>',
  1317.                 "</td>"
  1318.             );
  1319.             this.cellTpl.disableFormats = true;
  1320.         }
  1321.         this.cellTpl.compile();
  1322.     },
  1323.     /**
  1324.      * Toggle the display of the summary row on/off
  1325.      * @param {Boolean} visible <tt>true</tt> to show the summary, <tt>false</tt> to hide the summary.
  1326.      */
  1327.     toggleSummaries : function(visible){
  1328.         var el = this.grid.getGridEl();
  1329.         if(el){
  1330.             if(visible === undefined){
  1331.                 visible = el.hasClass('x-grid-hide-summary');
  1332.             }
  1333.             el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');
  1334.         }
  1335.     },
  1336.     renderSummary : function(o, cs){
  1337.         cs = cs || this.view.getColumnData();
  1338.         var cfg = this.cm.config;
  1339.         var buf = [], c, p = {}, cf, last = cs.length-1;
  1340.         for(var i = 0, len = cs.length; i < len; i++){
  1341.             c = cs[i];
  1342.             cf = cfg[i];
  1343.             p.id = c.id;
  1344.             p.style = c.style;
  1345.             p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
  1346.             if(cf.summaryType || cf.summaryRenderer){
  1347.                 p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);
  1348.             }else{
  1349.                 p.value = '';
  1350.             }
  1351.             if(p.value == undefined || p.value === "") p.value = "&#160;";
  1352.             buf[buf.length] = this.cellTpl.apply(p);
  1353.         }
  1354.         return this.rowTpl.apply({
  1355.             tstyle: 'width:'+this.view.getTotalWidth()+';',
  1356.             cells: buf.join('')
  1357.         });
  1358.     },
  1359.     /**
  1360.      * @private
  1361.      * @param {Object} rs
  1362.      * @param {Object} cs
  1363.      */
  1364.     calculate : function(rs, cs){
  1365.         var data = {}, r, c, cfg = this.cm.config, cf;
  1366.         for(var j = 0, jlen = rs.length; j < jlen; j++){
  1367.             r = rs[j];
  1368.             for(var i = 0, len = cs.length; i < len; i++){
  1369.                 c = cs[i];
  1370.                 cf = cfg[i];
  1371.                 if(cf.summaryType){
  1372.                     data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);
  1373.                 }
  1374.             }
  1375.         }
  1376.         return data;
  1377.     },
  1378.     doGroupEnd : function(buf, g, cs, ds, colCount){
  1379.         var data = this.calculate(g.rs, cs);
  1380.         buf.push('</div>', this.renderSummary({data: data}, cs), '</div>');
  1381.     },
  1382.     doWidth : function(col, w, tw){
  1383.         var gs = this.view.getGroups(), s;
  1384.         for(var i = 0, len = gs.length; i < len; i++){
  1385.             s = gs[i].childNodes[2];
  1386.             s.style.width = tw;
  1387.             s.firstChild.style.width = tw;
  1388.             s.firstChild.rows[0].childNodes[col].style.width = w;
  1389.         }
  1390.     },
  1391.     doAllWidths : function(ws, tw){
  1392.         var gs = this.view.getGroups(), s, cells, wlen = ws.length;
  1393.         for(var i = 0, len = gs.length; i < len; i++){
  1394.             s = gs[i].childNodes[2];
  1395.             s.style.width = tw;
  1396.             s.firstChild.style.width = tw;
  1397.             cells = s.firstChild.rows[0].childNodes;
  1398.             for(var j = 0; j < wlen; j++){
  1399.                 cells[j].style.width = ws[j];
  1400.             }
  1401.         }
  1402.     },
  1403.     doHidden : function(col, hidden, tw){
  1404.         var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';
  1405.         for(var i = 0, len = gs.length; i < len; i++){
  1406.             s = gs[i].childNodes[2];
  1407.             s.style.width = tw;
  1408.             s.firstChild.style.width = tw;
  1409.             s.firstChild.rows[0].childNodes[col].style.display = display;
  1410.         }
  1411.     },
  1412.     // Note: requires that all (or the first) record in the
  1413.     // group share the same group value. Returns false if the group
  1414.     // could not be found.
  1415.     refreshSummary : function(groupValue){
  1416.         return this.refreshSummaryById(this.view.getGroupId(groupValue));
  1417.     },
  1418.     getSummaryNode : function(gid){
  1419.         var g = Ext.fly(gid, '_gsummary');
  1420.         if(g){
  1421.             return g.down('.x-grid3-summary-row', true);
  1422.         }
  1423.         return null;
  1424.     },
  1425.     refreshSummaryById : function(gid){
  1426.         var g = document.getElementById(gid);
  1427.         if(!g){
  1428.             return false;
  1429.         }
  1430.         var rs = [];
  1431.         this.grid.store.each(function(r){
  1432.             if(r._groupId == gid){
  1433.                 rs[rs.length] = r;
  1434.             }
  1435.         });
  1436.         var cs = this.view.getColumnData();
  1437.         var data = this.calculate(rs, cs);
  1438.         var markup = this.renderSummary({data: data}, cs);
  1439.         var existing = this.getSummaryNode(gid);
  1440.         if(existing){
  1441.             g.removeChild(existing);
  1442.         }
  1443.         Ext.DomHelper.append(g, markup);
  1444.         return true;
  1445.     },
  1446.     doUpdate : function(ds, record){
  1447.         this.refreshSummaryById(record._groupId);
  1448.     },
  1449.     doRemove : function(ds, record, index, isUpdate){
  1450.         if(!isUpdate){
  1451.             this.refreshSummaryById(record._groupId);
  1452.         }
  1453.     },
  1454.     /**
  1455.      * Show a message in the summary row.
  1456.      * <pre><code>
  1457. grid.on('afteredit', function(){
  1458.     var groupValue = 'Ext Forms: Field Anchoring';
  1459.     summary.showSummaryMsg(groupValue, 'Updating Summary...');
  1460. });
  1461.      * </code></pre>
  1462.      * @param {String} groupValue
  1463.      * @param {String} msg Text to use as innerHTML for the summary row.
  1464.      */
  1465.     showSummaryMsg : function(groupValue, msg){
  1466.         var gid = this.view.getGroupId(groupValue);
  1467.         var node = this.getSummaryNode(gid);
  1468.         if(node){
  1469.             node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>';
  1470.         }
  1471.     }
  1472. });
  1473. //backwards compat
  1474. Ext.grid.GroupSummary = Ext.ux.grid.GroupSummary;
  1475. /**
  1476.  * Calculation types for summary row:</p><div class="mdetail-params"><ul>
  1477.  * <li><b><tt>sum</tt></b> : <div class="sub-desc"></div></li>
  1478.  * <li><b><tt>count</tt></b> : <div class="sub-desc"></div></li>
  1479.  * <li><b><tt>max</tt></b> : <div class="sub-desc"></div></li>
  1480.  * <li><b><tt>min</tt></b> : <div class="sub-desc"></div></li>
  1481.  * <li><b><tt>average</tt></b> : <div class="sub-desc"></div></li>
  1482.  * </ul></div>
  1483.  * <p>Custom calculations may be implemented.  An example of
  1484.  * custom <code>summaryType=totalCost</code>:</p><pre><code>
  1485. // define a custom summary function
  1486. Ext.ux.grid.GroupSummary.Calculations['totalCost'] = function(v, record, field){
  1487.     return v + (record.data.estimate * record.data.rate);
  1488. };
  1489.  * </code></pre>
  1490.  * @property Calculations
  1491.  */
  1492. Ext.ux.grid.GroupSummary.Calculations = {
  1493.     'sum' : function(v, record, field){
  1494.         return v + (record.data[field]||0);
  1495.     },
  1496.     'count' : function(v, record, field, data){
  1497.         return data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);
  1498.     },
  1499.     'max' : function(v, record, field, data){
  1500.         var v = record.data[field];
  1501.         var max = data[field+'max'] === undefined ? (data[field+'max'] = v) : data[field+'max'];
  1502.         return v > max ? (data[field+'max'] = v) : max;
  1503.     },
  1504.     'min' : function(v, record, field, data){
  1505.         var v = record.data[field];
  1506.         var min = data[field+'min'] === undefined ? (data[field+'min'] = v) : data[field+'min'];
  1507.         return v < min ? (data[field+'min'] = v) : min;
  1508.     },
  1509.     'average' : function(v, record, field, data){
  1510.         var c = data[field+'count'] ? ++data[field+'count'] : (data[field+'count'] = 1);
  1511.         var t = (data[field+'total'] = ((data[field+'total']||0) + (record.data[field]||0)));
  1512.         return t === 0 ? 0 : t / c;
  1513.     }
  1514. };
  1515. Ext.grid.GroupSummary.Calculations = Ext.ux.grid.GroupSummary.Calculations;
  1516. /**
  1517.  * @class Ext.ux.grid.HybridSummary
  1518.  * @extends Ext.ux.grid.GroupSummary
  1519.  * Adds capability to specify the summary data for the group via json as illustrated here:
  1520.  * <pre><code>
  1521. {
  1522.     data: [
  1523.         {
  1524.             projectId: 100,     project: 'House',
  1525.             taskId:    112, description: 'Paint',
  1526.             estimate:    6,        rate:     150,
  1527.             due:'06/24/2007'
  1528.         },
  1529.         ...
  1530.     ],
  1531.     summaryData: {
  1532.         'House': {
  1533.             description: 14, estimate: 9,
  1534.                    rate: 99, due: new Date(2009, 6, 29),
  1535.                    cost: 999
  1536.         }
  1537.     }
  1538. }
  1539.  * </code></pre>
  1540.  *
  1541.  */
  1542. Ext.ux.grid.HybridSummary = Ext.extend(Ext.ux.grid.GroupSummary, {
  1543.     /**
  1544.      * @private
  1545.      * @param {Object} rs
  1546.      * @param {Object} cs
  1547.      */
  1548.     calculate : function(rs, cs){
  1549.         var gcol = this.view.getGroupField();
  1550.         var gvalue = rs[0].data[gcol];
  1551.         var gdata = this.getSummaryData(gvalue);
  1552.         return gdata || Ext.ux.grid.HybridSummary.superclass.calculate.call(this, rs, cs);
  1553.     },
  1554.     /**
  1555.      * <pre><code>
  1556. grid.on('afteredit', function(){
  1557.     var groupValue = 'Ext Forms: Field Anchoring';
  1558.     summary.showSummaryMsg(groupValue, 'Updating Summary...');
  1559.     setTimeout(function(){ // simulate server call
  1560.         // HybridSummary class implements updateSummaryData
  1561.         summary.updateSummaryData(groupValue,
  1562.             // create data object based on configured dataIndex
  1563.             {description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});
  1564.     }, 2000);
  1565. });
  1566.      * </code></pre>
  1567.      * @param {String} groupValue
  1568.      * @param {Object} data data object
  1569.      * @param {Boolean} skipRefresh (Optional) Defaults to false
  1570.      */
  1571.     updateSummaryData : function(groupValue, data, skipRefresh){
  1572.         var json = this.grid.store.reader.jsonData;
  1573.         if(!json.summaryData){
  1574.             json.summaryData = {};
  1575.         }
  1576.         json.summaryData[groupValue] = data;
  1577.         if(!skipRefresh){
  1578.             this.refreshSummary(groupValue);
  1579.         }
  1580.     },
  1581.     /**
  1582.      * Returns the summaryData for the specified groupValue or null.
  1583.      * @param {String} groupValue
  1584.      * @return {Object} summaryData
  1585.      */
  1586.     getSummaryData : function(groupValue){
  1587.         var json = this.grid.store.reader.jsonData;
  1588.         if(json && json.summaryData){
  1589.             return json.summaryData[groupValue];
  1590.         }
  1591.         return null;
  1592.     }
  1593. });
  1594. //backwards compat
  1595. Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary;
  1596. Ext.ux.GroupTab = Ext.extend(Ext.Container, {
  1597.     mainItem: 0,
  1598.     
  1599.     expanded: true,
  1600.     
  1601.     deferredRender: true,
  1602.     
  1603.     activeTab: null,
  1604.     
  1605.     idDelimiter: '__',
  1606.     
  1607.     headerAsText: false,
  1608.     
  1609.     frame: false,
  1610.     
  1611.     hideBorders: true,
  1612.     
  1613.     initComponent: function(config){
  1614.         Ext.apply(this, config);
  1615.         this.frame = false;
  1616.         
  1617.         Ext.ux.GroupTab.superclass.initComponent.call(this);
  1618.         
  1619.         this.addEvents('activate', 'deactivate', 'changemainitem', 'beforetabchange', 'tabchange');
  1620.         
  1621.         this.setLayout(new Ext.layout.CardLayout({
  1622.             deferredRender: this.deferredRender
  1623.         }));
  1624.         
  1625.         if (!this.stack) {
  1626.             this.stack = Ext.TabPanel.AccessStack();
  1627.         }
  1628.         
  1629.         this.initItems();
  1630.         
  1631.         this.on('beforerender', function(){
  1632.             this.groupEl = this.ownerCt.getGroupEl(this);
  1633.         }, this);
  1634.         
  1635.         this.on('add', this.onAdd, this, {
  1636.             target: this
  1637.         });
  1638.         this.on('remove', this.onRemove, this, {
  1639.             target: this
  1640.         });
  1641.         
  1642.         if (this.mainItem !== undefined) {
  1643.             var item = (typeof this.mainItem == 'object') ? this.mainItem : this.items.get(this.mainItem);
  1644.             delete this.mainItem;
  1645.             this.setMainItem(item);
  1646.         }
  1647.     },
  1648.     
  1649.     /**
  1650.      * Sets the specified tab as the active tab. This method fires the {@link #beforetabchange} event which
  1651.      * can return false to cancel the tab change.
  1652.      * @param {String/Panel} tab The id or tab Panel to activate
  1653.      */
  1654.     setActiveTab : function(item){
  1655.         item = this.getComponent(item);
  1656.         if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
  1657.             return;
  1658.         }
  1659.         if(!this.rendered){
  1660.             this.activeTab = item;
  1661.             return;
  1662.         }
  1663.         if(this.activeTab != item){
  1664.             if(this.activeTab && this.activeTab != this.mainItem){
  1665.                 var oldEl = this.getTabEl(this.activeTab);
  1666.                 if(oldEl){
  1667.                     Ext.fly(oldEl).removeClass('x-grouptabs-strip-active');
  1668.                 }
  1669.                 this.activeTab.fireEvent('deactivate', this.activeTab);
  1670.             }
  1671.             var el = this.getTabEl(item);
  1672.             Ext.fly(el).addClass('x-grouptabs-strip-active');
  1673.             this.activeTab = item;
  1674.             this.stack.add(item);
  1675.             this.layout.setActiveItem(item);
  1676.             if(this.layoutOnTabChange && item.doLayout){
  1677.                 item.doLayout();
  1678.             }
  1679.             if(this.scrolling){
  1680.                 this.scrollToTab(item, this.animScroll);
  1681.             }
  1682.             item.fireEvent('activate', item);
  1683.             this.fireEvent('tabchange', this, item);
  1684.         }
  1685.     },
  1686.     
  1687.     getTabEl: function(item){
  1688.         if (item == this.mainItem) {
  1689.             return this.groupEl;
  1690.         }
  1691.         return Ext.TabPanel.prototype.getTabEl.call(this, item);
  1692.     },
  1693.     
  1694.     onRender: function(ct, position){
  1695.         Ext.ux.GroupTab.superclass.onRender.call(this, ct, position);
  1696.         
  1697.         this.strip = Ext.fly(this.groupEl).createChild({
  1698.             tag: 'ul',
  1699.             cls: 'x-grouptabs-sub'
  1700.         });
  1701.         this.tooltip = new Ext.ToolTip({
  1702.            target: this.groupEl,
  1703.            delegate: 'a.x-grouptabs-text',
  1704.            trackMouse: true,
  1705.            renderTo: document.body,
  1706.            listeners: {
  1707.                beforeshow: function(tip) {
  1708.                    var item = (tip.triggerElement.parentNode === this.mainItem.tabEl)
  1709.                        ? this.mainItem
  1710.                        : this.findById(tip.triggerElement.parentNode.id.split(this.idDelimiter)[1]);
  1711.                    if(!item.tabTip) {
  1712.                        return false;
  1713.                    }
  1714.                    tip.body.dom.innerHTML = item.tabTip;
  1715.                },
  1716.                scope: this
  1717.            }
  1718.         });
  1719.                 
  1720.         if (!this.itemTpl) {
  1721.             var tt = new Ext.Template('<li class="{cls}" id="{id}">', '<a onclick="return false;" class="x-grouptabs-text {iconCls}">{text}</a>', '</li>');
  1722.             tt.disableFormats = true;
  1723.             tt.compile();
  1724.             Ext.ux.GroupTab.prototype.itemTpl = tt;
  1725.         }
  1726.         
  1727.         this.items.each(this.initTab, this);
  1728.     },
  1729.     
  1730.     afterRender: function(){
  1731.         Ext.ux.GroupTab.superclass.afterRender.call(this);
  1732.         
  1733.         if (this.activeTab !== undefined) {
  1734.             var item = (typeof this.activeTab == 'object') ? this.activeTab : this.items.get(this.activeTab);
  1735.             delete this.activeTab;
  1736.             this.setActiveTab(item);
  1737.         }
  1738.     },
  1739.     
  1740.     // private
  1741.     initTab: function(item, index){
  1742.         var before = this.strip.dom.childNodes[index];
  1743.         var p = Ext.TabPanel.prototype.getTemplateArgs.call(this, item);
  1744.         
  1745.         if (item === this.mainItem) {
  1746.             item.tabEl = this.groupEl;
  1747.             p.cls += ' x-grouptabs-main-item';
  1748.         }
  1749.         
  1750.         var el = before ? this.itemTpl.insertBefore(before, p) : this.itemTpl.append(this.strip, p);
  1751.         
  1752.         item.tabEl = item.tabEl || el;
  1753.                 
  1754.         item.on('disable', this.onItemDisabled, this);
  1755.         item.on('enable', this.onItemEnabled, this);
  1756.         item.on('titlechange', this.onItemTitleChanged, this);
  1757.         item.on('iconchange', this.onItemIconChanged, this);
  1758.         item.on('beforeshow', this.onBeforeShowItem, this);
  1759.     },
  1760.     
  1761.     setMainItem: function(item){
  1762.         item = this.getComponent(item);
  1763.         if (!item || this.fireEvent('changemainitem', this, item, this.mainItem) === false) {
  1764.             return;
  1765.         }
  1766.         
  1767.         this.mainItem = item;
  1768.     },
  1769.     
  1770.     getMainItem: function(){
  1771.         return this.mainItem || null;
  1772.     },
  1773.     
  1774.     // private
  1775.     onBeforeShowItem: function(item){
  1776.         if (item != this.activeTab) {
  1777.             this.setActiveTab(item);
  1778.             return false;
  1779.         }
  1780.     },
  1781.     
  1782.     // private
  1783.     onAdd: function(gt, item, index){
  1784.         if (this.rendered) {
  1785.             this.initTab.call(this, item, index);
  1786.         }
  1787.     },
  1788.     
  1789.     // private
  1790.     onRemove: function(tp, item){
  1791.         Ext.destroy(Ext.get(this.getTabEl(item)));
  1792.         this.stack.remove(item);
  1793.         item.un('disable', this.onItemDisabled, this);
  1794.         item.un('enable', this.onItemEnabled, this);
  1795.         item.un('titlechange', this.onItemTitleChanged, this);
  1796.         item.un('iconchange', this.onItemIconChanged, this);
  1797.         item.un('beforeshow', this.onBeforeShowItem, this);
  1798.         if (item == this.activeTab) {
  1799.             var next = this.stack.next();
  1800.             if (next) {
  1801.                 this.setActiveTab(next);
  1802.             }
  1803.             else if (this.items.getCount() > 0) {
  1804.                 this.setActiveTab(0);
  1805.             }
  1806.             else {
  1807.                 this.activeTab = null;
  1808.             }
  1809.         }
  1810.     },
  1811.     
  1812.     // private
  1813.     onBeforeAdd: function(item){
  1814.         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
  1815.         if (existing) {
  1816.             this.setActiveTab(item);
  1817.             return false;
  1818.         }
  1819.         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
  1820.         var es = item.elements;
  1821.         item.elements = es ? es.replace(',header', '') : es;
  1822.         item.border = (item.border === true);
  1823.     },
  1824.     
  1825.     // private
  1826.     onItemDisabled: Ext.TabPanel.prototype.onItemDisabled,
  1827.     onItemEnabled: Ext.TabPanel.prototype.onItemEnabled,
  1828.     
  1829.     // private
  1830.     onItemTitleChanged: function(item){
  1831.         var el = this.getTabEl(item);
  1832.         if (el) {
  1833.             Ext.fly(el).child('a.x-grouptabs-text', true).innerHTML = item.title;
  1834.         }
  1835.     },
  1836.     
  1837.     //private
  1838.     onItemIconChanged: function(item, iconCls, oldCls){
  1839.         var el = this.getTabEl(item);
  1840.         if (el) {
  1841.             Ext.fly(el).child('a.x-grouptabs-text').replaceClass(oldCls, iconCls);
  1842.         }
  1843.     },
  1844.     
  1845.     beforeDestroy: function(){
  1846.         Ext.TabPanel.prototype.beforeDestroy.call(this);
  1847.         this.tooltip.destroy();
  1848.     }
  1849. });
  1850. Ext.reg('grouptab', Ext.ux.GroupTab);
  1851. Ext.ns('Ext.ux');
  1852. Ext.ux.GroupTabPanel = Ext.extend(Ext.TabPanel, {
  1853.     tabPosition: 'left',
  1854.     
  1855.     alternateColor: false,
  1856.     
  1857.     alternateCls: 'x-grouptabs-panel-alt',
  1858.     
  1859.     defaultType: 'grouptab',
  1860.     
  1861.     deferredRender: false,
  1862.     
  1863.     activeGroup : null,
  1864.     
  1865.     initComponent: function(){
  1866.         Ext.ux.GroupTabPanel.superclass.initComponent.call(this);
  1867.         
  1868.         this.addEvents(
  1869.             'beforegroupchange',
  1870.             'groupchange'
  1871.         );
  1872.         this.elements = 'body,header';
  1873.         this.stripTarget = 'header';
  1874.         
  1875.         this.tabPosition = this.tabPosition == 'right' ? 'right' : 'left';
  1876.         
  1877.         this.addClass('x-grouptabs-panel');
  1878.         
  1879.         if (this.tabStyle && this.tabStyle != '') {
  1880.             this.addClass('x-grouptabs-panel-' + this.tabStyle);
  1881.         }
  1882.         
  1883.         if (this.alternateColor) {
  1884.             this.addClass(this.alternateCls);
  1885.         }
  1886.         
  1887.         this.on('beforeadd', function(gtp, item, index){
  1888.             this.initGroup(item, index);
  1889.         });      
  1890.     },
  1891.     
  1892.     initEvents : function() {
  1893.         this.mon(this.strip, 'mousedown', this.onStripMouseDown, this);
  1894.     },
  1895.         
  1896.     onRender: function(ct, position){
  1897.         Ext.TabPanel.superclass.onRender.call(this, ct, position);
  1898.         if(this.plain){
  1899.             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
  1900.             this[pos].addClass('x-tab-panel-'+pos+'-plain');
  1901.         }
  1902.         var st = this[this.stripTarget];
  1903.         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap ', cn:{
  1904.             tag:'ul', cls:'x-grouptabs-strip x-grouptabs-tab-strip-'+this.tabPosition}});
  1905.         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
  1906.         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
  1907. this.header.addClass('x-grouptabs-panel-header');
  1908. this.bwrap.addClass('x-grouptabs-bwrap');
  1909.         this.body.addClass('x-tab-panel-body-'+this.tabPosition + ' x-grouptabs-panel-body');
  1910.         if (!this.itemTpl) {
  1911.             var tt = new Ext.Template(
  1912.                 '<li class="{cls}" id="{id}">', 
  1913.                 '<a class="x-grouptabs-expand" onclick="return false;"></a>', 
  1914.                 '<a class="x-grouptabs-text {iconCls}" href="#" onclick="return false;">',
  1915.                 '<span>{text}</span></a>', 
  1916.                 '</li>'
  1917.             );
  1918.             tt.disableFormats = true;
  1919.             tt.compile();
  1920.             Ext.ux.GroupTabPanel.prototype.itemTpl = tt;
  1921.         }
  1922.         this.items.each(this.initGroup, this);
  1923.     },
  1924.     
  1925.     afterRender: function(){
  1926.         Ext.ux.GroupTabPanel.superclass.afterRender.call(this);
  1927.         
  1928.         this.tabJoint = Ext.fly(this.body.dom.parentNode).createChild({
  1929.             cls: 'x-tab-joint'
  1930.         });
  1931.         
  1932.         this.addClass('x-tab-panel-' + this.tabPosition);
  1933.         this.header.setWidth(this.tabWidth);
  1934.         
  1935.         if (this.activeGroup !== undefined) {
  1936.             var group = (typeof this.activeGroup == 'object') ? this.activeGroup : this.items.get(this.activeGroup);
  1937.             delete this.activeGroup;
  1938.             this.setActiveGroup(group);
  1939.             group.setActiveTab(group.getMainItem());
  1940.         }
  1941.     },
  1942.     getGroupEl : Ext.TabPanel.prototype.getTabEl,
  1943.         
  1944.     // private
  1945.     findTargets: function(e){
  1946.         var item = null;
  1947.         var itemEl = e.getTarget('li', this.strip);
  1948.         if (itemEl) {
  1949.             item = this.findById(itemEl.id.split(this.idDelimiter)[1]);
  1950.             if (item.disabled) {
  1951.                 return {
  1952.                     expand: null,
  1953.                     item: null,
  1954.                     el: null
  1955.                 };
  1956.             }
  1957.         }
  1958.         return {
  1959.             expand: e.getTarget('.x-grouptabs-expand', this.strip),
  1960.             isGroup: !e.getTarget('ul.x-grouptabs-sub', this.strip),
  1961.             item: item,
  1962.             el: itemEl
  1963.         };
  1964.     },
  1965.     
  1966.     // private
  1967.     onStripMouseDown: function(e){
  1968.         if (e.button != 0) {
  1969.             return;
  1970.         }
  1971.         e.preventDefault();
  1972.         var t = this.findTargets(e);
  1973.         if (t.expand) {
  1974.             this.toggleGroup(t.el);
  1975.         }
  1976.         else if (t.item) {
  1977.             if(t.isGroup) {
  1978.                 t.item.setActiveTab(t.item.getMainItem());
  1979.             }
  1980.             else {
  1981.                 t.item.ownerCt.setActiveTab(t.item);
  1982.             }
  1983.         }
  1984.     },
  1985.     
  1986.     expandGroup: function(groupEl){
  1987.         if(groupEl.isXType) {
  1988.             groupEl = this.getGroupEl(groupEl);
  1989.         }
  1990.         Ext.fly(groupEl).addClass('x-grouptabs-expanded');
  1991.     },
  1992.     
  1993.     toggleGroup: function(groupEl){
  1994.         if(groupEl.isXType) {
  1995.             groupEl = this.getGroupEl(groupEl);
  1996.         }        
  1997.         Ext.fly(groupEl).toggleClass('x-grouptabs-expanded');
  1998. this.syncTabJoint();
  1999.     },    
  2000.     
  2001.     syncTabJoint: function(groupEl){
  2002.         if (!this.tabJoint) {
  2003.             return;
  2004.         }
  2005.         
  2006.         groupEl = groupEl || this.getGroupEl(this.activeGroup);
  2007.         if(groupEl) {
  2008.             this.tabJoint.setHeight(Ext.fly(groupEl).getHeight() - 2); 
  2009.             var y = Ext.isGecko2 ? 0 : 1;
  2010.             if (this.tabPosition == 'left'){
  2011.                 this.tabJoint.alignTo(groupEl, 'tl-tr', [-2,y]);
  2012.             }
  2013.             else {
  2014.                 this.tabJoint.alignTo(groupEl, 'tr-tl', [1,y]);
  2015.             }           
  2016.         }
  2017.         else {
  2018.             this.tabJoint.hide();
  2019.         }
  2020.     },
  2021.     
  2022.     getActiveTab : function() {
  2023.         if(!this.activeGroup) return null;
  2024.         return this.activeGroup.getTabEl(this.activeGroup.activeTab) || null;  
  2025.     },
  2026.     
  2027.     onResize: function(){
  2028.         Ext.ux.GroupTabPanel.superclass.onResize.apply(this, arguments);
  2029.         this.syncTabJoint();
  2030.     },
  2031.     
  2032.     createCorner: function(el, pos){
  2033.         return Ext.fly(el).createChild({
  2034.             cls: 'x-grouptabs-corner x-grouptabs-corner-' + pos
  2035.         });
  2036.     },
  2037.     
  2038.     initGroup: function(group, index){
  2039.         var before = this.strip.dom.childNodes[index];        
  2040.         var p = this.getTemplateArgs(group);
  2041.         if (index === 0) {
  2042.             p.cls += ' x-tab-first';
  2043.         }
  2044.         p.cls += ' x-grouptabs-main';
  2045.         p.text = group.getMainItem().title;
  2046.         
  2047.         var el = before ? this.itemTpl.insertBefore(before, p) : this.itemTpl.append(this.strip, p);
  2048.         
  2049.         var tl = this.createCorner(el, 'top-' + this.tabPosition);
  2050.         var bl = this.createCorner(el, 'bottom-' + this.tabPosition);
  2051.         if (group.expanded) {
  2052.             this.expandGroup(el);
  2053.         }
  2054.         if (Ext.isIE6 || (Ext.isIE && !Ext.isStrict)){
  2055.             bl.setLeft('-10px');
  2056.             bl.setBottom('-5px');
  2057.             tl.setLeft('-10px');
  2058.             tl.setTop('-5px');
  2059.         }
  2060.         this.mon(group, 'changemainitem', this.onGroupChangeMainItem, this);
  2061.         this.mon(group, 'beforetabchange', this.onGroupBeforeTabChange, this);
  2062.     },
  2063.     
  2064.     setActiveGroup : function(group) {
  2065.         group = this.getComponent(group);
  2066.         if(!group || this.fireEvent('beforegroupchange', this, group, this.activeGroup) === false){
  2067.             return;
  2068.         }
  2069.         if(!this.rendered){
  2070.             this.activeGroup = group;
  2071.             return;
  2072.         }
  2073.         if(this.activeGroup != group){
  2074.             if(this.activeGroup){
  2075.                 var oldEl = this.getGroupEl(this.activeGroup);
  2076.                 if(oldEl){
  2077.                     Ext.fly(oldEl).removeClass('x-grouptabs-strip-active');
  2078.                 }
  2079.                 this.activeGroup.fireEvent('deactivate', this.activeTab);
  2080.             }
  2081.             var groupEl = this.getGroupEl(group);
  2082.             Ext.fly(groupEl).addClass('x-grouptabs-strip-active');
  2083.                         
  2084.             this.activeGroup = group;
  2085.             this.stack.add(group);
  2086.             this.layout.setActiveItem(group);
  2087.             this.syncTabJoint(groupEl);
  2088.             group.fireEvent('activate', group);
  2089.             this.fireEvent('groupchange', this, group);
  2090.         }        
  2091.     },
  2092.     
  2093.     onGroupBeforeTabChange: function(group, newTab, oldTab){
  2094.         if(group !== this.activeGroup || newTab !== oldTab) {
  2095.             this.strip.select('.x-grouptabs-sub > li.x-grouptabs-strip-active', true).removeClass('x-grouptabs-strip-active');
  2096.         } 
  2097.         
  2098.         this.expandGroup(this.getGroupEl(group));
  2099.         this.setActiveGroup(group);
  2100.     },
  2101.     
  2102.     getFrameHeight: function(){
  2103.         var h = this.el.getFrameWidth('tb');
  2104.         h += (this.tbar ? this.tbar.getHeight() : 0) +
  2105.         (this.bbar ? this.bbar.getHeight() : 0);
  2106.         
  2107.         return h;
  2108.     },
  2109.     
  2110.     adjustBodyWidth: function(w){
  2111.         return w - this.tabWidth;
  2112.     }
  2113. });
  2114. Ext.reg('grouptabpanel', Ext.ux.GroupTabPanel);/*
  2115.  * Note that this control will most likely remain as an example, and not as a core Ext form
  2116.  * control.  However, the API will be changing in a future release and so should not yet be
  2117.  * treated as a final, stable API at this time.
  2118.  */
  2119. /**
  2120.  * @class Ext.ux.form.ItemSelector
  2121.  * @extends Ext.form.Field
  2122.  * A control that allows selection of between two Ext.ux.form.MultiSelect controls.
  2123.  *
  2124.  *  @history
  2125.  *    2008-06-19 bpm Original code contributed by Toby Stuart (with contributions from Robert Williams)
  2126.  *
  2127.  * @constructor
  2128.  * Create a new ItemSelector
  2129.  * @param {Object} config Configuration options
  2130.  * @xtype itemselector 
  2131.  */
  2132. Ext.ux.form.ItemSelector = Ext.extend(Ext.form.Field,  {
  2133.     hideNavIcons:false,
  2134.     imagePath:"",
  2135.     iconUp:"up2.gif",
  2136.     iconDown:"down2.gif",
  2137.     iconLeft:"left2.gif",
  2138.     iconRight:"right2.gif",
  2139.     iconTop:"top2.gif",
  2140.     iconBottom:"bottom2.gif",
  2141.     drawUpIcon:true,
  2142.     drawDownIcon:true,
  2143.     drawLeftIcon:true,
  2144.     drawRightIcon:true,
  2145.     drawTopIcon:true,
  2146.     drawBotIcon:true,
  2147.     delimiter:',',
  2148.     bodyStyle:null,
  2149.     border:false,
  2150.     defaultAutoCreate:{tag: "div"},
  2151.     /**
  2152.      * @cfg {Array} multiselects An array of {@link Ext.ux.form.MultiSelect} config objects, with at least all required parameters (e.g., store)
  2153.      */
  2154.     multiselects:null,
  2155.     initComponent: function(){
  2156.         Ext.ux.form.ItemSelector.superclass.initComponent.call(this);
  2157.         this.addEvents({
  2158.             'rowdblclick' : true,
  2159.             'change' : true
  2160.         });
  2161.     },
  2162.     onRender: function(ct, position){
  2163.         Ext.ux.form.ItemSelector.superclass.onRender.call(this, ct, position);
  2164.         // Internal default configuration for both multiselects
  2165.         var msConfig = [{
  2166.             legend: 'Available',
  2167.             draggable: true,
  2168.             droppable: true,
  2169.             width: 100,
  2170.             height: 100
  2171.         },{
  2172.             legend: 'Selected',
  2173.             droppable: true,
  2174.             draggable: true,
  2175.             width: 100,
  2176.             height: 100
  2177.         }];
  2178.         this.fromMultiselect = new Ext.ux.form.MultiSelect(Ext.applyIf(this.multiselects[0], msConfig[0]));
  2179.         this.fromMultiselect.on('dblclick', this.onRowDblClick, this);
  2180.         this.toMultiselect = new Ext.ux.form.MultiSelect(Ext.applyIf(this.multiselects[1], msConfig[1]));
  2181.         this.toMultiselect.on('dblclick', this.onRowDblClick, this);
  2182.         var p = new Ext.Panel({
  2183.             bodyStyle:this.bodyStyle,
  2184.             border:this.border,
  2185.             layout:"table",