From d81ddeecb21edfe27401017eb4d0cc01dfae425b Mon Sep 17 00:00:00 2001 From: Alan Knowles Date: Mon, 26 Jul 2021 14:57:57 +0800 Subject: [PATCH] Fix #6874 - Grid column resize --- Roo.js | 25 +- Roo/bootstrap/Table.js | 540 +- Roo/bootstrap/Table/AbstractSelectionModel.js | 48 +- Roo/bootstrap/Table/RowSelectionModel.js | 9 +- Roo/grid/ColumnModel.js | 49 +- Roo/grid/RowSelectionModel.js | 116 +- Roo/grid/SplitDragZone.js | 57 +- buildSDK/dependancy_bootstrap.txt | 7 +- css-bootstrap4/bootstrap.css.map | 2 +- css-bootstrap4/bootstrap.min.css.map | 2 +- css-bootstrap4/roojs-bootstrap-debug.css | 34 +- css-bootstrap4/roojs-bootstrap-debug.css.map | 4 +- css-bootstrap4/roojs-bootstrap.css | 2 +- css-bootstrap4/roojs-bootstrap.css.map | 4 +- css-bootstrap4/sb-admin-2.css | 84 +- css-bootstrap4/sb-admin-2.css.map | 4 +- css-bootstrap4/sb-admin-2.min.css | 2 +- css-bootstrap4/sb-admin-2.min.css.map | 4 +- docs/json/roodata.json | 1760 ++-- docs/src/Roo.js.html | 25 +- docs/src/Roo_bootstrap_Table.js.html | 607 +- ...strap_Table_AbstractSelectionModel.js.html | 49 +- docs/src/Roo_grid_ColumnModel.js.html | 49 +- docs/src/Roo_grid_RowSelectionModel.js.html | 116 +- docs/src/Roo_grid_SplitDragZone.js.html | 57 +- ...Roo.bootstrap.Table.RowSelectionModel.json | 351 +- docs/symbols/Roo.bootstrap.Table.json | 268 +- docs/symbols/Roo.grid.ColumnModel.json | 68 +- docs/symbols/Roo.grid.SplitDragZone.json | 1424 ++++ docs/symbols/Roo.json | 14 + docs/tree.json | 18 +- roojs-all.js | 56 +- roojs-bootstrap-debug.js | 7257 +++++++++-------- roojs-bootstrap.js | 178 +- roojs-core-debug.js | 25 +- roojs-core.js | 3 +- roojs-debug.js | 247 +- roojs-ui-debug.js | 222 +- roojs-ui.js | 53 +- scss/roojs-bootstrap/table.scss | 37 + 40 files changed, 8431 insertions(+), 5446 deletions(-) create mode 100644 docs/symbols/Roo.grid.SplitDragZone.json diff --git a/Roo.js b/Roo.js index 67147c5ee6..bb98fe5ec8 100644 --- a/Roo.js +++ b/Roo.js @@ -668,7 +668,30 @@ Roo.factory(conf, Roo.data); { var node = Roo.DomQuery.selectNode(selector,root); return node ? Roo.get(node) : new Roo.Element(false); - } + }, + /** + * Find the current bootstrap width Grid size + * Note xs is the default for smaller.. - this is currently used by grids to render correct columns + * @returns {String} (xs|sm|md|lg|xl) + */ + + getGridSize : function() + { + var w = Roo.lib.Dom.getViewWidth(); + switch(true) { + case w > 1200: + return 'xl'; + case w > 992: + return 'lg'; + case w > 768: + return 'md'; + case w > 576: + return 'sm'; + default: + return 'xs' + } + + } }); diff --git a/Roo/bootstrap/Table.js b/Roo/bootstrap/Table.js index 2cb7520fb9..b61a7dc27f 100644 --- a/Roo/bootstrap/Table.js +++ b/Roo/bootstrap/Table.js @@ -1,26 +1,74 @@ -/* - * - LGPL - * - * table - * - */ - /** * @class Roo.bootstrap.Table + * @licence LGBL * @extends Roo.bootstrap.Component - * Bootstrap Table class + * Bootstrap Table class. This class represents the primary interface of a component based grid control. + * Similar to Roo.grid.Grid + *

