Richard
Richard

Reputation: 65510

Selections in D3: how to use parentNode.appendChild?

I'd like to deal with overlapping SVG elements in D3.js using this method from StackOverflow.

However, due to the nature of my code, I want to use a D3 selector rather than this to re-add the element to the DOM. My question is: how can I use a D3 selector to get the relevant node?

This is how the original example does it:

this.parentNode.appendChild(this);

This is my attempt, which fails with "Uncaught TypeError: Cannot call method 'appendChild' of undefined":

var thisNode = d3.select("#" + id);
thisNode.parentNode.appendChild(thisNode);

This JSFiddle (adapted from the original example) demonstrates the problem: http://jsfiddle.net/cpcj5/

How is my D3 selection different from the this in the original example? I tried using thisNode.node().parentNode.appendChild(thisNode) but that also failed.

Upvotes: 5

Views: 10408

Answers (2)

ChristianT
ChristianT

Reputation: 11

You can also use selection.node() in D3:

var thisNode = d3.select("#" + id);
thisNode.node().parentNode.appendChild(thisNode.node());

Upvotes: 1

minikomi
minikomi

Reputation: 8503

The .parentNode method is for a DOM element, not a d3 selection.

To access the DOM element from a d3 selection is a little tricky, and there are often better ways to achieve what you want to do. Regardless, if you have a single element selected, it will be the first and only item within the first item of a d3.selection - i.e. you need to access it like so:

var someIdDOMelement = d3.select("#someid")[0][0];

An edited example of your original using this: http://jsfiddle.net/cpcj5/1/

If you have the id and specifically want to get the DOM element, I'd just go with getElementById:

var someIdDOMElement = document.getElementById("someid")  

Looking at d3 documentation for binding events using on, we can see that, within the function you bind, the this variable is the DOM element for the event which was triggered. So, when dealing with event handling in d3, you can just use this to get the DOM element from within a bound function.

But, looking at your code, I think it's easier to stick with the original implementation for re-appending the node using the original javascript methods, and then creating a d3 selection using d3.select on the dom element bound to this. This is how the original code does it: http://jsfiddle.net/cpcj5/3/

If you have any difficulties caused by this, please comment so I can address them.

Upvotes: 8

Related Questions