採用新的方法解決extjs4.1 grid合併單元格問題

首先技術原理基於狂人論壇的大大yunfengcheng發的帖子《100行代碼解決ExtJs4.1合併單元格問題》,表示感謝。

如果需要他的代碼各位可自行下載,在此不方便貼出(人家可賣30個金錢的呢,雖然有點小貴,呵呵)。

好了,進入正題吧。首先使用他的代碼後效果如下:

1344043251_6970.jpg

從這幅圖可以看出,該合併的都合併了,不該合併的也合併了,第三列“A單元”,屬於不同的地塊,不同棟數,常理是不應該合併的,所以引出一個問題,合併列時應該判斷前一列的合併情況,屬於不同合併區的單元格雖然值相等但不進行合併。效果應該是這樣:

1344043515_4954.jpg

這是優化後的代碼效果,下面說說具體方法:

如果你看了《100行代碼解決ExtJs4.1合併單元格問題》的代碼會發現,其中寫了很多each語句,而且是嵌套的,在實現上圖效果時,已經明顯感覺速度有點慢,所以筆者就奇怪搞這麼多each幹嘛呢?直接用數組多好,參數已經指定合併的列了,用數組直接取不就得啦。

代碼如下:

[javascript]view plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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],跳過第一列即可。


原文:http://blog.csdn.net/kunoy/article/details/7829395

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章