Comment accéder au code parent d'un d3.js sélection?

j'ai créé le document suivant:

<g>
    <path class=​"line" name=​"gene_1" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    <path class=​"line" name=​"gene_2" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    <path class=​"line" name=​"gene_3" stroke=​"#aec7e8" d=​"M10.47...">​</path>​
    ...
</g>

quand je souris sur chaque chemin, je veux l'ajouter en dernier à l'intérieur du svg: g pour qu'il apparaisse en haut des autres lignes, mais je ne sais pas comment sélectionner correctement le mode parent:

function onmouseover(d, i){
    var current_gene_name = d3.select(this).attr("name"),
        current_gene_pcp = d3.select(".line[name=" + current_gene_name + "]");

    p1 = this.parentNode 

    p2 = current_gene_pcp[0].parentNode

    p3 = current_gene_pcp[0][0].parentNode

    //p.appendChild(this);
}

p1 fonctionne, mais je voulais m'assurer que "cela" est une .line, donc j'ai préféré utiliser current_gene_pcp, mais p2 renvoie <html></html> comme parent, même si p3 renvoie le bon <g></g> . Cette dernière version semble être un bug en attente. Est-il un meilleur moyen?

36
demandé sur Phrogz 2012-05-15 23:44:40

3 réponses

Un D3 sélection est juste un double-tableau enroulé autour de l'élément(s) sélectionné. Comme vous avez trouvé avec p3 , vous pouvez déréférencer les tableaux pour trouver votre premier noeud, si vous voulez. Toutefois, il existe une meilleure méthode:

du docs pour selection.node() :

renvoie le premier élément non - null dans la sélection courante. Si la sélection est vide, renvoie null .

dans votre cas:

var dad = current_gene_pcp.node().parentNode;

cependant, si vous n'avez pas besoin de la ligne autre que la poignée DOM, vous pouvez tout aussi bien obtenir que directement:

// Search document-wide...
var dad = document.querySelector(".line[name=" + current_gene_name + "]");

// ...or only as a child of the current DOM element
var dad = this.querySelector(".line[name=" + current_gene_name + "]");
42
répondu Phrogz 2012-05-15 19:55:15

voici un moyen rapide de déplacer l'élément mouseover à l'avant:

selection.on("mouseover", function() { this.parentNode.appendChild(this); });

Voir aussi un thread apparenté dans le groupe d3-js.

33
répondu mbostock 2012-05-15 21:08:30

Il y a deux façons d'y accéder.

Soit utiliser la troisième variable comme ceci: someNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); }); . Le j contient les données que vous avez fournies au noeud parent.

ou utilisez d3.select(this.parentNode).data()[0].id; .

un exemple:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="area", width="1000px" height="1000px"></div>
<script>
var GAP = 10, NODE_RADIUS = 14;

  var nodes = [
    {id: 1, prop: [{id: 1, something: 1}], abc: 1},
    {id: 2, prop: [{id: 1, something: 1}, {id: 2, something: 1}, {id: 3, something: 1}], abc: 2},
    {id: 3, prop: [{id: 1, something: 1}, {id: 2, something: 1}], abc: 3},
    {id: 4, prop: [{id: 1, something: 1}], abc: 4},
    {id: 5, prop: [{id: 1, something: 1}], abc: 5},
    {id: 6, prop: [], abc: 6}
  ];

var nodeLayer = d3.select("#area").selectAll(".node").data(nodes, function(d) {return d.id; });
var iNodes = nodeLayer.enter().append("svg").attr("class", "node");
    //append the black circle
    iNodes.append("circle")
                .style("fill", "black")
                .attr("r", NODE_RADIUS)
                .attr("cx", function(d) {return 10 + d.id * 10;})
                .attr("cy", 100);

    iNodes.append("g").selectAll(".prop").data(function(d) {return d.prop;}).enter()
            .append("text")
                .text(function(d,i,j){console.log("parent id="+j); return d3.select(this.parentNode).data()[0].id;})
                .attr("dx", 50)
                .attr("dy", 50)
                .style("font-size", "8px")
                .style("fill", d3.rgb(180,0,0))
                .style("text-anchor", "middle");

</script>
</body>
5
répondu Nav 2017-05-23 12:01:31