Javascript 使用D3创建一个表,其中两行是同级的
我正在使用D3创建一个表,该表来源于Javascript 使用D3创建一个表,其中两行是同级的,javascript,html,d3.js,Javascript,Html,D3.js,我正在使用D3创建一个表,该表来源于CSV文件。我可以让行与CSV中的每一行匹配,但我有一列包含冗长的文本数据。为了可读性,我希望将该列放在跨整个表的其他列下面的单元格中: <table> ... <tr> <td>col1</td><td>col2</td>...<td>colN</td> </tr> <tr> <
CSV
文件。我可以让行与CSV
中的每一行匹配,但我有一列包含冗长的文本数据。为了可读性,我希望将该列放在跨整个表的其他列下面的单元格中:
<table>
...
<tr>
<td>col1</td><td>col2</td>...<td>colN</td>
</tr>
<tr>
<td colspan="N">lengthy text</td>
</tr>
...
</table>
在所有第一行之后追加所有第二行
如果我尝试:
var row = mytable.enter().append("tr").attr("class","firstrow");
var row2 = mytable.enter().append("tr").attr("class","secondrow");
var row = mytable.enter().append("tr").attr("class","firstrow");
var row2 = mytable.insert("tr").attr("class","secondrow");
第二行追加到第一行中
这与上述结果相同:
var row = mytable.enter().append("tr").attr("class","firstrow");
var row2 = mytable.insert("tr","tr").attr("class","secondrow");
感谢您的帮助
编辑:
对于那些想要玩东西的人,这里是整个shebang:
function createTable(source, title, columns, hook) {
var tableOutput = d3.select(hook).append("table");
var headingRow = tableOutput.append("tr");
var datasets = [source];
var tableHeadings = headingRow.selectAll(".column_headings")
.data(columns)
.enter().append("th").text(function (d) {return d;}).attr("class","column_headings");
var tableChart = function(source) {
d3.csv(source, function(d) {
return {
thing1: +d.thing1,
thing2: d.thing2,
lengthything: d.lengthything, //the text that needs to go in the second row
link: d.link //wrap a link around lenthything
};
},
function(error, data) {
//do the table
var mytable = tableOutput.selectAll().data(data);
var row = mytable.enter().append("tr").attr("class","firstrow");
var row2 = mytable.insert("tr","tr").attr("class","secondrow");
row.append("td").attr("class","numeric").text(function(d) { return d.thing1 });
row.append("td").text(function(d) { return d.thing2 });
});
};
tableChart(datasets[0]);
}重新构造数据。不要让N大小的数据数组中的每个对象对应一行,而是修改数据,以便在现有行之间添加N个新行,其中每一新行都是一个包含长文本的对象,以及一个可用于将其与其他行区分开来的标识符 我明白了。我不认为有一个严格的D3方式来做这件事(仍然只开放给D3的答案)
这很难看,但很管用。有人有更干净/更高效的方法吗?我会重新格式化数据以符合您想要显示的结构。我不控制数据源。您不需要这样做,您可以用Javascript重新格式化。在哪里?在d3.csv(源代码,函数(d){})调用之前?源文件是文件名。有没有可能我们可以使用JSFIDLE?这里有一个可能的相关链接-你有代码来说明这一点吗?我不太明白D3是如何做到这一点的,它更像是一个Javascript练习,而不是D3。本质上,您有一个数组形式的CSV。该数组中的每个项目对应CSV中的一行,对吗?D3喜欢数组,并将该数组中的每个项目渲染为单个项目。但实际上,在CSV中,每个原始行需要两个,其中第二行仅包含该特别长的列的值。因此,在数据数组中循环,并在每个原始行之后添加一个新行。如果你设置了一个JS提琴来浓缩你的用例,我很乐意帮助你编辑它来说明我的意思。@dochran我贴出的答案和你说的相符吗?这是你可以选择的另一种方式,但是的,它有点难看。我的建议(以及其他人的建议)依赖于更改数据数组。将从服务器获取的数据视为您的“模型”,您需要重新调整该数据以适应您的视图--这可以称为“视图模型”。我认为您现在应该按照您所了解的内容进行操作,但在d3中创建可视化完全取决于您传入的数据的结构。即使默认的服务器数据(模型)不符合可视化结构,您也应该能够轻松地处理这些数据。我的数据来自CSV文件,而不是服务器的响应(比如,如果它是通过JSON来的,我就有很多机会对它进行预处理。D3的CSV文件读起来非常简单,所以这是一个巨大的优势,我不想失去它,也不想“滚我自己的”。)我真的认为D3的一个弱点是没有办法处理兄弟元素。
function(error, data) {
//do the table
var mytable = tableOutput.selectAll().data(data);
var row = mytable.enter().append("tr").attr("class","firstrow");
//var row2 = mytable.insert("tr","tr").attr("class","secondrow");
//the above is replaced with:
d3.selectAll("tr.firstrow").each(function(d) {
p = this.parentNode; //grab the parent table element
r = document.createElement("tr");
r.setAttribute("class","secondrow");
c = document.createElement("td");
c.setAttribute("colspan","8");
a = document.createElement("a");
a.setAttribute("href",d.link);
a.innerText = d.message;
//glue everything together
c.appendChild(a);
r.appendChild(c);
//insert the second row after the first
p.insertBefore(r,this.nextSibling);
});
row.append("td").attr("class","numeric").text(function(d) { return d.thing1 });
row.append("td").text(function(d) { return d.thing2 });
});