X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=docs%2Fsrc%2FRoo_grid_GridView.js.html;fp=docs%2Fsrc%2FRoo_grid_GridView.js.html;h=ae4daed395726091cc0a8f318bd9a1866af93797;hb=9ff8ded6bbbd258ecd646184ba26020874e2c085;hp=0000000000000000000000000000000000000000;hpb=2542b67d1a0768025056f2f330bfe50b64d1ad38;p=roojs1 diff --git a/docs/src/Roo_grid_GridView.js.html b/docs/src/Roo_grid_GridView.js.html new file mode 100644 index 0000000000..ae4daed395 --- /dev/null +++ b/docs/src/Roo_grid_GridView.js.html @@ -0,0 +1,1743 @@ +/home/alan/gitlive/roojs1/Roo/grid/GridView.js/* + * Based on: + * Ext JS Library 1.1.1 + * Copyright(c) 2006-2007, Ext JS, LLC. + * + * Originally Released Under LGPL - original licence link has changed is not relivant. + * + * Fork - LGPL + * <script type="text/javascript"> + */ + +/** + * @class Roo.grid.GridView + * @extends Roo.util.Observable + * + * @constructor + * @param {Object} config + */ +Roo.grid.GridView = function(config){ + Roo.grid.GridView.superclass.constructor.call(this); + this.el = null; + + Roo.apply(this, config); +}; + +Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, { + + unselectable : 'unselectable="on"', + unselectableCls : 'x-unselectable', + + + rowClass : "x-grid-row", + + cellClass : "x-grid-col", + + tdClass : "x-grid-td", + + hdClass : "x-grid-hd", + + splitClass : "x-grid-split", + + sortClasses : ["sort-asc", "sort-desc"], + + enableMoveAnim : false, + + hlColor: "C3DAF9", + + dh : Roo.DomHelper, + + fly : Roo.Element.fly, + + css : Roo.util.CSS, + + borderWidth: 1, + + splitOffset: 3, + + scrollIncrement : 22, + + cellRE: /(?:.*?)x-grid-(?:hd|cell|csplit)-(?:[\d]+)-([\d]+)(?:.*?)/, + + findRE: /\s?(?:x-grid-hd|x-grid-col|x-grid-csplit)\s/, + + bind : function(ds, cm){ + if(this.ds){ + this.ds.un("load", this.onLoad, this); + this.ds.un("datachanged", this.onDataChange, this); + this.ds.un("add", this.onAdd, this); + this.ds.un("remove", this.onRemove, this); + this.ds.un("update", this.onUpdate, this); + this.ds.un("clear", this.onClear, this); + } + if(ds){ + ds.on("load", this.onLoad, this); + ds.on("datachanged", this.onDataChange, this); + ds.on("add", this.onAdd, this); + ds.on("remove", this.onRemove, this); + ds.on("update", this.onUpdate, this); + ds.on("clear", this.onClear, this); + } + this.ds = ds; + + if(this.cm){ + this.cm.un("widthchange", this.onColWidthChange, this); + this.cm.un("headerchange", this.onHeaderChange, this); + this.cm.un("hiddenchange", this.onHiddenChange, this); + this.cm.un("columnmoved", this.onColumnMove, this); + this.cm.un("columnlockchange", this.onColumnLock, this); + } + if(cm){ + this.generateRules(cm); + cm.on("widthchange", this.onColWidthChange, this); + cm.on("headerchange", this.onHeaderChange, this); + cm.on("hiddenchange", this.onHiddenChange, this); + cm.on("columnmoved", this.onColumnMove, this); + cm.on("columnlockchange", this.onColumnLock, this); + } + this.cm = cm; + }, + + init: function(grid){ + Roo.grid.GridView.superclass.init.call(this, grid); + + this.bind(grid.dataSource, grid.colModel); + + grid.on("headerclick", this.handleHeaderClick, this); + + if(grid.trackMouseOver){ + grid.on("mouseover", this.onRowOver, this); + grid.on("mouseout", this.onRowOut, this); + } + grid.cancelTextSelection = function(){}; + this.gridId = grid.id; + + var tpls = this.templates || {}; + + if(!tpls.master){ + tpls.master = new Roo.Template( + '<div class="x-grid" hidefocus="true">', + '<a href="#" class="x-grid-focus" tabIndex="-1"></a>', + '<div class="x-grid-topbar"></div>', + '<div class="x-grid-scroller"><div></div></div>', + '<div class="x-grid-locked">', + '<div class="x-grid-header">{lockedHeader}</div>', + '<div class="x-grid-body">{lockedBody}</div>', + "</div>", + '<div class="x-grid-viewport">', + '<div class="x-grid-header">{header}</div>', + '<div class="x-grid-body">{body}</div>', + "</div>", + '<div class="x-grid-bottombar"></div>', + + '<div class="x-grid-resize-proxy">&#160;</div>', + "</div>" + ); + tpls.master.disableformats = true; + } + + if(!tpls.header){ + tpls.header = new Roo.Template( + '<table border="0" cellspacing="0" cellpadding="0">', + '<tbody><tr class="x-grid-hd-row">{cells}</tr></tbody>', + "</table>{splits}" + ); + tpls.header.disableformats = true; + } + tpls.header.compile(); + + if(!tpls.hcell){ + tpls.hcell = new Roo.Template( + '<td class="x-grid-hd x-grid-td-{id} {cellId}"><div title="{title}" class="x-grid-hd-inner x-grid-hd-{id}">', + '<div class="x-grid-hd-text ' + this.unselectableCls + '" ' + this.unselectable +'>{value}<img class="x-grid-sort-icon" src="', Roo.BLANK_IMAGE_URL, '" /></div>', + "</div></td>" + ); + tpls.hcell.disableFormats = true; + } + tpls.hcell.compile(); + + if(!tpls.hsplit){ + tpls.hsplit = new Roo.Template('<div class="x-grid-split {splitId} x-grid-split-{id}" style="{style} ' + + this.unselectableCls + '" ' + this.unselectable +'>&#160;</div>'); + tpls.hsplit.disableFormats = true; + } + tpls.hsplit.compile(); + + if(!tpls.body){ + tpls.body = new Roo.Template( + '<table border="0" cellspacing="0" cellpadding="0">', + "<tbody>{rows}</tbody>", + "</table>" + ); + tpls.body.disableFormats = true; + } + tpls.body.compile(); + + if(!tpls.row){ + tpls.row = new Roo.Template('<tr class="x-grid-row {alt}">{cells}</tr>'); + tpls.row.disableFormats = true; + } + tpls.row.compile(); + + if(!tpls.cell){ + tpls.cell = new Roo.Template( + '<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">', + '<div class="x-grid-col-{id} x-grid-cell-inner"><div class="x-grid-cell-text ' + + this.unselectableCls + '" ' + this.unselectable +'" {attr}>{value}</div></div>', + "</td>" + ); + tpls.cell.disableFormats = true; + } + tpls.cell.compile(); + + this.templates = tpls; + }, + + // remap these for backwards compat + onColWidthChange : function(){ + this.updateColumns.apply(this, arguments); + }, + onHeaderChange : function(){ + this.updateHeaders.apply(this, arguments); + }, + onHiddenChange : function(){ + this.handleHiddenChange.apply(this, arguments); + }, + onColumnMove : function(){ + this.handleColumnMove.apply(this, arguments); + }, + onColumnLock : function(){ + this.handleLockChange.apply(this, arguments); + }, + + onDataChange : function(){ + this.refresh(); + this.updateHeaderSortState(); + }, + + onClear : function(){ + this.refresh(); + }, + + onUpdate : function(ds, record){ + this.refreshRow(record); + }, + + refreshRow : function(record){ + var ds = this.ds, index; + if(typeof record == 'number'){ + index = record; + record = ds.getAt(index); + }else{ + index = ds.indexOf(record); + } + this.insertRows(ds, index, index, true); + this.onRemove(ds, record, index+1, true); + this.syncRowHeights(index, index); + this.layout(); + this.fireEvent("rowupdated", this, index, record); + }, + + onAdd : function(ds, records, index){ + this.insertRows(ds, index, index + (records.length-1)); + }, + + onRemove : function(ds, record, index, isUpdate){ + if(isUpdate !== true){ + this.fireEvent("beforerowremoved", this, index, record); + } + var bt = this.getBodyTable(), lt = this.getLockedTable(); + if(bt.rows[index]){ + bt.firstChild.removeChild(bt.rows[index]); + } + if(lt.rows[index]){ + lt.firstChild.removeChild(lt.rows[index]); + } + if(isUpdate !== true){ + this.stripeRows(index); + this.syncRowHeights(index, index); + this.layout(); + this.fireEvent("rowremoved", this, index, record); + } + }, + + onLoad : function(){ + this.scrollToTop(); + }, + + /** + * Scrolls the grid to the top + */ + scrollToTop : function(){ + if(this.scroller){ + this.scroller.dom.scrollTop = 0; + this.syncScroll(); + } + }, + + /** + * Gets a panel in the header of the grid that can be used for toolbars etc. + * After modifying the contents of this panel a call to grid.autoSize() may be + * required to register any changes in size. + * @param {Boolean} doShow By default the header is hidden. Pass true to show the panel + * @return Roo.Element + */ + getHeaderPanel : function(doShow){ + if(doShow){ + this.headerPanel.show(); + } + return this.headerPanel; + }, + + /** + * Gets a panel in the footer of the grid that can be used for toolbars etc. + * After modifying the contents of this panel a call to grid.autoSize() may be + * required to register any changes in size. + * @param {Boolean} doShow By default the footer is hidden. Pass true to show the panel + * @return Roo.Element + */ + getFooterPanel : function(doShow){ + if(doShow){ + this.footerPanel.show(); + } + return this.footerPanel; + }, + + initElements : function(){ + var E = Roo.Element; + var el = this.grid.getGridEl().dom.firstChild; + var cs = el.childNodes; + + this.el = new E(el); + + this.focusEl = new E(el.firstChild); + this.focusEl.swallowEvent("click", true); + + this.headerPanel = new E(cs[1]); + this.headerPanel.enableDisplayMode("block"); + + this.scroller = new E(cs[2]); + this.scrollSizer = new E(this.scroller.dom.firstChild); + + this.lockedWrap = new E(cs[3]); + this.lockedHd = new E(this.lockedWrap.dom.firstChild); + this.lockedBody = new E(this.lockedWrap.dom.childNodes[1]); + + this.mainWrap = new E(cs[4]); + this.mainHd = new E(this.mainWrap.dom.firstChild); + this.mainBody = new E(this.mainWrap.dom.childNodes[1]); + + this.footerPanel = new E(cs[5]); + this.footerPanel.enableDisplayMode("block"); + + this.resizeProxy = new E(cs[6]); + + this.headerSelector = String.format( + '#{0} td.x-grid-hd, #{1} td.x-grid-hd', + this.lockedHd.id, this.mainHd.id + ); + + this.splitterSelector = String.format( + '#{0} div.x-grid-split, #{1} div.x-grid-split', + this.idToCssName(this.lockedHd.id), this.idToCssName(this.mainHd.id) + ); + }, + idToCssName : function(s) + { + return s.replace(/[^a-z0-9]+/ig, '-'); + }, + + getHeaderCell : function(index){ + return Roo.DomQuery.select(this.headerSelector)[index]; + }, + + getHeaderCellMeasure : function(index){ + return this.getHeaderCell(index).firstChild; + }, + + getHeaderCellText : function(index){ + return this.getHeaderCell(index).firstChild.firstChild; + }, + + getLockedTable : function(){ + return this.lockedBody.dom.firstChild; + }, + + getBodyTable : function(){ + return this.mainBody.dom.firstChild; + }, + + getLockedRow : function(index){ + return this.getLockedTable().rows[index]; + }, + + getRow : function(index){ + return this.getBodyTable().rows[index]; + }, + + getRowComposite : function(index){ + if(!this.rowEl){ + this.rowEl = new Roo.CompositeElementLite(); + } + var els = [], lrow, mrow; + if(lrow = this.getLockedRow(index)){ + els.push(lrow); + } + if(mrow = this.getRow(index)){ + els.push(mrow); + } + this.rowEl.elements = els; + return this.rowEl; + }, + /** + * Gets the 'td' of the cell + * + * @param {Integer} rowIndex row to select + * @param {Integer} colIndex column to select + * + * @return {Object} + */ + getCell : function(rowIndex, colIndex){ + var locked = this.cm.getLockedCount(); + var source; + if(colIndex < locked){ + source = this.lockedBody.dom.firstChild; + }else{ + source = this.mainBody.dom.firstChild; + colIndex -= locked; + } + return source.rows[rowIndex].childNodes[colIndex]; + }, + + getCellText : function(rowIndex, colIndex){ + return this.getCell(rowIndex, colIndex).firstChild.firstChild; + }, + + getCellBox : function(cell){ + var b = this.fly(cell).getBox(); + if(Roo.isOpera){ // opera fails to report the Y + b.y = cell.offsetTop + this.mainBody.getY(); + } + return b; + }, + + getCellIndex : function(cell){ + var id = String(cell.className).match(this.cellRE); + if(id){ + return parseInt(id[1], 10); + } + return 0; + }, + + findHeaderIndex : function(n){ + var r = Roo.fly(n).findParent("td." + this.hdClass, 6); + return r ? this.getCellIndex(r) : false; + }, + + findHeaderCell : function(n){ + var r = Roo.fly(n).findParent("td." + this.hdClass, 6); + return r ? r : false; + }, + + findRowIndex : function(n){ + if(!n){ + return false; + } + var r = Roo.fly(n).findParent("tr." + this.rowClass, 6); + return r ? r.rowIndex : false; + }, + + findCellIndex : function(node){ + var stop = this.el.dom; + while(node && node != stop){ + if(this.findRE.test(node.className)){ + return this.getCellIndex(node); + } + node = node.parentNode; + } + return false; + }, + + getColumnId : function(index){ + return this.cm.getColumnId(index); + }, + + getSplitters : function() + { + if(this.splitterSelector){ + return Roo.DomQuery.select(this.splitterSelector); + }else{ + return null; + } + }, + + getSplitter : function(index){ + return this.getSplitters()[index]; + }, + + onRowOver : function(e, t){ + var row; + if((row = this.findRowIndex(t)) !== false){ + this.getRowComposite(row).addClass("x-grid-row-over"); + } + }, + + onRowOut : function(e, t){ + var row; + if((row = this.findRowIndex(t)) !== false && row !== this.findRowIndex(e.getRelatedTarget())){ + this.getRowComposite(row).removeClass("x-grid-row-over"); + } + }, + + renderHeaders : function(){ + var cm = this.cm; + var ct = this.templates.hcell, ht = this.templates.header, st = this.templates.hsplit; + var cb = [], lb = [], sb = [], lsb = [], p = {}; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + p.cellId = "x-grid-hd-0-" + i; + p.splitId = "x-grid-csplit-0-" + i; + p.id = cm.getColumnId(i); + p.value = cm.getColumnHeader(i) || ""; + p.title = cm.getColumnTooltip(i) || (''+p.value).match(/\</) ? '' : p.value || ""; + p.style = (this.grid.enableColumnResize === false || !cm.isResizable(i) || cm.isFixed(i)) ? 'cursor:default' : ''; + if(!cm.isLocked(i)){ + cb[cb.length] = ct.apply(p); + sb[sb.length] = st.apply(p); + }else{ + lb[lb.length] = ct.apply(p); + lsb[lsb.length] = st.apply(p); + } + } + return [ht.apply({cells: lb.join(""), splits:lsb.join("")}), + ht.apply({cells: cb.join(""), splits:sb.join("")})]; + }, + + updateHeaders : function(){ + var html = this.renderHeaders(); + this.lockedHd.update(html[0]); + this.mainHd.update(html[1]); + }, + + /** + * Focuses the specified row. + * @param {Number} row The row index + */ + focusRow : function(row) + { + //Roo.log('GridView.focusRow'); + var x = this.scroller.dom.scrollLeft; + this.focusCell(row, 0, false); + this.scroller.dom.scrollLeft = x; + }, + + /** + * Focuses the specified cell. + * @param {Number} row The row index + * @param {Number} col The column index + * @param {Boolean} hscroll false to disable horizontal scrolling + */ + focusCell : function(row, col, hscroll) + { + //Roo.log('GridView.focusCell'); + var el = this.ensureVisible(row, col, hscroll); + this.focusEl.alignTo(el, "tl-tl"); + if(Roo.isGecko){ + this.focusEl.focus(); + }else{ + this.focusEl.focus.defer(1, this.focusEl); + } + }, + + /** + * Scrolls the specified cell into view + * @param {Number} row The row index + * @param {Number} col The column index + * @param {Boolean} hscroll false to disable horizontal scrolling + */ + ensureVisible : function(row, col, hscroll) + { + //Roo.log('GridView.ensureVisible,' + row + ',' + col); + //return null; //disable for testing. + if(typeof row != "number"){ + row = row.rowIndex; + } + if(row < 0 && row >= this.ds.getCount()){ + return null; + } + col = (col !== undefined ? col : 0); + var cm = this.grid.colModel; + while(cm.isHidden(col)){ + col++; + } + + var el = this.getCell(row, col); + if(!el){ + return null; + } + var c = this.scroller.dom; + + var ctop = parseInt(el.offsetTop, 10); + var cleft = parseInt(el.offsetLeft, 10); + var cbot = ctop + el.offsetHeight; + var cright = cleft + el.offsetWidth; + + var ch = c.clientHeight - this.mainHd.dom.offsetHeight; + var stop = parseInt(c.scrollTop, 10); + var sleft = parseInt(c.scrollLeft, 10); + var sbot = stop + ch; + var sright = sleft + c.clientWidth; + /* + Roo.log('GridView.ensureVisible:' + + ' ctop:' + ctop + + ' c.clientHeight:' + c.clientHeight + + ' this.mainHd.dom.offsetHeight:' + this.mainHd.dom.offsetHeight + + ' stop:' + stop + + ' cbot:' + cbot + + ' sbot:' + sbot + + ' ch:' + ch + ); + */ + if(ctop < stop){ + c.scrollTop = ctop; + //Roo.log("set scrolltop to ctop DISABLE?"); + }else if(cbot > sbot){ + //Roo.log("set scrolltop to cbot-ch"); + c.scrollTop = cbot-ch; + } + + if(hscroll !== false){ + if(cleft < sleft){ + c.scrollLeft = cleft; + }else if(cright > sright){ + c.scrollLeft = cright-c.clientWidth; + } + } + + return el; + }, + + updateColumns : function(){ + this.grid.stopEditing(); + var cm = this.grid.colModel, colIds = this.getColumnIds(); + //var totalWidth = cm.getTotalWidth(); + var pos = 0; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + //if(cm.isHidden(i)) continue; + var w = cm.getColumnWidth(i); + this.css.updateRule(this.colSelector+this.idToCssName(colIds[i]), "width", (w - this.borderWidth) + "px"); + this.css.updateRule(this.hdSelector+this.idToCssName(colIds[i]), "width", (w - this.borderWidth) + "px"); + } + this.updateSplitters(); + }, + + generateRules : function(cm){ + var ruleBuf = [], rulesId = this.idToCssName(this.grid.id)+ '-cssrules'; + Roo.util.CSS.removeStyleSheet(rulesId); + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + var cid = cm.getColumnId(i); + var align = ''; + if(cm.config[i].align){ + align = 'text-align:'+cm.config[i].align+';'; + } + var hidden = ''; + if(cm.isHidden(i)){ + hidden = 'display:none;'; + } + var width = "width:" + (cm.getColumnWidth(i) - this.borderWidth) + "px;"; + ruleBuf.push( + this.colSelector, cid, " {\n", cm.config[i].css, align, width, "\n}\n", + this.hdSelector, cid, " {\n", align, width, "}\n", + this.tdSelector, cid, " {\n",hidden,"\n}\n", + this.splitSelector, cid, " {\n", hidden , "\n}\n"); + } + return Roo.util.CSS.createStyleSheet(ruleBuf.join(""), rulesId); + }, + + updateSplitters : function(){ + var cm = this.cm, s = this.getSplitters(); + if(s){ // splitters not created yet + var pos = 0, locked = true; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + if(cm.isHidden(i)) { + continue; + } + var w = cm.getColumnWidth(i); // make sure it's a number + if(!cm.isLocked(i) && locked){ + pos = 0; + locked = false; + } + pos += w; + s[i].style.left = (pos-this.splitOffset) + "px"; + } + } + }, + + handleHiddenChange : function(colModel, colIndex, hidden){ + if(hidden){ + this.hideColumn(colIndex); + }else{ + this.unhideColumn(colIndex); + } + }, + + hideColumn : function(colIndex){ + var cid = this.getColumnId(colIndex); + this.css.updateRule(this.tdSelector+this.idToCssName(cid), "display", "none"); + this.css.updateRule(this.splitSelector+this.idToCssName(cid), "display", "none"); + if(Roo.isSafari){ + this.updateHeaders(); + } + this.updateSplitters(); + this.layout(); + }, + + unhideColumn : function(colIndex){ + var cid = this.getColumnId(colIndex); + this.css.updateRule(this.tdSelector+this.idToCssName(cid), "display", ""); + this.css.updateRule(this.splitSelector+this.idToCssName(cid), "display", ""); + + if(Roo.isSafari){ + this.updateHeaders(); + } + this.updateSplitters(); + this.layout(); + }, + + insertRows : function(dm, firstRow, lastRow, isUpdate){ + if(firstRow == 0 && lastRow == dm.getCount()-1){ + this.refresh(); + }else{ + if(!isUpdate){ + this.fireEvent("beforerowsinserted", this, firstRow, lastRow); + } + var s = this.getScrollState(); + var markup = this.renderRows(firstRow, lastRow); + this.bufferRows(markup[0], this.getLockedTable(), firstRow); + this.bufferRows(markup[1], this.getBodyTable(), firstRow); + this.restoreScroll(s); + if(!isUpdate){ + this.fireEvent("rowsinserted", this, firstRow, lastRow); + this.syncRowHeights(firstRow, lastRow); + this.stripeRows(firstRow); + this.layout(); + } + } + }, + + bufferRows : function(markup, target, index){ + var before = null, trows = target.rows, tbody = target.tBodies[0]; + if(index < trows.length){ + before = trows[index]; + } + var b = document.createElement("div"); + b.innerHTML = "<table><tbody>"+markup+"</tbody></table>"; + var rows = b.firstChild.rows; + for(var i = 0, len = rows.length; i < len; i++){ + if(before){ + tbody.insertBefore(rows[0], before); + }else{ + tbody.appendChild(rows[0]); + } + } + b.innerHTML = ""; + b = null; + }, + + deleteRows : function(dm, firstRow, lastRow){ + if(dm.getRowCount()<1){ + this.fireEvent("beforerefresh", this); + this.mainBody.update(""); + this.lockedBody.update(""); + this.fireEvent("refresh", this); + }else{ + this.fireEvent("beforerowsdeleted", this, firstRow, lastRow); + var bt = this.getBodyTable(); + var tbody = bt.firstChild; + var rows = bt.rows; + for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){ + tbody.removeChild(rows[firstRow]); + } + this.stripeRows(firstRow); + this.fireEvent("rowsdeleted", this, firstRow, lastRow); + } + }, + + updateRows : function(dataSource, firstRow, lastRow){ + var s = this.getScrollState(); + this.refresh(); + this.restoreScroll(s); + }, + + handleSort : function(dataSource, sortColumnIndex, sortDir, noRefresh){ + if(!noRefresh){ + this.refresh(); + } + this.updateHeaderSortState(); + }, + + getScrollState : function(){ + + var sb = this.scroller.dom; + return {left: sb.scrollLeft, top: sb.scrollTop}; + }, + + stripeRows : function(startRow){ + if(!this.grid.stripeRows || this.ds.getCount() < 1){ + return; + } + startRow = startRow || 0; + var rows = this.getBodyTable().rows; + var lrows = this.getLockedTable().rows; + var cls = ' x-grid-row-alt '; + for(var i = startRow, len = rows.length; i < len; i++){ + var row = rows[i], lrow = lrows[i]; + var isAlt = ((i+1) % 2 == 0); + var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1; + if(isAlt == hasAlt){ + continue; + } + if(isAlt){ + row.className += " x-grid-row-alt"; + }else{ + row.className = row.className.replace("x-grid-row-alt", ""); + } + if(lrow){ + lrow.className = row.className; + } + } + }, + + restoreScroll : function(state){ + //Roo.log('GridView.restoreScroll'); + var sb = this.scroller.dom; + sb.scrollLeft = state.left; + sb.scrollTop = state.top; + this.syncScroll(); + }, + + syncScroll : function(){ + //Roo.log('GridView.syncScroll'); + var sb = this.scroller.dom; + var sh = this.mainHd.dom; + var bs = this.mainBody.dom; + var lv = this.lockedBody.dom; + sh.scrollLeft = bs.scrollLeft = sb.scrollLeft; + lv.scrollTop = bs.scrollTop = sb.scrollTop; + }, + + handleScroll : function(e){ + this.syncScroll(); + var sb = this.scroller.dom; + this.grid.fireEvent("bodyscroll", sb.scrollLeft, sb.scrollTop); + e.stopEvent(); + }, + + handleWheel : function(e){ + var d = e.getWheelDelta(); + this.scroller.dom.scrollTop -= d*22; + // set this here to prevent jumpy scrolling on large tables + this.lockedBody.dom.scrollTop = this.mainBody.dom.scrollTop = this.scroller.dom.scrollTop; + e.stopEvent(); + }, + + renderRows : function(startRow, endRow){ + // pull in all the crap needed to render rows + var g = this.grid, cm = g.colModel, ds = g.dataSource, stripe = g.stripeRows; + var colCount = cm.getColumnCount(); + + if(ds.getCount() < 1){ + return ["", ""]; + } + + // build a map for all the columns + var cs = []; + for(var i = 0; i < colCount; i++){ + var name = cm.getDataIndex(i); + cs[i] = { + name : typeof name == 'undefined' ? ds.fields.get(i).name : name, + renderer : cm.getRenderer(i), + id : cm.getColumnId(i), + locked : cm.isLocked(i), + has_editor : cm.isCellEditable(i) + }; + } + + startRow = startRow || 0; + endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow; + + // records to render + var rs = ds.getRange(startRow, endRow); + + return this.doRender(cs, rs, ds, startRow, colCount, stripe); + }, + + // As much as I hate to duplicate code, this was branched because FireFox really hates + // [].join("") on strings. The performance difference was substantial enough to + // branch this function + doRender : Roo.isGecko ? + function(cs, rs, ds, startRow, colCount, stripe){ + var ts = this.templates, ct = ts.cell, rt = ts.row; + // buffers + var buf = "", lbuf = "", cb, lcb, c, p = {}, rp = {}, r, rowIndex; + + var hasListener = this.grid.hasListener('rowclass'); + var rowcfg = {}; + for(var j = 0, len = rs.length; j < len; j++){ + r = rs[j]; cb = ""; lcb = ""; rowIndex = (j+startRow); + for(var i = 0; i < colCount; i++){ + c = cs[i]; + p.cellId = "x-grid-cell-" + rowIndex + "-" + i; + p.id = c.id; + p.css = p.attr = ""; + p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds); + if(p.value == undefined || p.value === "") { + p.value = "&#160;"; + } + if(c.has_editor){ + p.css += ' x-grid-editable-cell'; + } + if(c.dirty && typeof r.modified[c.name] !== 'undefined'){ + p.css += ' x-grid-dirty-cell'; + } + var markup = ct.apply(p); + if(!c.locked){ + cb+= markup; + }else{ + lcb+= markup; + } + } + var alt = []; + if(stripe && ((rowIndex+1) % 2 == 0)){ + alt.push("x-grid-row-alt") + } + if(r.dirty){ + alt.push( " x-grid-dirty-row"); + } + rp.cells = lcb; + if(this.getRowClass){ + alt.push(this.getRowClass(r, rowIndex)); + } + if (hasListener) { + rowcfg = { + + record: r, + rowIndex : rowIndex, + rowClass : '' + }; + this.grid.fireEvent('rowclass', this, rowcfg); + alt.push(rowcfg.rowClass); + } + rp.alt = alt.join(" "); + lbuf+= rt.apply(rp); + rp.cells = cb; + buf+= rt.apply(rp); + } + return [lbuf, buf]; + } : + function(cs, rs, ds, startRow, colCount, stripe){ + var ts = this.templates, ct = ts.cell, rt = ts.row; + // buffers + var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r, rowIndex; + var hasListener = this.grid.hasListener('rowclass'); + + var rowcfg = {}; + for(var j = 0, len = rs.length; j < len; j++){ + r = rs[j]; cb = []; lcb = []; rowIndex = (j+startRow); + for(var i = 0; i < colCount; i++){ + c = cs[i]; + p.cellId = "x-grid-cell-" + rowIndex + "-" + i; + p.id = c.id; + p.css = p.attr = ""; + p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds); + if(p.value == undefined || p.value === "") { + p.value = "&#160;"; + } + //Roo.log(c); + if(c.has_editor){ + p.css += ' x-grid-editable-cell'; + } + if(r.dirty && typeof r.modified[c.name] !== 'undefined'){ + p.css += ' x-grid-dirty-cell' + } + + var markup = ct.apply(p); + if(!c.locked){ + cb[cb.length] = markup; + }else{ + lcb[lcb.length] = markup; + } + } + var alt = []; + if(stripe && ((rowIndex+1) % 2 == 0)){ + alt.push( "x-grid-row-alt"); + } + if(r.dirty){ + alt.push(" x-grid-dirty-row"); + } + rp.cells = lcb; + if(this.getRowClass){ + alt.push( this.getRowClass(r, rowIndex)); + } + if (hasListener) { + rowcfg = { + + record: r, + rowIndex : rowIndex, + rowClass : '' + }; + this.grid.fireEvent('rowclass', this, rowcfg); + alt.push(rowcfg.rowClass); + } + + rp.alt = alt.join(" "); + rp.cells = lcb.join(""); + lbuf[lbuf.length] = rt.apply(rp); + rp.cells = cb.join(""); + buf[buf.length] = rt.apply(rp); + } + return [lbuf.join(""), buf.join("")]; + }, + + renderBody : function(){ + var markup = this.renderRows(); + var bt = this.templates.body; + return [bt.apply({rows: markup[0]}), bt.apply({rows: markup[1]})]; + }, + + /** + * Refreshes the grid + * @param {Boolean} headersToo + */ + refresh : function(headersToo){ + this.fireEvent("beforerefresh", this); + this.grid.stopEditing(); + var result = this.renderBody(); + this.lockedBody.update(result[0]); + this.mainBody.update(result[1]); + if(headersToo === true){ + this.updateHeaders(); + this.updateColumns(); + this.updateSplitters(); + this.updateHeaderSortState(); + } + this.syncRowHeights(); + this.layout(); + this.fireEvent("refresh", this); + }, + + handleColumnMove : function(cm, oldIndex, newIndex){ + this.indexMap = null; + var s = this.getScrollState(); + this.refresh(true); + this.restoreScroll(s); + this.afterMove(newIndex); + }, + + afterMove : function(colIndex){ + if(this.enableMoveAnim && Roo.enableFx){ + this.fly(this.getHeaderCell(colIndex).firstChild).highlight(this.hlColor); + } + // if multisort - fix sortOrder, and reload.. + if (this.grid.dataSource.multiSort) { + // the we can call sort again.. + var dm = this.grid.dataSource; + var cm = this.grid.colModel; + var so = []; + for(var i = 0; i < cm.config.length; i++ ) { + + if ((typeof(dm.sortToggle[cm.config[i].dataIndex]) == 'undefined')) { + continue; // dont' bother, it's not in sort list or being set. + } + + so.push(cm.config[i].dataIndex); + }; + dm.sortOrder = so; + dm.load(dm.lastOptions); + + + } + + }, + + updateCell : function(dm, rowIndex, dataIndex){ + var colIndex = this.getColumnIndexByDataIndex(dataIndex); + if(typeof colIndex == "undefined"){ // not present in grid + return; + } + var cm = this.grid.colModel; + var cell = this.getCell(rowIndex, colIndex); + var cellText = this.getCellText(rowIndex, colIndex); + + var p = { + cellId : "x-grid-cell-" + rowIndex + "-" + colIndex, + id : cm.getColumnId(colIndex), + css: colIndex == cm.getColumnCount()-1 ? "x-grid-col-last" : "" + }; + var renderer = cm.getRenderer(colIndex); + var val = renderer(dm.getValueAt(rowIndex, dataIndex), p, rowIndex, colIndex, dm); + if(typeof val == "undefined" || val === "") { + val = "&#160;"; + } + cellText.innerHTML = val; + cell.className = this.cellClass + " " + this.idToCssName(p.cellId) + " " + p.css; + this.syncRowHeights(rowIndex, rowIndex); + }, + + calcColumnWidth : function(colIndex, maxRowsToMeasure){ + var maxWidth = 0; + if(this.grid.autoSizeHeaders){ + var h = this.getHeaderCellMeasure(colIndex); + maxWidth = Math.max(maxWidth, h.scrollWidth); + } + var tb, index; + if(this.cm.isLocked(colIndex)){ + tb = this.getLockedTable(); + index = colIndex; + }else{ + tb = this.getBodyTable(); + index = colIndex - this.cm.getLockedCount(); + } + if(tb && tb.rows){ + var rows = tb.rows; + var stopIndex = Math.min(maxRowsToMeasure || rows.length, rows.length); + for(var i = 0; i < stopIndex; i++){ + var cell = rows[i].childNodes[index].firstChild; + maxWidth = Math.max(maxWidth, cell.scrollWidth); + } + } + return maxWidth + /*margin for error in IE*/ 5; + }, + /** + * Autofit a column to its content. + * @param {Number} colIndex + * @param {Boolean} forceMinSize true to force the column to go smaller if possible + */ + autoSizeColumn : function(colIndex, forceMinSize, suppressEvent){ + if(this.cm.isHidden(colIndex)){ + return; // can't calc a hidden column + } + if(forceMinSize){ + var cid = this.cm.getColumnId(colIndex); + this.css.updateRule(this.colSelector +this.idToCssName( cid), "width", this.grid.minColumnWidth + "px"); + if(this.grid.autoSizeHeaders){ + this.css.updateRule(this.hdSelector + this.idToCssName(cid), "width", this.grid.minColumnWidth + "px"); + } + } + var newWidth = this.calcColumnWidth(colIndex); + this.cm.setColumnWidth(colIndex, + Math.max(this.grid.minColumnWidth, newWidth), suppressEvent); + if(!suppressEvent){ + this.grid.fireEvent("columnresize", colIndex, newWidth); + } + }, + + /** + * Autofits all columns to their content and then expands to fit any extra space in the grid + */ + autoSizeColumns : function(){ + var cm = this.grid.colModel; + var colCount = cm.getColumnCount(); + for(var i = 0; i < colCount; i++){ + this.autoSizeColumn(i, true, true); + } + if(cm.getTotalWidth() < this.scroller.dom.clientWidth){ + this.fitColumns(); + }else{ + this.updateColumns(); + this.layout(); + } + }, + + /** + * Autofits all columns to the grid's width proportionate with their current size + * @param {Boolean} reserveScrollSpace Reserve space for a scrollbar + */ + fitColumns : function(reserveScrollSpace){ + var cm = this.grid.colModel; + var colCount = cm.getColumnCount(); + var cols = []; + var width = 0; + var i, w; + for (i = 0; i < colCount; i++){ + if(!cm.isHidden(i) && !cm.isFixed(i)){ + w = cm.getColumnWidth(i); + cols.push(i); + cols.push(w); + width += w; + } + } + var avail = Math.min(this.scroller.dom.clientWidth, this.el.getWidth()); + if(reserveScrollSpace){ + avail -= 17; + } + var frac = (avail - cm.getTotalWidth())/width; + while (cols.length){ + w = cols.pop(); + i = cols.pop(); + cm.setColumnWidth(i, Math.floor(w + w*frac), true); + } + this.updateColumns(); + this.layout(); + }, + + onRowSelect : function(rowIndex){ + var row = this.getRowComposite(rowIndex); + row.addClass("x-grid-row-selected"); + }, + + onRowDeselect : function(rowIndex){ + var row = this.getRowComposite(rowIndex); + row.removeClass("x-grid-row-selected"); + }, + + onCellSelect : function(row, col){ + var cell = this.getCell(row, col); + if(cell){ + Roo.fly(cell).addClass("x-grid-cell-selected"); + } + }, + + onCellDeselect : function(row, col){ + var cell = this.getCell(row, col); + if(cell){ + Roo.fly(cell).removeClass("x-grid-cell-selected"); + } + }, + + updateHeaderSortState : function(){ + + // sort state can be single { field: xxx, direction : yyy} + // or { xxx=>ASC , yyy : DESC ..... } + + var mstate = {}; + if (!this.ds.multiSort) { + var state = this.ds.getSortState(); + if(!state){ + return; + } + mstate[state.field] = state.direction; + // FIXME... - this is not used here.. but might be elsewhere.. + this.sortState = state; + + } else { + mstate = this.ds.sortToggle; + } + //remove existing sort classes.. + + var sc = this.sortClasses; + var hds = this.el.select(this.headerSelector).removeClass(sc); + + for(var f in mstate) { + + var sortColumn = this.cm.findColumnIndex(f); + + if(sortColumn != -1){ + var sortDir = mstate[f]; + hds.item(sortColumn).addClass(sc[sortDir == "DESC" ? 1 : 0]); + } + } + + + + }, + + + handleHeaderClick : function(g, index,e){ + + Roo.log("header click"); + + if (Roo.isTouch) { + // touch events on header are handled by context + this.handleHdCtx(g,index,e); + return; + } + + + if(this.headersDisabled){ + return; + } + var dm = g.dataSource, cm = g.colModel; + if(!cm.isSortable(index)){ + return; + } + g.stopEditing(); + + if (dm.multiSort) { + // update the sortOrder + var so = []; + for(var i = 0; i < cm.config.length; i++ ) { + + if ((typeof(dm.sortToggle[cm.config[i].dataIndex]) == 'undefined') && (index != i)) { + continue; // dont' bother, it's not in sort list or being set. + } + + so.push(cm.config[i].dataIndex); + }; + dm.sortOrder = so; + } + + + dm.sort(cm.getDataIndex(index)); + }, + + + destroy : function(){ + if(this.colMenu){ + this.colMenu.removeAll(); + Roo.menu.MenuMgr.unregister(this.colMenu); + this.colMenu.getEl().remove(); + delete this.colMenu; + } + if(this.hmenu){ + this.hmenu.removeAll(); + Roo.menu.MenuMgr.unregister(this.hmenu); + this.hmenu.getEl().remove(); + delete this.hmenu; + } + if(this.grid.enableColumnMove){ + var dds = Roo.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id]; + if(dds){ + for(var dd in dds){ + if(!dds[dd].config.isTarget && dds[dd].dragElId){ + var elid = dds[dd].dragElId; + dds[dd].unreg(); + Roo.get(elid).remove(); + } else if(dds[dd].config.isTarget){ + dds[dd].proxyTop.remove(); + dds[dd].proxyBottom.remove(); + dds[dd].unreg(); + } + if(Roo.dd.DDM.locationCache[dd]){ + delete Roo.dd.DDM.locationCache[dd]; + } + } + delete Roo.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id]; + } + } + Roo.util.CSS.removeStyleSheet(this.idToCssName(this.grid.id) + '-cssrules'); + this.bind(null, null); + Roo.EventManager.removeResizeListener(this.onWindowResize, this); + }, + + handleLockChange : function(){ + this.refresh(true); + }, + + onDenyColumnLock : function(){ + + }, + + onDenyColumnHide : function(){ + + }, + + handleHdMenuClick : function(item){ + var index = this.hdCtxIndex; + var cm = this.cm, ds = this.ds; + switch(item.id){ + case "asc": + ds.sort(cm.getDataIndex(index), "ASC"); + break; + case "desc": + ds.sort(cm.getDataIndex(index), "DESC"); + break; + case "lock": + var lc = cm.getLockedCount(); + if(cm.getColumnCount(true) <= lc+1){ + this.onDenyColumnLock(); + return; + } + if(lc != index){ + cm.setLocked(index, true, true); + cm.moveColumn(index, lc); + this.grid.fireEvent("columnmove", index, lc); + }else{ + cm.setLocked(index, true); + } + break; + case "unlock": + var lc = cm.getLockedCount(); + if((lc-1) != index){ + cm.setLocked(index, false, true); + cm.moveColumn(index, lc-1); + this.grid.fireEvent("columnmove", index, lc-1); + }else{ + cm.setLocked(index, false); + } + break; + case 'wider': // used to expand cols on touch.. + case 'narrow': + var cw = cm.getColumnWidth(index); + cw += (item.id == 'wider' ? 1 : -1) * 50; + cw = Math.max(0, cw); + cw = Math.min(cw,4000); + cm.setColumnWidth(index, cw); + break; + + default: + index = cm.getIndexById(item.id.substr(4)); + if(index != -1){ + if(item.checked && cm.getColumnCount(true) <= 1){ + this.onDenyColumnHide(); + return false; + } + cm.setHidden(index, item.checked); + } + } + return true; + }, + + beforeColMenuShow : function(){ + var cm = this.cm, colCount = cm.getColumnCount(); + this.colMenu.removeAll(); + for(var i = 0; i < colCount; i++){ + this.colMenu.add(new Roo.menu.CheckItem({ + id: "col-"+cm.getColumnId(i), + text: cm.getColumnHeader(i), + checked: !cm.isHidden(i), + hideOnClick:false + })); + } + }, + + handleHdCtx : function(g, index, e){ + e.stopEvent(); + var hd = this.getHeaderCell(index); + this.hdCtxIndex = index; + var ms = this.hmenu.items, cm = this.cm; + ms.get("asc").setDisabled(!cm.isSortable(index)); + ms.get("desc").setDisabled(!cm.isSortable(index)); + if(this.grid.enableColLock !== false){ + ms.get("lock").setDisabled(cm.isLocked(index)); + ms.get("unlock").setDisabled(!cm.isLocked(index)); + } + this.hmenu.show(hd, "tl-bl"); + }, + + handleHdOver : function(e){ + var hd = this.findHeaderCell(e.getTarget()); + if(hd && !this.headersDisabled){ + if(this.grid.colModel.isSortable(this.getCellIndex(hd))){ + this.fly(hd).addClass("x-grid-hd-over"); + } + } + }, + + handleHdOut : function(e){ + var hd = this.findHeaderCell(e.getTarget()); + if(hd){ + this.fly(hd).removeClass("x-grid-hd-over"); + } + }, + + handleSplitDblClick : function(e, t){ + var i = this.getCellIndex(t); + if(this.grid.enableColumnResize !== false && this.cm.isResizable(i) && !this.cm.isFixed(i)){ + this.autoSizeColumn(i, true); + this.layout(); + } + }, + + render : function(){ + + var cm = this.cm; + var colCount = cm.getColumnCount(); + + if(this.grid.monitorWindowResize === true){ + Roo.EventManager.onWindowResize(this.onWindowResize, this, true); + } + var header = this.renderHeaders(); + var body = this.templates.body.apply({rows:""}); + var html = this.templates.master.apply({ + lockedBody: body, + body: body, + lockedHeader: header[0], + header: header[1] + }); + + //this.updateColumns(); + + this.grid.getGridEl().dom.innerHTML = html; + + this.initElements(); + + // a kludge to fix the random scolling effect in webkit + this.el.on("scroll", function() { + this.el.dom.scrollTop=0; // hopefully not recursive.. + },this); + + this.scroller.on("scroll", this.handleScroll, this); + this.lockedBody.on("mousewheel", this.handleWheel, this); + this.mainBody.on("mousewheel", this.handleWheel, this); + + this.mainHd.on("mouseover", this.handleHdOver, this); + this.mainHd.on("mouseout", this.handleHdOut, this); + this.mainHd.on("dblclick", this.handleSplitDblClick, this, + {delegate: "."+this.splitClass}); + + this.lockedHd.on("mouseover", this.handleHdOver, this); + this.lockedHd.on("mouseout", this.handleHdOut, this); + this.lockedHd.on("dblclick", this.handleSplitDblClick, this, + {delegate: "."+this.splitClass}); + + if(this.grid.enableColumnResize !== false && Roo.grid.SplitDragZone){ + new Roo.grid.SplitDragZone(this.grid, this.lockedHd.dom, this.mainHd.dom); + } + + this.updateSplitters(); + + if(this.grid.enableColumnMove && Roo.grid.HeaderDragZone){ + new Roo.grid.HeaderDragZone(this.grid, this.lockedHd.dom, this.mainHd.dom); + new Roo.grid.HeaderDropZone(this.grid, this.lockedHd.dom, this.mainHd.dom); + } + + if(this.grid.enableCtxMenu !== false && Roo.menu.Menu){ + this.hmenu = new Roo.menu.Menu({id: this.grid.id + "-hctx"}); + this.hmenu.add( + {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"}, + {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"} + ); + if(this.grid.enableColLock !== false){ + this.hmenu.add('-', + {id:"lock", text: this.lockText, cls: "xg-hmenu-lock"}, + {id:"unlock", text: this.unlockText, cls: "xg-hmenu-unlock"} + ); + } + if (Roo.isTouch) { + this.hmenu.add('-', + {id:"wider", text: this.columnsWiderText}, + {id:"narrow", text: this.columnsNarrowText } + ); + + + } + + if(this.grid.enableColumnHide !== false){ + + this.colMenu = new Roo.menu.Menu({id:this.grid.id + "-hcols-menu"}); + this.colMenu.on("beforeshow", this.beforeColMenuShow, this); + this.colMenu.on("itemclick", this.handleHdMenuClick, this); + + this.hmenu.add('-', + {id:"columns", text: this.columnsText, menu: this.colMenu} + ); + } + this.hmenu.on("itemclick", this.handleHdMenuClick, this); + + this.grid.on("headercontextmenu", this.handleHdCtx, this); + } + + if((this.grid.enableDragDrop || this.grid.enableDrag) && Roo.grid.GridDragZone){ + this.dd = new Roo.grid.GridDragZone(this.grid, { + ddGroup : this.grid.ddGroup || 'GridDD' + }); + + } + + /* + for(var i = 0; i < colCount; i++){ + if(cm.isHidden(i)){ + this.hideColumn(i); + } + if(cm.config[i].align){ + this.css.updateRule(this.colSelector + i, "textAlign", cm.config[i].align); + this.css.updateRule(this.hdSelector + i, "textAlign", cm.config[i].align); + } + }*/ + + this.updateHeaderSortState(); + + this.beforeInitialResize(); + this.layout(true); + + // two part rendering gives faster view to the user + this.renderPhase2.defer(1, this); + }, + + renderPhase2 : function(){ + // render the rows now + this.refresh(); + if(this.grid.autoSizeColumns){ + this.autoSizeColumns(); + } + }, + + beforeInitialResize : function(){ + + }, + + onColumnSplitterMoved : function(i, w){ + this.userResized = true; + var cm = this.grid.colModel; + cm.setColumnWidth(i, w, true); + var cid = cm.getColumnId(i); + this.css.updateRule(this.colSelector + this.idToCssName(cid), "width", (w-this.borderWidth) + "px"); + this.css.updateRule(this.hdSelector + this.idToCssName(cid), "width", (w-this.borderWidth) + "px"); + this.updateSplitters(); + this.layout(); + this.grid.fireEvent("columnresize", i, w); + }, + + syncRowHeights : function(startIndex, endIndex){ + if(this.grid.enableRowHeightSync === true && this.cm.getLockedCount() > 0){ + startIndex = startIndex || 0; + var mrows = this.getBodyTable().rows; + var lrows = this.getLockedTable().rows; + var len = mrows.length-1; + endIndex = Math.min(endIndex || len, len); + for(var i = startIndex; i <= endIndex; i++){ + var m = mrows[i], l = lrows[i]; + var h = Math.max(m.offsetHeight, l.offsetHeight); + m.style.height = l.style.height = h + "px"; + } + } + }, + + layout : function(initialRender, is2ndPass){ + var g = this.grid; + var auto = g.autoHeight; + var scrollOffset = 16; + var c = g.getGridEl(), cm = this.cm, + expandCol = g.autoExpandColumn, + gv = this; + //c.beginMeasure(); + + if(!c.dom.offsetWidth){ // display:none? + if(initialRender){ + this.lockedWrap.show(); + this.mainWrap.show(); + } + return; + } + + var hasLock = this.cm.isLocked(0); + + var tbh = this.headerPanel.getHeight(); + var bbh = this.footerPanel.getHeight(); + + if(auto){ + var ch = this.getBodyTable().offsetHeight + tbh + bbh + this.mainHd.getHeight(); + var newHeight = ch + c.getBorderWidth("tb"); + if(g.maxHeight){ + newHeight = Math.min(g.maxHeight, newHeight); + } + c.setHeight(newHeight); + } + + if(g.autoWidth){ + c.setWidth(cm.getTotalWidth()+c.getBorderWidth('lr')); + } + + var s = this.scroller; + + var csize = c.getSize(true); + + this.el.setSize(csize.width, csize.height); + + this.headerPanel.setWidth(csize.width); + this.footerPanel.setWidth(csize.width); + + var hdHeight = this.mainHd.getHeight(); + var vw = csize.width; + var vh = csize.height - (tbh + bbh); + + s.setSize(vw, vh); + + var bt = this.getBodyTable(); + + if(cm.getLockedCount() == cm.config.length){ + bt = this.getLockedTable(); + } + + var ltWidth = hasLock ? + Math.max(this.getLockedTable().offsetWidth, this.lockedHd.dom.firstChild.offsetWidth) : 0; + + var scrollHeight = bt.offsetHeight; + var scrollWidth = ltWidth + bt.offsetWidth; + var vscroll = false, hscroll = false; + + this.scrollSizer.setSize(scrollWidth, scrollHeight+hdHeight); + + var lw = this.lockedWrap, mw = this.mainWrap; + var lb = this.lockedBody, mb = this.mainBody; + + setTimeout(function(){ + var t = s.dom.offsetTop; + var w = s.dom.clientWidth, + h = s.dom.clientHeight; + + lw.setTop(t); + lw.setSize(ltWidth, h); + + mw.setLeftTop(ltWidth, t); + mw.setSize(w-ltWidth, h); + + lb.setHeight(h-hdHeight); + mb.setHeight(h-hdHeight); + + if(is2ndPass !== true && !gv.userResized && expandCol){ + // high speed resize without full column calculation + + var ci = cm.getIndexById(expandCol); + if (ci < 0) { + ci = cm.findColumnIndex(expandCol); + } + ci = Math.max(0, ci); // make sure it's got at least the first col. + var expandId = cm.getColumnId(ci); + var tw = cm.getTotalWidth(false); + var currentWidth = cm.getColumnWidth(ci); + var cw = Math.min(Math.max(((w-tw)+currentWidth-2)-/*scrollbar*/(w <= s.dom.offsetWidth ? 0 : 18), g.autoExpandMin), g.autoExpandMax); + if(currentWidth != cw){ + cm.setColumnWidth(ci, cw, true); + gv.css.updateRule(gv.colSelector+gv.idToCssName(expandId), "width", (cw - gv.borderWidth) + "px"); + gv.css.updateRule(gv.hdSelector+gv.idToCssName(expandId), "width", (cw - gv.borderWidth) + "px"); + gv.updateSplitters(); + gv.layout(false, true); + } + } + + if(initialRender){ + lw.show(); + mw.show(); + } + //c.endMeasure(); + }, 10); + }, + + onWindowResize : function(){ + if(!this.grid.monitorWindowResize || this.grid.autoHeight){ + return; + } + this.layout(); + }, + + appendFooter : function(parentEl){ + return null; + }, + + sortAscText : "Sort Ascending", + sortDescText : "Sort Descending", + lockText : "Lock Column", + unlockText : "Unlock Column", + columnsText : "Columns", + + columnsWiderText : "Wider", + columnsNarrowText : "Thinner" +}); + + +Roo.grid.GridView.ColumnDragZone = function(grid, hd){ + Roo.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null); + this.proxy.el.addClass('x-grid3-col-dd'); +}; + +Roo.extend(Roo.grid.GridView.ColumnDragZone, Roo.grid.HeaderDragZone, { + handleMouseDown : function(e){ + + }, + + callHandleMouseDown : function(e){ + Roo.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e); + } +}); + \ No newline at end of file