title: How to wrap text to fit screen in d3?
body: <p>i am kinda new in using d3 as visualization.
  Here is my program to visualize document cluster.
  <a href="https://i.stack.imgur.com/LWUWM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LWUWM.png" alt="the document titles exceed the screen"></a></p>
  
  <p>the titles of the documents are so long that the screen cannot show the whole titles, so i want to make the title label of each members wrapped.</p>
  
  <p>here is the d3 code:</p>
  
  <pre><code>var CodeFlower = function(selector, w, h) {
    this.w = w;
    this.h = h;
  
    d3.select(selector).selectAll("svg").remove();
  
    this.svg = d3.select(selector).append("svg:svg")
      .attr('width', w)
      .attr('height', h);
  
    this.svg.append("svg:rect")
      .style("stroke", "#6BB6CF")
      .style("fill", "#6BB6CF")
      .attr('width', "615px")
      .attr('height', h);
  
    this.force = d3.layout.force()
      .on("tick", this.tick.bind(this))
      .charge(function(d) { return d._children ? -d.size / 100 : -40; })
      .linkDistance(function(d) { return d.target._children ? 80 : 25; })
      .size([h, w]);
  };
  
  CodeFlower.prototype.update = function(json) {
    if (json) this.json = json;
  
    this.json.fixed = true;
    this.json.x = this.w / 2;
    this.json.y = this.h / 2;
  
    var nodes = this.flatten(this.json);
    var links = d3.layout.tree().links(nodes);
    var total = nodes.length || 1;
  
    // remove existing text (will readd it afterwards to be sure it's on top)
    this.svg.selectAll("text").remove();
  
    // Restart the force layout
    this.force
      .gravity(Math.atan(total / 50) / Math.PI * 0.4)
      .nodes(nodes)
      .links(links)
      .start();
  
    // Update the links
    this.link = this.svg.selectAll("line.link")
      .data(links, function(d) { return d.target.name; });
  
    // Enter any new links
    this.link.enter().insert("svg:line", ".node")
      .attr("class", "link")
      .attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });
  
    // Exit any old links.
    this.link.exit().remove();
  
    // Update the nodes
    this.node = this.svg.selectAll("circle.node")
      .data(nodes, function(d) { return d.name; })
      .classed("collapsed", function(d) { return d._children ? 1 : 0; });
  
    this.node.transition()
      .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; });
  
    // Enter any new nodes
    this.node.enter().append('svg:circle')
      .attr("class", "node")
      .classed('directory', function(d) { return (d._children || d.children) ? 1 : 0; })
      .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; })
      .style("fill", function color(d) {
        return "hsl(" + parseInt(360 / total * d.id, 10) + ",90%,70%)";
      })
      .call(this.force.drag)
      .on("click", this.click.bind(this))
      .on("mouseover", this.mouseover.bind(this))
      .on("mouseout", this.mouseout.bind(this));
  
    // Exit any old nodes
    this.node.exit().remove();
  
    this.text = this.svg.append('svg:text')
      .attr('class', 'nodetext')
      .attr('dy', 0)
      .attr('dx', 0)
      .attr('text-anchor', 'middle');
  
    return this;
  };
  
  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, // 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() &gt; 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);
        }
      }
    });
  }
  
  function type(d) {
    d.value = +d.value;
    return d;
  }
  
  
  CodeFlower.prototype.flatten = function(root) {
    var nodes = [], i = 0;
  
    function recurse(node) {
      if (node.children) {
        node.size = node.children.reduce(function(p, v) {
          return p + recurse(v);
        }, 0);
      }
      if (!node.id) node.id = ++i;
      nodes.push(node);
      return node.size;
    }
  
    root.size = recurse(root);
    return nodes;
  };
  
  CodeFlower.prototype.click = function(d) {
    // Toggle children on click.
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    this.update();
  };
  
  CodeFlower.prototype.mouseover = function(d) {
    this.text.attr('transform', 'translate(' + d.x + ',' + (d.y - 5 - (d.children ? 3.5 : Math.sqrt(d.size) / 2)) + ')')
      .text(d.name)
      .style('display', null);
  };
  
  CodeFlower.prototype.mouseout = function(d) {
    this.text.style('display', 'none');
  };
  
  CodeFlower.prototype.tick = function() {
    var h = this.h;
    var w = this.w;
    this.link.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });
  
    this.node.attr("transform", function(d) {
      return "translate(" + Math.max(5, Math.min(w - 5, d.x)) + "," + Math.max(5, Math.min(h - 5, d.y)) + ")";
    });
  };
  
  CodeFlower.prototype.cleanup = function() {
    this.update([]);
    this.force.stop();
  };
  </code></pre>
  
  <p>i have tried wrapping text function in some sites but it doesn't work.
  Any help would be appreciated, many thanks :)</p>