D3.js essayant de mettre en œuvre la table svg sortable

Comme mon titre indique que je tente d'implémenter une table interactive avec de belles transitions, c'est pourquoi j'ai choisi D3.js en combinaison avec des éléments svg.

J'ai réussi à mettre en place une table tritable avec des éléments HTML normaux (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;}); } 

Comme vous pouvez le voir, le tableau trie les données correctement en cliquant sur les éléments d'en-tête. Sur la base du tableau ci-dessus, j'ai commencé à mettre en œuvre la version svg de cette table et c'est ainsi que je suis arrivé jusqu'à présent:

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); } 

Le problème que je suis actuellement incapable de résoudre, c'est que le tri n'est pas un bon travail. Lorsque vous cliquez sur les en-têtes, quelque chose se passe, mais les lignes ne sont pas classées correctement. Ce qui me semble très étrange, c'est que, lors de l'inspection des éléments html dans le navigateur, les éléments g.row sont triés correctement en fonction des données qui leur sont liées.

Je ne pense pas qu'il y ait un problème avec ma fonction de tri, parce que j'utilise le même dans les deux tables. Je suppose que les lignes nouvellement triées ne sont pas alimentées avec les cellules correctes, mais je ne sais pas comment résoudre ce problème.

EDIT: Ok j'ai réussi à mettre à jour correctement le texte dans les cellules vers le nouveau tri. Le code corrigé est sur jsfiddle et également édité ici. Mais il reste encore un problème que je ne comprends pas:

La transition des lignes vers leurs nouvelles positions ne correspond pas aux données nouvellement triées qui leur sont liées. Par exemple, lorsque vous cliquez plusieurs fois sur "id", vous verrez ce que je veux dire. Est-il possible que le paramètre «i», que j'utilise pour passer aux nouvelles positions, ne représente pas l'ordre nouvellement trié? J'ai trouvé cet exemple, qui est similaire à celui du mien et que la transition fonctionne correctement:

Http: // examples.oreilly.com/0636920026938/chapter_10/10_delay.html (désolé, je ne peux pas poster plus de 2 liens)

Où est l'erreur dans mon code?

J'ai trouvé la solution à mon problème sur cette page:

http://bost.ocks.org/mike/constancy/

Le problème était une fonction de clé manquante pour que les données soient correctement liées aux lignes.

En changeant cette ligne:

 var rows = rowsGrp.selectAll("g.row").data(jsonData); 

à

 var rows = rowsGrp.selectAll("g.row").data(jsonData, function(d){ return d.id; }); 

Et en supprimant la mise à jour de la cellule après la transition:

 //update cells rows.selectAll("g.cell").select("text").text(String); 

La table trie et transforme correctement maintenant.