论坛首页 Web前端技术论坛

jquery写的合并单元格的一个方法

浏览 8730 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-01-19   最后修改:2011-06-10

项目中经常使用的一个功能就是把排序之后的表格进行单元格的合并,一般是列的合并.

之前使用的方法是在后台进行html拼串,结果造成后台及其复杂,可维护性很差.

 

自己的想法就是在画完了表格之后再修改表格的结果,添加rowspan属性达到合并单元格的目的.

 

思路: 假如表格列数据依次是A,A,A,B,B,B,C,C,C 显示表格完之后,进行逐行进行查找得到这样的一个数组[3,3,3] ,表示重复的单元格的次数,然后在进行一次循环,再根据这里的数组里面的数字进行处理,将第一个遇到的单元格设置rowspan属性,剩余的重复的单元格remove掉...有点小小复杂的算法. 

 

用jquery写完之后,到网上搜了一下,才发现有普通的js的版本的,看了一下,思路基本差不多.这里把我写的jquery的版本代码粘贴出来,附件有两个版本的网页.

/**
  * willcheck:要进行处理的表格对象(或者行的集合即可)
  * colnum:要进行合并单元格的列
  */
function coltogather(willcheck,colnum){ 
	var alltext = [],togotherNum = [],oldnum = [],id=1,lasttext=null,rmflag=1; 
	//逐列的数据进行扫描,得到里面的不重复的数据,以及各个数据的数目,然后将依据此结果进行设置rowspan属性
	willcheck.each(function(){
	      var _rmnum = this.getAttribute('rmnum');
		  if(!_rmnum)_rmnum=0;
	      var trdom= jQuery('td:eq('+(colnum-_rmnum)+')',this)
		  var text = jQuery(trdom).text();  
		  //如果上一行记录文本为空,说明是第一行
		  if(lasttext==null) {
			   lasttext = text;
		  }else {
			  //如果当前行和上一行记录一样,说明要进行合并,合并的单元格数目就加1
			  if(lasttext!=text){  
				   togotherNum.push(id);
				   lasttext = text;
				   id = 1;
			  } else{
			      id++;
			  }
		  }
		  
	 });   
	 togotherNum.push(id); 
	 //复制allnum数组中的数据到oldnum数组
	 jQuery.each(togotherNum, function(i, n){
         oldnum[i] =n;
     }); 
     var index = 0,len = togotherNum.length;
	 //逐行进行处理,设置指定列的rowspan属性,以及将要合并的单元格remove!
	 willcheck.each(function() {
				// 得到一个属性表示该行已经被移除了几个td
				var _rmnum = this.getAttribute('rmnum');
				if (!_rmnum)
					_rmnum = 0;
				var tddom = jQuery('td:eq(' + (colnum - _rmnum) + ')', this)
				if (togotherNum[index] == oldnum[index]) {
					tddom.attr('rowSpan', togotherNum[index]);
					if(togotherNum[index]>1)
					  togotherNum[index] = togotherNum[index] - 1;
					 else
					   index++;
				} else { 
					if (togotherNum[index] == 0) {
						index++;
					    tddom.attr('rowSpan', togotherNum[index]);
					} else {
				    	tddom.remove(); 
						if(--togotherNum[index]==0){
							index++;
						}
					}
					// 移除了td之后,要在tr里面添加一个属性标示已经移除的td的数目
					if (_rmnum == 0) {
						jQuery(this).attr('rmnum', 1);
					} else {
						jQuery(this).attr('rmnum', 1 + _rmnum * 1);
					}
				}
			});   
	 //清空数组
	 alltext = null;
	 togotherNum = null;
	 oldnum = null; 
}

 全部的可执行网页见附件.

 

感觉没有必要总是使用jquery做这些事情,因为可以看到普通的js一样可以处理很多的事情,用jquery的话有点杀鸡用牛刀了,不过jquery确实很方便.

   发表时间:2011-01-20  
和我做类似功能的思路很不一样
我倾向于在服务器端就做好一定的合并,然后页面上直接遍历构建

