index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <title>ExtJS Merge Cells</title> <link type="text/css" rel="stylesheet" href="../extjs4/resources/css/ext-all-neptune.css" /> <link type="text/css" rel="stylesheet" href="../extjs4/resources/theme/ext-theme-neptune-all.css" /> <script type="text/javascript" src="../extjs4/ext-all-debug.js"></script> <script type="text/javascript" src="../MergeCellTable.js"></script> <script type="text/javascript" src="../MergeCellPanel.js"></script> <script type="text/javascript" src="example.js"></script> <style type="text/css"> .x-grid-td { border-width: 0; overflow: hidden; vertical-align: middle; } </style> </head> <body> </body> </html>
example.js
Ext.onReady(function() { Ext.create('Ext.data.Store', { storeId:'simpsonsStore', fields:['cat1', 'cat2', 'cat2_desc','name'], data:{'items':[ { "cat1": "分类1", "cat2": "分类21", "name": "名称1" }, { "cat1": "分类1", "cat2": "分类22", "name": "名称1" }, { "cat1": "分类1", "cat2": "分类22", "name": "名称2" }, { "cat1": "分类1", "cat2": "分类23", "name": "名称1" }, { "cat1": "分类2", "cat2": "分类21", "name": "名称1" }, { "cat1": "分类2", "cat2": "分类21", "name": "名称2" }, { "cat1": "分类2", "cat2": "分类22", "name": "名称1" }, { "cat1": "分类2", "cat2": "分类23", "name": "名称1" }, { "cat1": "分类2", "cat2": "分类24", "name": "名称1" }, { "cat1": "分类2", "cat2": "分类24", "name": "名称2" }, { "cat1": "分类2", "cat2": "分类24", "name": "名称3" }, { "cat1": "分类3", "cat2": "分类21", "name": "名称1" }, { "cat1": "分类3", "cat2": "分类22", "name": "名称1" }, { "cat1": "分类3", "cat2": "分类23", "name": "名称1" }, { "cat1": "分类3", "cat2": "分类24", "name": "名称1" }, { "cat1": "分类3", "cat2": "分类24", "name": "名称2" }, { "cat1": "分类3", "cat2": "分类25", "name": "名称1" } ]}, proxy: { type: 'memory', reader: { type: 'json', root: 'items' } } }); Ext.create('Ext.ux.grid.MergeCellPanel', { title: 'Simpsons', renderTo: Ext.getBody(), viewConfig: { mergeColumns: 'cat1>cat2|cat2_desc' }, store: Ext.data.StoreManager.lookup('simpsonsStore'), columns: [ { text: '分类1', dataIndex: 'cat1' }, { text: '分类2', dataIndex: 'cat2' }, { text: '分类2描述', dataIndex: 'cat2_desc', flex: 1 }, { text: '名称', dataIndex: 'name' }, { text: '列合并', columns:[ { text: 'C1' }, { text: 'C2' }, { text: 'C3' }, { text: 'C4' }, { text: 'C5' } ]} ] }); });
重要核心文件如下
MergeCellTable.js
Ext.define('Ext.ux.view.MergeCellTable', { extend: 'Ext.view.Table', alias: ['widget.mergecelltableview'], type: 'mergecelltableview', baseCls: Ext.baseCSSPrefix + 'mergegrid-view', stripeRows: false, separator: '>', // 不同级别分割符 sameLevelSeparator: '|', // 同级别分割符 __rowspans: null, // 缓存要合并的列中每个单元格的rowspan, refresh时会删除重新计算 __merge_columns: null, // 缓存要合并的列, refresh时会删除重新获取 cellTpl: [ // 增加了rowspan属性 '<td role="gridcell" class="{tdCls}" {tdAttr} id="{[Ext.id()]}" rowspan="{rowspan}" <tpl if="hidden">style="display:none"</tpl>>', '<div {unselectableAttr} class="' + Ext.baseCSSPrefix + 'grid-cell-inner {innerCls}"', 'style="height:auto;text-align:{align};<tpl if="style">{style}</tpl>">{value}</div>', '</td>', { priority: 0 } ], renderCell: function(column, record, recordIndex, columnIndex, out) { // 添加rowspan与隐藏td var me = this, rowspans = me.getRowspans(); var rowspan = (rowspans[recordIndex] || {})[column.dataIndex]; cellValues = me.cellValues, cellValues.rowspan = rowspan; // cellTpl采用了display:none而不是不生成td, 因为若不生成td在使用rowediting时会出错 cellValues.hidden = rowspan === 0; me.callParent(arguments); }, onAdd: function(store, records, index, cfg) { this.refresh(); }, onRemove: function() { this.refresh(); }, onUpdate: function() { this.refresh(); }, refresh: function() { var me = this; // 刷新时要重新计算rowspan delete me.__rowspans; delete me.__merge_columns; me.callParent(arguments); }, getRowspans: function() { var me = this; // 已经计算过直接返回 var rowspans = me.__rowspans; if (rowspans != null) { return rowspans; } // 计算rowspan rowspans = []; var store = me.dataSource, mergeColumns = me.getMergeColumns(); var setSameLevelRowspan = function(rowspans, rowIndex, columns, rowspan) {// 设置同级其他列的rowspan var i, temp, len = columns.length; for (i = 1; i < len; i++) { temp = columns[i]; rowspans[rowIndex][temp] = rowspan; } }; var calculateRowspans = function(rowspans, mergeColumns, currentColumnIndex, store, from, to) { if (currentColumnIndex >= mergeColumns.length) { return; } var columns = mergeColumns[currentColumnIndex], i, current, prev, mergeStart = 0; var column = columns[0]; try { for (i = from; i < to + 1; i++) { current = store.getAt(i).get(column); if (current !== prev) { rowspans[i] = rowspans[i] || {}; rowspans[i][column] = 1; setSameLevelRowspan(rowspans, i, columns, 1); // 递归获取子列 if (prev != null) { calculateRowspans(rowspans, mergeColumns, currentColumnIndex + 1, store, mergeStart, i - 1); } prev = current; mergeStart = i; } else { rowspans[mergeStart][column]++; setSameLevelRowspan(rowspans, mergeStart, columns, rowspans[mergeStart][column]); rowspans[i] = rowspans[i] || {}; rowspans[i][column] = 0; setSameLevelRowspan(rowspans, i, columns, 0); } } if (i > mergeStart) { calculateRowspans(rowspans, mergeColumns, currentColumnIndex + 1, store, mergeStart, i - 1); } } catch(e) { if (console) { console.error(e); } } }; calculateRowspans(rowspans, mergeColumns, 0, store, 0, store.data.length - 1); // 缓存 me.__rowspans = rowspans; return rowspans; }, getMergeColumns: function() { var me = this; var columns = me.__merge_columns; if (columns != null) { return columns; } // 未配置时直接返回 var mergeColumns = me.mergeColumns; if (Ext.isEmpty(mergeColumns)) { return []; } // 转换合并规则 var separator = me.separator, sameLevelSeparator = me.sameLevelSeparator; columns = mergeColumns.split(separator); var i, len = columns.length; for (i = 0; i < len; i++) { columns[i] = columns[i].split(sameLevelSeparator); } // 缓存 me.__merge_columns = columns; return columns; } });
MergeCellPanel.js
Ext.define('Ext.ux.grid.MergeCellPanel', { extend: 'Ext.grid.Panel', alias: ['widget.mergecellgrid'], viewType: 'mergecelltableview', initComponent: function() { var me = this; Ext.apply(me, { selType: 'cellmodel', // 按单元格选择 sortableColumns: false, // 禁止排序 columnLines: true, // 显示网格线 rowLines: true, // 显示网格线 trackMouseOver: false // 禁止跟踪鼠标变色 }); me.callParent(); } });
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/lianghl8090/article/details/47775403