leumashz
leumashz

Reputation: 73

Copy and Insert in d3 selection

In a d3 program I need to get a node (with d3.selection) and then I want to insert in the same svg.

I know there are some functions like append, and insert, but these functions are for new elements.

var node = d3.select("rect#someId"); //node with some attributes and listeners

Now my var node got the following attributes: {_groups, _parents}

var anotherNode = d3.select("anotherNode").insert(node); //It work but it would be great a similar function or a workaround

Note. I need to preserve the listeners of the node

Upvotes: 7

Views: 8423

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

New answer

D3 v5.0 introduced selection.clone, which:

Inserts clones of the selected elements immediately following the selected elements and returns a selection of the newly added clones.

Here is a demo:

var copy = d3.select("#group").clone(true).attr("transform", "translate(120,100)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="200" height="200">
	<g id="group">
		<rect x="10" y="10" width="50" height="20" fill="teal"></rect>
		<circle cx="35" cy="40" r="20" fill="red"></circle>
	</g>
</svg>

Note that, just as the solution in the original answer, selection.clone will not clone the listeners.


Original answer

Use this function to clone your selection:

function clone(selector) {
    var node = d3.select(selector).node();
    return d3.select(node.parentNode.insertBefore(node.cloneNode(true), node.nextSibling));
}

Then, you can call it with clone("#foo") (by ID) or clone(".foo") (by class).

Here is an example, where the group (one rect and one circle) with ID "group" is cloned (the translate is just to better see the clone):

function clone(selector) {
    var node = d3.select(selector).node();
    return d3.select(node.parentNode.insertBefore(node.cloneNode(true),
node.nextSibling));
}

var copy = clone("#group").attr("transform", "translate(120,100)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="200" height="200">
	<g id="group">
		<rect x="10" y="10" width="50" height="20" fill="teal"></rect>
		<circle cx="35" cy="40" r="20" fill="red"></circle>
	</g>
</svg>

PS: This will not clone the listeners. Also, this function is not mine, it was written by Bostock.

Upvotes: 14

Related Questions