Skip to content

Instantly share code, notes, and snippets.

@erlenstar
Last active October 24, 2015 02:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erlenstar/a6c022b92df8b918547d to your computer and use it in GitHub Desktop.
Save erlenstar/a6c022b92df8b918547d to your computer and use it in GitHub Desktop.
d3.unconf() 2015 Block

Trying to build simple time travel for data displayed via d3 (with Ramda for data generation); very much still a work in progres...

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link type="text/css" rel="stylesheet" href="style.css"/>
</head>
<body>
<input id="time-slider" type="range" min="0" max="1" step="0.01" value="1"></input>
<div id="table-target">
<table>
<thead>
<tr>
<th>Series</th>
<th>Value</th>
<th>Time</th>
</tr>
</thead>
<tbody id="data-table"></tbody>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.18.0/ramda.min.js"></script>
<script src="src.js"></script>
</body>
</html>
// construct keys, start and end time; currently using 1 hour as baseline
var keys = ["a", "b", "c", "d", "e"]
, now = new Date().valueOf()
, duration = 1000 * 60 * 60
, start = now - duration
, end = now
, min = 1
, max = 100
, sample_count = 20
;
// generate some data
var data = generateData(keys, sample_count, start, end, min, max);
// need the time range for the slider
var t = d3.scale.linear().domain([0, 1]).rangeRound([start, end]);
// start with the last known values
var cursor = R.map(R.last, data);
// draw the table
var $table = d3.select("#data-table");
$table.selectAll("tr")
.data(cursor)
.enter().append("tr").selectAll("td")
.data(function(d) { return [d.series, d.value, d.iso_time]; })
.enter().append("td")
.text(function(d) { return d; });
// setup the range slider; update when the value changes
$slider = d3.select("#time-slider").on("input", function() {
updateTable($table, select(t(this.value), data));
});
// debugging table
var $debugging = d3.selectAll("div.series")
.data(data)
.enter().append("div").classed("series", true);
$debugging.append("h3").text(function(d) { return d[0].series; });
$debugging.append("table")
.selectAll("tr")
.data(function(d) { return d; })
.enter().append("tr")
.selectAll("td")
.data(function(d) { return [d.series, d.step, d.value, d.time, d.iso_time]; })
.enter().append("td")
.text(function(d) { return d; });
// update the table values
function updateTable($target, data) {
$target.selectAll("tr")
.data(data)
.selectAll("td")
.data(function(d) { return [d.series, d.value, d.iso_time]; })
.text(function(d) { return d; });
}
function select(time, data) {
// var predicate = R.compose(R.gte(time), R.prop("time"));
// return R.map(R.find(predicate), data);
// ugh
return R.map(function(d) {
return R.findLast(function(v) {
return v.time <= time;
})(d) || R.head(d);
})(data);
}
/**
* data generation
*
*/
function generateData(keys, count, start, end, min, max) {
var generateFn = R.curry(generateDataForKey)(R.__, count, start, end, min, max);
return R.map(generateFn, keys);
}
/**
* generate data for a single key
*/
function generateDataForKey(key, count, start, end, min, max) {
// setup ranges
var timeRange = d3.scale.linear().domain([0, 1]).rangeRound([start, end])
, valueRange = d3.scale.linear().domain([0, 1]).rangeRound([min, max])
;
// sample function
var sampleFn = R.curry(makeSample)(timeRange, valueRange, key);
// generate samples
return R.sortBy(
R.prop("time"),
R.map(sampleFn, R.range(0, count))
);
}
/**
* generate a single random sample
*/
function makeSample(timeRange, valueRange, key, step) {
var t = timeRange(Math.random())
, isoTime = new Date(t).toISOString()
;
return {
series: key
, step: step
, time: t
, iso_time: isoTime
, value: valueRange(Math.random())
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment