采用新的方法解决extjs4.1 grid合并单元格问题
2013-11-04 11:38
204 查看
首先技术原理基于狂人论坛的大大yunfengcheng发的帖子《100行代码解决ExtJs4.1合并单元格问题》,表示感谢。如果需要他的代码各位可自行下载,在此不方便贴出(人家可卖30个金钱的呢,虽然有点小贵,呵呵)。好了,进入正题吧。首先使用他的代码后效果如下:
![](http://my.csdn.net/uploads/201208/04/1344043251_6970.jpg)
从这幅图可以看出,该合并的都合并了,不该合并的也合并了,第三列“A单元”,属于不同的地块,不同栋数,常理是不应该合并的,所以引出一个问题,合并列时应该判断前一列的合并情况,属于不同合并区的单元格虽然值相等但不进行合并。效果应该是这样:
![](http://my.csdn.net/uploads/201208/04/1344043515_4954.jpg)
这是优化后的代码效果,下面说说具体方法:如果你看了《100行代码解决ExtJs4.1合并单元格问题》的代码会发现,其中写了很多each语句,而且是嵌套的,在实现上图效果时,已经明显感觉速度有点慢,所以笔者就奇怪搞这么多each干嘛呢?直接用数组多好,参数已经指定合并的列了,用数组直接取不就得啦。代码如下:[javascript]view plaincopy/**
* Kunoy
* 合并单元格
* @param {} grid 要合并单元格的grid对象
* @param {} cols 要合并哪几列 [1,2,4]
*/
var mergeCells = function(grid,cols){
var arrayTr=document.getElementById(grid.getId()+"-body").firstChild.firstChild.firstChild.getElementsByTagName('tr');
var trCount = arrayTr.length;
var arrayTd;
var td;
var merge = function(rowspanObj,removeObjs){ //定义合并函数
if(rowspanObj.rowspan != 1){
arrayTd =arrayTr[rowspanObj.tr].getElementsByTagName("td"); //合并行
td=arrayTd[rowspanObj.td-1];
td.rowSpan=rowspanObj.rowspan;
td.vAlign="middle";
Ext.each(removeObjs,function(obj){ //隐身被合并的单元格
arrayTd =arrayTr[obj.tr].getElementsByTagName("td");
arrayTd[obj.td-1].style.display='none';
});
}
};
var rowspanObj = {}; //要进行跨列操作的td对象{tr:1,td:2,rowspan:5}
var removeObjs = []; //要进行删除的td对象[{tr:2,td:2},{tr:3,td:2}]
var col;
Ext.each(cols,function(colIndex){ //逐列去操作tr
var rowspan = 1;
var divHtml = null;//单元格内的数值
for(var i=1;i<trCount;i++){ //i=0表示表头等没用的行
arrayTd = arrayTr[i].getElementsByTagName("td");
var cold=0;
// Ext.each(arrayTd,function(Td){ //获取RowNumber列和check列
// if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)
// cold++;
// });
col=colIndex+cold;//跳过RowNumber列和check列
if(!divHtml){
divHtml = arrayTd[col-1].innerHTML;
rowspanObj = {tr:i,td:col,rowspan:rowspan}
}else{
var cellText = arrayTd[col-1].innerHTML;
var addf=function(){
rowspanObj["rowspan"] = rowspanObj["rowspan"]+1;
removeObjs.push({tr:i,td:col});
if(i==trCount-1)
merge(rowspanObj,removeObjs);//执行合并函数
};
var mergef=function(){
merge(rowspanObj,removeObjs);//执行合并函数
divHtml = cellText;
rowspanObj = {tr:i,td:col,rowspan:rowspan}
removeObjs = [];
};
if(cellText == divHtml){
if(colIndex!=cols[0]){
var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display
if(leftDisplay=='none')
addf();
else
mergef();
}else
addf();
}else
mergef();
}
}
});
};
从代码量来说,只有70行左右(本来想把标题也弄成70行代码解决、、、、呵呵,笔者不是标题党)。这里需要特别说一下getElementsByTagName这个东西,原先笔者也以为返回的是一个数组,其实不是,只是类似数组的东东,你可以用array[0]来访问里面的元素,但是却不能用push,pop,shift等操作数组的方法操作它,网上也有资源说定义一个数组把元素全部push过去,再进行删除等操作,笔者未采用,直接找到需要删除的元素下标跳过就可以了,因为getElementsByTagName得到的元素顺序和DOM的实际顺序是一致的。另外:[javascript]view plaincopyif(colIndex!=cols[0]){
var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display
if(leftDisplay=='none')
addf();
else
mergef();
}else
addf();
colIndex!=cols[0]是跳过第一列(开始合并的第一列),这一列不需要判断前一列的合并情况,这里采用display来做判断条件,因为被合并的都是display=none,没有合并的说明此处是两个合并区的分隔点,当然你也可以自己写另外的判断条件,可以定义一个函数判断一个单元格是否处于一个合并区里面,那么条件就是本单元格的左一个单元格和上左的单元格是否处于同一个合并区,是循环继续,不是则进行合并,方法很多,各位自由发挥,有了新的方法不防大家交流学习一下。代码中注释的部分是可以不用的:[javascript]view plaincopyExt.each(arrayTd,function(Td){ //获取RowNumber列和check列
if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)
cold++;
});
合并列的参数里直接把RowNumber列和check列算在内就OK了。使用方法:[javascript]view plaincopyExt.getCmp('grid').getStore().on('load',function(){
mergeCells(Ext.getCmp('grid'),[1,2,3,4,5,6]);
});
当数据加载完成后执行,从第一列开发合并;如果第一列是RowNumberer列,那么就用[2,3,4,5,6],跳过第一列即可。
原文:http://blog.csdn.net/kunoy/article/details/7829395
![](http://my.csdn.net/uploads/201208/04/1344043251_6970.jpg)
从这幅图可以看出,该合并的都合并了,不该合并的也合并了,第三列“A单元”,属于不同的地块,不同栋数,常理是不应该合并的,所以引出一个问题,合并列时应该判断前一列的合并情况,属于不同合并区的单元格虽然值相等但不进行合并。效果应该是这样:
![](http://my.csdn.net/uploads/201208/04/1344043515_4954.jpg)
这是优化后的代码效果,下面说说具体方法:如果你看了《100行代码解决ExtJs4.1合并单元格问题》的代码会发现,其中写了很多each语句,而且是嵌套的,在实现上图效果时,已经明显感觉速度有点慢,所以笔者就奇怪搞这么多each干嘛呢?直接用数组多好,参数已经指定合并的列了,用数组直接取不就得啦。代码如下:[javascript]view plaincopy/**
* Kunoy
* 合并单元格
* @param {} grid 要合并单元格的grid对象
* @param {} cols 要合并哪几列 [1,2,4]
*/
var mergeCells = function(grid,cols){
var arrayTr=document.getElementById(grid.getId()+"-body").firstChild.firstChild.firstChild.getElementsByTagName('tr');
var trCount = arrayTr.length;
var arrayTd;
var td;
var merge = function(rowspanObj,removeObjs){ //定义合并函数
if(rowspanObj.rowspan != 1){
arrayTd =arrayTr[rowspanObj.tr].getElementsByTagName("td"); //合并行
td=arrayTd[rowspanObj.td-1];
td.rowSpan=rowspanObj.rowspan;
td.vAlign="middle";
Ext.each(removeObjs,function(obj){ //隐身被合并的单元格
arrayTd =arrayTr[obj.tr].getElementsByTagName("td");
arrayTd[obj.td-1].style.display='none';
});
}
};
var rowspanObj = {}; //要进行跨列操作的td对象{tr:1,td:2,rowspan:5}
var removeObjs = []; //要进行删除的td对象[{tr:2,td:2},{tr:3,td:2}]
var col;
Ext.each(cols,function(colIndex){ //逐列去操作tr
var rowspan = 1;
var divHtml = null;//单元格内的数值
for(var i=1;i<trCount;i++){ //i=0表示表头等没用的行
arrayTd = arrayTr[i].getElementsByTagName("td");
var cold=0;
// Ext.each(arrayTd,function(Td){ //获取RowNumber列和check列
// if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)
// cold++;
// });
col=colIndex+cold;//跳过RowNumber列和check列
if(!divHtml){
divHtml = arrayTd[col-1].innerHTML;
rowspanObj = {tr:i,td:col,rowspan:rowspan}
}else{
var cellText = arrayTd[col-1].innerHTML;
var addf=function(){
rowspanObj["rowspan"] = rowspanObj["rowspan"]+1;
removeObjs.push({tr:i,td:col});
if(i==trCount-1)
merge(rowspanObj,removeObjs);//执行合并函数
};
var mergef=function(){
merge(rowspanObj,removeObjs);//执行合并函数
divHtml = cellText;
rowspanObj = {tr:i,td:col,rowspan:rowspan}
removeObjs = [];
};
if(cellText == divHtml){
if(colIndex!=cols[0]){
var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display
if(leftDisplay=='none')
addf();
else
mergef();
}else
addf();
}else
mergef();
}
}
});
};
从代码量来说,只有70行左右(本来想把标题也弄成70行代码解决、、、、呵呵,笔者不是标题党)。这里需要特别说一下getElementsByTagName这个东西,原先笔者也以为返回的是一个数组,其实不是,只是类似数组的东东,你可以用array[0]来访问里面的元素,但是却不能用push,pop,shift等操作数组的方法操作它,网上也有资源说定义一个数组把元素全部push过去,再进行删除等操作,笔者未采用,直接找到需要删除的元素下标跳过就可以了,因为getElementsByTagName得到的元素顺序和DOM的实际顺序是一致的。另外:[javascript]view plaincopyif(colIndex!=cols[0]){
var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display
if(leftDisplay=='none')
addf();
else
mergef();
}else
addf();
colIndex!=cols[0]是跳过第一列(开始合并的第一列),这一列不需要判断前一列的合并情况,这里采用display来做判断条件,因为被合并的都是display=none,没有合并的说明此处是两个合并区的分隔点,当然你也可以自己写另外的判断条件,可以定义一个函数判断一个单元格是否处于一个合并区里面,那么条件就是本单元格的左一个单元格和上左的单元格是否处于同一个合并区,是循环继续,不是则进行合并,方法很多,各位自由发挥,有了新的方法不防大家交流学习一下。代码中注释的部分是可以不用的:[javascript]view plaincopyExt.each(arrayTd,function(Td){ //获取RowNumber列和check列
if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)
cold++;
});
合并列的参数里直接把RowNumber列和check列算在内就OK了。使用方法:[javascript]view plaincopyExt.getCmp('grid').getStore().on('load',function(){
mergeCells(Ext.getCmp('grid'),[1,2,3,4,5,6]);
});
当数据加载完成后执行,从第一列开发合并;如果第一列是RowNumberer列,那么就用[2,3,4,5,6],跳过第一列即可。
原文:http://blog.csdn.net/kunoy/article/details/7829395
相关文章推荐
- 采用新的方法解决extjs4.1 grid合并单元格问题
- 采用新的方法解决extjs4.1 grid合并单元格问题
- 采用新的方法解决extjs4.1 grid合并单元格问题
- 对于大流量的网站,您采用什么样的方法来解决访问量问题?
- as3中的socket的readUTFBytes方法,它的UTF指的是UTF-8,只要服务器采用UTF-8编码,传输和修改中文的问题就能解决
- 采用Window对象shim属性解决IE下flash位于弹出窗口之上遮住窗口问题——此方法对firefox暂未解决
- 解决gedit中文乱码问题,采用命令行输入相关命令,简单实用的解决方法
- 对于大流量的网站,您采用什么样的方法来解决访问量问题?
- 对于大流量的网站,采用什么样的方法来解决访问量问题
- 要求顺序循环队不损失一个空间,全部能够得到有效利用,试采用设置标志位tag的方法解决“假溢出”问题,实现顺序循环队列算法
- 对于大流量的网站,您采用什么样的方法来解决访问量问题?
- 关于GridView导出Excel的一些问题(采用Ajax出现的的问题及解决方法)
- js 通过调用方法终止js代码继续执行的问题(采用throw解决)
- 分享一次分析/解决支付应用性能问题的全过程,细节和采用的工具和方法 推荐
- CSS中的浮动闭合问题,以及为了解决CSS中的浮动闭合所采用的清楚浮动的方法
- linux fedora14下采用代理时,yum命令失效问题解决方法
- 对于大流量的网站,您采用什么样的方法来解决访问量问题?
- MFC采用MSComm控件通信时,出现error LNK2001:无法解析的外部符号问题的解决方法
- 对于大流量的网站,采用什么样的方法解决访问量问题
- 对于大流量的网站,您采用什么样的方法来解决访问量问题?