Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 equivalent of jQuery parent()

Tags:

jquery

svg

d3.js

I have various SVG <g> objects, each with a <circle> child and a <text> child. I can use select() to find a particular <text> object, by the class attached to it, and then modify it:

d3.select('text.my-class')
    .classed("my-class",false).classed("new-class",true)
    .text("Next Stage!")
    ;

Now I need to modify it's circle sibling. The circle has no particular identifying class (hhmmm... perhaps giving it one would be the d3 way of doing this?), so my first try was jQuery-like:

d3.select('text.my-class').parent().select('circle')
    .attr('style','fill:#f00;')
    ;

That fails with "parent is not a function".

The answer to a similar question ( How to select parent element of current element in d3.js ) suggested this.parentNode, but either I'm using it wrong or it does not work here. I've tried both of these:

d3.select('text.my-class').select(parentNode).select('circle')
d3.select('text.my-class').select(this.parentNode).select('circle')
like image 626
Darren Cook Avatar asked Mar 25 '14 12:03

Darren Cook


2 Answers

D3 don't have a method to access parent nodes. You can access the DOM node of a selected element using the node() method. This element will have the parentNode attribute:

var textNode = d3.select('text.my-class').node(),  // DOM node
    parentNode = textNode.parentNode,              // Parent DOM node
    parentSelection = d3.select(parentNode),       // Selection containing the parent DOM node
    circle = parentSelection.select('circle');     // selection containing a circle under the parent selection

In a callback, you can use:

d3.select('text.my-class')
   .on('mouseover', function(d) {
      // The 'this' context is set to the DOM element, not the selection
      var circle = d3.select(this.parentNode).select('circle');
      circle.attr('fill', 'red');
   });

Regards,

like image 72
Pablo Navarro Avatar answered Sep 19 '22 23:09

Pablo Navarro


You can use:

selection.select(function() { return this.parentNode; });

You can also just add your own .parent() method to d3.selection.prototype:

d3.selection.prototype.parent = function() {
    return this.select(function() { return this.parentNode; });
};

// example!
d3.selectAll(".child").parent().each(function() {
  console.log(this.className);
});

demo on jsbin

like image 41
gnarf Avatar answered Sep 21 '22 23:09

gnarf