web-dev-qa-db-fra.com

Comment accéder au parentNode d'une sélection d3.js?

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>

Lorsque je passe la souris sur chaque chemin, je veux l'ajouter en dernier dans le svg: g pour qu'il apparaisse au-dessus des autres lignes, mais je ne sais pas comment sélectionner correctement le parentNode:

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 "ceci" est une ligne. J'ai donc 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 de se produire. Y a-t-il une meilleure façon?

38
nachocab

Une sélection D3 est simplement un double tableau enroulé autour du ou des éléments sélectionnés. Comme vous l'avez trouvé avec p3, Vous pouvez déréférencer les tableaux pour trouver votre premier nœud, si vous le souhaitez. Cependant, une meilleure méthode existe:

À partir des documents pour selection.node() :

Renvoie le premier élément non - null de la sélection actuelle. Si la sélection est vide, renvoie null.

Dans ton cas:

var dad = current_gene_pcp.node().parentNode;

Cependant, si vous n'avez pas besoin de la ligne autre que le descripteur DOM, vous pourriez tout aussi bien l'obtenir 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 + "]");
45
Phrogz

Voici un moyen rapide de déplacer l'élément mouseover vers l'avant:

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

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

35
mbostock

Il existe deux façons d'y accéder.
Soit utilisez la troisième variable comme ceci: someNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); });. j contient les données que vous avez fournies au nœud 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
Nav