0

I'm seeing some behavior in D3 that I'm not expecting, and I don't know how to get around it. With this block of code:

node.append("text")
    .attr("dy", ".3em")
    .style("text-anchor", "middle")
    .text(function (d) { return d.FSname; })
    .attr("radius", function (d) { return d.r;})
    .call(wrap, function(d) {return d.r;})
   //.call(wrap, 140)
;

Here is the wrap() function:

function wrap(text, width) {
    //reflows text to be within a pixel width
    console.log("hit wrap(",text,width,this,")");
    text.each(function () {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.0, // 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) {
                if (line.length > 1) 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);
            }
        }
    });
}

I want to pass the radius of the circle for a bubble chart into the wrap function, but what I get in the width argument is the function itself, and not the resolved d.r. Is there a way of getting this anonymous function to resolve to a value before passing it into the .call() ?

Craig Soich
  • 145
  • 10
  • `.call` is used to change the `this` of a _function_, are you sure you don't simply want to invoke? – Paul S. Nov 10 '15 at 16:58
  • @PaulS. here _call_ can be simple function from object, and not native _call_ function – Grundy Nov 10 '15 at 17:05
  • `wrap()` is MBostock's text wrap function (see edit above) – Craig Soich Nov 10 '15 at 17:08
  • what value for `text` parameter? it would be greate if you can provide sample fiddle – Grundy Nov 10 '15 at 17:14
  • try see [doc](https://github.com/mbostock/d3/wiki/Selections#call): first argument is _selection_ and second _arguments_, so it not call functino that you pass as second argument. – Grundy Nov 10 '15 at 17:30
  • FYI, [source function _call_](https://github.com/mbostock/d3/blob/master/src/selection/call.js#L4): as you can see this simplest _apply_ inside – Grundy Nov 10 '15 at 17:46

2 Answers2

2

You can use .each() instead of .call():

node.append("text")
  ...
  .each(function(d) { wrap(d3.select(this), d.r); });

Alternatively, you can change the definition of wrap() to apply the function:

function wrap(text, widthFunc) {
  // ...
  text.each(function(d) {
    var width = widthFunc(d);
    // ...
  });
}
Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • That did it! `each()` was the function to call. the examples I pulled this function from used `call()` but I guess it was because the width was constant. Thanks! – Craig Soich Nov 10 '15 at 17:54
  • The `wrap()` function is simply not intended to be called with a function. I would tend towards the latter approach; fixing the function so that it can be called as you want to call it. – Lars Kotthoff Nov 10 '15 at 17:58
0
.attr("radius", function (d) { return wrap.call(this, d.r) });

If wrap returns a number (or a string representing an number because d3 always does +value) it will work fine.

Stranded Kid
  • 1,395
  • 3
  • 15
  • 23
  • Sorry I wasn't clear. The `.attr("radius"....` line works as expected. it's the `call()` function that passes the function into the `width` parameter instead of the resultant value. – Craig Soich Nov 10 '15 at 17:13