summaryrefslogtreecommitdiff
path: root/public/js/util/trellis-chart.js
diff options
context:
space:
mode:
authorFreeyorp <TheFreeYorp@NOSPAM.G.m.a.i.l.replace>2013-05-28 16:52:10 +1200
committerFreeyorp <TheFreeYorp@NOSPAM.G.m.a.i.l.replace>2013-05-28 16:52:10 +1200
commitd7634e357e7410484d1e31f3db84fb4f51fdc9c7 (patch)
treeb58542b94f2963f167c250b209362f2ec6f7f716 /public/js/util/trellis-chart.js
parent919ac3f8297f5b5b14809471a5c0f140859e2fa0 (diff)
downloadmanavis-d7634e357e7410484d1e31f3db84fb4f51fdc9c7.tar.gz
manavis-d7634e357e7410484d1e31f3db84fb4f51fdc9c7.tar.bz2
manavis-d7634e357e7410484d1e31f3db84fb4f51fdc9c7.tar.xz
manavis-d7634e357e7410484d1e31f3db84fb4f51fdc9c7.zip
Trellis external filtering and broadcastingbrushable-trellis
This also adjusts the method for comparing filters, allowing a chart to define a "filterCompare" method that will be used to compare filters if available. This finally removes the date chart special case for setting filters. Array instance checking will now use foo instanceof Array instead of typeof(foo) == "array", which was unreliable (sometimes it's "object"). Trellis chart brush containers will now redraw the brush when set externally. renderBrush no longer takes brushG as a parameter. I'm not sure what I was thinking when I made it so. The deselected area will not yet fade. The trellis chart still requires substantial refactoring and consistency fixes; I'm not sure that the parameter specifications are currently correct.
Diffstat (limited to 'public/js/util/trellis-chart.js')
-rw-r--r--public/js/util/trellis-chart.js71
1 files changed, 55 insertions, 16 deletions
diff --git a/public/js/util/trellis-chart.js b/public/js/util/trellis-chart.js
index 8b92344..473d7d3 100644
--- a/public/js/util/trellis-chart.js
+++ b/public/js/util/trellis-chart.js
@@ -31,14 +31,15 @@ function trellisChart(anchor, monoGroups) {
var g = anchor.select("g");
/* Main columns, one for each attr */
- var columns;
var colBodies;
+ var brushContainers;
var _chart = function() {
if (g.empty()) {
renderBase();
}
colBodies.each(redrawCells);
+ brushContainers.each(redrawBrush);
}
function renderBase() {
@@ -157,19 +158,32 @@ function trellisChart(anchor, monoGroups) {
;
})
;
- dimLabelsG.selectAll("g.brush-container")
+ brushContainers = dimLabelsG.selectAll("g.brush-container")
.data(monoGroups)
.enter().append("g").attr("class", "brush-container")
.attr("transform", function(d, i) { return "translate(" + (i * subChartLength) + ",0)"; })
.each(function (d, i) {
d.id = i;
d.brush = d3.svg.brush();
+ d.brushRedrawNeeded = false;
d.filter = function(_) {
if (!arguments.length) return d._filter;
- d.dim.filter(_);
- d._filter = _;
+ if (_ != null) {
+ d._filter = _;
+ d.brush.extent(_);
+ d.dim.filter(_);
+ d.brushRedrawNeeded = true;
+ } else {
+ d.filterAll();
+ }
return d;
};
+ d.filterAll = function() {
+ d._filter = null;
+ d.brush.clear();
+ d.dim.filterAll();
+ d.brushRedrawNeeded = true;
+ }
})
.each(renderBrush)
;
@@ -179,7 +193,7 @@ function trellisChart(anchor, monoGroups) {
* monoGroups is an array of each stat dimension. We can consider each column to have data in the following format:
* { group: function, dim: function, name: stat }
*/
- columns = g.selectAll(".column")
+ var columns = g.selectAll(".column")
.data(monoGroups);
var colE = columns.enter().append("g").attr("class", "column")
@@ -253,7 +267,8 @@ function trellisChart(anchor, monoGroups) {
}
function renderBrush(d, i) {
- var columnG = d3.select(this);
+ var columnGDOM = this;
+ var columnG = d3.select(columnGDOM);
var brushG = columnG.select(".brush");
d.brush
@@ -261,7 +276,7 @@ function trellisChart(anchor, monoGroups) {
.on("brush", function () {
var extent = extendBrush(d, brushG);
- redrawBrush(d, i, brushG);
+ redrawBrush.call(columnGDOM, d, i);
if (brushIsEmpty(extent, d.brush)) {
dc.events.trigger(function () {
@@ -287,13 +302,20 @@ function trellisChart(anchor, monoGroups) {
}
}
- function redrawBrush(d, i, brushG) {
- if (d.filter() && d.brush.empty())
+ function redrawBrush(d, i) {
+ if (!d.brushRedrawNeeded) {
+ return;
+ }
+ if (d.filter() && d.brush.empty()) {
d.brush.extent(d.filter());
+ }
+ var brushG = d3.select(this).select(".brush");
brushG.call(d.brush.x(_scale));
brushG.selectAll("rect").attr("height", chartLen);
+ d.brushRedrawNeeded = false;
+
// TODO: fade the deselected area
}
@@ -326,18 +348,35 @@ function trellisChart(anchor, monoGroups) {
+ "V" + (2 * y - 8);
}
+ /*
+ * Interface assumptions:
+ * - filter with one argument uses this argument as a filter in a manner defined by the chart.
+ * - filter with no arguments returns a description of the chart's active filter(s) suitable for applying to a filter() function of the same chart type.
+ *
+ * Most chart's filter() uses the data type of crossfilter's filter(). The trellis chart, using multiple dimensions, cannot.
+ * Therefore, it uses the format { [name] -> filter } where filter is the format used by crossfilter's filter.
+ */
_chart.filter = function(_) {
- /*
- * TODO:
- * This is going to be interesting. As the chart is not charting a single
- * monogroup, and most code is built around this assumption, this might
- * well end up being a messy special case.
- */
if (!arguments.length) {
- return null;
+ var ret = null;
+ for (var key in monoGroups) {
+ if (monoGroups[key].filter()) {
+ (ret || (ret = {}))[attrs[key]] = monoGroups[key].filter();
+ }
+ }
+ return ret;
+ }
+ for (key in _) {
+ monoGroups[attrsIdByName[key]].filter(_[key]);
}
return _chart;
}
+ _chart.filterAll = function(_) {
+ for (var key in monoGroups) {
+ monoGroups[key].filterAll();
+ }
+ }
+
return _chart;
}