<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="jquery.min.js"></script>
<script src="d3.js"></script>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h3>Load in the stocks dataset with d3, but then do the filtering using JS and update using Vega.</h3>
<p>This filters for the data to be added and removed on the fly using Javascript, not D3. But it still uses D3 to load in and parse the stocks.csv file for the default values.</p>
<div class="form-group">
<label>Time Period: </label>
<input type="date" class="form-control" id="time-period-min" placeholder=""> -
<input type="date" class="form-control" id="time-period-max" placeholder="">
<p><button type="button" id="time-period-filter" class="btn btn-default" onclick="filterData()">Filter</button></p>
</div>
<div id="vis"></div>
<script type="text/javascript">
loadData();
// create a d3 parser for dates: from string to date in expected format Jan 1 2000
var parseDate = d3.timeParse("%b %e %Y");
// create a d3 parser for dates: from dates to string in outputted format Jan 1 2000
var formatDate = d3.timeFormat("%Y-%m-%d");
// variable to store the loaded data
var data;
// Load CSV file
function loadData() {
d3.csv("stocks.csv", function(error, csv) {
// ensure numbers are read as numbers and dates as dates
csv.forEach(function(d){
d.date = parseDate(d.date);
d.price = +d.price;
});
// Store csv data in global variable
data = csv;
// Get full time period
var originalTimePeriod = d3.extent(data, function(d) { return d.date; });
d3.select("#time-period-min").attr("value", formatDate(originalTimePeriod[0]));
d3.select("#time-period-max").attr("value", formatDate(originalTimePeriod[1]));
});
};
var view;
vega.loader()
.load('vega-line-chart-d3-datefilter.json')
.then(function(spec_data) {
render(JSON.parse(spec_data));
});
function render(spec) {
view = new vega.View(vega.parse(spec))
.renderer('canvas') // set renderer (canvas or svg)
.initialize('#vis') // initialize view within parent DOM container
.hover() // enable hover encode set processing
.run();
};
function filterData() {
console.log("Filter function has been triggered");
var parseDate_input = d3.timeParse("%Y-%m-%d");
// get the newly selected options for time period
var timePeriodMin = document.getElementById("time-period-min").value;
var timePeriodMax = document.getElementById("time-period-max").value;
console.log("The string versions of the time period I am filtering for is: " + timePeriodMin + " to " + timePeriodMax);
// timePeriodMin and timePeriodMax are both strings
var newData = data.filter(function(d){
return d.date >= parseDate_input(timePeriodMin) && d.date <= parseDate_input(timePeriodMax);
});
// The following code does not work, and I do not know why
view.change('source',
vega.changeset()
.remove(view.data('source').slice())
.insert(newData)
)
.run()
// I thought the below code did the same thing as above
// but the below works while the above (changeset) does not
// view.remove('source', view.data('source').slice())
// .run();
// view.insert('source', newData)
// .run();
};
</script>
</body>