Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / source / widgets / grid / GridView.js
diff --git a/source/widgets/grid/GridView.js b/source/widgets/grid/GridView.js
deleted file mode 100644 (file)
index da8f8b2..0000000
+++ /dev/null
@@ -1,1662 +0,0 @@
-/*\r
- * Ext JS Library 2.2.1\r
- * Copyright(c) 2006-2009, Ext JS, LLC.\r
- * licensing@extjs.com\r
- * \r
- * http://extjs.com/license\r
- */\r
-\r
-/**\r
- * @class Ext.grid.GridView\r
- * @extends Ext.util.Observable\r
- * <p>This class encapsulates the user interface of an {@link Ext.grid.GridPanel}.\r
- * Methods of this class may be used to access user interface elements to enable\r
- * special display effects. Do not change the DOM structure of the user interface.</p>\r
- * <p>This class does not provide ways to manipulate the underlying data. The data\r
- * model of a Grid is held in an {@link Ext.data.Store}.</p>\r
- * @constructor\r
- * @param {Object} config\r
- */\r
-Ext.grid.GridView = function(config){\r
-    Ext.apply(this, config);\r
-    // These events are only used internally by the grid components\r
-    this.addEvents(\r
-      /**\r
-         * @event beforerowremoved\r
-         * Internal UI Event. Fired before a row is removed.\r
-         * @param {Ext.grid.GridView} view\r
-         * @param {Number} rowIndex The index of the row to be removed.\r
-         * @param {Ext.data.Record} record The Record to be removed\r
-       */\r
-      "beforerowremoved",\r
-      /**\r
-         * @event beforerowsinserted\r
-         * Internal UI Event. Fired before rows are inserted.\r
-         * @param {Ext.grid.GridView} view\r
-         * @param {Number} firstRow The index of the first row to be inserted.\r
-         * @param {Number} lastRow The index of the last row to be inserted.\r
-       */\r
-      "beforerowsinserted",\r
-      /**\r
-         * @event beforerefresh\r
-         * Internal UI Event. Fired before the view is refreshed.\r
-         * @param {Ext.grid.GridView} view\r
-       */\r
-      "beforerefresh",\r
-      /**\r
-         * @event rowremoved\r
-         * Internal UI Event. Fired after a row is removed.\r
-         * @param {Ext.grid.GridView} view\r
-         * @param {Number} rowIndex The index of the row that was removed.\r
-         * @param {Ext.data.Record} record The Record that was removed\r
-       */\r
-      "rowremoved",\r
-      /**\r
-         * @event rowsinserted\r
-         * Internal UI Event. Fired after rows are inserted.\r
-         * @param {Ext.grid.GridView} view\r
-         * @param {Number} firstRow The index of the first inserted.\r
-         * @param {Number} lastRow The index of the last row inserted.\r
-       */\r
-      "rowsinserted",\r
-      /**\r
-         * @event rowupdated\r
-         * Internal UI Event. Fired after a row has been updated.\r
-         * @param {Ext.grid.GridView} view\r
-         * @param {Number} firstRow The index of the row updated.\r
-         * @param {Ext.data.record} record The Record backing the row updated.\r
-       */\r
-      "rowupdated",\r
-      /**\r
-         * @event refresh\r
-         * Internal UI Event. Fired after the GridView's body has been refreshed.\r
-         * @param {Ext.grid.GridView} view\r
-       */\r
-      "refresh"\r
-  );\r
-    Ext.grid.GridView.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.grid.GridView, Ext.util.Observable, {\r
-    /**\r
-     * Override this function to apply custom CSS classes to rows during rendering.  You can also supply custom\r
-     * parameters to the row template for the current row to customize how it is rendered using the <b>rowParams</b>\r
-     * parameter.  This function should return the CSS class name (or empty string '' for none) that will be added\r
-     * to the row's wrapping div.  To apply multiple class names, simply return them space-delimited within the string\r
-     * (e.g., 'my-class another-class').\r
-     * @param {Record} record The {@link Ext.data.Record} corresponding to the current row\r
-     * @param {Number} index The row index\r
-     * @param {Object} rowParams A config object that is passed to the row template during rendering that allows\r
-     * customization of various aspects of a body row, if applicable.  Note that this object will only be applied if\r
-     * {@link #enableRowBody} = true, otherwise it will be ignored. The object may contain any of these properties:<ul>\r
-     * <li><code>body</code> : String <div class="sub-desc">An HTML fragment to be rendered as the cell's body content (defaults to '').</div></li>\r
-     * <li><code>bodyStyle</code> : String <div class="sub-desc">A CSS style string that will be applied to the row's TR style attribute (defaults to '').</div></li>\r
-     * <li><code>cols</code> : Number <div class="sub-desc">The column count to apply to the body row's TD colspan attribute (defaults to the current\r
-     * column count of the grid).</div></li>\r
-     * </ul>\r
-     * @param {Store} store The {@link Ext.data.Store} this grid is bound to\r
-     * @method getRowClass\r
-     * @return {String} a CSS class name to add to the row.\r
-     */\r
-    /**\r
-     * @cfg {Boolean} enableRowBody True to add a second TR element per row that can be used to provide a row body\r
-     * that spans beneath the data row.  Use the {@link #getRowClass} method's rowParams config to customize the row body.\r
-     */\r
-    /**\r
-     * @cfg {String} emptyText Default text to display in the grid body when no rows are available (defaults to '').\r
-     */\r
-    /**\r
-     * @property dragZone\r
-     * @type Ext.grid.GridDragZone\r
-     * <p><b>This will only be present if the owning GridPanel was configured with {@link Ext.grid.GridPanel#enableDragDrop enableDragDrop} <tt>true</tt>.</b></p>\r
-     * <p><b>This will only be present after the owning GridPanel has been rendered</b>.</p>\r
-     * <p>A customized implementation of a {@link Ext.dd.DragZone DragZone} which provides default implementations of the\r
-     * template methods of DragZone to enable dragging of the selected rows of a GridPanel. See {@link Ext.grid.GridDragZone} for details.</p>\r
-     */\r
-    /**\r
-     * @cfg {Boolean} deferEmptyText True to defer emptyText being applied until the store's first load\r
-     */\r
-    deferEmptyText: true,\r
-    /**\r
-     * The amount of space to reserve for the scrollbar (defaults to 19 pixels)\r
-     * @type Number\r
-     */\r
-    scrollOffset: 19,\r
-    /**\r
-     * @cfg {Boolean} autoFill True to auto expand the columns to fit the grid <b>when the grid is created</b>.\r
-     */\r
-    autoFill: false,\r
-    /**\r
-     * @cfg {Boolean} forceFit True to auto expand/contract the size of the columns to fit the grid width and prevent horizontal scrolling.\r
-     * This option overrides any (@link Ext.grid.ColumnModel#width width} settings in the ColumnModel.\r
-     */\r
-    forceFit: false,\r
-    /**\r
-     * The CSS classes applied to a header when it is sorted. (defaults to ["sort-asc", "sort-desc"])\r
-     * @type Array\r
-     */\r
-    sortClasses : ["sort-asc", "sort-desc"],\r
-    /**\r
-     * The text displayed in the "Sort Ascending" menu item\r
-     * @type String\r
-     */\r
-    sortAscText : "Sort Ascending",\r
-    /**\r
-     * The text displayed in the "Sort Descending" menu item\r
-     * @type String\r
-     */\r
-    sortDescText : "Sort Descending",\r
-    /**\r
-     * The text displayed in the "Columns" menu item\r
-     * @type String\r
-     */\r
-    columnsText : "Columns",\r
-\r
-    // private\r
-    borderWidth: 2,\r
-    tdClass: 'x-grid3-cell',\r
-    hdCls: 'x-grid3-hd',\r
-\r
-    /**\r
-     * @cfg {Number} cellSelectorDepth The number of levels to search for cells in event delegation (defaults to 4)\r
-     */\r
-    cellSelectorDepth: 4,\r
-    /**\r
-     * @cfg {Number} rowSelectorDepth The number of levels to search for rows in event delegation (defaults to 10)\r
-     */\r
-    rowSelectorDepth: 10,\r
-\r
-    /**\r
-     * @cfg {String} cellSelector The selector used to find cells internally\r
-     */\r
-    cellSelector: 'td.x-grid3-cell',\r
-    /**\r
-     * @cfg {String} rowSelector The selector used to find rows internally\r
-     */\r
-    rowSelector: 'div.x-grid3-row',\r
-\r
-    /* -------------------------------- UI Specific ----------------------------- */\r
-\r
-    // private\r
-    initTemplates : function(){\r
-        var ts = this.templates || {};\r
-        if(!ts.master){\r
-            ts.master = new Ext.Template(\r
-                    '<div class="x-grid3" hidefocus="true">',\r
-                        '<div class="x-grid3-viewport">',\r
-                            '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}</div></div><div class="x-clear"></div></div>',\r
-                            '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',\r
-                        "</div>",\r
-                        '<div class="x-grid3-resize-marker">&#160;</div>',\r
-                        '<div class="x-grid3-resize-proxy">&#160;</div>',\r
-                    "</div>"\r
-                    );\r
-        }\r
-\r
-        if(!ts.header){\r
-            ts.header = new Ext.Template(\r
-                    '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
-                    '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',\r
-                    "</table>"\r
-                    );\r
-        }\r
-\r
-        if(!ts.hcell){\r
-            ts.hcell = new Ext.Template(\r
-                    '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',\r
-                    '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',\r
-                    "</div></td>"\r
-                    );\r
-        }\r
-\r
-        if(!ts.body){\r
-            ts.body = new Ext.Template('{rows}');\r
-        }\r
-\r
-        if(!ts.row){\r
-            ts.row = new Ext.Template(\r
-                    '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
-                    '<tbody><tr>{cells}</tr>',\r
-                    (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>' : ''),\r
-                    '</tbody></table></div>'\r
-                    );\r
-        }\r
-\r
-        if(!ts.cell){\r
-            ts.cell = new Ext.Template(\r
-                    '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',\r
-                    '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',\r
-                    "</td>"\r
-                    );\r
-        }\r
-\r
-        for(var k in ts){\r
-            var t = ts[k];\r
-            if(t && typeof t.compile == 'function' && !t.compiled){\r
-                t.disableFormats = true;\r
-                t.compile();\r
-            }\r
-        }\r
-\r
-        this.templates = ts;\r
-        this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");\r
-    },\r
-\r
-    // private\r
-    fly : function(el){\r
-        if(!this._flyweight){\r
-            this._flyweight = new Ext.Element.Flyweight(document.body);\r
-        }\r
-        this._flyweight.dom = el;\r
-        return this._flyweight;\r
-    },\r
-\r
-    // private\r
-    getEditorParent : function(){\r
-        return this.scroller.dom;\r
-    },\r
-\r
-    // private\r
-    initElements : function(){\r
-        var E = Ext.Element;\r
-\r
-        var el = this.grid.getGridEl().dom.firstChild;\r
-        var cs = el.childNodes;\r
-\r
-        this.el = new E(el);\r
-\r
-        this.mainWrap = new E(cs[0]);\r
-        this.mainHd = new E(this.mainWrap.dom.firstChild);\r
-\r
-        if(this.grid.hideHeaders){\r
-            this.mainHd.setDisplayed(false);\r
-        }\r
-\r
-        this.innerHd = this.mainHd.dom.firstChild;\r
-        this.scroller = new E(this.mainWrap.dom.childNodes[1]);\r
-        if(this.forceFit){\r
-            this.scroller.setStyle('overflow-x', 'hidden');\r
-        }\r
-        /**\r
-         * The GridView's body Element which encapsulates all rows in the Grid. {@link Ext.Element Element}. Read-only.\r
-         * <p>This Element is only available after the GridPanel has been rendered.</p>\r
-         * @type Ext.Element\r
-         * @property mainBody\r
-         */\r
-        this.mainBody = new E(this.scroller.dom.firstChild);\r
-\r
-        this.focusEl = new E(this.scroller.dom.childNodes[1]);\r
-        this.focusEl.swallowEvent("click", true);\r
-\r
-        this.resizeMarker = new E(cs[1]);\r
-        this.resizeProxy = new E(cs[2]);\r
-    },\r
-\r
-    // private\r
-    getRows : function(){\r
-        return this.hasRows() ? this.mainBody.dom.childNodes : [];\r
-    },\r
-\r
-    // finder methods, used with delegation\r
-\r
-    // private\r
-    findCell : function(el){\r
-        if(!el){\r
-            return false;\r
-        }\r
-        return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);\r
-    },\r
-\r
-    // private\r
-    findCellIndex : function(el, requiredCls){\r
-        var cell = this.findCell(el);\r
-        if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){\r
-            return this.getCellIndex(cell);\r
-        }\r
-        return false;\r
-    },\r
-\r
-    // private\r
-    getCellIndex : function(el){\r
-        if(el){\r
-            var m = el.className.match(this.colRe);\r
-            if(m && m[1]){\r
-                return this.cm.getIndexById(m[1]);\r
-            }\r
-        }\r
-        return false;\r
-    },\r
-\r
-    // private\r
-    findHeaderCell : function(el){\r
-        var cell = this.findCell(el);\r
-        return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;\r
-    },\r
-\r
-    // private\r
-    findHeaderIndex : function(el){\r
-        return this.findCellIndex(el, this.hdCls);\r
-    },\r
-\r
-/**\r
- * Return the HtmlElement representing the grid row which contains the passed element.\r
- * @param {Element} el The target element\r
- * @return The row element, or null if the target element is not within a row of this GridView.\r
- */\r
-    findRow : function(el){\r
-        if(!el){\r
-            return false;\r
-        }\r
-        return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);\r
-    },\r
-\r
-/**\r
- * Return the index of the grid row which contains the passed element.\r
- * @param {Element} el The target element\r
- * @return The row index, or <b>false</b> if the target element is not within a row of this GridView.\r
- */\r
-    findRowIndex : function(el){\r
-        var r = this.findRow(el);\r
-        return r ? r.rowIndex : false;\r
-    },\r
-\r
-    // getter methods for fetching elements dynamically in the grid\r
-\r
-/**\r
- * Return the &lt;TR> HtmlElement which represents a Grid row for the specified index.\r
- * @param {Number} index The row index\r
- * @return {HtmlElement} The &lt;TR> element.\r
- */\r
-    getRow : function(row){\r
-        return this.getRows()[row];\r
-    },\r
-\r
-/**\r
- * Returns the grid's &lt;TD> HtmlElement at the specified coordinates.\r
- * @param {Number} row The row index in which to find the cell.\r
- * @param {Number} col The column index of the cell.\r
- * @return {HtmlElement} The &lt;TD> at the specified coordinates.\r
- */\r
-    getCell : function(row, col){\r
-        return this.getRow(row).getElementsByTagName('td')[col];\r
-    },\r
-\r
-/**\r
- * Return the &lt;TD> HtmlElement which represents the Grid's header cell for the specified column index.\r
- * @param {Number} index The column index\r
- * @return {HtmlElement} The &lt;TD> element.\r
- */\r
-    getHeaderCell : function(index){\r
-      return this.mainHd.dom.getElementsByTagName('td')[index];\r
-    },\r
-\r
-    // manipulating elements\r
-\r
-    // private - use getRowClass to apply custom row classes\r
-    addRowClass : function(row, cls){\r
-        var r = this.getRow(row);\r
-        if(r){\r
-            this.fly(r).addClass(cls);\r
-        }\r
-    },\r
-\r
-    // private\r
-    removeRowClass : function(row, cls){\r
-        var r = this.getRow(row);\r
-        if(r){\r
-            this.fly(r).removeClass(cls);\r
-        }\r
-    },\r
-\r
-    // private\r
-    removeRow : function(row){\r
-        Ext.removeNode(this.getRow(row));\r
-        this.syncFocusEl(row);\r
-    },\r
-    \r
-    // private\r
-    removeRows : function(firstRow, lastRow){\r
-        var bd = this.mainBody.dom;\r
-        for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){\r
-            Ext.removeNode(bd.childNodes[firstRow]);\r
-        }\r
-        this.syncFocusEl(firstRow);\r
-    },\r
-\r
-    // scrolling stuff\r
-\r
-    // private\r
-    getScrollState : function(){\r
-        var sb = this.scroller.dom;\r
-        return {left: sb.scrollLeft, top: sb.scrollTop};\r
-    },\r
-\r
-    // private\r
-    restoreScroll : function(state){\r
-        var sb = this.scroller.dom;\r
-        sb.scrollLeft = state.left;\r
-        sb.scrollTop = state.top;\r
-    },\r
-\r
-    /**\r
-     * Scrolls the grid to the top\r
-     */\r
-    scrollToTop : function(){\r
-        this.scroller.dom.scrollTop = 0;\r
-        this.scroller.dom.scrollLeft = 0;\r
-    },\r
-\r
-    // private\r
-    syncScroll : function(){\r
-      this.syncHeaderScroll();\r
-      var mb = this.scroller.dom;\r
-        this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);\r
-    },\r
-\r
-    // private\r
-    syncHeaderScroll : function(){\r
-        var mb = this.scroller.dom;\r
-        this.innerHd.scrollLeft = mb.scrollLeft;\r
-        this.innerHd.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)\r
-    },\r
-\r
-    // private\r
-    updateSortIcon : function(col, dir){\r
-        var sc = this.sortClasses;\r
-        var hds = this.mainHd.select('td').removeClass(sc);\r
-        hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);\r
-    },\r
-\r
-    // private\r
-    updateAllColumnWidths : function(){\r
-        var tw = this.getTotalWidth();\r
-        var clen = this.cm.getColumnCount();\r
-        var ws = [];\r
-        for(var i = 0; i < clen; i++){\r
-            ws[i] = this.getColumnWidth(i);\r
-        }\r
-\r
-        this.innerHd.firstChild.firstChild.style.width = tw;\r
-\r
-        for(var i = 0; i < clen; i++){\r
-            var hd = this.getHeaderCell(i);\r
-            hd.style.width = ws[i];\r
-        }\r
-\r
-        var ns = this.getRows(), row, trow;\r
-        for(var i = 0, len = ns.length; i < len; i++){\r
-            row = ns[i];\r
-            row.style.width = tw;\r
-            if(row.firstChild){\r
-                row.firstChild.style.width = tw;\r
-                trow = row.firstChild.rows[0];\r
-                for (var j = 0; j < clen; j++) {\r
-                   trow.childNodes[j].style.width = ws[j];\r
-                }\r
-            }\r
-        }\r
-\r
-        this.onAllColumnWidthsUpdated(ws, tw);\r
-    },\r
-\r
-    // private\r
-    updateColumnWidth : function(col, width){\r
-        var w = this.getColumnWidth(col);\r
-        var tw = this.getTotalWidth();\r
-\r
-        this.innerHd.firstChild.firstChild.style.width = tw;\r
-        var hd = this.getHeaderCell(col);\r
-        hd.style.width = w;\r
-\r
-        var ns = this.getRows(), row;\r
-        for(var i = 0, len = ns.length; i < len; i++){\r
-            row = ns[i];\r
-            row.style.width = tw;\r
-            if(row.firstChild){\r
-                row.firstChild.style.width = tw;\r
-                row.firstChild.rows[0].childNodes[col].style.width = w;\r
-            }\r
-        }\r
-\r
-        this.onColumnWidthUpdated(col, w, tw);\r
-    },\r
-\r
-    // private\r
-    updateColumnHidden : function(col, hidden){\r
-        var tw = this.getTotalWidth();\r
-\r
-        this.innerHd.firstChild.firstChild.style.width = tw;\r
-\r
-        var display = hidden ? 'none' : '';\r
-\r
-        var hd = this.getHeaderCell(col);\r
-        hd.style.display = display;\r
-\r
-        var ns = this.getRows(), row;\r
-        for(var i = 0, len = ns.length; i < len; i++){\r
-            row = ns[i];\r
-            row.style.width = tw;\r
-            if(row.firstChild){\r
-                row.firstChild.style.width = tw;\r
-                row.firstChild.rows[0].childNodes[col].style.display = display;\r
-            }\r
-        }\r
-\r
-        this.onColumnHiddenUpdated(col, hidden, tw);\r
-\r
-        delete this.lastViewWidth; // force recalc\r
-        this.layout();\r
-    },\r
-\r
-    // private\r
-    doRender : function(cs, rs, ds, startRow, colCount, stripe){\r
-        var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;\r
-        var tstyle = 'width:'+this.getTotalWidth()+';';\r
-        // buffers\r
-        var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;\r
-        for(var j = 0, len = rs.length; j < len; j++){\r
-            r = rs[j]; cb = [];\r
-            var rowIndex = (j+startRow);\r
-            for(var i = 0; i < colCount; i++){\r
-                c = cs[i];\r
-                p.id = c.id;\r
-                p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
-                p.attr = p.cellAttr = "";\r
-                p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);\r
-                p.style = c.style;\r
-                if(p.value == undefined || p.value === "") p.value = "&#160;";\r
-                if(r.dirty && typeof r.modified[c.name] !== 'undefined'){\r
-                    p.css += ' x-grid3-dirty-cell';\r
-                }\r
-                cb[cb.length] = ct.apply(p);\r
-            }\r
-            var alt = [];\r
-            if(stripe && ((rowIndex+1) % 2 == 0)){\r
-                alt[0] = "x-grid3-row-alt";\r
-            }\r
-            if(r.dirty){\r
-                alt[1] = " x-grid3-dirty-row";\r
-            }\r
-            rp.cols = colCount;\r
-            if(this.getRowClass){\r
-                alt[2] = this.getRowClass(r, rowIndex, rp, ds);\r
-            }\r
-            rp.alt = alt.join(" ");\r
-            rp.cells = cb.join("");\r
-            buf[buf.length] =  rt.apply(rp);\r
-        }\r
-        return buf.join("");\r
-    },\r
-\r
-    // private\r
-    processRows : function(startRow, skipStripe){\r
-        if(this.ds.getCount() < 1){\r
-            return;\r
-        }\r
-        skipStripe = skipStripe || !this.grid.stripeRows;\r
-        startRow = startRow || 0;\r
-        var rows = this.getRows();\r
-        var cls = ' x-grid3-row-alt ';\r
-        rows[0].className += ' x-grid3-row-first';\r
-        rows[rows.length - 1].className += ' x-grid3-row-last';\r
-        for(var i = startRow, len = rows.length; i < len; i++){\r
-            var row = rows[i];\r
-            row.rowIndex = i;\r
-            if(!skipStripe){\r
-                var isAlt = ((i+1) % 2 == 0);\r
-                var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;\r
-                if(isAlt == hasAlt){\r
-                    continue;\r
-                }\r
-                if(isAlt){\r
-                    row.className += " x-grid3-row-alt";\r
-                }else{\r
-                    row.className = row.className.replace("x-grid3-row-alt", "");\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    afterRender: function(){\r
-        this.mainBody.dom.innerHTML = this.renderRows();\r
-        this.processRows(0, true);\r
-\r
-        if(this.deferEmptyText !== true){\r
-            this.applyEmptyText();\r
-        }\r
-    },\r
-\r
-    // private\r
-    renderUI : function(){\r
-\r
-        var header = this.renderHeaders();\r
-        var body = this.templates.body.apply({rows:''});\r
-\r
-\r
-        var html = this.templates.master.apply({\r
-            body: body,\r
-            header: header\r
-        });\r
-\r
-        var g = this.grid;\r
-\r
-        g.getGridEl().dom.innerHTML = html;\r
-\r
-        this.initElements();\r
-\r
-        // get mousedowns early\r
-        Ext.fly(this.innerHd).on("click", this.handleHdDown, this);\r
-        this.mainHd.on("mouseover", this.handleHdOver, this);\r
-        this.mainHd.on("mouseout", this.handleHdOut, this);\r
-        this.mainHd.on("mousemove", this.handleHdMove, this);\r
-\r
-        this.scroller.on('scroll', this.syncScroll,  this);\r
-        if(g.enableColumnResize !== false){\r
-            this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);\r
-        }\r
-\r
-        if(g.enableColumnMove){\r
-            this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);\r
-            this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);\r
-        }\r
-\r
-        if(g.enableHdMenu !== false){\r
-            if(g.enableColumnHide !== false){\r
-                this.colMenu = new Ext.menu.Menu({id:g.id + "-hcols-menu"});\r
-                this.colMenu.on("beforeshow", this.beforeColMenuShow, this);\r
-                this.colMenu.on("itemclick", this.handleHdMenuClick, this);\r
-            }\r
-            this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});\r
-            this.hmenu.add(\r
-                {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},\r
-                {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}\r
-            );\r
-            if(g.enableColumnHide !== false){\r
-                this.hmenu.add('-',\r
-                    {id:"columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon'}\r
-                );\r
-            }\r
-            this.hmenu.on("itemclick", this.handleHdMenuClick, this);\r
-\r
-            //g.on("headercontextmenu", this.handleHdCtx, this);\r
-        }\r
-\r
-        if(g.trackMouseOver){\r
-            this.mainBody.on("mouseover", this.onRowOver, this);\r
-            this.mainBody.on("mouseout", this.onRowOut, this);\r
-        }\r
-        if(g.enableDragDrop || g.enableDrag){\r
-            this.dragZone = new Ext.grid.GridDragZone(g, {\r
-                ddGroup : g.ddGroup || 'GridDD'\r
-            });\r
-        }\r
-\r
-        this.updateHeaderSortState();\r
-\r
-    },\r
-\r
-    // private\r
-    layout : function(){\r
-        if(!this.mainBody){\r
-            return; // not rendered\r
-        }\r
-        var g = this.grid;\r
-        var c = g.getGridEl();\r
-        var csize = c.getSize(true);\r
-        var vw = csize.width;\r
-\r
-        if(vw < 20 || csize.height < 20){ // display: none?\r
-            return;\r
-        }\r
-\r
-        if(g.autoHeight){\r
-            this.scroller.dom.style.overflow = 'visible';\r
-            if(Ext.isSafari){\r
-                this.scroller.dom.style.position = 'static';\r
-            }\r
-        }else{\r
-            this.el.setSize(csize.width, csize.height);\r
-\r
-            var hdHeight = this.mainHd.getHeight();\r
-            var vh = csize.height - (hdHeight);\r
-\r
-            this.scroller.setSize(vw, vh);\r
-            if(this.innerHd){\r
-                this.innerHd.style.width = (vw)+'px';\r
-            }\r
-        }\r
-        if(this.forceFit){\r
-            if(this.lastViewWidth != vw){\r
-                this.fitColumns(false, false);\r
-                this.lastViewWidth = vw;\r
-            }\r
-        }else {\r
-            this.autoExpand();\r
-            this.syncHeaderScroll();\r
-        }\r
-        this.onLayout(vw, vh);\r
-    },\r
-\r
-    // template functions for subclasses and plugins\r
-    // these functions include precalculated values\r
-    onLayout : function(vw, vh){\r
-        // do nothing\r
-    },\r
-\r
-    onColumnWidthUpdated : function(col, w, tw){\r
-        //template method\r
-        this.focusEl.setWidth(tw);\r
-    },\r
-\r
-    onAllColumnWidthsUpdated : function(ws, tw){\r
-        //template method\r
-        this.focusEl.setWidth(tw);\r
-    },\r
-\r
-    onColumnHiddenUpdated : function(col, hidden, tw){\r
-        // template method\r
-        this.focusEl.setWidth(tw);\r
-    },\r
-\r
-    updateColumnText : function(col, text){\r
-        // template method\r
-    },\r
-\r
-    afterMove : function(colIndex){\r
-        // template method\r
-    },\r
-\r
-    /* ----------------------------------- Core Specific -------------------------------------------*/\r
-    // private\r
-    init: function(grid){\r
-        this.grid = grid;\r
-\r
-        this.initTemplates();\r
-        this.initData(grid.store, grid.colModel);\r
-        this.initUI(grid);\r
-    },\r
-\r
-    // private\r
-    getColumnId : function(index){\r
-      return this.cm.getColumnId(index);\r
-    },\r
-\r
-    // private\r
-    renderHeaders : function(){\r
-        var cm = this.cm, ts = this.templates;\r
-        var ct = ts.hcell;\r
-\r
-        var cb = [], sb = [], p = {};\r
-        var len = cm.getColumnCount();\r
-        var last = len - 1;\r
-        for(var i = 0; i < len; i++){\r
-            p.id = cm.getColumnId(i);\r
-            p.value = cm.getColumnHeader(i) || "";\r
-            p.style = this.getColumnStyle(i, true);\r
-            p.tooltip = this.getColumnTooltip(i);\r
-            p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
-            if(cm.config[i].align == 'right'){\r
-                p.istyle = 'padding-right:16px';\r
-            } else {\r
-                delete p.istyle;\r
-            }\r
-            cb[cb.length] = ct.apply(p);\r
-        }\r
-        return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});\r
-    },\r
-\r
-    // private\r
-    getColumnTooltip : function(i){\r
-        var tt = this.cm.getColumnTooltip(i);\r
-        if(tt){\r
-            if(Ext.QuickTips.isEnabled()){\r
-                return 'ext:qtip="'+tt+'"';\r
-            }else{\r
-                return 'title="'+tt+'"';\r
-            }\r
-        }\r
-        return "";\r
-    },\r
-\r
-    // private\r
-    beforeUpdate : function(){\r
-        this.grid.stopEditing(true);\r
-    },\r
-\r
-    // private\r
-    updateHeaders : function(){\r
-        this.innerHd.firstChild.innerHTML = this.renderHeaders();\r
-    },\r
-\r
-    /**\r
-     * Focuses the specified row.\r
-     * @param {Number} row The row index\r
-     */\r
-    focusRow : function(row){\r
-        this.focusCell(row, 0, false);\r
-    },\r
-\r
-    /**\r
-     * Focuses the specified cell.\r
-     * @param {Number} row The row index\r
-     * @param {Number} col The column index\r
-     */\r
-    focusCell : function(row, col, hscroll){\r
-               this.syncFocusEl(this.ensureVisible(row, col, hscroll));\r
-        if(Ext.isGecko){\r
-            this.focusEl.focus();\r
-        }else{\r
-            this.focusEl.focus.defer(1, this.focusEl);\r
-        }\r
-    },\r
-\r
-       resolveCell : function(row, col, hscroll){\r
-               if(typeof row != "number"){\r
-            row = row.rowIndex;\r
-        }\r
-        if(!this.ds){\r
-            return null;\r
-        }\r
-        if(row < 0 || row >= this.ds.getCount()){\r
-            return null;\r
-        }\r
-        col = (col !== undefined ? col : 0);\r
-\r
-        var rowEl = this.getRow(row), cellEl;\r
-        if(!(hscroll === false && col === 0)){\r
-            while(this.cm.isHidden(col)){\r
-                col++;\r
-            }\r
-            cellEl = this.getCell(row, col);\r
-        }\r
-\r
-               return {row: rowEl, cell: cellEl};\r
-       },\r
-\r
-       getResolvedXY : function(resolved){\r
-               if(!resolved){\r
-                       return null;\r
-               }\r
-               var s = this.scroller.dom, c = resolved.cell, r = resolved.row;\r
-               return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];\r
-       },\r
-\r
-       syncFocusEl : function(row, col, hscroll){\r
-               var xy = row;\r
-               if(!Ext.isArray(xy)){\r
-                       row = Math.min(row, Math.max(0, this.getRows().length-1));\r
-               xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));\r
-               }\r
-        this.focusEl.setXY(xy||this.scroller.getXY());\r
-    },\r
-\r
-       ensureVisible : function(row, col, hscroll){\r
-        var resolved = this.resolveCell(row, col, hscroll);\r
-               if(!resolved || !resolved.row){\r
-                       return;\r
-               }\r
-\r
-               var rowEl = resolved.row, cellEl = resolved.cell;\r
-\r
-               var c = this.scroller.dom;\r
-\r
-        var ctop = 0;\r
-        var p = rowEl, stop = this.el.dom;\r
-        while(p && p != stop){\r
-            ctop += p.offsetTop;\r
-            p = p.offsetParent;\r
-        }\r
-        ctop -= this.mainHd.dom.offsetHeight;\r
-\r
-        var cbot = ctop + rowEl.offsetHeight;\r
-\r
-        var ch = c.clientHeight;\r
-        var stop = parseInt(c.scrollTop, 10);\r
-        var sbot = stop + ch;\r
-\r
-               if(ctop < stop){\r
-          c.scrollTop = ctop;\r
-        }else if(cbot > sbot){\r
-            c.scrollTop = cbot-ch;\r
-        }\r
-\r
-        if(hscroll !== false){\r
-            var cleft = parseInt(cellEl.offsetLeft, 10);\r
-            var cright = cleft + cellEl.offsetWidth;\r
-\r
-            var sleft = parseInt(c.scrollLeft, 10);\r
-            var sright = sleft + c.clientWidth;\r
-            if(cleft < sleft){\r
-                c.scrollLeft = cleft;\r
-            }else if(cright > sright){\r
-                c.scrollLeft = cright-c.clientWidth;\r
-            }\r
-        }\r
-        return this.getResolvedXY(resolved);\r
-    },\r
-\r
-    // private\r
-    insertRows : function(dm, firstRow, lastRow, isUpdate){\r
-        if(!isUpdate && firstRow === 0 && lastRow >= dm.getCount()-1){\r
-            this.refresh();\r
-        }else{\r
-            if(!isUpdate){\r
-                this.fireEvent("beforerowsinserted", this, firstRow, lastRow);\r
-            }\r
-            var html = this.renderRows(firstRow, lastRow);\r
-            var before = this.getRow(firstRow);\r
-            if(before){\r
-                Ext.DomHelper.insertHtml('beforeBegin', before, html);\r
-            }else{\r
-                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);\r
-            }\r
-            if(!isUpdate){\r
-                this.fireEvent("rowsinserted", this, firstRow, lastRow);\r
-                this.processRows(firstRow);\r
-            }\r
-        }\r
-        this.syncFocusEl(firstRow);\r
-    },\r
-\r
-    // private\r
-    deleteRows : function(dm, firstRow, lastRow){\r
-        if(dm.getRowCount()<1){\r
-            this.refresh();\r
-        }else{\r
-            this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);\r
-\r
-            this.removeRows(firstRow, lastRow);\r
-\r
-            this.processRows(firstRow);\r
-            this.fireEvent("rowsdeleted", this, firstRow, lastRow);\r
-        }\r
-    },\r
-\r
-    // private\r
-    getColumnStyle : function(col, isHeader){\r
-        var style = !isHeader ? (this.cm.config[col].css || '') : '';\r
-        style += 'width:'+this.getColumnWidth(col)+';';\r
-        if(this.cm.isHidden(col)){\r
-            style += 'display:none;';\r
-        }\r
-        var align = this.cm.config[col].align;\r
-        if(align){\r
-            style += 'text-align:'+align+';';\r
-        }\r
-        return style;\r
-    },\r
-\r
-    // private\r
-    getColumnWidth : function(col){\r
-        var w = this.cm.getColumnWidth(col);\r
-        if(typeof w == 'number'){\r
-            return (Ext.isBorderBox ? w : (w-this.borderWidth > 0 ? w-this.borderWidth:0)) + 'px';\r
-        }\r
-        return w;\r
-    },\r
-\r
-    // private\r
-    getTotalWidth : function(){\r
-        return this.cm.getTotalWidth()+'px';\r
-    },\r
-\r
-    // private\r
-    fitColumns : function(preventRefresh, onlyExpand, omitColumn){\r
-        var cm = this.cm, leftOver, dist, i;\r
-        var tw = cm.getTotalWidth(false);\r
-        var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;\r
-\r
-        if(aw < 20){ // not initialized, so don't screw up the default widths\r
-            return;\r
-        }\r
-        var extra = aw - tw;\r
-\r
-        if(extra === 0){\r
-            return false;\r
-        }\r
-\r
-        var vc = cm.getColumnCount(true);\r
-        var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);\r
-        if(ac === 0){\r
-            ac = 1;\r
-            omitColumn = undefined;\r
-        }\r
-        var colCount = cm.getColumnCount();\r
-        var cols = [];\r
-        var extraCol = 0;\r
-        var width = 0;\r
-        var w;\r
-        for (i = 0; i < colCount; i++){\r
-            if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){\r
-                w = cm.getColumnWidth(i);\r
-                cols.push(i);\r
-                extraCol = i;\r
-                cols.push(w);\r
-                width += w;\r
-            }\r
-        }\r
-        var frac = (aw - cm.getTotalWidth())/width;\r
-        while (cols.length){\r
-            w = cols.pop();\r
-            i = cols.pop();\r
-            cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);\r
-        }\r
-\r
-        if((tw = cm.getTotalWidth(false)) > aw){\r
-            var adjustCol = ac != vc ? omitColumn : extraCol;\r
-             cm.setColumnWidth(adjustCol, Math.max(1,\r
-                     cm.getColumnWidth(adjustCol)- (tw-aw)), true);\r
-        }\r
-\r
-        if(preventRefresh !== true){\r
-            this.updateAllColumnWidths();\r
-        }\r
-\r
-\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    autoExpand : function(preventUpdate){\r
-        var g = this.grid, cm = this.cm;\r
-        if(!this.userResized && g.autoExpandColumn){\r
-            var tw = cm.getTotalWidth(false);\r
-            var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;\r
-            if(tw != aw){\r
-                var ci = cm.getIndexById(g.autoExpandColumn);\r
-                var currentWidth = cm.getColumnWidth(ci);\r
-                var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);\r
-                if(cw != currentWidth){\r
-                    cm.setColumnWidth(ci, cw, true);\r
-                    if(preventUpdate !== true){\r
-                        this.updateColumnWidth(ci, cw);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    getColumnData : function(){\r
-        // build a map for all the columns\r
-        var cs = [], cm = this.cm, colCount = cm.getColumnCount();\r
-        for(var i = 0; i < colCount; i++){\r
-            var name = cm.getDataIndex(i);\r
-            cs[i] = {\r
-                name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),\r
-                renderer : cm.getRenderer(i),\r
-                id : cm.getColumnId(i),\r
-                style : this.getColumnStyle(i)\r
-            };\r
-        }\r
-        return cs;\r
-    },\r
-\r
-    // private\r
-    renderRows : function(startRow, endRow){\r
-        // pull in all the crap needed to render rows\r
-        var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;\r
-        var colCount = cm.getColumnCount();\r
-\r
-        if(ds.getCount() < 1){\r
-            return "";\r
-        }\r
-\r
-        var cs = this.getColumnData();\r
-\r
-        startRow = startRow || 0;\r
-        endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;\r
-\r
-        // records to render\r
-        var rs = ds.getRange(startRow, endRow);\r
-\r
-        return this.doRender(cs, rs, ds, startRow, colCount, stripe);\r
-    },\r
-\r
-    // private\r
-    renderBody : function(){\r
-        var markup = this.renderRows();\r
-        return this.templates.body.apply({rows: markup});\r
-    },\r
-\r
-    // private\r
-    refreshRow : function(record){\r
-        var ds = this.ds, index;\r
-        if(typeof record == 'number'){\r
-            index = record;\r
-            record = ds.getAt(index);\r
-        }else{\r
-            index = ds.indexOf(record);\r
-        }\r
-        var cls = [];\r
-        this.insertRows(ds, index, index, true);\r
-        this.getRow(index).rowIndex = index;\r
-        this.onRemove(ds, record, index+1, true);\r
-        this.fireEvent("rowupdated", this, index, record);\r
-    },\r
-\r
-    /**\r
-     * Refreshs the grid UI\r
-     * @param {Boolean} headersToo (optional) True to also refresh the headers\r
-     */\r
-    refresh : function(headersToo){\r
-        this.fireEvent("beforerefresh", this);\r
-        this.grid.stopEditing(true);\r
-\r
-        var result = this.renderBody();\r
-        this.mainBody.update(result);\r
-\r
-        if(headersToo === true){\r
-            this.updateHeaders();\r
-            this.updateHeaderSortState();\r
-        }\r
-        this.processRows(0, true);\r
-        this.layout();\r
-        this.applyEmptyText();\r
-        this.fireEvent("refresh", this);\r
-    },\r
-\r
-    // private\r
-    applyEmptyText : function(){\r
-        if(this.emptyText && !this.hasRows()){\r
-            this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');\r
-        }\r
-    },\r
-\r
-    // private\r
-    updateHeaderSortState : function(){\r
-        var state = this.ds.getSortState();\r
-        if(!state){\r
-            return;\r
-        }\r
-        if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){\r
-            this.grid.fireEvent('sortchange', this.grid, state);\r
-        }\r
-        this.sortState = state;\r
-        var sortColumn = this.cm.findColumnIndex(state.field);\r
-        if(sortColumn != -1){\r
-            var sortDir = state.direction;\r
-            this.updateSortIcon(sortColumn, sortDir);\r
-        }\r
-    },\r
-\r
-    // private\r
-    destroy : function(){\r
-        if(this.colMenu){\r
-            Ext.menu.MenuMgr.unregister(this.colMenu);\r
-            this.colMenu.destroy();\r
-            delete this.colMenu;\r
-        }\r
-        if(this.hmenu){\r
-            Ext.menu.MenuMgr.unregister(this.hmenu);\r
-            this.hmenu.destroy();\r
-            delete this.hmenu;\r
-        }\r
-        if(this.grid.enableColumnMove){\r
-            var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];\r
-            if(dds){\r
-                for(var dd in dds){\r
-                    if(!dds[dd].config.isTarget && dds[dd].dragElId){\r
-                        var elid = dds[dd].dragElId;\r
-                        dds[dd].unreg();\r
-                        Ext.get(elid).remove();\r
-                    } else if(dds[dd].config.isTarget){\r
-                        dds[dd].proxyTop.remove();\r
-                        dds[dd].proxyBottom.remove();\r
-                        dds[dd].unreg();\r
-                    }\r
-                    if(Ext.dd.DDM.locationCache[dd]){\r
-                        delete Ext.dd.DDM.locationCache[dd];\r
-                    }\r
-                }\r
-                delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];\r
-            }\r
-        }\r
-        \r
-        if(this.dragZone){\r
-            this.dragZone.unreg();\r
-        }\r
-        \r
-        Ext.fly(this.innerHd).removeAllListeners();\r
-        Ext.removeNode(this.innerHd);\r
-        \r
-        Ext.destroy(this.resizeMarker, this.resizeProxy, this.focusEl, this.mainBody, \r
-                    this.scroller, this.mainHd, this.mainWrap, this.dragZone, \r
-                    this.splitZone, this.columnDrag, this.columnDrop);\r
-\r
-        this.initData(null, null);\r
-        Ext.EventManager.removeResizeListener(this.onWindowResize, this);\r
-        this.purgeListeners();\r
-    },\r
-\r
-    // private\r
-    onDenyColumnHide : function(){\r
-\r
-    },\r
-\r
-    // private\r
-    render : function(){\r
-        if(this.autoFill){\r
-            var ct = this.grid.ownerCt;\r
-            if (ct && ct.getLayout()){\r
-                ct.on('afterlayout', function(){ \r
-                    this.fitColumns(true, true);\r
-                    this.updateHeaders(); \r
-                }, this, {single: true}); \r
-            }else{ \r
-                this.fitColumns(true, true); \r
-            }\r
-        }else if(this.forceFit){\r
-            this.fitColumns(true, false);\r
-        }else if(this.grid.autoExpandColumn){\r
-            this.autoExpand(true);\r
-        }\r
-\r
-        this.renderUI();\r
-    },\r
-\r
-    /* --------------------------------- Model Events and Handlers --------------------------------*/\r
-    // private\r
-    initData : function(ds, cm){\r
-        if(this.ds){\r
-            this.ds.un("load", this.onLoad, this);\r
-            this.ds.un("datachanged", this.onDataChange, this);\r
-            this.ds.un("add", this.onAdd, this);\r
-            this.ds.un("remove", this.onRemove, this);\r
-            this.ds.un("update", this.onUpdate, this);\r
-            this.ds.un("clear", this.onClear, this);\r
-        }\r
-        if(ds){\r
-            ds.on("load", this.onLoad, this);\r
-            ds.on("datachanged", this.onDataChange, this);\r
-            ds.on("add", this.onAdd, this);\r
-            ds.on("remove", this.onRemove, this);\r
-            ds.on("update", this.onUpdate, this);\r
-            ds.on("clear", this.onClear, this);\r
-        }\r
-        this.ds = ds;\r
-\r
-        if(this.cm){\r
-            this.cm.un("configchange", this.onColConfigChange, this);\r
-            this.cm.un("widthchange", this.onColWidthChange, this);\r
-            this.cm.un("headerchange", this.onHeaderChange, this);\r
-            this.cm.un("hiddenchange", this.onHiddenChange, this);\r
-            this.cm.un("columnmoved", this.onColumnMove, this);\r
-            this.cm.un("columnlockchange", this.onColumnLock, this);\r
-        }\r
-        if(cm){\r
-            delete this.lastViewWidth;\r
-            cm.on("configchange", this.onColConfigChange, this);\r
-            cm.on("widthchange", this.onColWidthChange, this);\r
-            cm.on("headerchange", this.onHeaderChange, this);\r
-            cm.on("hiddenchange", this.onHiddenChange, this);\r
-            cm.on("columnmoved", this.onColumnMove, this);\r
-            cm.on("columnlockchange", this.onColumnLock, this);\r
-        }\r
-        this.cm = cm;\r
-    },\r
-\r
-    // private\r
-    onDataChange : function(){\r
-        this.refresh();\r
-        this.updateHeaderSortState();\r
-        this.syncFocusEl(0);\r
-    },\r
-\r
-    // private\r
-    onClear : function(){\r
-        this.refresh();\r
-        this.syncFocusEl(0);\r
-    },\r
-\r
-    // private\r
-    onUpdate : function(ds, record){\r
-        this.refreshRow(record);\r
-    },\r
-\r
-    // private\r
-    onAdd : function(ds, records, index){\r
-        this.insertRows(ds, index, index + (records.length-1));\r
-    },\r
-\r
-    // private\r
-    onRemove : function(ds, record, index, isUpdate){\r
-        if(isUpdate !== true){\r
-            this.fireEvent("beforerowremoved", this, index, record);\r
-        }\r
-        this.removeRow(index);\r
-        if(isUpdate !== true){\r
-            this.processRows(index);\r
-            this.applyEmptyText();\r
-            this.fireEvent("rowremoved", this, index, record);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onLoad : function(){\r
-        this.scrollToTop();\r
-    },\r
-\r
-    // private\r
-    onColWidthChange : function(cm, col, width){\r
-        this.updateColumnWidth(col, width);\r
-    },\r
-\r
-    // private\r
-    onHeaderChange : function(cm, col, text){\r
-        this.updateHeaders();\r
-    },\r
-\r
-    // private\r
-    onHiddenChange : function(cm, col, hidden){\r
-        this.updateColumnHidden(col, hidden);\r
-    },\r
-\r
-    // private\r
-    onColumnMove : function(cm, oldIndex, newIndex){\r
-        this.indexMap = null;\r
-        var s = this.getScrollState();\r
-        this.refresh(true);\r
-        this.restoreScroll(s);\r
-        this.afterMove(newIndex);\r
-    },\r
-\r
-    // private\r
-    onColConfigChange : function(){\r
-        delete this.lastViewWidth;\r
-        this.indexMap = null;\r
-        this.refresh(true);\r
-    },\r
-\r
-    /* -------------------- UI Events and Handlers ------------------------------ */\r
-    // private\r
-    initUI : function(grid){\r
-        grid.on("headerclick", this.onHeaderClick, this);\r
-    },\r
-\r
-    // private\r
-    initEvents : function(){\r
-\r
-    },\r
-\r
-    // private\r
-    onHeaderClick : function(g, index){\r
-        if(this.headersDisabled || !this.cm.isSortable(index)){\r
-            return;\r
-        }\r
-        g.stopEditing(true);\r
-        g.store.sort(this.cm.getDataIndex(index));\r
-    },\r
-\r
-    // private\r
-    onRowOver : function(e, t){\r
-        var row;\r
-        if((row = this.findRowIndex(t)) !== false){\r
-            this.addRowClass(row, "x-grid3-row-over");\r
-        }\r
-    },\r
-\r
-    // private\r
-    onRowOut : function(e, t){\r
-        var row;\r
-        if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){\r
-            this.removeRowClass(row, "x-grid3-row-over");\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleWheel : function(e){\r
-        e.stopPropagation();\r
-    },\r
-\r
-    // private\r
-    onRowSelect : function(row){\r
-        this.addRowClass(row, "x-grid3-row-selected");\r
-    },\r
-\r
-    // private\r
-    onRowDeselect : function(row){\r
-        this.removeRowClass(row, "x-grid3-row-selected");\r
-    },\r
-\r
-    // private\r
-    onCellSelect : function(row, col){\r
-        var cell = this.getCell(row, col);\r
-        if(cell){\r
-            this.fly(cell).addClass("x-grid3-cell-selected");\r
-        }\r
-    },\r
-\r
-    // private\r
-    onCellDeselect : function(row, col){\r
-        var cell = this.getCell(row, col);\r
-        if(cell){\r
-            this.fly(cell).removeClass("x-grid3-cell-selected");\r
-        }\r
-    },\r
-\r
-    // private\r
-    onColumnSplitterMoved : function(i, w){\r
-        this.userResized = true;\r
-        var cm = this.grid.colModel;\r
-        cm.setColumnWidth(i, w, true);\r
-\r
-        if(this.forceFit){\r
-            this.fitColumns(true, false, i);\r
-            this.updateAllColumnWidths();\r
-        }else{\r
-            this.updateColumnWidth(i, w);\r
-            this.syncHeaderScroll();\r
-        }\r
-\r
-        this.grid.fireEvent("columnresize", i, w);\r
-    },\r
-\r
-    // private\r
-    handleHdMenuClick : function(item){\r
-        var index = this.hdCtxIndex;\r
-        var cm = this.cm, ds = this.ds;\r
-        switch(item.id){\r
-            case "asc":\r
-                ds.sort(cm.getDataIndex(index), "ASC");\r
-                break;\r
-            case "desc":\r
-                ds.sort(cm.getDataIndex(index), "DESC");\r
-                break;\r
-            default:\r
-                index = cm.getIndexById(item.id.substr(4));\r
-                if(index != -1){\r
-                    if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){\r
-                        this.onDenyColumnHide();\r
-                        return false;\r
-                    }\r
-                    cm.setHidden(index, item.checked);\r
-                }\r
-        }\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    isHideableColumn : function(c){\r
-        return !c.hidden && !c.fixed;\r
-    },\r
-\r
-    // private\r
-    beforeColMenuShow : function(){\r
-        var cm = this.cm,  colCount = cm.getColumnCount();\r
-        this.colMenu.removeAll();\r
-        for(var i = 0; i < colCount; i++){\r
-            if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){\r
-                this.colMenu.add(new Ext.menu.CheckItem({\r
-                    id: "col-"+cm.getColumnId(i),\r
-                    text: cm.getColumnHeader(i),\r
-                    checked: !cm.isHidden(i),\r
-                    hideOnClick:false,\r
-                    disabled: cm.config[i].hideable === false\r
-                }));\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleHdDown : function(e, t){\r
-        if(Ext.fly(t).hasClass('x-grid3-hd-btn')){\r
-            e.stopEvent();\r
-            var hd = this.findHeaderCell(t);\r
-            Ext.fly(hd).addClass('x-grid3-hd-menu-open');\r
-            var index = this.getCellIndex(hd);\r
-            this.hdCtxIndex = index;\r
-            var ms = this.hmenu.items, cm = this.cm;\r
-            ms.get("asc").setDisabled(!cm.isSortable(index));\r
-            ms.get("desc").setDisabled(!cm.isSortable(index));\r
-            this.hmenu.on("hide", function(){\r
-                Ext.fly(hd).removeClass('x-grid3-hd-menu-open');\r
-            }, this, {single:true});\r
-            this.hmenu.show(t, "tl-bl?");\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleHdOver : function(e, t){\r
-        var hd = this.findHeaderCell(t);\r
-        if(hd && !this.headersDisabled){\r
-            this.activeHd = hd;\r
-            this.activeHdIndex = this.getCellIndex(hd);\r
-            var fly = this.fly(hd);\r
-            this.activeHdRegion = fly.getRegion();\r
-            if(!this.cm.isMenuDisabled(this.activeHdIndex)){\r
-                fly.addClass("x-grid3-hd-over");\r
-                this.activeHdBtn = fly.child('.x-grid3-hd-btn');\r
-                if(this.activeHdBtn){\r
-                    this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleHdMove : function(e, t){\r
-        if(this.activeHd && !this.headersDisabled){\r
-            var hw = this.splitHandleWidth || 5;\r
-            var r = this.activeHdRegion;\r
-            var x = e.getPageX();\r
-            var ss = this.activeHd.style;\r
-            if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){\r
-                ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'e-resize' : 'col-resize'; // col-resize not always supported\r
-            }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){\r
-                ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'w-resize' : 'col-resize';\r
-            }else{\r
-                ss.cursor = '';\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleHdOut : function(e, t){\r
-        var hd = this.findHeaderCell(t);\r
-        if(hd && (!Ext.isIE || !e.within(hd, true))){\r
-            this.activeHd = null;\r
-            this.fly(hd).removeClass("x-grid3-hd-over");\r
-            hd.style.cursor = '';\r
-        }\r
-    },\r
-\r
-    // private\r
-    hasRows : function(){\r
-        var fc = this.mainBody.dom.firstChild;\r
-        return fc && fc.className != 'x-grid-empty';\r
-    },\r
-\r
-    // back compat\r
-    bind : function(d, c){\r
-        this.initData(d, c);\r
-    }\r
-});\r
-\r
-\r
-// private\r
-// This is a support class used internally by the Grid components\r
-Ext.grid.GridView.SplitDragZone = function(grid, hd){\r
-    this.grid = grid;\r
-    this.view = grid.getView();\r
-    this.marker = this.view.resizeMarker;\r
-    this.proxy = this.view.resizeProxy;\r
-    Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,\r
-        "gridSplitters" + this.grid.getGridEl().id, {\r
-        dragElId : Ext.id(this.proxy.dom), resizeFrame:false\r
-    });\r
-    this.scroll = false;\r
-    this.hw = this.view.splitHandleWidth || 5;\r
-};\r
-Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {\r
-\r
-    b4StartDrag : function(x, y){\r
-        this.view.headersDisabled = true;\r
-        var h = this.view.mainWrap.getHeight();\r
-        this.marker.setHeight(h);\r
-        this.marker.show();\r
-        this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);\r
-        this.proxy.setHeight(h);\r
-        var w = this.cm.getColumnWidth(this.cellIndex);\r
-        var minw = Math.max(w-this.grid.minColumnWidth, 0);\r
-        this.resetConstraints();\r
-        this.setXConstraint(minw, 1000);\r
-        this.setYConstraint(0, 0);\r
-        this.minX = x - minw;\r
-        this.maxX = x + 1000;\r
-        this.startPos = x;\r
-        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);\r
-    },\r
-\r
-\r
-    handleMouseDown : function(e){\r
-        var t = this.view.findHeaderCell(e.getTarget());\r
-        if(t){\r
-            var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];\r
-            var exy = e.getXY(), ex = exy[0], ey = exy[1];\r
-            var w = t.offsetWidth, adjust = false;\r
-            if((ex - x) <= this.hw){\r
-                adjust = -1;\r
-            }else if((x+w) - ex <= this.hw){\r
-                adjust = 0;\r
-            }\r
-            if(adjust !== false){\r
-                this.cm = this.grid.colModel;\r
-                var ci = this.view.getCellIndex(t);\r
-                if(adjust == -1){\r
-                  if (ci + adjust < 0) {\r
-                    return;\r
-                  }\r
-                    while(this.cm.isHidden(ci+adjust)){\r
-                        --adjust;\r
-                        if(ci+adjust < 0){\r
-                            return;\r
-                        }\r
-                    }\r
-                }\r
-                this.cellIndex = ci+adjust;\r
-                this.split = t.dom;\r
-                if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){\r
-                    Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);\r
-                }\r
-            }else if(this.view.columnDrag){\r
-                this.view.columnDrag.callHandleMouseDown(e);\r
-            }\r
-        }\r
-    },\r
-\r
-    endDrag : function(e){\r
-        this.marker.hide();\r
-        var v = this.view;\r
-        var endX = Math.max(this.minX, e.getPageX());\r
-        var diff = endX - this.startPos;\r
-        v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);\r
-        setTimeout(function(){\r
-            v.headersDisabled = false;\r
-        }, 50);\r
-    },\r
-\r
-    autoOffset : function(){\r
-        this.setDelta(0,0);\r
-    }\r
-});\r