block by vicapow 9591312

Using Angular expressions for D3 accessors

Full Screen

This is a code excerpt from the book D3 on Angular. http://leanpub.com/d3angularjs

The data was scraped from Wikipedia on 3/15/2014: https://en.wikipedia.org/wiki/List_of_The_Walking_Dead_episodes

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Walking Dead Viewership</title>
  </head>
  <style>
    body, html{
      margin: 0;
      width: 900px;
      color: white;
      background-color: black;
      font-family: helvetica;
      margin: auto;
    }
    .scatter-container{
      width: 50%;
      float: left;
      height: 400px;
    }
    .detail{
      width: 50%;
      float: left;
      height: 400px;
    }
    scatter{
      width: 100%;
      height: 100%;
      display: block;
      z-index: 0;
      overflow: hidden;
      font-size: 10px;
    }
    scatter circle{
      opacity: 0.4;
      cursor: pointer;
      stroke-width: 2;
    }
    scatter circle:hover{
      stroke: white;
    }
    scatter text{
      fill: white;
      stroke: none;
    }
    scatter .x-axis path, scatter .y-axis path{
      stroke: none;
      fill: none;
    }
    scatter .x-axis line, scatter .y-axis line{
      stroke: rgba(255, 255, 255, 0.2);
    }
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
  <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <body ng-app="myApp" ng-controller="MainCtrl">
    <h1>Walking Dead Viewership</h1>
    <div class="scatter-container">
      <scatter
        data="episodes"
        accessor-x="d.air_date"
        accessor-y="d.us_viewers"
        selected-point="selectedEpisode"
        color="color(d.season)">
      </scatter>
    </div>
    <div class="detail">
      <h2>Episode: {{selectedEpisode.title}}</h2>
      <h3>season: {{selectedEpisode.season}}</h3>
      <h3>us viewers: {{selectedEpisode.us_viewers | number}}</h3>
    </div>
  </body>
  <script>

var app = angular.module('myApp', []);

app.controller('MainCtrl', function($scope, $window){
  $scope.color = d3.scale.category10();
  angular.element($window).on('resize', function(){ $scope.$apply(); });
  d3.csv('./episodes.csv', function(row){
    row.season = +row.season; // number
    row.air_date = new Date(row.air_date);
    row.us_viewers = +row.us_viewers * 1e6; // us viwers in millions
    return row;
  }, function(err, episodes){
    if(err){ throw err; }
    $scope.$apply(function(){
      // remove the few episodes that haven't air yet at time of writing.
      episodes = episodes.slice(0, -3);
      $scope.episodes = episodes;
      $scope.selectedEpisode = episodes[0];
    });
  });
});

app.directive('scatter', function(){
  function link(scope, el, attr){
    el = el[0];
    var w, h;
    var svg = d3.select(el).append('svg');
    var xAxisG = svg.append('g').attr('class', 'x-axis');
    var yAxisG = svg.append('g').attr('class', 'y-axis');
    var points = svg.append('g').attr('class', 'points').selectAll('g.point');
    var x = d3.scale.linear();
    var y = d3.scale.linear();
    var yFormat = d3.format('.2s');
    var timeFormat = d3.time.format('%m-%y');
    var xFormat = function(d){ return timeFormat(new Date(d)) };
    var xAxis = d3.svg.axis().scale(x).orient('bottom').tickFormat(xFormat);
    var yAxis = d3.svg.axis().scale(y).orient('left').tickFormat(yFormat);
    var m = 50;

    scope.$watch(function(){
      w = el.clientWidth;
      h = el.clientHeight;
      return w + h;
    }, resize);

    function resize(){
      svg.attr({width: w, height: h});
      x.range([m, w - m]);
      y.range([h - m, m]);
      xAxis.tickSize(-h + 2 * m);
      yAxis.tickSize(-w + 2 * m);
      xAxisG.attr('transform', 'translate(' + [0, y.range()[0] + 0.5] + ')');
      yAxisG.attr('transform', 'translate(' + [x.range()[0], 0] + ')');
      update();
    }

    scope.$watch('data', update);

    function update(){
      if(!scope.data){ return };
      var data = scope.data;
      var x_extent = d3.extent(data, function(d){ return scope.accessorX({d:d}) });
      x.domain(x_extent);
      var y_max = d3.max(data, function(d){ return scope.accessorY({d:d}) });
      y.domain([0, y_max]);
      points = points.data(data);
      points.exit().remove();
      var point = points.enter().append('g').attr('class', 'point');
      point.append('circle').attr('r', 5)
        .style('fill', function(d){ return scope.color({d:d}); })
        .on('mouseover', function(d){
          scope.$apply(function(){
            scope.selectedPoint = d;
          });
        })

      // update the position of all the points
      points.attr('transform', function(d){
        return 'translate(' + [x(scope.accessorX({d:d})), y(scope.accessorY({d:d}))] + ')';
      });

      xAxisG.call(xAxis);
      yAxisG.call(yAxis);

    };
  }
  return {
    link: link,
    restrict: 'E',
    scope: { data: '=', accessorX: '&', accessorY: '&', color: '&', selectedPoint: '=' }
  };
});
  </script>
