Reputation: 59
complete d3 newbie here. I have this d3 tree that I'm using (here's the working jsfiddle https://jsfiddle.net/Joe123/vq4jpr1s/16/) and I have it so that the text for each node wraps to the size of the node. However, upon multiple clicks on the same node as you'll see, the text reverts back to being unwrapped and I cannot figure out why. Does anyone have any ideas? any help would be greatly appreciated.
Here is the wrap function:
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1,
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 5).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 5).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
d3.select(this.parentNode.children[0]).attr("height", 20 * (lineNumber+1));
});
}
wrap(d3.selectAll('text'),150);
And below is the click function, I tried calling the wrap function from here but no luck.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
}
update(d);
}
Upvotes: 3
Views: 182
Reputation: 102194
The problem is that you are using wrap
again and again in the same text. This is what I did:
First, I changed the class of any new text to newText
:
nodeEnter.append("text")
.attr("x", function(d) {
return d._children ? -0 : 8;
})
.attr("y", 3)
.attr("dy", "0em")
.attr("text-anchor", "middle")
.attr("class", "newText")
.text(function(d) {
return d.name;
})
wrap(d3.selectAll('.newText'),150);
And then, in the function click, I changed the class of all texts:
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
}
d3.selectAll("text").attr("class", "text");
update(d);
}
Upvotes: 1
Reputation: 32327
The problem is that the text is already devoid of space when you try to a split on the basis of whitespace (for second time on-wards).
So instead of doing
words = text.text().split(/\s+/).reverse(),
do it this way
words = d3.select(this).data()[0].name.split(/\s+/).reverse(),
working example here
Upvotes: 4