例如,原始的变量是这样
[
{ var1: "aa", var2: "b1", var3: "c1"},
{ var1: "aa", var2: "b2", var3: "c2"},
{ var1: "xx", var2: "yy", var3: "zz"},
……
]
我一般先在服务器端转换为这样的形式
[
{ var1: "aa", sub: [{var2: "b1", var3: "c1"}, {var2: "b2", var3: "c2"}]},
{ var1: "xx", sub: [{var2: "yy", var3: "zz"}],
……
]

然后按照数据,一次性生成合并行列的表格
可以减少对dom对象的操作,个人认为好些
0 请登录后投票
   发表时间:2011-01-20  
flamesea 写道
和我做类似功能的思路很不一样
我倾向于在服务器端就做好一定的合并,然后页面上直接遍历构建

例如,原始的变量是这样
[
{ var1: "aa", var2: "b1", var3: "c1"},
{ var1: "aa", var2: "b2", var3: "c2"},
{ var1: "xx", var2: "yy", var3: "zz"},
……
]
我一般先在服务器端转换为这样的形式
[
{ var1: "aa", sub: [{var2: "b1", var3: "c1"}, {var2: "b2", var3: "c2"}]},
{ var1: "xx", sub: [{var2: "yy", var3: "zz"}],
……
]

然后按照数据,一次性生成合并行列的表格
可以减少对dom对象的操作,个人认为好些

但是你这样的话,要改动后台代码,对吧?而只用前台js处理的话,就不用改动后台的java代码.前台数据量多了,可能会有性能的影响.
0 请登录后投票
   发表时间:2011-01-22  
对dom操作过多会有性能问题,我的做法一般是对后台传来的json对象进行直接拼合字符串统一输出,这样性能会好很多。
0 请登录后投票
   发表时间:2011-01-22  
interjc 写道
对dom操作过多会有性能问题,我的做法一般是对后台传来的json对象进行直接拼合字符串统一输出,这样性能会好很多。

恩 具体问题具体分析.我们的表格数据很大的,以前就是用的你的类似的方法在后台直接拼html显示在前台,结果后台代码乱七八糟.
现在的这样js处理,在显示一页1000条的时候略有影响可以看出白页的效果,其余不会出现明显的停顿.
0 请登录后投票
   发表时间:2011-01-22  
写的太不 jquery 了。
手痒写了一段

<script type="text/javascript">

$.fn.merge = function () {  
  return this.each(function(){
   for(var i= $(this).find('tr:first td').size() -1; i>=0; i--){
     var s = null;
     var prevTd = null;
     $(this).find('tr').each(function(){ 
       var td = $(this).find('td').eq(i);
       var s1= td.text() ;
       if (s1 == s) {
         td.remove();
         prevTd.attr('rowspan', prevTd.attr('rowspan')? parseInt(prevTd.attr('rowspan')) + 1:2);
       }
       else {
         s = s1;
         prevTd = td;
       }
     });
   }
  });
}

$(document).ready(function(){
  $('button').click(function(){
    $('table').merge();
  });
});
</script>
0 请登录后投票
   发表时间:2011-01-22  
lobbychmd 写道
写的太不 jquery 了。
手痒写了一段

<script type="text/javascript">

$.fn.merge = function () {  
  return this.each(function(){
   for(var i= $(this).find('tr:first td').size() -1; i>=0; i--){
     var s = null;
     var prevTd = null;
     $(this).find('tr').each(function(){ 
       var td = $(this).find('td').eq(i);
       var s1= td.text() ;
       if (s1 == s) {
         td.remove();
         prevTd.attr('rowspan', prevTd.attr('rowspan')? parseInt(prevTd.attr('rowspan')) + 1:2);
       }
       else {
         s = s1;
         prevTd = td;
       }
     });
   }
  });
}

$(document).ready(function(){
  $('button').click(function(){
    $('table').merge();
  });
});
</script>

谢谢指点!学习了!
0 请登录后投票
   发表时间:2011-01-23  
不错,.另外我觉得是还是像lz这样在js里面处理比较好,在服务器端合并性能更差,现在浏览器js引擎的性能已经不是当年了。
另外把计算的事情扔给各个客户端,在有一定并发压力的时候其实是更明智的办法。
0 请登录后投票
   发表时间:2011-01-24  
renjie120 写道

但是你这样的话,要改动后台代码,对吧?而只用前台js处理的话,就不用改动后台的java代码.前台数据量多了,可能会有性能的影响.

如果只是为了避免改,后台一样可以做成可配置形式。至于数据量大的问题,数据量大,前台PC的压力肯定比后台服务器来的大,况且我这样做,实际上是压缩了数据量,因为合并了一些重复的数据。另外,每页显示1000条数据,个人认为对用户是非常不友好的,所以我做表格显示的时候基本不会这样做。

flashing 写道
不错,.另外我觉得是还是像lz这样在js里面处理比较好,在服务器端合并性能更差,现在浏览器js引擎的性能已经不是当年了。
另外把计算的事情扔给各个客户端,在有一定并发压力的时候其实是更明智的办法。

你这个想法我是赞同的,但我做的是企业内部的应用,办公用PC难免良莠不齐,而且越是一线的业务员,所用的机器往往越差,去年因为这个栽过跟头,所以印象深刻。不过还是一句话,具体问题具体分析吧。

0 请登录后投票
   发表时间:2011-01-24  
试了下,点击合并按钮后没反应啊
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics