用jQuery合并表格中相同文本的相邻单元格
ONE
已经生成的数据表格大致内容如下:
地区 | 地区 | 商品代码 | 商品名称 | 数量 | 有效期至 | 距效期(月) | 产品批号 | 规格 | 单位 | 条形码 |
---|---|---|---|---|---|---|---|---|---|---|
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 广州 | 00027 | 白花油 | |||||||
广东 | 广州 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 | |||||||
广东 | 深圳 | 00028 | 红花油 |
需要将前四列具有相同文本的相邻单元格进行自动合并,合并后如下:
地区 | 地区 | 商品代码 | 商品名称 | 数量 | 有效期至 | 距效期(月) | 产品批号 | 规格 | 单位 | 条形码 |
---|---|---|---|---|---|---|---|---|---|---|
广东 | 深圳 | 00028 | 红花油 | |||||||
广州 | 00027 | 白花油 | ||||||||
00028 | 红花油 | |||||||||
深圳 | ||||||||||
1、在html的head中引入jQuery
2、添加合并单元格的函数
1. //函数说明:合并指定表格(表格id为_w_table_id)指定列(列数为_w_table_colnum)的相同文本的相邻单元格 2. //参数说明:_w_table_id 为需要进行合并单元格的表格的id。如在HTMl中指定表格 id="data" ,此参数应为 #data 3. //参数说明:_w_table_colnum 为需要合并单元格的所在列。为数字,从最左边第一列为1开始算起。 4. function _w_table_rowspan(_w_table_id,_w_table_colnum){ 5. _w_table_firsttd = ""; 6. _w_table_currenttd = ""; 7. _w_table_SpanNum = 0; 8. _w_table_Obj = $(_w_table_id + " tr td:nth-child(" + _w_table_colnum + ")"); 9. _w_table_Obj.each(function(i){ 10. if(i==0){ 11. _w_table_firsttd = $(this); 12. _w_table_SpanNum = 1; 13. }else{ 14. _w_table_currenttd = $(this); 15. if(_w_table_firsttd.text()==_w_table_currenttd.text()){ 16. _w_table_SpanNum++; 17. _w_table_currenttd.hide(); //remove(); 18. _w_table_firsttd.attr("rowSpan",_w_table_SpanNum); 19. }else{ 20. _w_table_firsttd = $(this); 21. _w_table_SpanNum = 1; 22. } 23. } 24. }); 25. } 26. 27. //函数说明:合并指定表格(表格id为_w_table_id)指定行(行数为_w_table_rownum)的相同文本的相邻单元格 28. //参数说明:_w_table_id 为需要进行合并单元格的表格id。如在HTMl中指定表格 id="data" ,此参数应为 #data 29. //参数说明:_w_table_rownum 为需要合并单元格的所在行。其参数形式请参考jQuery中nth-child的参数。 30. // 如果为数字,则从最左边第一行为1开始算起。 31. // "even" 表示偶数行 32. // "odd" 表示奇数行 33. // "3n+1" 表示的行数为1、4、7、10. 34. //参数说明:_w_table_maxcolnum 为指定行中单元格对应的最大列数,列数大于这个数值的单元格将不进行比较合并。 35. // 此参数可以为空,为空则指定行的所有单元格要进行比较合并。 36. function _w_table_colspan(_w_table_id,_w_table_rownum,_w_table_maxcolnum){ 37. if(_w_table_maxcolnum == void 0){_w_table_maxcolnum=0;} 38. _w_table_firsttd = ""; 39. _w_table_currenttd = ""; 40. _w_table_SpanNum = 0; 41. $(_w_table_id + " tr:nth-child(" + _w_table_rownum + ")").each(function(i){ 42. _w_table_Obj = $(this).children(); 43. _w_table_Obj.each(function(i){ 44. if(i==0){ 45. _w_table_firsttd = $(this); 46. _w_table_SpanNum = 1; 47. }else if((_w_table_maxcolnum>0)&&(i>_w_table_maxcolnum)){ 48. return ""; 49. }else{ 50. _w_table_currenttd = $(this); 51. if(_w_table_firsttd.text()==_w_table_currenttd.text()){ 52. _w_table_SpanNum++; 53. _w_table_currenttd.hide(); //remove(); 54. _w_table_firsttd.attr("colSpan",_w_table_SpanNum); 55. }else{ 56. _w_table_firsttd = $(this); 57. _w_table_SpanNum = 1; 58. } 59. } 60. }); 61. }); 62. }
3、在html的head中调用合并函数合并单元格
1. <script type="text/javascript"><!-- 2. $(document).ready(function(){ 3. _w_table_rowspan("#spdata",4); 4. _w_table_rowspan("#spdata",3); 5. _w_table_rowspan("#spdata",2); 6. _w_table_rowspan("#spdata",1); 7. }); 8. // --> 9. </script>
TWO
合并table相同单元格的jquery插件(很精简)
正好项目中有个小需求, 要求把表格指定列中内容相同的单元格进行合并,本质上涉及的就是td的rowspan属性, 数出含相同内容单元格的个数, 然后给第一个与上一行内容不同的td其rowspan属性附上正确的值即可, 为了能直观的理解, 效果如下
原表格:
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"> 02 <thead> 03 <tr > 04 <td>col0</td> 05 <td>col1</td> 06 <td>col2</td> 07 <td>col3</td> 08 </tr> 09 </thead> 10 <tbody> 11 <tr> 12 <td>SuZhou</td> 13 <td>11111</td> 14 <td>22222</td> 15 <td>SuZhouCity</td> 16 </tr> 17 <tr> 18 <td>SuZhou</td> 19 <td>33333</td> 20 <td>44444</td> 21 <td>SuZhouCity</td> 22 </tr> 23 <tr> 24 <td>SuZhou</td> 25 <td>55555</td> 26 <td>66666</td> 27 <td>SuZhouCity</td> 28 </tr> 29 <tr> 30 <td>ShangHai</td> 31 <td>77777</td> 32 <td>88888</td> 33 <td>ShangHaiCity</td> 34 </tr> 35 <tr> 36 <td>ShangHai</td> 37 <td>uuuuu</td> 38 <td>hhhhh</td> 39 <td>ShangHaiCity</td> 40 </tr> 41 <tr> 42 <td>ShangHai</td> 43 <td>ggggg</td> 44 <td>ccccc</td> 45 <td>ShangHaiCity</td> 46 </tr> 47 <tr> 48 <td>GuangZhou</td> 49 <td>ttttt</td> 50 <td>eeeee</td> 51 <td>GuangZhouCity</td> 52 </tr> 53 <tr> 54 <td>GuangZhou</td> 55 <td>ppppp</td> 56 <td>qqqqq</td> 57 <td>GuangZhouCity</td> 58 </tr> 59 </tbody> 60 </table>
// 这里写成了一个jquery插件的形式 2 $('#process').mergeCell({ 3 // 目前只有cols这么一个配置项, 用数组表示列的索引,从0开始 4 // 然后根据指定列来处理(合并)相同内容单元格 5 cols: [0, 3] 6 });
下面看看这个小插件的完整代码:
;(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
- 其他什么值得改进的, 我想应该会不少的