praekelt/sapphire — pull request #13 by justinvdm (2014-06-20 11:24:00+00:00)
Title: Give selection to view when drawing instead of on instantiation

The initial plan was to have sapphire's views closely follow the pattern described here: http://bost.ocks.org/mike/chart/

I diverged a bit from this pattern in order for sapphire drawing to be done without the programmer needing to interact with both d3 and sapphire:

```javascript
var dashboard = sapphire.dashboard('#dashboard');

dashboard({
title: 'foo',
...
});
```

Now that we have some views in place, I've realised that this wasn't a good idea.

The point of the pattern described at http://bost.ocks.org/mike/chart/ is to allow components to be 'configurable functions'. The approach I took made this configuration a bit clumsy, since dashboards now need to keep their own subtypes of each bundled widget type and we need allow to configuration on both the widget type and on its instances. Using the approach mike describes, we would keep an instance of each widget type, and configuring a widget would be as simple as configuring the dashboard's instance of the widget.

mike raises some points about why taking in a selection for the function doing the drawing makes sense, and I think these apply to sapphire more than I first realised:
> By taking a selection as input, charts have greater flexibility. For example, you can render a chart into multiple elements simultaneously, or easily move a chart between elements without explicitly unbinding and rebinding. You can control exactly when and how the chart gets updated when data or configuration changes (for example, using a transition rather than an instantaneous update). In effect, the chart becomes a rubber stamp for rendering data visually.

The pattern for drawing dashboards will now look something like:

```javascript
var dashboard = sapphire.dashboard();

d3.select('#dashboard')
.datum({
widgets: [{
title: 'A lastvalue widget',
type: 'lastvalue',
values [{
x: 123,
y: 345
}, {
x: 567,
y: 789
}]
}]
})
.call(dashboard);
```

It does mean the programmer needs to interact with both `d3` and `sapphire` to draw things, but we could abstract this away using a different approach later if it becomes a problem (maybe by taking in data as the second argument to a draw function?).