title: D3 Tree Chart with D3 Donut Chart Node
body: <p>I want to add Donut chart in each node of D3 tree chart (replace circle node in tree with Donut Chart)</p>
  
  <p>Below is my Code. I want to replace the circle node with Donut chart in each node with different data that sholud be read from sample json.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// Sample JSON Data 
  var jsondata = {
    "name": "CERT",
    "children": [{
      "name": ""
    }, {
      "name": ""
    }, {
      "name": "DNS",
      "children": [{
        "name": "FW",
        "children": [{
          "name": ""
        }, {
          "name": ""
        }, {
          "name": "ADC",
          "children": [{
            "name": ""
          }, {
            "name": ""
          }, {
            "name": "SERVERS",
            "children": [{
              "name": ""
            }, {
              "name": ""
            }]
          }]
        }]
      }]
    }, {
      "name": "FW",
      "children": [{
        "name": ""
      }, {
        "name": ""
      }, {
        "name": "DNS",
        "children": [{
          "name": ""
        }, {
          "name": ""
        }, {
          "name": "ADC",
          "children": [{
            "name": "SERVERS"
          }]
        }]
      }]
    }]
  };
  
  var margin = {
      top: 20,
      right: 120,
      bottom: 20,
      left: 120
    },
    //width = 960 - margin.right - margin.left, height = 800 - margin.top - margin.bottom;
    width = screen.width;
  height = 800 - margin.top - margin.bottom;
  
  var i = 0,
    duration = 750,
    root;
  
  var tree = d3.layout.tree()
    .separation(function(a, b) {
      return a.parent === b.parent ? 1 : 2;
    })
    .children(function(d) {
      return d.children;
    })
    .size([height, width]);
  
  
  var diagonal = d3.svg.diagonal()
    .projection(function(d) {
      return [d.y, d.x];
    });
  
  var line = d3.svg.line()
    .x(function(d) {
      return d.x;
    })
    .y(function(d) {
      return d.y;
    });
  
  var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
    .call(zm = d3.behavior.zoom().scaleExtent([1, 13]).on("zoom", redraw)).append("g")
    .attr("transform", "translate(" + 350 + "," + 20 + ")");;
  
  // put JSON data to root variable 
  root = jsondata;
  root.x0 = height / 2;
  root.y0 = 0;
  
  //necessary so that zoom knows where to zoom and unzoom from
  zm.translate([350, 20]);
  update(root);
  
  //d3.select(self.frameElement).style("height", "800px");
  
  function update(source) {
  
  
    // Compute the new tree layout.
    var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);
  
    // Normalize for fixed-depth.
    nodes.forEach(function(d) {
      d.y = d.depth * 180;
    });
  
  
    // Update the nodes 
    var node = svg.selectAll("g.node")
      .data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });
  
    // Enter any new nodes at the parent's previous position.
    var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) {
        return "translate(" + source.y0 + "," + source.x0 + ")";
      })
      .on("click", click)
      .on("mouseover", function(d) {
        var g = d3.select(this); // The node
        // The class is used to remove the additional text later
        var info = g.append('text')
          .classed('info', true)
          .attr('x', 30)
          .attr('y', 10)
          .text(function(d) {
            return d.name;
          });
      })
      // Remove the info text on mouse out.
      .on("mouseout", function() {
        d3.select(this).select('text.info').remove();
      });
  
    nodeEnter.append("circle")
      .attr("r", 1e-6)
      .style("fill", function(d) {
        return d._children ? "lightsteelblue" : "#fff";
      });
  
    nodeEnter.append("text")
      .attr("x", function(d) {
        return d.children || d._children ? -10 : 10;
      })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) {
        return d.children || d._children ? "end" : "start";
      })
      .text(function(d) {
        return d.name;
      })
      .style("fill-opacity", 1e-6);
  
    // Transition nodes to their new position.
    var nodeUpdate = node.transition()
      // .duration(duration)
      .attr("transform", function(d) {
        return "translate(" + d.y + "," + d.x + ")";
      });
  
    nodeUpdate.select("circle")
      .attr("r", function(d) {
        return d.children ? 20 : 10;
      })
      .style("fill", function(d) {
        return d._children ? "lightsteelblue" : "#fff";
      });
  
    nodeUpdate.select("text")
      .style("fill-opacity", 1);
  
    // Update the links…
    var link = svg.selectAll("path.link")
      .data(links, function(d) {
        return d.target.id;
      });
  
    // Enter any new links at the parent's previous position.
    link.enter().insert("path", "g")
      .attr("class", "link")
  
    .attr("d", function(d) {
      return line([{
        x: d.source.y,
        y: d.source.x
      }, {
        x: d.target.y,
        y: d.target.x
      }]);
    });
  
    // Transition links to their new position.
    link.transition()
      //.duration(900)
      .attr("d", function(d) {
        return line([{
          x: d.source.y,
          y: d.source.x
        }, {
          x: d.target.y,
          y: d.target.x
        }]);
      });
  
    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
      // .duration(duration)
  
    .attr("d", function(d) {
        return line([{
          x: d.source.y,
          y: d.source.x
        }, {
          x: d.target.y,
          y: d.target.x
        }]);
      })
      .remove();
  
    // Transition exiting nodes to the parent's new position.
    var nodeExit = node.exit().transition()
      .duration(duration)
      .attr("transform", function(d) {
        return "translate(" + source.y + "," + source.x + ")";
      })
      .remove();
  
    nodeExit.select("circle")
      .attr("r", 1e-6);
  
    nodeExit.select("text")
      .style("fill-opacity", 1e-6);
  
    // Stash the old positions for transition.
    nodes.forEach(function(d) {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }
  
  function elbow(d, i) {
    return "M" + d.source.y + "," + d.source.x + "H" + d.target.y + "V" + d.target.x + (d.target.children ? "" : "h" + margin.right);
  }
  
  // Toggle children on click.
  function click(d) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    update(d);
  }
  
  //redraw graph after zoom
  function redraw() {
    svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.node {
    cursor: pointer;
  }
  .node circle {
    fill: #fff;
    stroke: steelblue;
    stroke-width: 1.5px;
  }
  .node text {
    font: 10px sans-serif;
  }
  .link {
    fill: none;
    stroke: #ccc;
    stroke-width: 1.5px;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.3/d3.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>