Reputation: 1602
I would like to dynamically generate a table of key-value pairs for a selectable data point using d3.
For example, for the data.csv file pasted below, I have d3 code that will plot the x,y values of the 4 data points as circles in an svg. I would like to be able to generate a table of key-value pairs when each circle is clicked. So, for point1 (row 1) the table would be:
<table>
<thead>
<tr> <th>Key</th> <th>Value</th> </tr>
</thead>
<tbody>
<tr> <td>name</td> <td>point1</td> </tr>
<tr> <td>x</td> <td>50</td> </tr>
<tr> <td>y</td> <td>200</td> </tr>
<tr> <td>f</td> <td>1</td> </tr>
</tbody>
</table>
This table is to be updated depending on the data point that is selected - note the headers stay the same, but the content of the table should change. Example data and my d3 + html code so far are below. Any help much appreciated.
data.csv
name,x,y,f
point1,50,170,1
point2,100,75,2
point3,150,125,3
point4,35,25,4
example.js
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 200);
var mktable = function(dat) {
console.log(dat) // data is available!
var tr = d3.select("tbody").selectAll("tr")
.data(d3.keys(dat)).enter().append("tr")
var td = tr.selectAll("td")
.data(function(d){return d})
.enter().append("td")
.text(function(d) {return d})
};
d3.text("data.csv", function(text) {
var data = d3.csv.parse(text);
svg.selectAll("circle")
.data(data)
.enter()
.append("svg:circle")
.attr("cx", function(d) {
return parseFloat(d.x);
})
.attr("cy", function(d) {
return parseFloat(d.y);
})
.attr("r", function(d) {
return 3;
})
.on("mouseover", function() {
d3.select(this)
.attr("r", function(d) { return 7 });
})
.on("mouseout", function() {
d3.select(this)
.attr("r", function(d) { return 3 });
})
.on("click", mktable)
});
example.html
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script type="text/javascript" src="example.js"></script>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>
Upvotes: 0
Views: 2234
Reputation: 1602
Progress - this mktable function generates the correct table for the first click, but clicking on a second point adds extra td elements rather than replacing them.
var mktable = function(dat, i) {
var tr = d3.select("tbody").selectAll("tr")
.data(d3.entries(dat));
tr.enter().append("tr");
tr.append("td")
.text(function(d) { return d.key });
tr.append("td")
.text(function(d) { return d.value });
tr.exit().remove();
};
Upvotes: 2
Reputation: 12241
As you write attributes, you can also read them, handling the click event. So you can read any attribute you set in the vectorial circle
element, and use them to generate the table.
If you need extra values, you can save them in a data-
attribute in the circle, for example data-name
. The data-
attributes are structured this way in order to be complient with the w3c specifications.
In your case i think the table alignment would be hard to implement in an easy way, because the table is an HTML element and it cannot be appended to SVG elements. You could overlay the table with a z-index
, probably, but i suggest you other techniques to show the value, like setting title
or appending and SVG element.
Upvotes: 0