I have problem where I have to add a parent node by selection of multiple elements.
I have:
<g class="group">
<g class="Node" id="1">...</g>
<g class="Node" id="2">...</g>
<g class="Node" id="3">...</g>
<g class="Node" id="4">...</g>
</g>
Now in the above structure i have to select some elements which have class Node
by their ids and add a parent single parent element for them.
It should look something like this, if I select Node 2 & 3 for example:
<g class="group">
<g class="Node" id="1">...</g>
<g class="Grp">
<g class="Node" id="2">...</g>
<g class="Node" id="3">...</g>
</g>
<g class="Node" id="4">...</g>
</g>
Is there some way I can do this manipulation by using javascript or D3.
Just for completeness, this is (one of...) the idiomatic D3 for doing that:
var group = d3.select(".group");
var newGroup = group.insert("g", "#g2").attr("class", "Grp");
var nodes = group.selectAll("#g2, #g3").remove();
nodes.each(function() {
var self = this;
newGroup.append(function() {
return self
});
});
The nice thing about remove()
method is that, like several methods in D3, it returns the selection. Therefore, we can remove the elements but keeping a reference to them, so we can append them later (inside the new group).
Here is the demo. Nothing will show up in the SVG (painted in blue), you have to inspect the SVG using your browser's web inspector to see the groups structure:
var group = d3.select(".group");
var newGroup = group.insert("g", "#g2").attr("class", "Grp");
var nodes = group.selectAll("#g2, #g3").remove();
nodes.each(function() {
var self = this;
newGroup.append(function() {
return self
});
});
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg style="background-color:powderblue;">
<g class="group">
<g class="Node" id="g1"></g>
<g class="Node" id="g2"></g>
<g class="Node" id="g3"></g>
<g class="Node" id="g4"></g>
</g>
</svg>
With javascript you can do something like this
var els = document.querySelectorAll('.group, #id2, #id3'); // grab the parent and id2/3
var grp = document.createElement('g'); // create wrapper
grp.className = 'Grp'; // give it a class
els[0].insertBefore(grp, els[1]); // insert it before id2
grp.appendChild(els[1]); // move id2 to wrapper
grp.appendChild(els[2]); // move id3 to wrapper
.Grp {
color: red;
}
<g class="group">
<g class="Node" id="id1">.1.</g>
<g class="Node" id="id2">.2.</g>
<g class="Node" id="id3">.3.</g>
<g class="Node" id="id4">.4.</g>
</g>
If you are easy, you can do it with jQuery
. Less lines of code.
$( "#2, #3" ).wrapAll( "<div class='Grp'></div>" );
console.log($(".group").html())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<g class="group">
<g class="Node" id="1">...</g>
<g class="Node" id="2">...</g>
<g class="Node" id="3">...</g>
<g class="Node" id="4">...</g>
</g>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With