score:3

Accepted answer

first, after the work inside wrap() is done, you need to store the resulting height on the datum of the text: d.height = 19 * (linenumber + 1);. that way, the height becomes available to whatever needs it. for example, you can use that to set the rect height from outside of wrap() instead of the parentnode.children[0] thing, which is better separation of concerns. anyway, this is what wrap() ends up being:

    function wrap(text, width) {
        text.each(function (d) { // diff add param d
            var text = d3.select(this),
              // diff: use datum to get name, instead of element text
              words = d.name.split(/\s+/).reverse(), 
              word,
              line = [],
              linenumber = 0,
              lineheight = 1.1, // ems
              y = text.attr("y"),
              dy = parsefloat(text.attr("dy")),
              tspan = text.text(null).append("tspan").attr("x", 0).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", 0).attr("y", y).attr("dy", ++linenumber * lineheight + dy + "em").text(word);
                }
            }

            // diff: store the height via the datum, d
            d.height = 19 * (linenumber + 1);
            d3.select(this.parentnode.children[0]).attr('height', 19 * (linenumber + 1));

        });
    }
});

now that you have d.height you can use it to calculate the necessary offsets of the diagonal's endpoints.

    // calculate source and target offsets
    // d.height gets set by the wrap() function
    var diagonal = d3.svg.diagonal()
        .source(function (d) {
            return {
                "x": d.source.x + d.source.height / 2,
                "y": d.source.y + 150
            };
        })
        .target(function (d) {
            return {
                "x": d.target.x + d.target.height / 2,
                "y": d.target.y
            };
        })
        .projection(function (d) { return [d.y + 0, d.x + 0];
      });

see modified fiddle


Related Query