-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathlegend.js
146 lines (119 loc) · 4.74 KB
/
legend.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
export default function(dispatch) {
var thisData = [];
var thisDataKey = undefined;
var localDispatch = d3.dispatch("click");
var groups = ['unknown'];
var groupData = {name: 'unknown', active: true};
var groupCol = function(d) { return d; };
var colorScale = undefined;
var allActive = true;
function groupSelect(d, i) {
console.log("clicked on %s", d.name);
if (allActive) {
groupData.forEach(function(grp) {
if (grp.name != d.name)
grp.active = false;
});
allActive = false;
} else {
groupData[i].active = !groupData[i].active;
// check if all items are (in)active
if (!groupData.some(function(d) { return d.active; })) {
groupData.forEach(function(d) { d.active = true; });
allActive = true;
}
}
localDispatch.click(d, i);
if (allActive) {
dispatch.highlight(false);
} else {
var selectedGroups = groupData
.filter(function(d) { return d.active; })
.map(function(d) { return d.name; });
dispatch.highlight(function(d) { return selectedGroups.indexOf(groupCol(d)) != -1; });
}
}
function redraw(selection) {
selection.each(function (data, i) {
var g = d3.select(this);
var items = g.selectAll("g.item")
.data(data, function(d) { return d.name; });
var newItems = items.enter()
.append('g')
.attr('class', 'item')
.attr('transform', function(d, i) { return 'translate(0, ' + (20 * i) + ')' });
colorScale = colorScale || d3.scale.category10();
newItems.append('rect')
.attr('width', 10)
.attr('height', 10)
.on('click', groupSelect);
newItems.append('text')
.attr('x', 18)
.attr('y', 9)
.html(function(d) { return d.name; })
.on('click', groupSelect);
items.selectAll('rect')
.style('fill', function(d) { return colorScale(d.name); });
items.classed('disabled', function(d) { return !d.active; });
items.exit().remove();
});
}
function resetData(selection) {
groupData = groups.map(function(grp) {
return {'name': grp, 'active': true };
});
selection.each(function(d, i) {
d3.select(this).data([groupData], thisDataKey);
});
}
function legend(selection, name) {
resetData(selection);
redraw(selection);
dispatch.on('highlight.' + name, function(selectedIndices) {
console.log("called legend dispatch (redraw)");
redraw(selection);
});
dispatch.on('groupUpdate.' + name, function(newGroups, newColorScale) {
console.log("called legend dispatch (groupUpdate)");
groups = newGroups.sort();
colorScale = newColorScale;
resetData(selection);
redraw(selection);
});
}
/**
* Gets or sets the data bound to points in the scatterplot. Following D3.js convention, this should be an array of anonymous objects. Generally set all at once by the twoDFactory.setData() method
* @default Empty array: []
* @param {Object[]} [newData] - The data of the scatterplot. Set the `.x()` and `.y()` accessors for the x- and y-dimensions of the scatterplot
* @param {function(Object[]): string} [key] - The key function for the data (similar to the key function in `d3.data([data, [key]])`)
*/
legend.data = function(newData, key) {
if (!arguments.length) return thisData;
thisData = newData;
if (key) thisDataKey = key;
return legend;
}
/**
* The groups and color scale to display in the legend.
* @default One unknown class (e.g. ['unknown'])
* @param {string[]} [newGroups] - A string array of the new group names
* @param {function(string): string} [newColorScale] - A D3 categorical color scale that converts the group name to its representative color
*/
legend.groups = function(newGroups, newColorScale) {
if (!arguments.length) return groups;
groups = newGroups;
colorScale = newColorScale;
return legend;
}
/**
* The function to select the grouping value from the datapoint. Required in order to send updates to all other connected components when conditioning on groups
* @default Identity function, which has no effect when deselecting groups.
* @param {function(Object): string} [grpVal] - The function that returns the group identifier for a given point
*/
legend.groupColumn = function(grpVal) {
if (!arguments.length) return groupCol
groupCol = grpVal;
return legend;
}
return d3.rebind(legend, localDispatch, 'on');
}