[英]Javascript Create complex table header from json
我想用colspan創建一個html表頭,我迷路了; 我有這個json:
var metadata = [{
"colIndex": 0,
"colType": "String",
"colName": "PM"
}, {
"colIndex": 1,
"colType": "String",
"colName": "PROD"
}, {
"colIndex": 2,
"colType": "Numeric",
"colName": "NR/M1"
}, {
"colIndex": 3,
"colType": "Numeric",
"colName": "NR/M2"
}, {
"colIndex": 4,
"colType": "Numeric",
"colName": "NR/M3"
}, {
"colIndex": 5,
"colType": "Numeric",
"colName": "NR/M4"
}, {
"colIndex": 6,
"colType": "Numeric",
"colName": "NR/M5"
}, {
"colIndex": 7,
"colType": "Numeric",
"colName": "NR ART/M6"
}, {
"colIndex": 8,
"colType": "Numeric",
"colName": "NR ART/M1"
}, {
"colIndex": 9,
"colType": "Numeric",
"colName": "NR ART/M2"
}, {
"colIndex": 10,
"colType": "Numeric",
"colName": "NR ART/M3"
}, {
"colIndex": 11,
"colType": "Numeric",
"colName": "NR ART/MX"
}];
該表頭主要基於拆分“ colType”:“ Numeric”
+------+-------+-----+--------+-----+-----+-----+-----+------+----+----+----+
| | | NR | NR ART |
+ PAM | PROD +-----+--------+-----+-----+-----+-----+------+----+----+----+
| | M1 | M2 | M3 | M4 | M5 | M6 | M1 | M2 | M3 | MX |
+------+-------+-----+--------+-----+-----+-----+-----+------+----+----+----+
首先我嘗試在colType為數字的情況下拆分colName
var arr = [], a;
$.each(metadata, function (i, v) {
arr.push(v.colName.split("/"));
a = v.colName.split("/").length;
});
接下來,我得到了唯一的父母(?),但是我該怎么辦? 我認為我必須遍歷此數組(父級-子級,然后構造html標頭)。
該數組是動態的。
有什么建議嗎? 謝謝,麻煩您了。
下面的代碼應該做的工作,請檢查
var arr = {}, a;
$.each(metadata, function (i, v) {
arr[v.colName.split("/")[0]] = arr[v.colName.split("/")[0]].push(v.colName.split("/")[1]) || [] ;
});
為了顯示它
for(t1 in arr){
if(t1.length > 0){
//has children element
}
else{
//has only 1 element
}
}
使此問題復雜化的一件事是表中需要colspan
和rowspan
。 因此,您需要基於colName屬性對對象進行組計數。
這是如何實現的粗略示例。 說明在代碼注釋中。 (此示例對colspan
使用組計數,但對rowspan
進行硬編碼。您也可以對rowspan
進行組計數)。
在此示例中,我僅將jQuery用於創建和添加表。 核心邏輯使用純Javascript 。
片段 :
var metadata = [{"colIndex": 0, "colType": "String", "colName": "PM"}, {"colIndex": 1, "colType": "String", "colName": "PROD"}, {"colIndex": 2, "colType": "Numeric", "colName": "NR/M1"}, {"colIndex": 3, "colType": "Numeric", "colName": "NR/M2"}, {"colIndex": 4, "colType": "Numeric", "colName": "NR/M3"}, {"colIndex": 5, "colType": "Numeric", "colName": "NR/M4"}, {"colIndex": 6, "colType": "Numeric", "colName": "NR/M5"}, {"colIndex": 7, "colType": "Numeric", "colName": "NR ART/M6"}, {"colIndex": 8, "colType": "Numeric", "colName": "NR ART/M1"}, {"colIndex": 9, "colType": "Numeric", "colName": "NR ART/M2"}, {"colIndex": 10, "colType": "Numeric", "colName": "NR ART/M3"}, {"colIndex": 11, "colType": "Numeric", "colName": "NR ART/MX"}]; // First filtering objects which will form the headers var rowHeaders = metadata.filter(function(obj) { return obj.colType == "String"; }); var colHeaders = metadata.filter(function(obj) { return obj.colType == "Numeric"; }); // Now we need the grouping on colName with value before slash. // These will form the group header. Count will determine the colspan. var colHeadersMain = {}; metadata.forEach(function(obj) { if (obj.colType == "String") { return } // Only for Numeric colType // Check if the key has been stored in the colHeadersMain if (obj.colName.split('/')[0] in colHeadersMain) { // If yes, then increment the value of the key for object colHeadersMain colHeadersMain[obj.colName.split('/')[0]]++; } else { // If not, reset the value colHeadersMain[obj.colName.split('/')[0]] = 1; } }); // Variables to hold jQuery elements var $table = $("<table>"), $thead = $("<thead>"), $row1 = $("<tr>"), $row2 = $("<tr>"); // Iterate row headers and form the first row // Hard-coding the rowspan. // ToDo: Maintain count, similar to column headers. rowHeaders.forEach(function(obj, idx) { var $th = $("<th rowspan='2'>"); $th.text(obj.colName); $row1.append($th); }); // Iterate col grouping headers and continue the row // colpsan is the group count that we created earlier for (var key in colHeadersMain) { var $th = $("<th colspan='" + colHeadersMain[key] + "'>"); $th.text(key); $row1.append($th); } // Add the first header row to thead $thead.append($row1); // Iterate next line of col headers colHeaders.forEach(function(obj, idx) { var $th = $("<th>"); $th.text(obj.colName.split('/')[1]); $row2.append($th); }); // Add to the thead $thead.append($row2); // Add to the table $table.append($thead); // Add to the page / element $("#wrap").append($table); // Done.
table, td, th { border: 1px solid gray; border-collapse: collapse; } th, td { padding: 4px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="wrap"></div>
由於您沒有在帖子中標記jQuery,因此這是一個普通的JavaScript解決方案(盡管您確實在帖子代碼中使用了$
,這可能表示jQuery)。
下面的代碼應用於metadata
會將其解析為一種更有利於您要做的事情的格式:
var columns = [];
metadata.forEach(function(column, index, array) { // parse into a more friendly format for making columns
var col = {}, // will be the column
parts = column.colName.split('/'), // you're splitting on the column name in your post
match = null, // for lookup, leaving null for falsy test later
i = 0; // iterator / index
col.name = parts[0]; // store the name
col.type = column.colType; // and type
col.index = column.colIndex; // and index, if you want to use it later
col.subColumns = []; // make an empty array for any subcolumns that may exist so we can concat later
if (parts.length > 1) {
col.subColumns.push({ // subcolumn, push it into the array
"name": parts[1],
"index": col.index
});
}
for (i = 0; i < columns.length; i += 1) {
if (columns[i].name === col.name) { // [parent] column already exists
match = i; // store the index
break; // exit the loop
}
}
if (match) { // index found
columns[i].subColumns = columns[i].subColumns.concat(col.subColumns); // concat the subcolumns
} else {
columns.push(col); // did not exist, add it to the array
}
});
完成此操作后,循環遍歷columns
變量兩次以創建兩行(假定thead
, tr
和th
元素的變量)。
columns.forEach(function(column, index, array) { // loop through once to make "parent" headers
th = document.createElement('th'); // create th element
th.colSpan = column.subColumns.length; // set a colSpan as necessary
if (!column.subColumns.length) { // if there are no subcolumns, make the header span two rows
th.rowSpan = 2;
}
th.innerText = column.name; // set the header text
tr.appendChild(th); // add to row
});
columns.forEach(function(column, index, array) { // loop through a second time to get the child headers
column.subColumns.forEach(function(subColumn, index, array) { // loop through the child headers
th = document.createElement('th'); // create th
th.innerText = subColumn.name; // set the header text
tr.appendChild(th); // add to row
});
});
這是實際的:
var metadata = [{ "colIndex": 0, "colType": "String", "colName": "PM" }, { "colIndex": 1, "colType": "String", "colName": "PROD" }, { "colIndex": 2, "colType": "Numeric", "colName": "NR/M1" }, { "colIndex": 3, "colType": "Numeric", "colName": "NR/M2" }, { "colIndex": 4, "colType": "Numeric", "colName": "NR/M3" }, { "colIndex": 5, "colType": "Numeric", "colName": "NR/M4" }, { "colIndex": 6, "colType": "Numeric", "colName": "NR/M5" }, { "colIndex": 7, "colType": "Numeric", "colName": "NR ART/M6" }, { "colIndex": 8, "colType": "Numeric", "colName": "NR ART/M1" }, { "colIndex": 9, "colType": "Numeric", "colName": "NR ART/M2" }, { "colIndex": 10, "colType": "Numeric", "colName": "NR ART/M3" }, { "colIndex": 11, "colType": "Numeric", "colName": "NR ART/MX" }], columns = [], thead = document.getElementById('dynamic'), // cache this DOM lookup tr = document.createElement('tr'), th; // placeholder for th elements that will be created metadata.forEach(function(column, index, array) { // parse into a more friendly format for making columns var col = {}, // will be the column parts = column.colName.split('/'), // you're splitting on the column name in your post match = null, // for lookup, leaving null for falsy test later i = 0; // iterator / index col.name = parts[0]; // store the name col.type = column.colType; // and type col.index = column.colIndex; // and index, if you want to use it later col.subColumns = []; // make an empty array for any subcolumns that may exist so we can concat later if (parts.length > 1) { col.subColumns.push({ // subcolumn, push it into the array "name": parts[1], "index": col.index }); } for (i = 0; i < columns.length; i += 1) { if (columns[i].name === col.name) { // [parent] column already exists match = i; // store the index break; // exit the loop } } if (match) { // index found columns[i].subColumns = columns[i].subColumns.concat(col.subColumns); // concat the subcolumns } else { columns.push(col); // did not exist, add it to the array } }); columns.forEach(function(column, index, array) { // loop through once to make "parent" headers th = document.createElement('th'); // create th element th.colSpan = column.subColumns.length; // set a colSpan as necessary if (!column.subColumns.length) { // if there are no subcolumns, make the header span two rows th.rowSpan = 2; } th.innerText = column.name; // set the header text tr.appendChild(th); // add to row }); thead.appendChild(tr); // add row to thead tr = document.createElement('tr'); // reset row columns.forEach(function(column, index, array) { // loop through a second time to get the child headers column.subColumns.forEach(function(subColumn, index, array) { // loop through the child headers th = document.createElement('th'); // create th th.innerText = subColumn.name; // set the header text tr.appendChild(th); // add to row }); }); thead.appendChild(tr); // add row to thead
th {border: 1px solid black;}
<table> <thead id="dynamic"></thead> </table>
jQuery,如果您正在使用它,可以使此語法更加“有用”(主要是在制作行和標題單元格,請參見下文),但是原理是相同的。
columns.forEach(function(column, index, array) { // loop through once to make "parent" headers
th.clone().attr({
"colSpan": column.subColumns.length,
"rowSpan": column.subColumns.length === 0 ? 2 : 1
}).text(column.name).appendTo(tr);
});
tr.appendTo(thead);
tr = $('<tr />');
columns.forEach(function(column, index, array) { // loop through a second time to get the child headers
column.subColumns.forEach(function(subColumn, index, array) { // loop through the child headers
th.clone().text(subColumn.name).appendTo(tr);
});
});
tr.appendTo(thead);
幾個小時后,我找到了解決我問題的答案。 在第一部分中,我創建了tr和th(第一個非唯一的)
var a = [], l = 0;
for (var i = 0; i < metadata.length; i++) {
var d = {
"colName": metadata[i].colName.split("/"),
"colType": metadata[i].colType
};
a.push(d);
if (metadata[i].colType == "Numeric") {
trl = metadata[i].colName.split("/").length;
}
}
for (var l = 0; l < trl; l++) {
var tr = $("<tr/>").appendTo("thead");
}
for (var j = 0; j < a.length; j++) {
if (a[j].colType == "String") {
$("<th/>").addClass("string").attr("rowspan", l).html(a[j].colName).appendTo("thead tr:nth(0)");
} else {
for (var k = 0; k < a[j].colName.length; k++) {
$("<th/>").addClass("numeric").html(a[j].colName[k]).appendTo("thead tr:nth(" + k + ")");
}
}
}
這部分從這里改編。 現在,我收拾桌子thead居住唯一。
$('table tr').each(function () {
var tr = this;
var counter = 0;
var strLookupText = '';
$('th.numeric', tr).each(function (index, value) {
var td = $(this);
if ((td.text() == strLookupText) || (td.text() == "")) {
counter++;
td.prev().attr('colspan', '' + parseInt(counter + 1, 10) + '').css({
textAlign: 'center'
});
td.remove();
} else {
counter = 0;
}
strLookupText = td.text();
});
});
代碼有點混亂,但是已經晚了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.