Ext4.1grid单元格合并的解决方案

首先使用他的代码后效果如下:

从这幅图可以看出,该合并的都合并了,不该合并的也合并了,第三列“A单元”,属于不同的地块,不同栋数,常理是不应该合并的,所以引出一个问题,合并列时应该判断前一列的合并情况,属于不同合并区的单元格虽然值相等但不进行合并。效果应该是这样:


这是优化后的代码效果,下面说说具体方法:

如果你看了《100行代码解决ExtJs4.1合并单元格问题》的代码会发现,其中写了很多each语句,而且是嵌套的,在实现上图效果时,已经明显感觉速度有点慢,所以笔者就奇怪搞这么多each干嘛呢?直接用数组多好,参数已经指定合并的列了,用数组直接取不就得啦。

代码如下:

[javascript]  view plain copy
  1. /** 
  2.  * Kunoy 
  3.  * 合并单元格 
  4.  * @param {} grid  要合并单元格的grid对象 
  5.  * @param {} cols  要合并哪几列 [1,2,4] 
  6.  */  
  7. var mergeCells = function(grid,cols){  
  8.     var arrayTr=document.getElementById(grid.getId()+"-body").firstChild.firstChild.firstChild.getElementsByTagName('tr');    
  9.     var trCount = arrayTr.length;  
  10.     var arrayTd;  
  11.     var td;  
  12.     var merge = function(rowspanObj,removeObjs){ //定义合并函数  
  13.         if(rowspanObj.rowspan != 1){  
  14.             arrayTd =arrayTr[rowspanObj.tr].getElementsByTagName("td"); //合并行  
  15.             td=arrayTd[rowspanObj.td-1];  
  16.             td.rowSpan=rowspanObj.rowspan;  
  17.             td.vAlign="middle";               
  18.             Ext.each(removeObjs,function(obj){ //隐身被合并的单元格  
  19.                 arrayTd =arrayTr[obj.tr].getElementsByTagName("td");  
  20.                 arrayTd[obj.td-1].style.display='none';                           
  21.             });  
  22.         }     
  23.     };    
  24.     var rowspanObj = {}; //要进行跨列操作的td对象{tr:1,td:2,rowspan:5}      
  25.     var removeObjs = []; //要进行删除的td对象[{tr:2,td:2},{tr:3,td:2}]  
  26.     var col;  
  27.     Ext.each(cols,function(colIndex){ //逐列去操作tr  
  28.         var rowspan = 1;  
  29.         var divHtml = null;//单元格内的数值          
  30.         for(var i=1;i<trCount;i++){  //i=0表示表头等没用的行  
  31.             arrayTd = arrayTr[i].getElementsByTagName("td");  
  32.             var cold=0;  
  33. //          Ext.each(arrayTd,function(Td){ //获取RowNumber列和check列  
  34. //              if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)  
  35. //                  cold++;                               
  36. //          });  
  37.             col=colIndex+cold;//跳过RowNumber列和check列  
  38.             if(!divHtml){  
  39.                 divHtml = arrayTd[col-1].innerHTML;  
  40.                 rowspanObj = {tr:i,td:col,rowspan:rowspan}  
  41.             }else{  
  42.                 var cellText = arrayTd[col-1].innerHTML;  
  43.                 var addf=function(){   
  44.                     rowspanObj["rowspan"] = rowspanObj["rowspan"]+1;  
  45.                     removeObjs.push({tr:i,td:col});  
  46.                     if(i==trCount-1)  
  47.                         merge(rowspanObj,removeObjs);//执行合并函数  
  48.                 };  
  49.                 var mergef=function(){  
  50.                     merge(rowspanObj,removeObjs);//执行合并函数  
  51.                     divHtml = cellText;  
  52.                     rowspanObj = {tr:i,td:col,rowspan:rowspan}  
  53.                     removeObjs = [];  
  54.                 };  
  55.                 if(cellText == divHtml){  
  56.                     if(colIndex!=cols[0]){   
  57.                         var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display  
  58.                         if(leftDisplay=='none')  
  59.                             addf();   
  60.                         else  
  61.                             mergef();                             
  62.                     }else  
  63.                         addf();                                           
  64.                 }else  
  65.                     mergef();             
  66.             }  
  67.         }  
  68.     });   
  69. };  

从代码量来说,只有70行左右(本来想把标题也弄成70行代码解决、、、、呵呵,笔者不是标题党)。这里需要特别说一下getElementsByTagName这个东西,原先笔者也以为返回的是一个数组,其实不是,只是类似数组的东东,你可以用array[0]来访问里面的元素,但是却不能用push,pop,shift等操作数组的方法操作它,网上也有资源说定义一个数组把元素全部push过去,再进行删除等操作,笔者未采用,直接找到需要删除的元素下标跳过就可以了,因为getElementsByTagName得到的元素顺序和DOM的实际顺序是一致的。

另外:

[javascript]  view plain copy
  1. if(colIndex!=cols[0]){   
  2.     var leftDisplay=arrayTd[col-2].style.display;//判断左边单元格值是否已display  
  3.     if(leftDisplay=='none')  
  4.         addf();   
  5.     else  
  6.         mergef();                             
  7. }else  
  8.        addf();    

colIndex!=cols[0]是跳过第一列(开始合并的第一列),这一列不需要判断前一列的合并情况,这里采用display来做判断条件,因为被合并的都是display=none,没有合并的说明此处是两个合并区的分隔点,当然你也可以自己写另外的判断条件,可以定义一个函数判断一个单元格是否处于一个合并区里面,那么条件就是本单元格的左一个单元格和上左的单元格是否处于同一个合并区,是循环继续,不是则进行合并,方法很多,各位自由发挥,有了新的方法不防大家交流学习一下。

代码中注释的部分是可以不用的:
[javascript]  view plain copy
  1. Ext.each(arrayTd,function(Td){ //获取RowNumber列和check列  
  2.     if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)  
  3.         cold++;                               
  4. });  
合并列的参数里直接把RowNumber列和check列算在内就OK了。

使用方法:

[javascript]  view plain copy
  1. Ext.getCmp('grid').getStore().on('load',function(){  
  2.     mergeCells(Ext.getCmp('grid'),[1,2,3,4,5,6]);  
  3. });  

当数据加载完成后执行,从第一列开发合并;如果第一列是RowNumberer列,那么就用[2,3,4,5,6],跳过第一列即可。

 

2013-1-26回复7楼 sgq0085:

      谢谢你的提问,我特意测试一下,问题一,完成是可以的,如图:

      你自己仔细检查一下,源代码已经帖出,可能各自的环境不一样存在不同的问题,自己修改修改就可以了。

      问题二,你说的是不是这个问题:

      如果用html写一个table,我想效果也是这样的,因为设置rowspan的属性是开始合并的第一行,肯定就是这个效果。

作者: kunoy
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值