title: Add a Legend to D3 Force Directed Graph
body: <p>So I am trying to create a legend in the bottom right corner of my D3. I have written all of the code for the legend but it comes up as just a black screen with the force-directed graph not showing up as well. Any advice would help.</p>
  
  <p><strong>Legend Code:</strong></p>
  
  <pre><code>var color = d3.scale.ordinal()
      .domain(["&lt;400", "400-549", "550-699", "700-849", "850-999", "1000-1149", "1150-1299", "1300-1449", "&gt;1450"])
      .range(["#1a9850", "#66bd63", "#a6d96a","#d9ef8b","#ffffbf","#fee08b","#fdae61","#f46d43","#d73027"]);
  
  
      var legend = d3.append('svg')
      .append("g")
      .selectAll("g")
      .data(color.domain())
      .enter()
      .append('g')
        .attr('class', 'legend')
        .attr('transform', function(d, i) {
          var height = legendRectSize;
          var x = 0;
          var y = i * height;
          return 'translate(' + x + ',' + y + ')';
      });
  
      legend.append('rect')
      .attr('width', legendRectSize)
      .attr('height', legendRectSize)
      .style('fill', color)
      .style('stroke', color);
  
  legend.append('text')
      .attr('x', legendRectSize + legendSpacing)
      .attr('y', legendRectSize - legendSpacing)
      .text(function(d) { return d; });
  </code></pre>
  
  <p><strong>D3 Code:</strong></p>
  
  <pre><code>function start(){
  var w = 1200,
      h = 600,
      radius = 10,
      node,
      link,
      root;
  
  var count = 0;
  
  var color = d3.scale.ordinal()
      .domain(["&lt;400", "400-549", "550-699", "700-849", "850-999", "1000-1149", "1150-1299", "1300-1449", "&gt;1450"])
      .range(["#1a9850", "#66bd63", "#a6d96a","#d9ef8b","#ffffbf","#fee08b","#fdae61","#f46d43","#d73027"]);
  
  var force = d3.layout.force()
      .on("tick", tick)
      .charge(function(d) { return -500; })
      .linkDistance(function(d) { return d.target._children ? 100 : 50; })
      .size([w, h - 160]);
  
      `
  var svg = d3.select("body").append("svg")
      .attr("width", w)
      .attr("height", h);
  
  
  
  
  svg.append("rect")
      .attr("width", "100%")
      .attr("height", "100%")
      .attr("fill", "#000");
  
      var legend = d3.append('svg')
      .append("g")
      .selectAll("g")
      .data(color.domain())
      .enter()
      .append('g')
        .attr('class', 'legend')
        .attr('transform', function(d, i) {
          var height = legendRectSize;
          var x = 0;
          var y = i * height;
          return 'translate(' + x + ',' + y + ')';
      });
  
      legend.append('rect')
      .attr('width', legendRectSize)
      .attr('height', legendRectSize)
      .style('fill', color)
      .style('stroke', color);
  
  legend.append('text')
      .attr('x', legendRectSize + legendSpacing)
      .attr('y', legendRectSize - legendSpacing)
      .text(function(d) { return d; });
  
  
  
  
  root = JSON.parse(jsonObject);
  console.log("root"+root);
  root.fixed = true; 
  root.x = w / 2;
  root.y = h / 2 - 80;
  update();
  
  
  
  
  function update() {
      var nodes = root.nodes,
          links = root.links;
  
      // Restart the force layout.
      force
          .nodes(nodes)
          .links(links)
          .start();
  
  
      // Update the links…
      link = svg.selectAll(".link")
          .data(links);
  
      // Enter any new links.
      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.
      link.exit().remove();
  
      // Update the nodes…
        node = svg.selectAll("circle.node")
              .data(nodes, function(d) {
                  return d.name;
              })
              .style("fill", color);
  
      node.transition()
          .attr("r", radius);
  
  
      // Enter any new nodes.
      node.enter().append("svg:circle")
          .attr("xlink:href",  function(d) { return d.image;})
          .attr("class", "node")
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })
          .attr("r", radius)
          .attr("r", function(d)
                {return d.size * 2 ;})
          .style("fill", color)
          .on("click", click)
          .call(force.drag);
      node.append("title")
      .text(function(d) { return d.name; });
  
      // Exit any old nodes.
      node.exit().remove();
  
  
      title = svg.selectAll("text.title")    
           .data(nodes);
  
      // Enter any new titles.
      title.enter()
          .append("text")
          .attr("class", "title");
          //.text(function(d) { return d.name; });
  
      // Exit any old titles.
      title.exit().remove();
  }
  
  function tick() {
      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; });
  
      node.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });
  
      title.attr("transform", function(d){ return "translate("+d.x+","+d.y+")"; });
  }
  
  // Color leaf nodes orange, and packages white or blue.
  function color(d) {
      if(d._children){
          return "#95a5a6";
      }else{
          switch(d.group) {
              case 'r': //adverb
                  return "#e74c3c";
                  break;
              case 'n': //noun
                  return "#3498db";
                  break;
              case 'v': //verb
                  return "#2ecc71";
                  break;
              case 's': //adjective
                  return "#e78229";
                  break;
              default:
                  return "rgb(0, 238, 238)";
          }
      }
  }
  
  // Toggle children on click.
  function click(d) {
  document.getElementById("image").src = d.image;
  document.getElementById("username").innerHTML = "Username:"+d.name;
  document.getElementById("id").innerHTML = "ID:" + d.id;
  document.getElementById("friends").innerHTML = d.friend;
  document.getElementById("nodeTitle").innerHTML = "";
  document.getElementById("size").innerHTML = d.size;
  //document.getElementById("id").innerHTML = "Friend Count:" + d.name;
  //if (d._children)
  //grabImage();
  //document.getElementById("image").innerHTML = (d.image);
  
  /*if (d.children) { 
          d._children = d.children;
          d.children = null;
      } else {
          d.children = d._children;
          d._children = null;
      }
      update();*/
  }
  
  function mouseover() {
    d3.select(this).select("circle").transition()
        .duration(750)
        .attr("r", 16);
  }
  
  
  function mouseout() {
    d3.select(this).select("circle").transition()
        .duration(750)
        .attr("r", 8);
  }
  
  // Returns a list of all nodes under the root.
  function flatten(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;
  }};
  
  do{
  var intervalID = window.setTimeout(start, 1000)
  }
  while(jsonObject!=""){
  }
  </code></pre>
  
  <p><strong>I believe the error is in here somewhere:</strong></p>
  
  <pre><code>    var force = d3.layout.force()
          .on("tick", tick)
          .charge(function(d) { return -500; })
          .linkDistance(function(d) { return d.target._children ? 100 : 50; })
          .size([w, h - 160]);
  
          `
      var svg = d3.select("body").append("svg")
          .attr("width", w)
          .attr("height", h);
  
  
  
  
  svg.append("rect")
      .attr("width", "100%")
      .attr("height", "100%")
      .attr("fill", "#000");
  
      var legend = d3.append('svg')
      .append("g")
      .selectAll("g")
      .data(color.domain())
      .enter()
      .append('g')
        .attr('class', 'legend')
        .attr('transform', function(d, i) {
          var height = legendRectSize;
          var x = 0;
          var y = i * height;
          return 'translate(' + x + ',' + y + ')';
      });
  
      legend.append('rect')
      .attr('width', legendRectSize)
      .attr('height', legendRectSize)
      .style('fill', color)
      .style('stroke', color);
  
  legend.append('text')
      .attr('x', legendRectSize + legendSpacing)
      .attr('y', legendRectSize - legendSpacing)
      .text(function(d) { return d; });
  </code></pre>
  
  <p>JSFIDDLE :</p>
  
  <p><a href="http://jsfiddle.net/d1kp0qeL/1" rel="nofollow">jsfiddle.net/d1kp0qeL/1</a> </p>