</html>

episodes.csv

season,title,directed_by,written_by,air_date,us_viewers
1,Days Gone Bye,Frank Darabont,Teleplay by: Frank Darabont,2010-10-31,5.35
1,Guts,Michelle MacLaren,Frank Darabont,2010-11-07,4.71
1,Tell It to the Frogs,Gwyneth Horder-Payton,"Story by: Charles H. Eglee & Jack LoGiudice
Teleplay by: Charles H. Eglee & Jack LoGiudice and Frank Darabont",2010-11-14,5.07
1,Vatos,Johan Renck,Robert Kirkman,2010-11-21,4.75
1,Wildfire,Ernest Dickerson,Glen Mazzara,2010-11-28,5.56
1,TS-19,Guy Ferland,Adam Fierro and Frank Darabont,2010-12-05,5.97
2,What Lies Ahead,Ernest Dickerson & Gwyneth Horder-Payton,Ardeth Bey and Robert Kirkman,2011-10-16,7.26
2,Bloodletting,Ernest Dickerson,Glen Mazzara,2011-10-23,6.70
2,Save the Last One,Phil Abraham,Scott M. Gimple,2011-10-30,6.10
2,Cherokee Rose,Billy Gierhart,Evan Reilly,2011-11-06,6.29
2,Chupacabra,Guy Ferland,David Leslie Johnson,2011-11-13,6.12
2,Secrets,David Boyd,Angela Kang,2011-11-20,6.08
2,Pretty Much Dead Already,Michelle MacLaren,Scott M. Gimple,2011-11-27,6.62
2,Nebraska,Clark Johnson,Evan Reilly,2012-02-12,8.10
2,Triggerfinger,Billy Gierhart,David Leslie Johnson,2012-02-19,6.89
2,18 Miles Out,Ernest Dickerson,Scott M. Gimple & Glen Mazzara,2012-02-26,7.04
2,"Judge, Jury, Executioner",Greg Nicotero,Angela Kang,2012-03-04,6.77
2,Better Angels,Guy Ferland,Evan Reilly & Glen Mazzara,2012-03-11,6.89
2,Beside the Dying Fire,Ernest Dickerson,Robert Kirkman & Glen Mazzara,2012-03-18,8.99
3,Seed,Ernest Dickerson,Glen Mazzara,2012-10-14,10.87
3,Sick,Billy Gierhart,Nichole Beattie,2012-10-21,9.55
3,Walk with Me,Guy Ferland,Evan Reilly,2012-10-28,10.51
3,Killer Within,Guy Ferland,Sang Kyu Kim,2012-11-04,9.27
3,Say the Word,Greg Nicotero,Angela Kang,2012-11-11,10.37
3,Hounded,Dan Attias,Scott M. Gimple,2012-11-18,9.21
3,When the Dead Come Knocking,Dan Sackheim,Frank Renzulli,2012-11-25,10.43
3,Made to Suffer,Billy Gierhart,Robert Kirkman,2012-12-02,10.48
3,The Suicide King,Lesli Linka Glatter,Evan Reilly,2013-02-10,12.26
3,Home,Seith Mann,Nichole Beattie,2013-02-17,11.05
3,I Ain't a Judas,Greg Nicotero,Angela Kang,2013-02-24,11.01
3,Clear,Tricia Brock,Scott M. Gimple,2013-03-03,11.30
3,Arrow on the Doorpost,David Boyd,Ryan C. Coleman,2013-03-10,11.46
3,Prey,Stefan Schwartz,Glen Mazzara & Evan Reilly,2013-03-17,10.84
3,This Sorrowful Life,Greg Nicotero,Scott M. Gimple,2013-03-24,10.99
3,Welcome to the Tombs,Ernest Dickerson,Glen Mazzara,2013-03-31,12.42
4,30 Days Without an Accident,Greg Nicotero,Scott M. Gimple,2013-10-13,16.11
4,Infected,Guy Ferland,Angela Kang,2013-10-20,13.95
4,Isolation,Dan Sackheim,Robert Kirkman,2013-10-27,12.92
4,Indifference,Tricia Brock,Matthew Negrete,2013-11-03,13.31
4,Internment,David Boyd,Channing Powell,2013-11-10,12.20
4,Live Bait,Michael Uppendahl,Nichole Beattie,2013-11-17,12.00
4,Dead Weight,Jeremy Podeswa,Curtis Gwinn,2013-11-24,11.29
4,Too Far Gone,Ernest Dickerson,Seth Hoffman,2013-12-01,12.05
4,After,Greg Nicotero,Robert Kirkman,2014-02-09,15.76
4,Inmates,Tricia Brock,Matthew Negrete & Channing Powell,2014-02-16,13.34
4,Claimed,Seith Mann,Nichole Beattie & Seth Hoffman,2014-02-23,13.12
4,Still,Julius Ramsay,Angela Kang,2014-03-02,12.61
4,Alone,Ernest Dickerson,Curtis Gwinn,2014-03-09,12.65
4,The Grove,Michael Satrazemis,Scott M. Gimple,2014-03-16,
4,Us,David S. Goyer,,2014-03-23,
4,A,Michelle MacLaren,,2014-03-30,