title: d3.js : Applying styles to individual lines
body: <p>Was trying out the <a href="http://bl.ocks.org/mbostock/4566102" rel="nofollow">draggable network</a> and wanted to be able to use different colours for different links. When I commented out the lines  </p>
  
  <pre><code>/*var link = svg.append("g")
      .attr("class", "link") 
      .selectAll("line");*/
  </code></pre>
  
  <p>and replaced it with <code>var link = svg.append("g");</code><br>
  so that I could try adding links one by one, with if-else conditions where I could apply a different line style to each line. But when I tried applying just a single style uniformly to all lines itself, the lines didn't show up on the screen. Firebug also didn't show any error.  </p>
  
  <pre><code>  link = link.data(graph.links).enter().append("line")
        .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; })
        .attr("class", "link");
  </code></pre>
  
  <p>I had added the <code>.attr("class", "link");</code> section, thinking that it'd apply the style to the lines. But it didn't. Could you help with the right way to append attributes selectively?  </p>
  
  <p>This is the entire code:  </p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;meta charset="utf-8"&gt;
  
  &lt;svg id="mySvg" width="20" height="20"&gt;
    &lt;defs id="mdef"&gt;
          &lt;pattern id="image" x="0" y="0" height="20" width="20"&gt;
            &lt;image x="0" y="0" width="20" height="20" xlink:href="url.png"&gt;&lt;/image&gt;
          &lt;/pattern&gt;
    &lt;/defs&gt;
    &lt;defs&gt;
    &lt;pattern id="tile-ww" patternUnits="userSpaceOnUse" width="25" height="25"&gt;
    &lt;image xlink:href="url.png" x="15" y="15" width="15" height="15"&gt;&lt;/image&gt;&lt;/pattern&gt;
    &lt;/defs&gt;
  &lt;/svg&gt;
  
  &lt;style&gt;
  
  .node {
    stroke: green;
    stroke-width: 1px;
    opacity: 0.8;
    fill: url(#image);  
  }
  
  .node .selected {
    stroke: red;
  }
  
  .link {
    stroke: orange;
    stroke-width: 3;
    stroke-dasharray: 20,10,5,5,5,10;
    opacity: 0.5;
  }
  
  .dotted {border: 1px dotted #ff0000; border-style: none none dotted; color: #fff; background-color: #fff; }
  
  .brush .extent {
    fill-opacity: .1;
    stroke: #fff;
    shape-rendering: crispEdges;
  }
  
  &lt;/style&gt;
  &lt;body&gt;
  &lt;script src="d3/d3.v3.js"&gt;&lt;/script&gt;
  
  &lt;script&gt;
  
  var width = 960, height = 500, shiftKey;
  
  var svg = d3.select("body")
      .attr("tabindex", 1)
      .on("keydown.brush", keydown)
      .on("keyup.brush", keyup)
      .each(function() { this.focus(); })
      .append("svg")
      .attr("width", width)
      .attr("height", height);
  
  /*var link = svg.append("g")
      .attr("class", "link") 
      .selectAll("line");*/
  var link = svg.append("g");
  
  var brush = svg.append("g")
      .datum(function() { return {selected: false, previouslySelected: false}; })
      .attr("class", "brush");
  
  var node = svg.append("g")
      .attr("class", "node")
      .selectAll("circle");
  
  //Add the SVG Text Element to the svgContainer
  text = svg.append('text').text('This is some information about whatever')
                          .attr('x', 50)
                          .attr('y', 200)
                          .attr('fill', 'black');
  
  //you can delete this circle
  svg.append("circle")
           .attr("class", "logo")
           .attr("cx", 225)
           .attr("cy", 225)
           .attr("r", 20)
           .style("fill", "transparent")       
           .style("stroke", "black")     
           .style("stroke-width", 0.25)
           .on("mouseover", function(){ 
                 d3.select(this)
                     .style("fill", "url(#image)");
           })
            .on("mouseout", function(){ 
                 d3.select(this)
                     .style("fill", "transparent");
           });
  
  //get the json file with either error messages or the entire data as "graph" object
  d3.json("graph.json", function(error, graph) {
  
    //"links" is a property in "graph", and contains some data in it. Iterate through all of them
    graph.links.forEach(function(d) //iterate through each data object in link
    {
      d.source = graph.nodes[d.source];//we got nodes too, with graph so access its data
      d.target = graph.nodes[d.target];
      d.linkStatus = d.status;
      console.log(d.source);
    });
  
  
    link = link.data(graph.links).enter().append("line")
        .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; })
        .attr("class", "link");
  
    brush.call(d3.svg.brush()
          .x(d3.scale.identity().domain([0, width]))
          .y(d3.scale.identity().domain([0, height]))
          .on("brushstart", function(d) {
            node.each(function(d) { d.previouslySelected = shiftKey &amp;&amp; d.selected; });
          })
          .on("brush", function() {
            var extent = d3.event.target.extent();
            node.classed("selected", function(d) {
              return d.selected = d.previouslySelected ^
                  (extent[0][0] &lt;= d.x &amp;&amp; d.x &lt; extent[1][0]
                  &amp;&amp; extent[0][1] &lt;= d.y &amp;&amp; d.y &lt; extent[1][1]);
            });
          })
          .on("brushend", function() {
            d3.event.target.clear();
            d3.select(this).call(d3.event.target);
          }));
  
    node = node.data(graph.nodes).enter().append("circle")
        .attr("r", 10)//radius
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .on("mousedown", function(d) {
          if (!d.selected) { // Don't deselect on shift-drag.
            if (!shiftKey) node.classed("selected", function(p) { return p.selected = d === p; });
            else d3.select(this).classed("selected", d.selected = true);
          }
        })
        .on("mouseup", function(d) {
          if (d.selected &amp;&amp; shiftKey) d3.select(this).classed("selected", d.selected = false);
        })
        .call(d3.behavior.drag()
          .on("drag", function(d) { nudge(d3.event.dx, d3.event.dy); }));
  });
  
  function nudge(dx, dy) 
  {
    node.filter(function(d) { return d.selected; })
        .attr("cx", function(d) { return d.x += dx; })
        .attr("cy", function(d) { return d.y += dy; })
  
    link.filter(function(d) { return d.source.selected; })
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; });
  
    link.filter(function(d) { return d.target.selected; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
  
    d3.event.preventDefault();
  }
  
  function keydown() 
  {
    if (!d3.event.metaKey) switch (d3.event.keyCode) {
      case 38: nudge( 0, -1); break; // UP
      case 40: nudge( 0, +1); break; // DOWN
      case 37: nudge(-1,  0); break; // LEFT
      case 39: nudge(+1,  0); break; // RIGHT
    }
    shiftKey = d3.event.shiftKey || d3.event.metaKey;
  }
  
  function keyup() 
  {
    shiftKey = d3.event.shiftKey || d3.event.metaKey;
  }
  
  &lt;/script&gt;
  </code></pre>