Reputation: 136
I'm looking to implement storing filters in the URL so they can easily be shared. It's working fine for simple filters for row and pie charts, but I'm trying to work out how to restore a filter from the URL on a date range.
I've implemented the same code that was used here -> https://github.com/Edouard-Legoupil/3W-Dashboard/blob/gh-pages/index.html
function showFilters() {
var filterStrings = [];
var charts = dc.chartRegistry.list();
charts.forEach(function (chart) {
chart.filters().forEach(function (filter) {
filterStrings.push(filter);
})
})
d3.select("#filters").text(filterStrings);
}
function getFiltersValues() {
var filters = [
{ name: 'season', value: seasonChart.filters()},
{ name: 'homeaway', value: homeAwayChart.filters()}];
var recursiveEncoded = $.param( filters );
location.hash = recursiveEncoded;
console.log(filters);
}
function initFilters() {
// Get hash values
var parseHash = /^#season=([A-Za-z0-9,_\-\/\s]*)&homeaway=([A-Za-z0-9,_\-\/\s]*)$/;
var parsed = parseHash.exec(decodeURIComponent(location.hash));
function filter(chart, rank) {
if (parsed[rank] == "") {
chart.filter(null);
}
else {
var filterValues = parsed[rank].split(",");
for (var i = 0; i < filterValues.length; i++ ) {
chart.filter(filterValues[i]);
}
}
}
//filter the charts using the filters we've got from the url
if (parsed) {
filter(seasonChart, 1);
filter(homeAwayChart, 2);
}
}
The full dashboard can be found here to see how it's currently working - http://www.vitalswansea.com/stats/index2.php
I noticed in this question - storing dc.js filters in URI and restoring them that Gordon had written similar code (below) to get around this issue but I'm having difficulty implementing myself.
for (var i = 0; i< filterObjects.length; i++)
{
var filter = filterObjects[i].Filter;
if(filter instanceof Array) filter = dc.filters.RangedFilter(filter[0], filter[1]);
dc.chartRegistry.list()[filterObjects[i].ChartID-1].filter(filter);
}
Thank you in advance.
Upvotes: 1
Views: 244
Reputation: 136
I added another function within the initFilters() function:
function filterDateRange(chart, rank) {
if (parsed[rank] == "") {
chart.filter(null);
}
else {
var filterValues = parsed[rank].split(",");
var filter = dc.filters.RangedFilter(new Date(filterValues[0]), new Date(filterValues[1]));
chart.filter(filter);
}
}
and then just used this function to apply the filter to the chart:
if (parsed) {
filter(seasonChart, 1);
filter(homeAwayChart, 2);
filterDateRange(positionChart, 3);
}
I also had to change the parseHash variable to look at brackets within the dates etc:
var parseHash = /^#season=([A-Za-z0-9,_\-\/\s]*)&homeaway=([A-Za-z0-9,_\-\/\s]*)&dates=([A-Za-z0-9,:&+(/\)_\-\/\s]*)$/;
Upvotes: 1
Reputation: 20150
The initialization for a date range would look like this, parsing the date and building a RangedFilter
:
else {
var filterValues = parsed[rank].split(",");
var filter = dc.filters.RangedFilter(new Date(filterValues[0], filterValues[1]);
chart.filter(filter);
}
It's going to be different for every chart, so I don't know how to put it into one function like that.
The above would be appropriate for saving the date ranges in the League Table Position chart. It won't work for the Season Total Points chart because that uses an ordinal x scale. That's why you click to select individual bars instead of using a brush with that one.
For that one, your filterValues
will be an array of individual dates, and it doesn't look like you parse the dates for this column, in which case you'd do
chart.filter([filterValues]);
When you pass an array containing a single array, dc.js assumes that the inner array is a set of filters which should be toggled. (I don't know why.)
In general, each chart is going to have a different kind of filter. There are only a few kinds of filters, so perhaps this could be generalized into a general utility, but you still have to know what type, and what shape, each chart is expecting.
Upvotes: 1