最近遇到一需求,要求数据报表正复杂样式展示,那么想到的思路就是先纵向合并,然后再横向合并,后台数据按明细倒入,前端先渲染成普通的表,然后在对表进行重构,代码如下:
/*
@param
{
oprIndex:[],需要合并的列index,index从0开始
}
*/
var deleteObjR = [],
deleteObjC = [];
function combine(oprIndex,table){
//转成数字数字
var rowIndex = [],
colIndex = [];
var index = oprIndex.split(";");
//纵向合并
var cols = index[1];
if(cols!=undefined && cols!="") {
var col = cols.split(",");
//转成数字数字
for(var i= 0,len=col.length;i<len;i++) {
colIndex.push(parseInt(col[i]));
}
combineCol(colIndex, table);
chgTable(table);
//横向合并
var row = index[0].split(",");
for(var i= 0,len=row.length;i<len;i++) {
rowIndex.push(parseInt(row[i]));
}
var indexList = chgRowIndex(rowIndex.sort());
if(indexList.length){
for(var k=0,len=indexList.length; k<len; k++){
combineRow(indexList[k],table);
}
}
chgTable(table);
}
}
function chgRowIndex(arr){
var tempArr = [],
result =[],
last=0;
if(arr.length){
last = arr[0];
tempArr.push(last);
}
for(var k=1,len=arr.length; k<len; k++){
if(last+1 == arr[k]){//同一组
tempArr.push(arr[k]);
last = arr[k];
}else{
tempArr.length > 1 && result.push(tempArr);
last = arr[k];
tempArr = [last];
}
}
tempArr.length > 1 && result.push(tempArr)
return result.length && result;
}
//横向合并时,如果被纵向合并过,调整横向合并列索引
function onCombinCol(self,indexList,table){
var colLen = $(table).find("thead tr").find("th").length,
isCol = false,
tmplen = 0,
resultIndexList = [],
lastIndex = 0;
self.find("td").each(function(index){
lastIndex = index;
if(index==(colLen-1)){
isCol = true;
}
});
if(!isCol) {
tmplen = colLen - 1 - lastIndex;
}
for(var i= 0,len=indexList.length-tmplen;i<len;i++){
resultIndexList.push(indexList[i]);
}
return resultIndexList;
}
function combineRow(indexList,table){
var table = $(table),
max = Math.max.apply(null,indexList),
self = null,
begin = 0,
count = 1,
tmpIndexList = [],
temp = "";
table.find('tbody tr').each(function(index){
self = $(this);
begin = 0;
count = 1;
temp = "";
//判断当前行,td是否被合并过
tmpIndexList = onCombinCol(self,indexList,table);
self.find('td').each(function(index1){
if(tmpIndexList.indexOf(index1) == -1 || index1 > max)
return;
if(temp == ""){
temp = $.trim($(this).html());
begin = index1;
}else{
var current = $.trim($(this).html());
if(temp == current){
count++;
if (index1 == max) {
deleteObjR.unshift({begin:begin,count:count,row:index});
}
}else{
if(count >1){
deleteObjR.unshift({begin:begin,count:count,row:index});
}
temp = current;
begin = index1;
count = 1;
}
}
});
});
}
function combineCol(indexList,table){
var table = $(table),
temp = "",
begin = 0,
current = "",
count = 1,
selector = '';
for(var j=0,len=indexList.length;j<len;j++){
var n = indexList[j];
selector = '.col'+ n;
temp = "";
begin = 0;
current = "";
count = 1;
table.find(selector).each(function(index1){
var self = $(this);
if(index1 == 0 ){
temp = $.trim(self.html());
begin = index1;
}else{
current = $.trim(self.html());
if(temp == current){
if(n!=0) {
var boolist = [];
isCombin(table, index1, n-1,boolist);
if(!boolist.contains(false)) {//前一列是否合并,是合并,否不合并
count++;
}else {
if(count > 1){
deleteObjC.unshift({begin:begin,count:count,col:n});
}
temp = current;
begin = index1;
count = 1;
}
}else {
count++;
}
if(index1 == (table.find(selector).length-1)){
deleteObjC.unshift({begin:begin,count:count,col:n});
}
}else{
if(count > 1){
deleteObjC.unshift({begin:begin,count:count,col:n});
}
temp = current;
begin = index1;
count = 1;
}
}
});
}
}
function isCombin(table,index,n,boolist) {
var preCurrent = '',
current = '',
cur = '' ,
pre = '',
selector = '',
preSelector = '';
if(boolist.contains(false) || n<0){
return;
}
selector = ".col" + n +":eq("+index+")";
preSelector = ".col" + n + ":eq("+(index-1)+")";
pre = table.find(preSelector);
cur = table.find(selector);
preCurrent = $.trim(pre.html());
current = $.trim(cur.html());
if(preCurrent != current) {
boolist.push(false);
}
//追溯到最最源头,看是否相同,不同则不能合并
if(!boolist.contains(false)){
isCombin(table,index,n-1,boolist);
}
}
function chgTable(table){
var table = $(table),
currentObj = {},
selector = "",
tempCount = 0,
tempBegin = 0,
currentRow = null;
for(; deleteObjR.length; ){
currentObj = deleteObjR[0];
tempCount = currentObj.count;
tempBegin = currentObj.begin;
selector = 'tbody tr:eq('+currentObj.row+')';
currentRow = table.find(selector);
currentRow.find('td:eq('+tempBegin+')').attr('colspan',tempCount);
for(; tempCount > 1 ; tempCount--){
currentRow.find('td:eq('+(tempBegin+1)+')').remove();
}
deleteObjR.shift(currentObj);
}
for(; deleteObjC.length; ){
currentObj = deleteObjC[0];
tempCount = currentObj.count;
tempBegin = currentObj.begin;
selector = '.col'+currentObj.col+':eq('+tempBegin+')';
table.find(selector).attr('rowspan',tempCount);
for (;tempCount > 1; tempCount--) {
selector = '.col'+currentObj.col+':eq('+(tempBegin+1)+')';
table.find(selector).remove();
}
deleteObjC.shift(currentObj);
}
}
调用时传入参数表名和索引,表名,要合并的行索引;要合并列索引,如
var oprIndex = “0,1,2;0,1,2,3”;
combine(oprIndex,table);
结果:
原表:
重构后的表: