forked from dc-js/dc.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdata-grid.js
253 lines (227 loc) · 7.81 KB
/
data-grid.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/**
* Data grid is a simple widget designed to list the filtered records, providing
* a simple way to define how the items are displayed.
*
* Note: Unlike other charts, the data grid chart (and data table) use the {@link dc.dataGrid#group group} attribute as a keying function
* for {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#nest nesting} the data together in groups.
* Do not pass in a crossfilter group as this will not work.
*
* Examples:
* - {@link http://europarl.me/dc.js/web/ep/index.html List of members of the european parliament}
* @class dataGrid
* @memberof dc
* @mixes dc.baseMixin
* @param {String|node|d3.selection} parent - Any valid
* {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements d3 single selector} specifying
* a dom block element such as a div; or a dom element or d3 selection.
* @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.
* Interaction with a chart will only trigger events and redraws within the chart's group.
* @returns {dc.dataGrid}
*/
dc.dataGrid = function (parent, chartGroup) {
var LABEL_CSS_CLASS = 'dc-grid-label';
var ITEM_CSS_CLASS = 'dc-grid-item';
var GROUP_CSS_CLASS = 'dc-grid-group';
var GRID_CSS_CLASS = 'dc-grid-top';
var _chart = dc.baseMixin({});
var _size = 999; // shouldn't be needed, but you might
var _html = function (d) { return 'you need to provide an html() handling param: ' + JSON.stringify(d); };
var _sortBy = function (d) {
return d;
};
var _order = d3.ascending;
var _beginSlice = 0, _endSlice;
var _htmlGroup = function (d) {
return '<div class=\'' + GROUP_CSS_CLASS + '\'><h1 class=\'' + LABEL_CSS_CLASS + '\'>' +
_chart.keyAccessor()(d) + '</h1></div>';
};
_chart._doRender = function () {
_chart.selectAll('div.' + GRID_CSS_CLASS).remove();
renderItems(renderGroups());
return _chart;
};
function renderGroups () {
var groups = _chart.root().selectAll('div.' + GRID_CSS_CLASS)
.data(nestEntries(), function (d) {
return _chart.keyAccessor()(d);
});
var itemGroup = groups
.enter()
.append('div')
.attr('class', GRID_CSS_CLASS);
if (_htmlGroup) {
itemGroup
.html(function (d) {
return _htmlGroup(d);
});
}
groups.exit().remove();
return itemGroup;
}
function nestEntries () {
var entries = _chart.dimension().top(_size);
return d3.nest()
.key(_chart.group())
.sortKeys(_order)
.entries(entries.sort(function (a, b) {
return _order(_sortBy(a), _sortBy(b));
}).slice(_beginSlice, _endSlice));
}
function renderItems (groups) {
var items = groups.order()
.selectAll('div.' + ITEM_CSS_CLASS)
.data(function (d) {
return d.values;
});
items.enter()
.append('div')
.attr('class', ITEM_CSS_CLASS)
.html(function (d) {
return _html(d);
});
items.exit().remove();
return items;
}
_chart._doRedraw = function () {
return _chart._doRender();
};
/**
* Get or set the group function for the data grid. The group function takes a data row and
* returns the key to specify to {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_nest d3.nest}
* to split rows into groups.
*
* Do not pass in a crossfilter group as this will not work.
* @method group
* @memberof dc.dataGrid
* @instance
* @example
* // group rows by the value of their field
* chart
* .group(function(d) { return d.field; })
* @param {Function} groupFunction Function taking a row of data and returning the nest key.
* @returns {Function|dc.dataTable}
*/
/**
* Get or set the index of the beginning slice which determines which entries get displayed by the widget.
* Useful when implementing pagination.
* @method beginSlice
* @memberof dc.dataGrid
* @instance
* @param {Number} [beginSlice=0]
* @returns {Number|dc.dataGrid}
*/
_chart.beginSlice = function (beginSlice) {
if (!arguments.length) {
return _beginSlice;
}
_beginSlice = beginSlice;
return _chart;
};
/**
* Get or set the index of the end slice which determines which entries get displayed by the widget.
* Useful when implementing pagination.
* @method endSlice
* @memberof dc.dataGrid
* @instance
* @param {Number} [endSlice]
* @returns {Number|dc.dataGrid}
*/
_chart.endSlice = function (endSlice) {
if (!arguments.length) {
return _endSlice;
}
_endSlice = endSlice;
return _chart;
};
/**
* Get or set the grid size which determines the number of items displayed by the widget.
* @method size
* @memberof dc.dataGrid
* @instance
* @param {Number} [size=999]
* @returns {Number|dc.dataGrid}
*/
_chart.size = function (size) {
if (!arguments.length) {
return _size;
}
_size = size;
return _chart;
};
/**
* Get or set the function that formats an item. The data grid widget uses a
* function to generate dynamic html. Use your favourite templating engine or
* generate the string directly.
* @method html
* @memberof dc.dataGrid
* @instance
* @example
* chart.html(function (d) { return '<div class='item '+data.exampleCategory+''>'+data.exampleString+'</div>';});
* @param {Function} [html]
* @returns {Function|dc.dataGrid}
*/
_chart.html = function (html) {
if (!arguments.length) {
return _html;
}
_html = html;
return _chart;
};
/**
* Get or set the function that formats a group label.
* @method htmlGroup
* @memberof dc.dataGrid
* @instance
* @example
* chart.htmlGroup (function (d) { return '<h2>'.d.key . 'with ' . d.values.length .' items</h2>'});
* @param {Function} [htmlGroup]
* @returns {Function|dc.dataGrid}
*/
_chart.htmlGroup = function (htmlGroup) {
if (!arguments.length) {
return _htmlGroup;
}
_htmlGroup = htmlGroup;
return _chart;
};
/**
* Get or set sort-by function. This function works as a value accessor at the item
* level and returns a particular field to be sorted.
* @method sortBy
* @memberof dc.dataGrid
* @instance
* @example
* chart.sortBy(function(d) {
* return d.date;
* });
* @param {Function} [sortByFunction]
* @returns {Function|dc.dataGrid}
*/
_chart.sortBy = function (sortByFunction) {
if (!arguments.length) {
return _sortBy;
}
_sortBy = sortByFunction;
return _chart;
};
/**
* Get or set sort the order function.
* @method order
* @memberof dc.dataGrid
* @instance
* @see {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_ascending d3.ascending}
* @see {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_descending d3.descending}
* @example
* chart.order(d3.descending);
* @param {Function} [order=d3.ascending]
* @returns {Function|dc.dataGrid}
*/
_chart.order = function (order) {
if (!arguments.length) {
return _order;
}
_order = order;
return _chart;
};
return _chart.anchor(parent, chartGroup);
};