+ var table = Roo.factory({
+    xtype : 'Table',
+    xns : Roo.bootstrap,
+    autoSizeColumns: true,
+    
+    
+    store : {
+        xtype : 'Store',
+        xns : Roo.data,
+        remoteSort : true,
+        sortInfo : { direction : 'ASC', field: 'name' },
+        proxy : {
+           xtype : 'HttpProxy',
+           xns : Roo.data,
+           method : 'GET',
+           url : 'https://example.com/some.data.url.json'
+        },
+        reader : {
+           xtype : 'JsonReader',
+           xns : Roo.data,
+           fields : [ 'id', 'name', whatever' ],
+           id : 'id',
+           root : 'data'
+        }
+    },
+    cm : [
+        {
+            xtype : 'ColumnModel',
+            xns : Roo.grid,
+            align : 'center',
+            cursor : 'pointer',
+            dataIndex : 'is_in_group',
+            header : "Name",
+            sortable : true,
+            renderer : function(v, x , r) {  
+            
+                return String.format("{0}", v)
+            }
+            width : 3
+        } // more columns..
+    ],
+    selModel : {
+        xtype : 'RowSelectionModel',
+        xns : Roo.bootstrap.Table
+        // you can add listeners to catch selection change here....
+    }
+     
+
+ });
+ // set any options
+ grid.render(Roo.get("some-div"));
+
+ +Currently the Table uses multiple headers to try and handle XL / Medium etc... styling + + + + * + * @cfg {Roo.grid.RowSelectionModel|Roo.grid.CellSelectionModel} sm The selection model to use (cell selection is not supported yet) + * @cfg {Roo.data.Store|Roo.data.SimpleStore} store The data store to use + * @cfg {Roo.grid.ColumnModel} cm[] A column for th grid. + * * @cfg {String} cls table class - * @cfg {String} align (left|center|right) Specifies the alignment of a table according to surrounding text - * @cfg {String} bgcolor Specifies the background color for a table - * @cfg {Number} border Specifies whether the table cells should have borders or not - * @cfg {Number} cellpadding Specifies the space between the cell wall and the cell content - * @cfg {Number} cellspacing Specifies the space between cells - * @cfg {String} frame Specifies which parts of the outside borders that should be visible - * @cfg {String} rules Specifies which parts of the inside borders that should be visible - * @cfg {String} sortable Specifies that the table should be sortable - * @cfg {String} summary Specifies a summary of the content of a table - * @cfg {Number} width Specifies the width of a table - * @cfg {String} layout table layout (auto | fixed | initial | inherit) + * * * @cfg {boolean} striped Should the rows be alternative striped * @cfg {boolean} bordered Add borders to the table @@ -36,28 +84,30 @@ * @cfg {Roo.bootstrap.PagingToolbar} footer a paging toolbar * @cfg {Boolean} lazyLoad auto load data while scrolling to the end (default false) * @cfg {Boolean} auto_hide_footer auto hide footer if only one page (default false) - + * @cfg {Boolean} enableColumnResize default true if columns can be resized (drag/drop) + * @cfg {Number} minColumnWidth default 50 pixels minimum column width * * @constructor * Create a new Table * @param {Object} config The config object */ -Roo.bootstrap.Table = function(config){ +Roo.bootstrap.Table = function(config) +{ Roo.bootstrap.Table.superclass.constructor.call(this, config); - - - + // BC... this.rowSelection = (typeof(config.rowSelection) != 'undefined') ? config.rowSelection : this.rowSelection; this.cellSelection = (typeof(config.cellSelection) != 'undefined') ? config.cellSelection : this.cellSelection; this.headerShow = (typeof(config.thead) != 'undefined') ? config.thead : this.headerShow; this.footerShow = (typeof(config.tfoot) != 'undefined') ? config.tfoot : this.footerShow; + this.view = this; // compat with grid. + this.sm = this.sm || {xtype: 'RowSelectionModel'}; if (this.sm) { this.sm.grid = this; - this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table); + this.selModel = Roo.factory(this.sm, Roo.grid); this.sm = this.selModel; this.sm.xmodule = this.xmodule || false; } @@ -181,23 +231,21 @@ Roo.bootstrap.Table = function(config){ * @param {Number} columnIndex * @param {Roo.EventObject} e */ - "headercontextmenu" : true + "headercontextmenu" : true, + /** + * @event mousedown + * The raw mousedown event for the entire grid. + * @param {Roo.EventObject} e + */ + "mousedown" : true + }); }; Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { cls: false, - align: false, - bgcolor: false, - border: false, - cellpadding: false, - cellspacing: false, - frame: false, - rules: false, - sortable: false, - summary: false, - width: false, + striped : false, scrollBody : false, bordered: false, @@ -210,15 +258,20 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { loadMask : false, footerShow : true, headerShow : true, + enableColumnResize: true, rowSelection : false, cellSelection : false, layout : false, + + minColumnWidth : 50, // Roo.Element - the tbody - mainBody: false, - // Roo.Element - thead element - mainHead: false, + bodyEl: false, // Roo.Element - thead element + headEl: false, // Roo.Element - thead element + resizeProxy : false, // proxy element for dragging? + + container: false, // used by gridpanel... @@ -228,15 +281,18 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { auto_hide_footer : false, + view: false, // actually points to this.. + getAutoCreate : function() { var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this)); cfg = { tag: 'table', - cls : 'table', + cls : 'table', cn : [] }; + // this get's auto added by panel.Grid if (this.scrollBody) { cfg.cls += ' table-body-fixed'; } @@ -253,6 +309,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { if (this.condensed) { cfg.cls += ' table-condensed'; } + if (this.responsive) { cfg.cls += ' table-responsive'; } @@ -261,24 +318,6 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { cfg.cls+= ' ' +this.cls; } - // this lot should be simplifed... - var _t = this; - var cp = [ - 'align', - 'bgcolor', - 'border', - 'cellpadding', - 'cellspacing', - 'frame', - 'rules', - 'sortable', - 'summary', - 'width' - ].forEach(function(k) { - if (_t[k]) { - cfg[k] = _t[k]; - } - }); if (this.layout) { @@ -314,8 +353,8 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { //Roo.log('initEvents with ds!!!!'); - this.mainBody = this.el.select('tbody', true).first(); - this.mainHead = this.el.select('thead', true).first(); + this.bodyEl = this.el.select('tbody', true).first(); + this.headEl = this.el.select('thead', true).first(); this.mainFoot = this.el.select('tfoot', true).first(); @@ -325,8 +364,6 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { e.on('click', this.sort, this); }, this); - this.mainBody.on("click", this.onClick, this); - this.mainBody.on("dblclick", this.onDblClick, this); // why is this done????? = it breaks dialogs?? //this.parent().el.setStyle('position', 'relative'); @@ -353,14 +390,119 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { this.el.on("contextmenu", this.onContextMenu, this); - this.mainBody.on('scroll', this.onBodyScroll, this); this.cm.on("headerchange", this.onHeaderChange, this); - this.cm.on("hiddenchange", this.onHiddenChange, this, arguments); + + //?? does bodyEl get replaced on render? + this.bodyEl.on("click", this.onClick, this); + this.bodyEl.on("dblclick", this.onDblClick, this); + this.bodyEl.on('scroll', this.onBodyScroll, this); + + // guessing mainbody will work - this relays usually caught by selmodel at present. + this.relayEvents(this.bodyEl, ["mousedown","mouseup","mouseover","mouseout","keypress"]); + + + this.resizeProxy = Roo.get(document.body).createChild({ cls:"x-grid-resize-proxy", html: ' ' }); + + + if(this.headEl && this.enableColumnResize !== false && Roo.grid.SplitDragZone){ + new Roo.grid.SplitDragZone(this, this.headEl.dom, false); // not sure what 'lockedHd is for this implementation..) + } + + this.initCSS(); + }, + // Compatibility with grid - we implement all the view features at present. + getView : function() + { + return this; + }, + + initCSS : function() + { + + + var cm = this.cm, styles = []; + this.CSS.removeStyleSheet(this.id + '-cssrules'); + var headHeight = this.headEl ? this.headEl.dom.clientHeight : 0; + // we can honour xs/sm/md/xl as widths... + // we first have to decide what widht we are currently at... + var sz = Roo.getGridSize(); + + var total = 0; + var last = -1; + var cols = []; // visable cols. + var total_abs = 0; + for(var i = 0, len = cm.getColumnCount(); i < len; i++) { + var w = cm.getColumnWidth(i, false); + if(cm.isHidden(i)){ + cols.push( { rel : false, abs : 0 }); + continue; + } + if (w !== false) { + cols.push( { rel : false, abs : w }); + total_abs += w; + last = i; // not really.. + continue; + } + var w = cm.getColumnWidth(i, sz); + if (w > 0) { + last = i + } + total += w; + cols.push( { rel : w, abs : false }); + } + + var avail = this.bodyEl.dom.clientWidth - total_abs; + + var unitWidth = Math.floor(avail / total); + var rem = avail - (unitWidth * total); + + var hidden, width, pos = 0 , splithide , left; + for(var i = 0, len = cm.getColumnCount(); i < len; i++) { + + hidden = 'display:none;'; + left = ''; + width = 'width:0px;'; + splithide = ''; + if(!cm.isHidden(i)){ + hidden = ''; + + + // we can honour xs/sm/md/xl ? + var w = cols[i].rel == false ? cols[i].abs : (cols[i].rel * unitWidth); + if (w===0) { + hidden = 'display:none;'; + } + // width should return a small number... + if (i == last) { + w+=rem; // add the remaining with.. + } + pos += w; + left = "left:" + (pos -4) + "px;"; + width = "width:" + w+ "px;"; + + } + + styles.push( '#' , this.id , ' .x-col-' , i, " {", cm.config[i].css, width, hidden, "}\n" ); + if (this.headEl) { + if (i == last) { + splithide = 'display:none;'; + } + + styles.push('#' , this.id , ' .x-hcol-' , i, " { ", width, hidden," }\n", + '#' , this.id , ' .x-grid-split-' , i, " { ", left, splithide,'height:', (headHeight - 4), "px;}\n" + ); + } + + } + Roo.log(styles.join('')); + this.CSS.createStyleSheet( styles.join(''), this.id + '-cssrules'); }, + + onContextMenu : function(e, t) { this.processEvent("contextmenu", e); @@ -537,7 +679,19 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { this.fireEvent('rowdblclick', this, row, rowIndex, e); } }, - + findRowIndex : function(el) + { + var cell = Roo.get(el); + if(!cell) { + return false; + } + var row = cell.findParent('tr', false, true); + + if(!row || typeof(row) == 'undefined'){ + return false; + } + return this.getRowIndex(row); + }, sort : function(e,el) { var col = Roo.get(el); @@ -595,7 +749,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var hh = ''; if(typeof(config.sortable) != 'undefined' && config.sortable){ - c.cls = 'sortable'; + c.cls += ' sortable'; c.html = '' + c.html; } @@ -629,9 +783,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { c.colspan = config.colspan; } - if(typeof(config.hidden) != 'undefined' && config.hidden){ - c.style += ' display:none;'; - } + // hidden is handled by CSS now if(typeof(config.dataIndex) != 'undefined'){ c.sort = config.dataIndex; @@ -643,16 +795,21 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { c.style += ' text-align:' + config.align + ';'; } - if(typeof(config.width) != 'undefined'){ + /* width is done in CSS + *if(typeof(config.width) != 'undefined'){ c.style += ' width:' + config.width + 'px;'; this.totalWidth += config.width; } else { this.totalWidth += 100; // assume minimum of 100 per column? } + */ if(typeof(config.cls) != 'undefined'){ c.cls = (typeof(c.cls) == 'undefined') ? config.cls : (c.cls + ' ' + config.cls); } + // this is the bit that doesnt reall work at all... + + /* ['xs','sm','md','lg'].map(function(size){ @@ -672,6 +829,13 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { }); + */ + // at the end? + + c.html +=' '; + + + header.cn.push(c) } @@ -744,7 +908,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { } }); - var tbody = this.mainBody; + var tbody = this.bodyEl; if(ds.getCount() > 0){ ds.data.each(function(d,rowIndex){ @@ -786,6 +950,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { this.fireEvent('rowsrendered', this); this.autoSize(); + + this.initCSS(); /// resize cols + + }, @@ -799,7 +967,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { if(isUpdate !== true){ this.fireEvent("beforerowremoved", this, index, record); } - var bt = this.mainBody.dom; + var bt = this.bodyEl.dom; var rows = this.el.select('tbody > tr', true).elements; @@ -823,7 +991,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { { //Roo.log('on Add called'); // - note this does not handle multiple adding very well.. - var bt = this.mainBody.dom; + var bt = this.bodyEl.dom; for (var i =0 ; i < records.length;i++) { //Roo.log('call insert row Add called on ' + rowIndex + ':' + i); //Roo.log(records[i]); @@ -854,6 +1022,120 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { //this.layout(); this.fireEvent("rowupdated", this, index, record); }, + // private - called by RowSelection + onRowSelect : function(rowIndex){ + var row = this.getRowDom(rowIndex); + row.addClass(['bg-info','info']); + }, + // private - called by RowSelection + onRowDeselect : function(rowIndex) + { + if (rowIndex < 0) { + return; + } + var row = this.getRowDom(rowIndex); + row.removeClass(['bg-info','info']); + }, + /** + * Focuses the specified row. + * @param {Number} row The row index + */ + focusRow : function(row) + { + //Roo.log('GridView.focusRow'); + var x = this.bodyEl.dom.scrollLeft; + this.focusCell(row, 0, false); + this.bodyEl.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); + // not sure what focusEL achives = it's a pos relative + //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.cm; + while(cm.isHidden(col)){ + col++; + } + + var el = this.getCellDom(row, col); + if(!el){ + return null; + } + var c = this.bodyEl.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 ch = 0; //?? header is not withing the area? + 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; + }, + insertRow : function(dm, rowIndex, isUpdate){ @@ -863,7 +1145,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { //var s = this.getScrollState(); var row = this.renderRow(this.cm, this.store, rowIndex); // insert before rowIndex.. - var e = this.mainBody.createChild(row,this.getRowDom(rowIndex)); + var e = this.bodyEl.createChild(row,this.getRowDom(rowIndex)); var _this = this; @@ -890,6 +1172,17 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { return (typeof(rows[rowIndex]) == 'undefined') ? false : rows[rowIndex]; }, + getCellDom : function(rowIndex, colIndex) + { + var row = this.getRowDom(rowIndex); + if (row === false) { + return false; + } + var cols = row.select('td', true).elements; + return (typeof(cols[colIndex]) == 'undefined') ? false : cols[colIndex]; + + }, + // returns the object tree for a tr.. @@ -953,9 +1246,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { td.colspan = config.colspan; } - if(typeof(config.hidden) != 'undefined' && config.hidden){ - td.style += ' display:none;'; - } + if(typeof(config.align) != 'undefined' && config.align.length){ td.style += ' text-align:' + config.align + ';'; @@ -963,10 +1254,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { if(typeof(config.valign) != 'undefined' && config.valign.length){ td.style += ' vertical-align:' + config.valign + ';'; } - + /* if(typeof(config.width) != 'undefined'){ td.style += ' width:' + config.width + 'px;'; } + */ if(typeof(config.cursor) != 'undefined'){ td.style += ' cursor:' + config.cursor + ';'; @@ -975,7 +1267,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { if(typeof(config.cls) != 'undefined'){ td.cls = (typeof(td.cls) == 'undefined') ? config.cls : (td.cls + ' ' + config.cls); } - + /* ['xs','sm','md','lg'].map(function(size){ if(typeof(config[size]) == 'undefined'){ @@ -996,7 +1288,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { }); - + */ row.cn.push(td); } @@ -1027,14 +1319,15 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { */ setRowVisibility : function(rowIndex, state) { - var bt = this.mainBody.dom; + var bt = this.bodyEl.dom; var rows = this.el.select('tbody > tr', true).elements; if(typeof(rows[rowIndex]) == 'undefined'){ return; } - rows[rowIndex].dom.style.display = state ? '' : 'none'; + rows[rowIndex][ state ? 'removeClass' : 'addClass']('d-none'); + }, @@ -1065,7 +1358,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { }) } }, - + /** + * get the Row Index from a dom element. + * @param {Roo.Element} row The row to look for + * @returns {Number} the row + */ getRowIndex : function(row) { var rowIndex = -1; @@ -1079,6 +1376,29 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { }); return rowIndex; + }, + /** + * get the header TH element for columnIndex + * @param {Number} columnIndex + * @returns {Roo.Element} + */ + getHeaderIndex: function(colIndex) + { + var cols = this.headEl.select('th', true).elements; + return cols[colIndex]; + }, + /** + * get the Column Index from a dom element. (using regex on x-hcol-{colid}) + * @param {domElement} cell to look for + * @returns {Number} the column + */ + getCellIndex : function(cell) + { + var id = String(cell.className).match(Roo.bootstrap.Table.cellRE); + if(id){ + return parseInt(id[1], 10); + } + return 0; }, /** * Returns the grid's underlying element = used by panel.Grid @@ -1116,6 +1436,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { } cw = Math.max(cw, this.totalWidth); this.getGridEl().select('tbody tr',true).setWidth(cw); + this.initCSS(); // resize 'expandable coloumn? @@ -1124,21 +1445,21 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { }, onBodyScroll: function() { - //Roo.log("body scrolled');" + this.mainBody.dom.scrollLeft); - if(this.mainHead){ - this.mainHead.setStyle({ + //Roo.log("body scrolled');" + this.bodyEl.dom.scrollLeft); + if(this.headEl){ + this.headEl.setStyle({ 'position' : 'relative', - 'left': (-1* this.mainBody.dom.scrollLeft) + 'px' + 'left': (-1* this.bodyEl.dom.scrollLeft) + 'px' }); } if(this.lazyLoad){ - var scrollHeight = this.mainBody.dom.scrollHeight; + var scrollHeight = this.bodyEl.dom.scrollHeight; - var scrollTop = Math.ceil(this.mainBody.getScroll().top); + var scrollTop = Math.ceil(this.bodyEl.getScroll().top); - var height = this.mainBody.getHeight(); + var height = this.bodyEl.getHeight(); if(scrollHeight - height == scrollTop) { @@ -1158,19 +1479,43 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { } }, - + onColumnSplitterMoved : function(i, diff) + { + this.userResized = true; + + var cm = this.colModel; + + var w = this.getHeaderIndex(i).getWidth() + diff; + + + cm.setColumnWidth(i, w, true); + this.initCSS(); + //var cid = cm.getColumnId(i); << not used in this version? + /* Roo.log(['#' + this.id + ' .x-col-' + i, "width", w + "px"]); + + this.CSS.updateRule( '#' + this.id + ' .x-col-' + i, "width", w + "px"); + this.CSS.updateRule('#' + this.id + ' .x-hcol-' + i, "width", w + "px"); + this.CSS.updateRule('#' + this.id + ' .x-grid-split-' + i, "left", w + "px"); +*/ + //this.updateSplitters(); + //this.layout(); << ?? + this.fireEvent("columnresize", i, w); + }, onHeaderChange : function() { var header = this.renderHeader(); var table = this.el.select('table', true).first(); - this.mainHead.remove(); - this.mainHead = table.createChild(header, this.mainBody, false); + this.headEl.remove(); + this.headEl = table.createChild(header, this.bodyEl, false); Roo.each(this.el.select('thead th.sortable', true).elements, function(e){ e.on('click', this.sort, this); }, this); + if(this.enableColumnResize !== false && Roo.grid.SplitDragZone){ + new Roo.grid.SplitDragZone(this, this.headEl.dom, false); // not sure what 'lockedHd is for this implementation..) + } }, @@ -1257,6 +1602,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { } }); - +// currently only used to find the split on drag.. +Roo.bootstrap.Table.cellRE = /(?:.*?)x-grid-(?:hd|cell|split)-([\d]+)(?:.*?)/; - \ No newline at end of file +/** + * @depricated +*/ +Roo.bootstrap.Table.AbstractSelectionModel = Roo.grid.AbstractSelectionModel; +Roo.bootstrap.Table.RowSelectionModel = Roo.grid.RowSelectionModel; diff --git a/Roo/bootstrap/Table/AbstractSelectionModel.js b/Roo/bootstrap/Table/AbstractSelectionModel.js index 4fc52b9b73..6d80350cbd 100644 --- a/Roo/bootstrap/Table/AbstractSelectionModel.js +++ b/Roo/bootstrap/Table/AbstractSelectionModel.js @@ -1,49 +1,5 @@ /** - * @class Roo.bootstrap.Table.AbstractSelectionModel - * @extends Roo.util.Observable - * Abstract base class for grid SelectionModels. It provides the interface that should be - * implemented by descendant classes. This class should not be directly instantiated. - * @constructor + * @depricated + * Just use grid selection model */ -Roo.bootstrap.Table.AbstractSelectionModel = function(){ - this.locked = false; - Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this); -}; - - -Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable, { - /** @ignore Called by the grid automatically. Do not call directly. */ - init : function(grid){ - this.grid = grid; - this.initEvents(); - }, - - /** - * Locks the selections. - */ - lock : function(){ - this.locked = true; - }, - - /** - * Unlocks the selections. - */ - unlock : function(){ - this.locked = false; - }, - - /** - * Returns true if the selections are locked. - * @return {Boolean} - */ - isLocked : function(){ - return this.locked; - }, - - - initEvents : function () - { - - } -}); \ No newline at end of file diff --git a/Roo/bootstrap/Table/RowSelectionModel.js b/Roo/bootstrap/Table/RowSelectionModel.js index ee342da9d3..eaf7c33bfe 100644 --- a/Roo/bootstrap/Table/RowSelectionModel.js +++ b/Roo/bootstrap/Table/RowSelectionModel.js @@ -1,11 +1,8 @@ /** - * @extends Roo.bootstrap.Table.AbstractSelectionModel - * @class Roo.bootstrap.Table.RowSelectionModel - * The default SelectionModel used by {@link Roo.bootstrap.Table}. - * It supports multiple selections and keyboard selection/navigation. - * @constructor - * @param {Object} config + * @deprecated + * + * */ Roo.bootstrap.Table.RowSelectionModel = function(config){ diff --git a/Roo/grid/ColumnModel.js b/Roo/grid/ColumnModel.js index a779a1b6a8..ef3dd49363 100644 --- a/Roo/grid/ColumnModel.js +++ b/Roo/grid/ColumnModel.js @@ -108,6 +108,21 @@ Roo.grid.ColumnModel = function(config){ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, { /** * @cfg {String} header The header text to display in the Grid view. + */ + /** + * @cfg {String} xsHeader Header at Bootsrap Extra Small width (default for all) + */ + /** + * @cfg {String} smHeader Header at Bootsrap Small width + */ + /** + * @cfg {String} mdHeader Header at Bootsrap Medium width + */ + /** + * @cfg {String} lgHeader Header at Bootsrap Large width + */ + /** + * @cfg {String} xlHeader Header at Bootsrap extra Large width */ /** * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s @@ -157,16 +172,19 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, { * @cfg {String} tooltip (Optional) */ /** - * @cfg {Number} xs (Optional) + * @cfg {Number} xs (Optional) can be '0' for hidden at this size (number less than 12) */ /** - * @cfg {Number} sm (Optional) + * @cfg {Number} sm (Optional) can be '0' for hidden at this size (number less than 12) */ /** - * @cfg {Number} md (Optional) + * @cfg {Number} md (Optional) can be '0' for hidden at this size (number less than 12) */ /** - * @cfg {Number} lg (Optional) + * @cfg {Number} lg (Optional) can be '0' for hidden at this size (number less than 12) + */ + /** + * @cfg {Number} xl (Optional) can be '0' for hidden at this size (number less than 12) */ /** * Returns the id of the column at the specified index. @@ -349,10 +367,29 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, { /** * Returns the width for the specified column. * @param {Number} col The column index + * @param (optional) {String} gridSize bootstrap width size. * @return {Number} */ - getColumnWidth : function(col){ - return this.config[col].width * 1 || this.defaultWidth; + getColumnWidth : function(col, gridSize) + { + var cfg = this.config[col]; + + if (typeof(gridSize) == 'undefined') { + return cfg.width * 1 || this.defaultWidth; + } + if (gridSize === false) { // if we set it.. + return cfg.width || false; + } + var sizes = ['xl', 'lg', 'md', 'sm', 'xs']; + + for(var i = sizes.indexOf(gridSize); i < sizes.length; i++) { + if (typeof(cfg[ sizes[i] ] ) == 'undefined') { + continue; + } + return cfg[ sizes[i] ]; + } + return 1; + }, /** diff --git a/Roo/grid/RowSelectionModel.js b/Roo/grid/RowSelectionModel.js index ab87cce312..032e884b25 100644 --- a/Roo/grid/RowSelectionModel.js +++ b/Roo/grid/RowSelectionModel.js @@ -27,39 +27,39 @@ Roo.grid.RowSelectionModel = function(config){ this.addEvents({ /** - * @event selectionchange - * Fires when the selection changes - * @param {SelectionModel} this - */ - "selectionchange" : true, - /** - * @event afterselectionchange - * Fires after the selection changes (eg. by key press or clicking) - * @param {SelectionModel} this - */ - "afterselectionchange" : true, - /** - * @event beforerowselect - * Fires when a row is selected being selected, return false to cancel. - * @param {SelectionModel} this - * @param {Number} rowIndex The selected index - * @param {Boolean} keepExisting False if other selections will be cleared - */ - "beforerowselect" : true, - /** - * @event rowselect - * Fires when a row is selected. - * @param {SelectionModel} this - * @param {Number} rowIndex The selected index - * @param {Roo.data.Record} r The record - */ - "rowselect" : true, - /** - * @event rowdeselect - * Fires when a row is deselected. - * @param {SelectionModel} this - * @param {Number} rowIndex The selected index - */ + * @event selectionchange + * Fires when the selection changes + * @param {SelectionModel} this + */ + "selectionchange" : true, + /** + * @event afterselectionchange + * Fires after the selection changes (eg. by key press or clicking) + * @param {SelectionModel} this + */ + "afterselectionchange" : true, + /** + * @event beforerowselect + * Fires when a row is selected being selected, return false to cancel. + * @param {SelectionModel} this + * @param {Number} rowIndex The selected index + * @param {Boolean} keepExisting False if other selections will be cleared + */ + "beforerowselect" : true, + /** + * @event rowselect + * Fires when a row is selected. + * @param {SelectionModel} this + * @param {Number} rowIndex The selected index + * @param {Roo.data.Record} r The record + */ + "rowselect" : true, + /** + * @event rowdeselect + * Fires when a row is deselected. + * @param {SelectionModel} this + * @param {Number} rowIndex The selected index + */ "rowdeselect" : true }); Roo.grid.RowSelectionModel.superclass.constructor.call(this); @@ -81,7 +81,8 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { }else{ // allow click to work like normal this.grid.on("rowclick", this.handleDragableRowClick, this); } - + // bootstrap does not have a view.. + var view = this.grid.view ? this.grid.view : this.grid; this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), { "up" : function(e){ if(!e.shiftKey){ @@ -89,7 +90,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { }else if(this.last !== false && this.lastActive !== false){ var last = this.last; this.selectRange(this.last, this.lastActive-1); - this.grid.getView().focusRow(this.lastActive); + view.focusRow(this.lastActive); if(last !== false){ this.last = last; } @@ -104,7 +105,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { }else if(this.last !== false && this.lastActive !== false){ var last = this.last; this.selectRange(this.last, this.lastActive+1); - this.grid.getView().focusRow(this.lastActive); + view.focusRow(this.lastActive); if(last !== false){ this.last = last; } @@ -116,7 +117,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { scope: this }); - var view = this.grid.view; + view.on("refresh", this.onRefresh, this); view.on("rowupdated", this.onRowUpdated, this); view.on("rowremoved", this.onRemove, this); @@ -124,7 +125,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { // private onRefresh : function(){ - var ds = this.grid.dataSource, i, v = this.grid.view; + var ds = this.grid.ds, i, v = this.grid.view; var s = this.selections; s.each(function(r){ if((i = ds.indexOfId(r.id)) != -1){ @@ -157,7 +158,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { if(!keepExisting){ this.clearSelections(); } - var ds = this.grid.dataSource; + var ds = this.grid.ds; for(var i = 0, len = records.length; i < len; i++){ this.selectRow(ds.indexOf(records[i]), true); } @@ -183,7 +184,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { * @param {Boolean} keepExisting (optional) True to keep existing selections */ selectLastRow : function(keepExisting){ - this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting); + this.selectRow(this.grid.ds.getCount() - 1, keepExisting); }, /** @@ -191,9 +192,10 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { * @param {Boolean} keepExisting (optional) True to keep existing selections */ selectNext : function(keepExisting){ - if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){ + if(this.last !== false && (this.last+1) < this.grid.ds.getCount()){ this.selectRow(this.last+1, keepExisting); - this.grid.getView().focusRow(this.last); + var view = this.grid.view ? this.grid.view : this.grid; + view.focusRow(this.last); } }, @@ -204,7 +206,8 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { selectPrevious : function(keepExisting){ if(this.last){ this.selectRow(this.last-1, keepExisting); - this.grid.getView().focusRow(this.last); + var view = this.grid.view ? this.grid.view : this.grid; + view.focusRow(this.last); } }, @@ -233,7 +236,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { return; } if(fast !== true){ - var ds = this.grid.dataSource; + var ds = this.grid.ds; var s = this.selections; s.each(function(r){ this.deselectRow(ds.indexOfId(r.id)); @@ -254,7 +257,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { return; } this.selections.clear(); - for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){ + for(var i = 0, len = this.grid.ds.getCount(); i < len; i++){ this.selectRow(i, true); } }, @@ -273,7 +276,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { * @return {Boolean} */ isSelected : function(index){ - var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index; + var r = typeof index == "number" ? this.grid.ds.getAt(index) : index; return (r && this.selections.key(r.id) ? true : false); }, @@ -287,8 +290,10 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { }, // private - handleMouseDown : function(e, t){ - var view = this.grid.getView(), rowIndex; + handleMouseDown : function(e, t) + { + var view = this.grid.view ? this.grid.view : this.grid; + var rowIndex; if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){ return; }; @@ -315,7 +320,8 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { { if(e.button === 0 && !e.shiftKey && !e.ctrlKey) { this.selectRow(rowIndex, false); - grid.view.focusRow(rowIndex); + var view = this.grid.view ? this.grid.view : this.grid; + view.focusRow(rowIndex); this.fireEvent("afterselectionchange", this); } }, @@ -378,18 +384,19 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { * @param {Boolean} keepExisting (optional) True to keep existing selections */ selectRow : function(index, keepExisting, preventViewNotify){ - if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) { + if(this.locked || (index < 0 || index >= this.grid.ds.getCount())) { return; } if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){ if(!keepExisting || this.singleSelect){ this.clearSelections(); } - var r = this.grid.dataSource.getAt(index); + var r = this.grid.ds.getAt(index); this.selections.add(r); this.last = this.lastActive = index; if(!preventViewNotify){ - this.grid.getView().onRowSelect(index); + var view = this.grid.view ? this.grid.view : this.grid; + view.onRowSelect(index); } this.fireEvent("rowselect", this, index, r); this.fireEvent("selectionchange", this); @@ -410,10 +417,11 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, { if(this.lastActive == index){ this.lastActive = false; } - var r = this.grid.dataSource.getAt(index); + var r = this.grid.ds.getAt(index); this.selections.remove(r); if(!preventViewNotify){ - this.grid.getView().onRowDeselect(index); + var view = this.grid.view ? this.grid.view : this.grid; + view.onRowDeselect(index); } this.fireEvent("rowdeselect", this, index); this.fireEvent("selectionchange", this); diff --git a/Roo/grid/SplitDragZone.js b/Roo/grid/SplitDragZone.js index 5f11ed589b..ec7daf3204 100644 --- a/Roo/grid/SplitDragZone.js +++ b/Roo/grid/SplitDragZone.js @@ -8,19 +8,34 @@ * Fork - LGPL *