可编辑的自动合并单元格的表格

N久没来了,最近项目中用到一个报表,需要能单元格自动合并,并且支持修改,在分页后重新生成表格。所以写了一个小插件在此做个记录。(感觉代码有点罗嗦,层次有点复杂,结构不太清晰,需进一步优化)

 

附件内容:代码、测试页面、操作截图

 

代码如下:

/*
表格插件是一个可编辑、可自动合并单元格的表格
TableView:表格类,
	主要初始化表格参数
	this.data:表格中的数据,要求是一个二维数组,第一维是行,第二维是列
	this.columns:是Column类的集合,对列属性的配置,是否隐藏,是否合并(和合并规则),是否可编辑
	this.tableName:表头需要用户自己设计,所以这里需要配置表格的Id
	this.noDataStr:如果没有数据时,显示的提示信息。
	
Column:列的配置类,列的信息和数据的信息是对应的
	this.isHidden:是否隐藏
	this.isMerged:是否需要合并
	this.mergeConditions:合并条件,是一个MergeCondition的数组
	this.isModified:是否可以修改
	
MergeCondition:合并依据类,根据这些条件决定当前列是否合并
	this.columnIndex:列索引,从0开始,和数据的列对应
	this.conditionType:合并方式,目前只支持列值相等(“eq”),默认可以不填

*/
//定义第一个table类
TableView = function(config){
	this.data = config.data;
	this.columns = config.columns;
	this.tableName = config.tableName;
	this.noDataStr = config.noDataStr?noDataStr:"抱歉,没有找到您需要的数据";
}
TableView.prototype.paint = function(){
	if(this.tableName==null || this.columns==null || this.columns.length<1)return;
	var __table = getE(this.tableName);
	if(__table==null)return;
	//如果没有数据集
	if(this.data==null || this.data.length<1){
		var __tr = __table.insertRow(-1);
		var __td = __tr.insertCell(-1);
		__td.innerHTML = this.noDataStr;
		var colNum = 0;
		for(var j=0; j<this.columns.length; j++){
			if(!this.columns[j].isHidden){
				colNum++;
			}
		}
		__td.setAttribute("colSpan", colNum);
		return;
	}
	//加载表格
	//合并后单元格的Id,只保存td
	var __mergeColumn = [];
	//合并的单元格的个数
	var __mergeNum = [];
	for(var i=0; i<this.data.length; i++){
		var __rowData = this.data[i];
		var __tr = __table.insertRow(-1);
		for(var j=0; j<this.columns.length; j++){
			var __createFlag = true;
			var __column = this.columns[j];
			/*
			如果不需要合并,创建一个新的单元格,
			如果需要合并,
				首先检查内容是否和合并字段内容一致,
				如果一致,直接跳过
				如果不一致,创建新的单元格
			*/
			//根据行和列生成单元格Id
			var __id = getColStr(j)+"_"+i;
			if(__column.isMerged){
				//第一行除外
				if(i>0&&__column.mergeConditions){
					for(var k=0; k<__column.mergeConditions.length; k++){
						var con = __column.mergeConditions[k];
						if(con.columnIndex>=0 && (!con.conditionType || con.conditionType=="eq")){
							__createFlag = this.data[i][con.columnIndex]!=this.data[i-1][con.columnIndex];
						}
						if(__createFlag)break;
					}
				}
			}	
			
			if(__createFlag){
				if(__column.isHidden){
					var __input = document.createElement("input");
					__input.setAttribute("id", __id);
					__input.setAttribute("name", __id);
					__input.setAttribute("type", "hidden");
					__input.setAttribute("value", __rowData[j]);
					__table.appendChild(__input);
				}else{
					var __td = __tr.insertCell(-1);
					__td.innerHTML = __rowData[j];
					__td.setAttribute("id", __id);
					__td.setAttribute("name", __id);
					//如果是可编辑的单元格,添加编辑事件
					if(__column.isModified){
						//双击单元格可编辑
						__td.ondblclick = function(event){
							var __tdinput = document.createElement("input");
							__tdinput.setAttribute("id", "temp_input");
							__tdinput.setAttribute("name", "temp_input");
							__tdinput.setAttribute("type", "text");
							var td;
							if(event==null){
								td=window.event.srcElement;
							}else{
								td=event.target;
							}
							__tdinput.setAttribute("value", td.innerHTML);
							td.innerHTML = "";
							td.appendChild(__tdinput);
							__tdinput.focus();
							__tdinput.select();
							
							//单元格失去焦点时,内容变成输入框的内容
							__tdinput.onblur = function(event){
								var td;
								if(event==null){
									td=window.event.srcElement.parentNode;
								}else{
									td=event.target.parentNode;
								}
								td.innerHTML = getE("temp_input").value;
							}
							//按下回车键时,内容变成输入框的内容
							__tdinput.onkeyup = function(event){
								if(event.keyCode!=13)return;
								var td;
								if(event==null){
									td=window.event.srcElement.parentNode;
								}else{
									td=event.target.parentNode;
								}
								td.innerHTML = getE("temp_input").value;
							}
						}
					}
					__mergeColumn[j] = __id;
					__mergeNum[j] = 1;
				}
			}else{
				getE(__mergeColumn[j]).setAttribute("rowSpan", (++__mergeNum[j]));
			}
		}
	}
}
//Table的列
Column = function(config){
	//是否隐藏
	this.isHidden = config&&(config.typeof("hidden")!="undefined")?config.hidden:false;
	//是否需要合并
	this.isMerged = config&&(config.typeof("isMerged")!="undefined")?config.hidden:false;
	//合并条件
	this.mergeConditions = config&&config.mergeConditions?config.mergeConditions:null;
	//是否可以修改
	this.isModified = config&&(config.typeof("isModified")!="undefined")?config.hidden:false;
	
}

//合并条件 索引从0开始
MergeCondition = function(config){
	this.columnIndex = config&&config.columnIndex?config.columnIndex:null;
	this.conditionType = config&&config.conditionType?config.conditionType:"eq";
}

//**************************************************
//utils
function getE(id){
	return document.getElementById(id);
}

function getColStr(num){
	var cs = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
	if(num<cs.length){
		return cs[num];
	}
	return (getColNum(Math.floor(num/cs.length))+getColNum(num%cs.length));
}

function getColNum(str){
	var cs = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
	if(num<=cs.length){
		return cs[num-1];
	}
	return (getColNum(Math.floor(num/cs.length))+getColNum(num%cs.length));
}

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值