在Ext JS 4中, 如何合併行的單元格, 已經選取的時候只能選擇某一列, 期望的效果如下:
在Ext JS 中, 合併表頭的列有現成方案, 但是合併行單元格不是extjs的現有功能,這個需要底層擴展, 也就是使用 table 的跨行實現。
而Ext JS 7以及新版本和Ext JS4在最底層的Grid組成上又有差別,所以不同版本的實現又存在一些差異。
實現思路
實現思路主要是兩個:
- 在底層使用 rowspan 合併
- 設置Grid的選取方式爲 cellmodel
完整代碼
1 /** 2 * @param {} grid 要合併單元格的grid對象 3 * @param {} cols 要合併哪幾列 例如 [1,2] 4 */ 5 var mergeCells = function (grid, cols) { 6 //==>ExtJs4.2的<tbody>改到上層<table>的lastChild . <tbody>是各個<tr>的集合 7 var arrayTr = document.getElementById(grid.getId() + "-body").firstChild.firstChild.lastChild.getElementsByTagName('tr'); 8 var trCount = arrayTr.length; //<tr>總行數 9 var arrayTd; 10 var td; 11 12 //==>顯示層將目標格的樣式改爲.display='none'; 13 var merge = function (rowspanObj, removeObjs)//定義合併函數 14 { 15 if (0 != rowspanObj.rowspan) { 16 arrayTd = arrayTr[rowspanObj.tr].getElementsByTagName("td"); //合併行 17 td = arrayTd[rowspanObj.td - 1]; 18 td.rowSpan = rowspanObj.rowspan; 19 td.vAlign = "middle"; 20 // td.style.font-size = '20px'; 21 // $(td).hide(); 22 $(td).css("font-size", "15px"); 23 $(td).attr("title", $(td).text()); 24 $(td).find('span').attr("title", $(td).text()); 25 $(td).css('color', 'rgb(148, 201, 36)'); 26 var height = $(td).innerHeight(); 27 if (removeObjs.length > 0) { 28 $(td).css("padding-top", height / 3); 29 // var showIndex = Math.ceil(removeObjs.length/2); 30 } 31 32 //隱身被合併的單元格 33 Ext.each(removeObjs, function (obj) { 34 arrayTd = arrayTr[obj.tr].getElementsByTagName("td"); 35 arrayTd[obj.td - 1].style.display = 'none'; 36 arrayTd[obj.td - 1].style.borderTop = "none"; 37 }); 38 39 } 40 }; 41 //==>顯示層將目標格的樣式改爲.display='none'; 42 43 var rowspanObj = {}; //要進行跨列操作的td對象{tr:1,td:2,rowspan:5} 44 var removeObjs = []; //要進行刪除的td對象[{tr:2,td:2},{tr:3,td:2}] 45 var col; 46 //==>逐列靠表內具體數值去合併各個<tr> (表內數值一樣則合併) 47 48 try { 49 Ext.each(cols, function (colIndex) { 50 var rowspan = 1; 51 var divHtml = null;//單元格內的數值 52 for (var i = 0; i < trCount; i++)//==>從第一行數據0開始 53 { 54 //==>一個arrayTr[i]是一整行的所有數據, 一個arrayTd是 <td xxxx ><div>具體數值</div></td> , 55 arrayTd = arrayTr[i].getElementsByTagName("td"); 56 var cold = 0; 57 // Ext.each(arrayTd,function(Td){ //獲取RowNumber列和check列 58 // if(Td.getAttribute("class").indexOf("x-grid-cell-special") != -1) 59 // cold++; 60 // }); 61 col = colIndex + cold;//跳過RowNumber列和check列 62 63 if (!divHtml) { 64 divHtml = arrayTd[col - 1].innerHTML; 65 divHtml = $(divHtml).text(); //==>拿到真正數值,相比Ext4.1多了一層<div> 66 rowspanObj = { tr: i, td: col, rowspan: rowspan } 67 } 68 else { 69 var cellText = arrayTd[col - 1].innerHTML; 70 cellText = $(cellText).text();//==>拿到真正數值 71 72 73 var addf = function () { 74 rowspanObj["rowspan"] = rowspanObj["rowspan"] + 1; 75 removeObjs.push({ tr: i, td: col }); 76 if (i == trCount - 1) { 77 merge(rowspanObj, removeObjs);//執行合併函數 78 } 79 }; 80 var mergef = function () { 81 merge(rowspanObj, removeObjs);//執行合併函數 82 divHtml = cellText; 83 rowspanObj = { tr: i, td: col, rowspan: rowspan } 84 removeObjs = []; 85 }; 86 87 if (cellText == divHtml) { 88 if (colIndex != cols[0]) { 89 var leftDisplay = arrayTd[col - 2].style.display;//判斷左邊單元格值是否已display 90 if (leftDisplay == 'none') { 91 addf(); 92 } 93 else { 94 mergef(); 95 } 96 } 97 else { 98 addf(); 99 } 100 } 101 else { 102 mergef(); 103 } 104 } 105 } 106 }); 107 } catch (e) { 108 console.log(e.message) 109 } 110 }; 111 112 113 114 115 Ext.onReady(function () { 116 117 var store = Ext.create('Ext.data.Store', { 118 storeId: 'myStore', 119 autoLoad: false, 120 fields: ['firstClass', 'secondClass'], 121 data: { 122 'items': 123 [{ 124 firstClass: '正極材料', 125 secondClass: '鎳鈷錳酸鋰' 126 }, { 127 firstClass: '正極材料', 128 secondClass: '錳酸鋰' 129 }, { 130 firstClass: '負極材料', 131 secondClass: '石墨' 132 }, { 133 firstClass: '負極材料', 134 secondClass: '六弗錳酸鋰' 135 }] 136 }, 137 proxy: { 138 type: 'memory', 139 reader: { 140 type: 'json', 141 root: 'items' 142 } 143 } 144 }); 145 146 var grid = Ext.create('Ext.grid.Panel', { 147 renderTo: Ext.getBody(), 148 selType: 'cellmodel', 149 /*tbar: [{ 150 text: '單元格合併', 151 handler: function () { 152 mergeCells(grid, [1]); 153 } 154 }],*/ 155 id: 'mygrid', 156 columns: [{ 157 text: '一級分類', 158 dataIndex: 'firstClass' 159 }, { 160 text: '二級分類', 161 dataIndex: 'secondClass' 162 }], 163 store: store 164 }); 165 166 setTimeout(function(){ 167 mergeCells(grid, [1]); 168 },100) 169 /* grid.getStore().load(function(){ 170 alert('1'); 171 mergeCells(grid, [1]); 172 });*/ 173 });