原表格:
col0 col1 col2 col3 SuZhou 11111 22222 SuZhouCity SuZhou 33333 44444 SuZhouCity SuZhou 55555 66666 SuZhouCity ShangHai 77777 88888 ShangHaiCity ShangHai uuuuu hhhhh ShangHaiCity ShangHai ggggg ccccc ShangHaiCity GuangZhou ttttt eeeee GuangZhouCity GuangZhou ppppp qqqqq GuangZhouCity處理之後的樣子:
col0 col1 col2 col3 SuZhou 11111 22222 SuZhouCity 33333 44444 55555 66666 ShangHai 77777 88888 ShangHaiCity uuuuu hhhhh ggggg ccccc GuangZhou ttttt eeeee GuangZhouCity ppppp qqqqq效果出來, 看上去比較簡單, 下面先看下頁面
代碼如下:
<table id="process" cellpadding="2" cellspacing="0" border="1">
<thead>
<tr >
<td>col0</td>
<td>col1</td>
<td>col2</td>
<td>col3</td>
</tr>
</thead>
<tbody>
<tr>
<td>SuZhou</td>
<td>11111</td>
<td>22222</td>
<td>SuZhouCity</td>
</tr>
<tr>
<td>SuZhou</td>
<td>33333</td>
<td>44444</td>
<td>SuZhouCity</td>
</tr>
<tr>
<td>SuZhou</td>
<td>55555</td>
<td>66666</td>
<td>SuZhouCity</td>
</tr>
<tr>
<td>ShangHai</td>
<td>77777</td>
<td>88888</td>
<td>ShangHaiCity</td>
</tr>
<tr>
<td>ShangHai</td>
<td>uuuuu</td>
<td>hhhhh</td>
<td>ShangHaiCity</td>
</tr>
<tr>
<td>ShangHai</td>
<td>ggggg</td>
<td>ccccc</td>
<td>ShangHaiCity</td>
</tr>
<tr>
<td>GuangZhou</td>
<td>ttttt</td>
<td>eeeee</td>
<td>GuangZhouCity</td>
</tr>
<tr>
<td>GuangZhou</td>
<td>ppppp</td>
<td>qqqqq</td>
<td>GuangZhouCity</td>
</tr>
</tbody>
</table>
核心代碼:
代碼如下:
// 這裡寫成了一個jquery插件的形式
$('#process').mergeCell({
// 目前只有cols這麼一個配置項, 用數組表示列的索引,從0開始
// 然後根據指定列來處理(合並)相同內容單元格
cols: [0, 3]
});
下面看看這個小插件的完整代碼:
代碼如下:
;(function($) {
// 看過jquery源碼就可以發現$.fn就是$.prototype, 只是為了兼容早期版本的插件
// 才保留了jQuery.prototype這個形式
$.fn.mergeCell = function(options) {
return this.each(function() {
var cols = options.cols;
for ( var i = cols.length - 1; cols[i] != undefined; i--) {
// fixbug console調試
// console.debug(cols[i]);
mergeCell($(this), cols[i]);
}
dispose($(this));
});
};
// 如果對javascript的closure和scope概念比較清楚, 這是個插件內部使用的private方法
// 具體可以參考本人前一篇隨筆裡介紹的那本書
function mergeCell($table, colIndex) {
$table.data('col-content', ''); // 存放單元格內容
$table.data('col-rowspan', 1); // 存放計算的rowspan值 默認為1
$table.data('col-td', $()); // 存放發現的第一個與前一行比較結果不同td(jQuery封裝過的), 默認一個"空"的jquery對象
$table.data('trNum', $('tbody tr', $table).length); // 要處理表格的總行數, 用於最後一行做特殊處理時進行判斷之用
// 我們對每一行數據進行"掃面"處理 關鍵是定位col-td, 和其對應的rowspan
$('tbody tr', $table).each(function(index) {
// td:eq中的colIndex即列索引
var $td = $('td:eq(' + colIndex + ')', this);
// 取出單元格的當前內容
var currentContent = $td.html();
// 第一次時走此分支
if ($table.data('col-content') == '') {
$table.data('col-content', currentContent);
$table.data('col-td', $td);
} else {
// 上一行與當前行內容相同
if ($table.data('col-content') == currentContent) {
// 上一行與當前行內容相同則col-rowspan累加, 保存新值
var rowspan = $table.data('col-rowspan') + 1;
$table.data('col-rowspan', rowspan);
// 值得注意的是 如果用了$td.remove()就會對其他列的處理造成影響
$td.hide();
// 最後一行的情況比較特殊一點
// 比如最後2行 td中的內容是一樣的, 那麼到最後一行就應該把此時的col-td裡保存的td設置rowspan
if (++index == $table.data('trNum'))
$table.data('col-td').attr('rowspan', $table.data('col-rowspan'));
} else { // 上一行與當前行內容不同
// col-rowspan默認為1, 如果統計出的col-rowspan沒有變化, 不處理
if ($table.data('col-rowspan') != 1) {
$table.data('col-td').attr('rowspan', $table.data('col-rowspan'));
}
// 保存第一次出現不同內容的td, 和其內容, 重置col-rowspan
$table.data('col-td', $td);
$table.data('col-content', $td.html());
$table.data('col-rowspan', 1);
}
}
});
}
// 同樣是個private函數 清理內存之用
function dispose($table) {
$table.removeData();
}
})(jQuery);
主要的說明在注釋裡應該都有了, 代碼的確比較簡單, 像有些地方還值得改進
•處理的table內容是從tbody開始查找的, 如果沒有tbody, 那應該給出個更通用化的方案
•for ( var i = cols.length - 1; cols[i] != undefined; i--)...如果表格數據量大, 處理的列也比較多, 這裡不進行優化會有造成浏覽器線程阻塞的風險, 可以考慮用setTimeout
•其他什麼值得改進的, 我想應該會不少的