Mithril with D3

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="//keen.github.io/dashboards/assets/css/keen-dashboards.css">
<div class="container-fluid" id='main'>
    <div class="row">
        <div class="col-xs-12 col-md-6" id='app'>
            Hello World
        </div>
        <div class="col-xs-12 col-md-6" id='readme'>
            <div class="well">
                This is an attempt to recreate a  <a href="http://nicolashery.com/integrating-d3js-visualizations-in-a-react-app/"><code>React</code> example</a> using Mithril. My objective is to show how one can write really concise code using <code>Mithril</code>.
            </div>
        </div>
    </div>
</div>

CSS

#main{
  margin-top: 20px;
}
#app .chart-notes{
  background: none;
  border-top: none;
}

CoffeeScript

Pagination = 
  view: (ctrl, args) ->
    m "ul.pagination", {
        style: {margin: "0 auto"; width: "50%"}
     },
     args.data.map (d, i) ->
       m 'li', {
         onclick: (e) -> args.active(i)
         class: if i is args.active() then 'active'  
        },
        m 'a[href="#"]', d

generate_point = ->
  x: Math.random() 
  y: Math.random()
  r: Math.abs(Math.random())
    
TitlePanel = 
  view: (ctrl, args) ->
    m 'div', 
      'Mithril with D3   '
      m 'a.btn.btn-danger.btn-sm', {
           onclick: (e) -> args.data.push(generate_point()) 
        }, "Add Point"
      m 'span.pull-right', 
        "Avg Size: ", m("b", "#{args.avg_size}")
    
Circles = 
  view: (ctrl, args) ->
    S = 
      x: d3.scale.linear()
      y: d3.scale.linear()
      r: d3.scale.linear()
    A = 
      x: (d) -> d.x
      y: (d) -> d.y
      r: (d) -> d.r
    S.x.range([0, 300]).domain(args.xDomain)
    S.y.range([200, 0]).domain(args.yDomain)
    S.r.range([3, 8])
    m 'svg', {width: 440, height: 240},
      m 'g.circle', {
         transform: "translate(20, 20)"
       }, 
       args.data[args.active()].map (d, i) ->
         m 'circle', {
            cx: S.x A.x(d)
            cy: S.y A.y(d)
            r: S.r A.r(d)
            fill: 'steelblue'
            stroke: 'white',
            config: (el) ->
              d3.select(el).on "mouseover", ->
                console.log(d)
         }

kPanel =
  view: (ctrl, args) ->
    m '.chart-wrapper',
      m '.chart-title', args.title
      m '.chart-stage', args.stage
      m '.chart-notes', args.footer

make_data = (N) ->
  d3.range(N).map (d, i) ->
    x: Math.random()
    y: Math.random(), 
    r: Math.abs(Math.random())
    
data = d3.range(5).map (d) ->
  make_data(20)
    
compute_avg_size = (dat) ->
  av = d3.sum(dat, (d) -> d.r)/dat.length

App = 
  controller: ->
    active: m.prop(0)
    data: data
    avg_size: ->
      d = data[@active()]
      av = compute_avg_size(d)
      d3.format('.2f')(av)
 ...