Extjs高级应用(一):实现GridPanel的单元格多选模组

2014-11-24 00:45:00 · 作者: · 浏览: 0
之前在项目中突然遇见一个很奇怪的需求,要求单元格能和Excel一样进行多选,比如框选其中一个矩形区域,然后复制到同页面另一个Grid中!!并添加统计报表功能。当时这个需求就把我们都怔住了!很变态很强悍的需求,因为这个模块是一个基于报表的统计功能,使用了一个第三方的报表工具,但是页面展示非常难看。。。。。客户就对我们说,为什么不用Ext来制作报表呢。呵呵最后当时是被我们回绝了,因为这确实是对我们团队来说难度太大,而且成本太高。具备统计功能的Ext Grid再加上可编辑等等,就几乎是一个网页版的Excel了,我们不认为我们团队能和Google Doc叫板.......

但是事后我看了看 CellSelectionModel 和 RowSelectionModel的源代码,发现单元格多选并不难,于是先没和项目经理说我的想法,而是抽时间没事研究了一下,终于搞了几天之后,初版的模型就出来,嘿嘿现在尝试着说服项目经理应用在系统中。OK,先上代码和理论知识吧:

先说说Ext GridPanel UI组件的结构,它由五个部分组成,GridView、ColumnModel、SelectionModel、Store、GridPanel,不得不佩服Ext团队的设计理念,这是一个典型的MVC结构组件。GridView负责管理表格的内容展示,ColumnModel负责列的定义,SelectionModel是选择模组,Store是数据层,最后它们全部组合在一起由GridPanel进行渲染,展现在我们的面前。因为只关注单元格多选,对我们有用的组件只有Gridview 和 SelecitonModel。

Grid选择模型的实现原理是这样的:Ext组件关系非常复杂,这里用图表进行说明吧

左侧是加载初始化时的操作,右侧是触发事件时的操作。

现在我们自定义的SelectionModel 主要关注于handleMouseDown方法就行。我们的多选规则和Excel一样,按住shift这是区域全选,按住ctrl则是添加被选中的单元格

   
Ext.hl.MultiCellSelectionModel = Ext.extend(Ext.grid.CellSelectionModel, {

last :
false , // 上一次选中的单元格
selections : [], // 选择区缓存

constructor :
function () {
Ext.hl.MultiCellSelectionModel.superclass.constructor.call(
this );
},
initEvents :
function () {
Ext.hl.MultiCellSelectionModel.superclass.initEvents.call(
this );
},
// 根据行列以及是否按住Ctrl键或者shift键,执行多选操作的逻辑
handleMouseDown :
function (grid, row, col, event) {
var isSelected;
if (event.button !== 0 || this .isLocked())
return ;
if (event.shiftKey && this .last !== false ) { //是否按下shift
this .selectMatrix(row, col);
grid.getView().focusCell(row, col);
return ;
}
else if (event.ctrlKey){ //是否按下ctrl
isSelected
= this .isSelected(row,col);
if (col === 0 && this .last[ 1 ] === 0 ){
isSelected
this .deselectRow(row) : this .selectRow(row, true );
}
if (isSelected){ // 是否已被选中,是则反选,否则选中
this .deselectCell(row, col);
}
else {
this .selectCell(row,col, true );
this .last = [row, col];
}
}
else if (col === 0 ){ // 第一列是NumberColumn 点击则选择列
this .selectRow(row);
this .last = [row, col];
}
else { // 选择单个单元格
this .selectCell(row,col);
this .last = [row, col];
}
if ( this .matrix)
delete this .matrix;
},
// 清楚选择区内所以单元格被选中的样式
clearCellSelections :
function (){
var l