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)); }