2012-05-15 13 views
35

Ho creato il seguente documento:Come accedere al parentNode di una selezione d3.js?

<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> 

Quando ho mouse su ogni percorso voglio aggiungere lo scorso all'interno della svg: g in modo che appaia in cima alle altre linee, ma non so come selezionare correttamente la 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 funziona, ma ho voluto fare in modo che "questo" è un .Line, così ho preferito usare current_gene_pcp, ma p2 restituisce <html></html> come il genitore, anche se p3 restituisce l'appropriato <g></g>. Quest'ultima versione sembra un bug che aspetta di accadere. C'è un modo migliore?

risposta

41

Una selezione D3 è solo una doppia matrice avvolta attorno agli elementi selezionati. Come hai trovato con p3, puoi rimuovere gli array per trovare il tuo primo nodo, se lo desideri. Tuttavia, un metodo migliore esiste:

Dalla documentazione per selection.node():

restituisce il primo non null elemento nella selezione corrente. Se la selezione è vuota, restituisce null.

Nel tuo caso:

var dad = current_gene_pcp.node().parentNode; 

Tuttavia, se non avete bisogno della linea diversa da quella maniglia DOM, si potrebbe anche solo ottenere che direttamente:

// 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 + "]"); 
32

Ecco un modo rapido per spostare l'elemento del mouseover in primo piano:

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

Vedere anche un related thread nel gruppo d3-js.

+0

Questo comportamento è instabile. Quando provo questo in Chrome in combinazione con gli stili ': hover', gli stili vengono applicati correttamente. Quando provo questo in Firefox (v20), gli stili non vengono applicati affatto. Quando rimuovo questo codice 'mouseover', gli stili sono applicati correttamente in Firefox. Immagino che questo sia causato dal passaggio del mouse di un elemento durante il tentativo di rimuovere se stesso prima di essere ricollegato come ultimo figlio del suo DOM. –

5

Ci sono due modi per accedervi.
Utilizzare lo third variable in questo modo: someNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); });. Lo j contiene i dati forniti al nodo genitore.
o utilizzare d3.select(this.parentNode).data()[0].id;.

Un esempio:

<!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>