Some D3 Fiddlin

by Trever Shick

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.3.1/lodash.min.js"></script>
<script>
data = [{
    "Client": "ABC",
    "sale": "202",
    "year": "2000"
}, {
    "Client": "ABC",
    "sale": "215",
    "year": "2002"
}, {
    "Client": "ABC",
    "sale": "179",
    "year": "2004"
}, {
    "Client": "ABC",
    "sale": "199",
    "year": "2006"
}, {
    "Client": "ABC",
    "sale": "134",
    "year": "2008"
}, {
    "Client": "ABC",
    "sale": "176",
    "year": "2010"
}, {
    "Client": "XYZ",
    "sale": "100",
    "year": "2000"
}, {
    "Client": "XYZ",
    "sale": "215",
    "year": "2002"
}, {
    "Client": "XYZ",
    "sale": "179",
    "year": "2004"
}, {
    "Client": "XYZ",
    "sale": "199",
    "year": "2006"
}, {
    "Client": "XYZ",
    "sale": "134",
    "year": "2008"
}, {
    "Client": "XYZ",
    "sale": "176",
    "year": "2013"
}];

dataGroup = _.groupBy(data, "Client");
colors = ['red','orange','green','blue','purple'];

</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<div class="container">
    <div class="jumbotron well">
        <div  id="j" style="margin:0;padding:0">
        </div>
        
    </div>
</div>

CSS

#j {
    height:80%;
}
.legend {
    font-weight:bold;
}

.jumbotron {
    padding:0;
    height:400px;
}
.axis path {
    fill: none;
    stroke: #777;
    shape-rendering: crispEdges;
}
.axis text {
    font-family: Lato;
    font-size: 13px;
}

JavaScript

var WIDTH = document.getElementById("j").offsetWidth;
var HEIGHT = 300;

var vis = d3.select("#j").append("svg")
    .attr("width",WIDTH)
    .attr("height",HEIGHT+50);


var MARGINS = {
        top: 20,
        right: 20,
        bottom: 20,
        left: 50
    };

// build the legend
var lSpace = WIDTH/_.size(dataGroup);

function randomColor(){
    return "hsl(" + Math.random() * 360 + ",100%,50%)"
}
function aggs(fns, data, onAttribute) {
    return _.map(fns, function(fn) { return agg(fn, data, onAttribute); });
}
function agg(fn, data, onAttribute) { 
    return fn(data, function(d) { return d[onAttribute]; });
}

var xScale = d3.scale
    .linear()
    .range([MARGINS.left, WIDTH - MARGINS.right])
    .domain(aggs([d3.min, d3.max], data, 'year'));

var yScale = d3.scale
    .linear()
    .range([HEIGHT - MARGINS.top, MARGINS.bottom])
    .domain(aggs([d3.min, d3.max], data, 'sale'));
  
var xAxis = d3.svg.axis()
    .ticks(4)
    .tickFormat(function(d){ return d; })
    .scale(xScale);
  
var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left");

vis.append("svg:g")
    .attr("class","axis")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")").call(xAxis);
vis.append("svg:g")
    .attr("class","axis")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)").call(yAxis);

var lineGen = d3.svg.line()
  .x(function(d) {
    return xScale(d.year);
  })
  .y(function(d) {
    return yScale(d.sale);
  })
  .interpolate("basis");

var i=0;
_.forEach(dataGroup, function(v,key) {
    vis.append('svg:path')
        .attr('d', lineGen(v))
        .attr('stroke', colors.pop())
        .attr('stroke-width', 2)
        .attr('id', 'line_'+key)
        .attr('fill', 'none');
    vis.append("text")
        .attr("class","legend")
        .attr("x", (lSpace / 2) + (i++) * lSpace)
        .attr("y", HEIGHT + 15)
        .attr('id', 'leg_'+key)
        .style("fill", "black")
        .on('click', function() {
            var active =...