Javascript 使用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> <

我正在使用D3创建一个表,该表来源于
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 });

});