首先技術原理基於狂人論壇的大大yunfengcheng發的帖子《100行代碼解決ExtJs4.1合併單元格問題》,表示感謝。javascript
若是須要他的代碼各位可自行下載,在此不方便貼出(人家可賣30個金錢的呢,雖然有點小貴,呵呵)。java
好了,進入正題吧。首先使用他的代碼後效果以下:數組
從這幅圖能夠看出,該合併的都合併了,不應合併的也合併了,第三列「A單元」,屬於不一樣的地塊,不一樣棟數,常理是不該該合併的,因此引出一個問題,合併列時應該判斷前一列的合併狀況,屬於不一樣合併區的單元格雖然值相等但不進行合併。效果應該是這樣:ide
這是優化後的代碼效果,下面說說具體方法:函數
若是你看了《100行代碼解決ExtJs4.1合併單元格問題》的代碼會發現,其中寫了不少each語句,並且是嵌套的,在實現上圖效果時,已經明顯感受速度有點慢,因此筆者就奇怪搞這麼多each幹嗎呢?直接用數組多好,參數已經指定合併的列了,用數組直接取不就得啦。學習
代碼以下:優化
/**spa
* Kunoy.net
* 合併單元格orm
* @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();
}
}
});
};
另外:
if(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,沒有合併的說明此處是兩個合併區的分隔點,固然你也能夠本身寫另外的判斷條件,能夠定義一個函數判斷一個單元格是否處於一個合併區裏面,那麼條件就是本單元格的左一個單元格和上左的單元格是否處於同一個合併區,是循環繼續,不是則進行合併,方法不少,各位自由發揮,有了新的方法不防你們交流學習一下。
代碼中註釋的部分是能夠不用的:Ext.each(arrayTd,function(Td){ //獲取RowNumber列和check列
if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1)
cold++;
});
使用方法:
Ext.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