As a title, I try to implement an interactive table with good transitions, so I choose D3.js in combination with SVG elements.
I managed to implement a sortable table with regular HTML elements (th, tr, td):
http://jsfiddle.net/recek/q6LE6/
// create the table header var thead = d3.select("thead").selectAll("th") .data(d3.keys(jsonData[0])) .enter().append("th").text(function(d){return d;}) .on("click", function(d){ return refreshTable(d);}); // fill the table // create rows var tr = d3.select("tbody").selectAll("tr").data(jsonData); tr.enter().append("tr"); // create cells var td = tr.selectAll("td").data(function(d){return d3.values(d);}); td.enter().append("td") .text(function(d) {return d;}); //update? if(sortOn !== null) { // update rows if(sortOn != previousSort){ tr.sort(function(a,b){return sort(a[sortOn], b[sortOn]);}); previousSort = sortOn; } else{ tr.sort(function(a,b){return sort(b[sortOn], a[sortOn]);}); previousSort = null; } //update cells td.text(function(d) {return d;}); }
As you can see, the table correctly sorts the data when clicking on the header elements. Based on the above table, I started implementing the svg version of this table, and so I got:
http://jsfiddle.net/recek/v58zT/
// create the table header var header = headerGrp.selectAll("g") .data(d3.keys(jsonData[0])) .enter().append("g") .attr("class", "header") .attr("transform", function (d, i){ return "translate(" + i * fieldWidth + ",0)"; }) .on("click", function(d){ return refreshTable(d);}); header.append("rect") .attr("width", fieldWidth-1) .attr("height", fieldHeight); header.append("text") .attr("x", fieldWidth / 2) .attr("y", fieldHeight / 2) .attr("dy", ".35em") .text(String); // fill the table // select rows var rows = rowsGrp.selectAll("g.row").data(jsonData); // create rows var rowsEnter = rows.enter().append("svg:g") .attr("class","row") .attr("transform", function (d, i){ return "translate(0," + (i+1) * (fieldHeight+1) + ")"; }); // select cells var cells = rows.selectAll("g.cell").data(function(d){return d3.values(d);}); // create cells var cellsEnter = cells.enter().append("svg:g") .attr("class", "cell") .attr("transform", function (d, i){ return "translate(" + i * fieldWidth + ",0)"; }); cellsEnter.append("rect") .attr("width", fieldWidth-1) .attr("height", fieldHeight); cellsEnter.append("text") .attr("x", fieldWidth / 2) .attr("y", fieldHeight / 2) .attr("dy", ".35em") .text(String); //update if not in initialisation if(sortOn !== null) { // update rows if(sortOn != previousSort){ rows.sort(function(a,b){return sort(a[sortOn], b[sortOn]);}); previousSort = sortOn; } else{ rows.sort(function(a,b){return sort(b[sortOn], a[sortOn]);}); previousSort = null; } rows.transition() .duration(500) .attr("transform", function (d, i){ return "translate(0," + (i+1) * (fieldHeight+1) + ")"; }); //update cells rows.selectAll("g.cell").select("text").text(String); }
Iam's problem, which currently cannot be solved, is that sorting does not quite work. When you click on the headers, something happens, but the lines are not sorted correctly. It seems very strange to me that when checking the html elements in the browser, the g.row elements are sorted correctly according to the data associated with them.
I don’t think there is a problem with my sort function because Iam uses the same in both tables. I assume that the rows you just sorted are not provided with the correct cells, but I don’t know how to solve this problem.
EDIT: Well, I was able to correctly update the text in the cells to a new sort order. The corrected code is on jsfiddle and is also edited here. But there is one more problem that I just don’t understand:
Moving rows to their new positions does not match newly sorted data associated with them. For example, when you click "id" several times, you will see what I mean. Is it possible that the parameter "i", which I use to move to new positions, does not reflect the newly sorted order? I found this example, which is similar to mine, and the transition works correctly:
http://examples.oreilly.com/0636920026938/chapter_10/10_delay.html( sorry, I can’t post more than two links)
Where is the error in my code?