Skip to content

Commit 069f4b2

Browse files
add stack filtering example
for #657
1 parent 1c7f21d commit 069f4b2

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

web/examples/filter-stacks.html

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>dc.js - Stacked Bar Example</title>
5+
<meta charset="UTF-8">
6+
<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css">
7+
<link rel="stylesheet" type="text/css" href="../css/dc.css"/>
8+
<style>
9+
.dc-chart g.chart-body {
10+
clip-path: none;
11+
}
12+
.dc-chart rect.stack-deselected {
13+
opacity: 0.2;
14+
}
15+
</style>
16+
</head>
17+
<body>
18+
19+
<div class="container">
20+
<script type="text/javascript" src="header.js"></script>
21+
<div id="test">
22+
<div class="reset" style="visibility: hidden;">selected: <span class="filter"></span>
23+
<a href="javascript:chart.filterAll();dc.redrawAll();">reset</a>
24+
</div>
25+
</div>
26+
<div id="pie">
27+
<div class="reset" style="visibility: hidden;">range: <span class="filter"></span>
28+
<a href="javascript:pie.filterAll();dc.redrawAll();">reset</a>
29+
</div>
30+
</div>
31+
32+
<script type="text/javascript" src="../js/d3.js"></script>
33+
<script type="text/javascript" src="../js/crossfilter.js"></script>
34+
<script type="text/javascript" src="../js/dc.js"></script>
35+
<script type="text/javascript">
36+
37+
var chart = dc.barChart("#test"),
38+
pie = dc.pieChart('#pie');
39+
d3.csv("morley.csv", function(error, experiments) {
40+
41+
experiments.forEach(function(x) {
42+
x.Speed = +x.Speed;
43+
});
44+
45+
// the way to combine multiple keys into one is domain-specific (and controversial)
46+
// array keys are risky but also valid sometimes, that would be
47+
// function multikey(x,y) {
48+
// return [x,y];
49+
// }
50+
// function splitkey(k) {
51+
// return k;
52+
// }
53+
function multikey(x,y) {
54+
return x + 'x' + y;
55+
}
56+
function splitkey(k) {
57+
return k.split('x');
58+
}
59+
function stack_second(group) {
60+
return {
61+
all: function() {
62+
var all = group.all(),
63+
m = {};
64+
// build matrix from multikey/value pairs
65+
all.forEach(function(kv) {
66+
var ks = splitkey(kv.key);
67+
m[ks[0]] = m[ks[0]] || {};
68+
m[ks[0]][ks[1]] = kv.value;
69+
});
70+
// then produce multivalue key/value pairs
71+
return Object.keys(m).map(function(k) {
72+
return {key: k, value: m[k]};
73+
});
74+
}
75+
};
76+
}
77+
78+
var ndx = crossfilter(experiments),
79+
runExptDim = ndx.dimension(function(d) { return multikey(d.Run, d.Expt); }),
80+
runExptGroup = runExptDim.group().reduceSum(function(d) {
81+
return d.Speed;
82+
}),
83+
stackedGroup = stack_second(runExptGroup);
84+
var quantizeSpeed = d3.scale.quantize().domain(d3.extent(experiments, function(d) {
85+
return d.Speed;
86+
})).range(['lowest', 'low', 'medium', 'high', 'highest']);
87+
var quantizeSpeedDim = ndx.dimension(function(d) {
88+
return quantizeSpeed(d.Speed);
89+
}), quantizeSpeedGroup = quantizeSpeedDim.group();
90+
91+
function set_filterer(dim) {
92+
var set = d3.set();
93+
function inkey(d) {
94+
return multikey(d.x, d.layer);
95+
}
96+
return {
97+
toggle: function(d) {
98+
var key = inkey(d);
99+
if(set.has(key))
100+
set.remove(key);
101+
else
102+
set.add(key);
103+
if(set.empty())
104+
dim.filter(null);
105+
else
106+
dim.filterFunction(function(k) {
107+
return set.has(k);
108+
});
109+
},
110+
has: function(d) {
111+
return set.has(inkey(d));
112+
},
113+
empty: function() {
114+
return set.empty();
115+
}
116+
};
117+
}
118+
var stack_filter = set_filterer(runExptDim);
119+
120+
function sel_stack(i) {
121+
return function(d) {
122+
return d.value[i];
123+
};
124+
}
125+
126+
chart
127+
.width(600)
128+
.height(400)
129+
.controlsUseVisibility(true)
130+
.x(d3.scale.linear().domain([1,21]))
131+
.margins({left: 80, top: 20, right: 10, bottom: 20})
132+
.brushOn(false)
133+
.clipPadding(10)
134+
.title(function(d) {
135+
return d.key + '[' + this.layer + ']: ' + d.value[this.layer];
136+
})
137+
.dimension(runExptDim)
138+
.group(stackedGroup, "1", sel_stack('1'))
139+
.renderLabel(true);
140+
141+
for(var i = 2; i<6; ++i)
142+
chart.stack(stackedGroup, ''+i, sel_stack(i));
143+
144+
chart.on('pretransition', function(chart) {
145+
chart.selectAll('rect.bar')
146+
.classed('stack-deselected', function(d) {
147+
return !stack_filter.empty() && !stack_filter.has(d);
148+
})
149+
.on('click', function(d) {
150+
stack_filter.toggle(d);
151+
if(stack_filter.empty())
152+
chart.turnOffControls();
153+
else
154+
chart.turnOnControls();
155+
dc.redrawAll();
156+
});
157+
});
158+
159+
pie
160+
.width(300)
161+
.height(300)
162+
.controlsUseVisibility(true)
163+
.dimension(quantizeSpeedDim)
164+
.group(quantizeSpeedGroup);
165+
166+
dc.renderAll();
167+
});
168+
169+
</script>
170+
171+
</div>
172+
</body>
173+
</html>

0 commit comments

Comments
 (0)