datavis-glide 4.0.0-PRE.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +129 -0
- package/datavis.js +101 -0
- package/dist/wcdatavis.css +1957 -0
- package/dist/wcdatavis.min.js +1 -0
- package/global-jquery.js +4 -0
- package/ie-fixes.js +13 -0
- package/index.js +70 -0
- package/meteor.js +1 -0
- package/package.json +102 -0
- package/src/flags.js +6 -0
- package/src/graph.js +1079 -0
- package/src/graph_renderer.js +85 -0
- package/src/grid.js +2777 -0
- package/src/grid_control.js +1957 -0
- package/src/grid_filter.js +1073 -0
- package/src/grid_renderer.js +276 -0
- package/src/group_fun_win.js +121 -0
- package/src/lang/en-US.js +188 -0
- package/src/lang/es-MX.js +188 -0
- package/src/lang/fr-FR.js +188 -0
- package/src/lang/id-ID.js +188 -0
- package/src/lang/nl-NL.js +188 -0
- package/src/lang/pt-BR.js +188 -0
- package/src/lang/ru-RU.js +188 -0
- package/src/lang/th-TH.js +188 -0
- package/src/lang/vi-VN.js +188 -0
- package/src/lang/zh-Hans-CN.js +188 -0
- package/src/operations_palette.js +176 -0
- package/src/prefs_modules.js +132 -0
- package/src/reg/graph_renderer.js +17 -0
- package/src/renderers/graph/chartjs.js +457 -0
- package/src/renderers/graph/google.js +584 -0
- package/src/renderers/graph/jit.js +61 -0
- package/src/renderers/graph/svelte-gantt.js +168 -0
- package/src/renderers/grid/dummy.js +79 -0
- package/src/renderers/grid/handlebars.js +217 -0
- package/src/renderers/grid/squirrelly.js +215 -0
- package/src/renderers/grid/table/group_detail.js +1404 -0
- package/src/renderers/grid/table/group_summary.js +380 -0
- package/src/renderers/grid/table/pivot.js +915 -0
- package/src/renderers/grid/table/plain.js +1592 -0
- package/src/renderers/grid/table.js +2510 -0
- package/src/trans.js +101 -0
- package/src/ui/collapsible.js +234 -0
- package/src/ui/filters/date.js +283 -0
- package/src/ui/grid_filter.js +398 -0
- package/src/ui/popup_menu.js +224 -0
- package/src/ui/popup_window.js +572 -0
- package/src/ui/slider.js +156 -0
- package/src/ui/tabs.js +202 -0
- package/src/ui/templates.js +131 -0
- package/src/ui/toolbar.js +63 -0
- package/src/ui/toolbars/grid.js +873 -0
- package/src/ui/windows/col_config.js +341 -0
- package/src/ui/windows/debug.js +164 -0
- package/src/ui/windows/grid_table_opts.js +139 -0
- package/src/util/handlebars.js +158 -0
- package/src/util/jquery.js +630 -0
- package/src/util/misc.js +1058 -0
- package/src/util/squirrelly.js +155 -0
- package/wcdatavis.css +1601 -0
|
@@ -0,0 +1,915 @@
|
|
|
1
|
+
// Imports {{{1
|
|
2
|
+
|
|
3
|
+
import _ from 'underscore';
|
|
4
|
+
import jQuery from 'jquery';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
format,
|
|
8
|
+
getElement,
|
|
9
|
+
getProp,
|
|
10
|
+
getPropDef,
|
|
11
|
+
isElement,
|
|
12
|
+
makeSubclass,
|
|
13
|
+
mixinLogging,
|
|
14
|
+
setPropDef,
|
|
15
|
+
setTableCell,
|
|
16
|
+
setElement,
|
|
17
|
+
} from '../../../util/misc.js';
|
|
18
|
+
|
|
19
|
+
import {ComputedView, GROUP_FUNCTION_REGISTRY} from 'datavis-ace';
|
|
20
|
+
import {GridRenderer} from '../../../grid_renderer.js';
|
|
21
|
+
|
|
22
|
+
import handlebarsUtil from '../../../util/handlebars.js';
|
|
23
|
+
import GridTable from '../table.js';
|
|
24
|
+
|
|
25
|
+
// GridTablePivot {{{1
|
|
26
|
+
// Constructor {{{2
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A grid table used for showing data that's been pivotted by the view.
|
|
30
|
+
*
|
|
31
|
+
* @class
|
|
32
|
+
* @extends GridTable
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
var GridTablePivot = makeSubclass('GridTablePivot', GridTable, function (grid, defn, view, features, opts, timing, id) {
|
|
36
|
+
var self = this;
|
|
37
|
+
|
|
38
|
+
self.super['GridTable'].ctor.apply(self, arguments);
|
|
39
|
+
|
|
40
|
+
self.features.limit = false;
|
|
41
|
+
self.features.footer = false;
|
|
42
|
+
self.features.rowSelect = false;
|
|
43
|
+
self.features.columnResize = false;
|
|
44
|
+
self.features.columnReorder = false;
|
|
45
|
+
|
|
46
|
+
self.logDebug(self.makeLogTag() + ' Constructing grid table; features = %O', features);
|
|
47
|
+
|
|
48
|
+
setPropDef(['rowVals', 'cells', 'groupAggregates', 'addCols'], self.opts, 'displayOrder');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
mixinLogging(GridTablePivot);
|
|
52
|
+
|
|
53
|
+
// #canRender {{{2
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Responds whether or not this grid table can render the type of data requested.
|
|
57
|
+
*
|
|
58
|
+
* @param {string} what
|
|
59
|
+
* The kind of data the caller wants us to show. Must be one of: plain, group, or pivot.
|
|
60
|
+
*
|
|
61
|
+
* @return {boolean}
|
|
62
|
+
* True if this grid table can render that kind of data, false if it can't.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
GridTablePivot.prototype.canRender = function (what) {
|
|
66
|
+
return ['pivot'].indexOf(what) >= 0;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// #drawHeader {{{2
|
|
70
|
+
|
|
71
|
+
GridTablePivot.prototype.drawHeader = function (columns, data, typeInfo, opts) {
|
|
72
|
+
var self = this,
|
|
73
|
+
aggInfo,
|
|
74
|
+
tr,
|
|
75
|
+
span,
|
|
76
|
+
headingThControls,
|
|
77
|
+
headingThContainer,
|
|
78
|
+
th;
|
|
79
|
+
|
|
80
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
81
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
82
|
+
// +---------------------------+------------+------------+------------+-----------+
|
|
83
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
84
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
85
|
+
// | GROUP FIELD | GROUP FIELD | | GROUP AGG |
|
|
86
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
87
|
+
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
|
88
|
+
|
|
89
|
+
var displayRowVals = function (tr) {
|
|
90
|
+
_.each(data.groupFields, function (field, fieldIdx) {
|
|
91
|
+
var fcc = self.colConfig.get(field) || {};
|
|
92
|
+
span = jQuery('<span>').addClass('wcdv_heading_title').text(fcc.displayText || field);
|
|
93
|
+
self.csv.addCol(fcc.displayText || field);
|
|
94
|
+
|
|
95
|
+
headingThControls = jQuery('<div>');
|
|
96
|
+
|
|
97
|
+
headingThContainer = jQuery('<div>')
|
|
98
|
+
.addClass('wcdv_heading_container')
|
|
99
|
+
.append(span, headingThControls);
|
|
100
|
+
|
|
101
|
+
th = jQuery('<th>', { scope: 'col' })
|
|
102
|
+
.dvAttr({
|
|
103
|
+
'gfi': fieldIdx,
|
|
104
|
+
'field': field,
|
|
105
|
+
'draggable-origin': 'GRID_TABLE_HEADER'
|
|
106
|
+
})
|
|
107
|
+
.append(headingThContainer)
|
|
108
|
+
._makeDraggableField();
|
|
109
|
+
|
|
110
|
+
self._addSortingToHeader(data, 'vertical', {groupFieldIndex: fieldIdx}, headingThControls.get(0), getPropDef([], data, 'agg', 'info', 'cell'));
|
|
111
|
+
|
|
112
|
+
self.setCss(th, field);
|
|
113
|
+
|
|
114
|
+
self.ui.thMap[field] = th;
|
|
115
|
+
tr.append(th);
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
120
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
121
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
122
|
+
// +---------------------------+------------+------------+------------+-----------+
|
|
123
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
124
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
125
|
+
// | GROUP FIELD | GROUP FIELD | | GROUP AGG |
|
|
126
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
127
|
+
|
|
128
|
+
var displayRowVals_padding = function (tr) {
|
|
129
|
+
if (data.groupFields.length > 1) {
|
|
130
|
+
tr.append(jQuery('<th>', { colspan: data.groupFields.length - 1 }));
|
|
131
|
+
for (var i = 0; i < data.groupFields.length - 1; i += 1) {
|
|
132
|
+
self.csv.addCol('');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
138
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
139
|
+
// | | PIVOT FIELD | COLVAL 1.1 | COLVAL 1.2 | |
|
|
140
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
141
|
+
// | | PIVOT FIELD | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
142
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
143
|
+
// | GROUP FIELD | GROUP FIELD | | GROUP AGG |
|
|
144
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
145
|
+
|
|
146
|
+
var displayCells = function (tr, pivotFieldIdx, displayOrderIndex) {
|
|
147
|
+
var colVal, colValIndex;
|
|
148
|
+
var ai = self._getAggInfo(data);
|
|
149
|
+
var df = self._getDisplayFormat();
|
|
150
|
+
// Indicates that we're on the last pivot field, i.e. the last row of the table header.
|
|
151
|
+
var isLastPivotField = pivotFieldIdx === data.pivotFields.length - 1;
|
|
152
|
+
var pivotField = data.pivotFields[pivotFieldIdx];
|
|
153
|
+
|
|
154
|
+
var fcc = self.colConfig.get(pivotField) || {};
|
|
155
|
+
var pivotSpec = data.pivotSpec[pivotFieldIdx];
|
|
156
|
+
var fti = self.typeInfo.get(pivotField);
|
|
157
|
+
|
|
158
|
+
if (pivotSpec.fun != null) {
|
|
159
|
+
fti = {
|
|
160
|
+
type: GROUP_FUNCTION_REGISTRY.get(pivotSpec.fun).resultType
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
165
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
166
|
+
// | | PIVOT FIELD | COLVAL 1.1 | COLVAL 1.2 | |
|
|
167
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
168
|
+
|
|
169
|
+
var span = jQuery('<span>').addClass('wcdv_heading_title').text(fcc.displayText || pivotField);
|
|
170
|
+
self.csv.addCol(fcc.displayText || pivotField);
|
|
171
|
+
|
|
172
|
+
var headingThControls = jQuery('<div>');
|
|
173
|
+
|
|
174
|
+
var headingThContainer = jQuery('<div>')
|
|
175
|
+
.addClass('wcdv_heading_container')
|
|
176
|
+
.append(span, headingThControls);
|
|
177
|
+
|
|
178
|
+
var th = jQuery('<th>', { scope: 'col' })
|
|
179
|
+
.dvAttr({
|
|
180
|
+
'field': pivotField,
|
|
181
|
+
'draggable-origin': 'GRID_TABLE_HEADER'
|
|
182
|
+
})
|
|
183
|
+
.append(headingThContainer)
|
|
184
|
+
._makeDraggableField();
|
|
185
|
+
|
|
186
|
+
self._addSortingToHeader(data, 'horizontal', {pivotFieldIndex: pivotFieldIdx}, headingThControls.get(0), getPropDef([], data, 'agg', 'info', 'cell'));
|
|
187
|
+
|
|
188
|
+
self.setCss(th, pivotField);
|
|
189
|
+
|
|
190
|
+
self.ui.thMap[pivotField] = th;
|
|
191
|
+
tr.append(th);
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
195
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
196
|
+
// | | PIVOT FIELD | COLVAL 1.1 | COLVAL 1.2 | |
|
|
197
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
198
|
+
|
|
199
|
+
// Create headers for the fields that we've pivotted by. The headers are the column values for
|
|
200
|
+
// those fields.
|
|
201
|
+
//
|
|
202
|
+
// +--------------------------------------------------+----------------+
|
|
203
|
+
// | PIVOT COLVAL 1 | PIVOT COLVAL 2 | < PIVOT FIELD #1
|
|
204
|
+
// +----------------+----------------+----------------+----------------+
|
|
205
|
+
// | PIVOT COLVAL A | PIVOT COLVAL B | PIVOT COLVAL C | PIVOT COLVAL A | < PIVOT FIELD #2
|
|
206
|
+
// +----------------+----------------+----------------+----------------+
|
|
207
|
+
//
|
|
208
|
+
// Col Vals = [[1,A], [1,B], [2,A]]
|
|
209
|
+
//
|
|
210
|
+
// When rendering the headers for Pivot Field #1, we go through the col vals and find that "1"
|
|
211
|
+
// is repeated three times. We don't make a cell for each one, instead we just increment
|
|
212
|
+
// lastColValCount. When the col val changes to "2", we set the colspan on the previous cell to
|
|
213
|
+
// be however many of that col val we found.
|
|
214
|
+
|
|
215
|
+
var lastColVal = null;
|
|
216
|
+
var lastColValCount = 0;
|
|
217
|
+
|
|
218
|
+
for (colValIndex = 0; colValIndex < data.colVals.length; colValIndex += 1) {
|
|
219
|
+
colVal = data.colVals[colValIndex][pivotFieldIdx];
|
|
220
|
+
colVal = format(self.colConfig.get(pivotField), fti, colVal);
|
|
221
|
+
|
|
222
|
+
if (colVal !== lastColVal || isLastPivotField) {
|
|
223
|
+
if (lastColVal !== null) {
|
|
224
|
+
// The we've hit a different colVal so count up how many of the last one we had to
|
|
225
|
+
// determine the column span. In the above example, there are three "Kennedy" and two
|
|
226
|
+
// "Roosevelt" so those are the colspans that we would set.
|
|
227
|
+
|
|
228
|
+
var colSpan = lastColValCount;
|
|
229
|
+
|
|
230
|
+
if ((df.cell.length || ai.cell.length) >= 2) {
|
|
231
|
+
colSpan *= ai.cell.length;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
th.attr('colspan', colSpan);
|
|
235
|
+
tr.append(th);
|
|
236
|
+
|
|
237
|
+
for (var i = 0; i < colSpan - 1; i += 1) {
|
|
238
|
+
self.csv.addCol('');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Update the tracking information and reset the counter to one.
|
|
243
|
+
|
|
244
|
+
lastColVal = colVal;
|
|
245
|
+
lastColValCount = 1;
|
|
246
|
+
|
|
247
|
+
span = jQuery('<span>').addClass('wcdv_heading_title');
|
|
248
|
+
setElement(span, colVal, {
|
|
249
|
+
field: pivotField,
|
|
250
|
+
colConfig: fcc,
|
|
251
|
+
typeInfo: fti
|
|
252
|
+
});
|
|
253
|
+
self.csv.addCol(span.text());
|
|
254
|
+
|
|
255
|
+
headingThControls = jQuery('<div>');
|
|
256
|
+
|
|
257
|
+
headingThContainer = jQuery('<div>')
|
|
258
|
+
.addClass('wcdv_heading_container')
|
|
259
|
+
.append(span, headingThControls);
|
|
260
|
+
|
|
261
|
+
th = jQuery('<th>', { scope: 'col' })
|
|
262
|
+
.dvAttr('cvi', colValIndex)
|
|
263
|
+
.append(headingThContainer);
|
|
264
|
+
|
|
265
|
+
self.setCss(th, colVal);
|
|
266
|
+
|
|
267
|
+
// We only allow sorting on the final
|
|
268
|
+
|
|
269
|
+
if (isLastPivotField) {
|
|
270
|
+
self._addSortingToHeader(data, 'vertical', {colVal: data.colVals[colValIndex], aggNum: 0}, headingThControls.get(0), getPropDef([], data, 'agg', 'info', 'cell'));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if ((df.cell.length || ai.cell.length) === 1) {
|
|
274
|
+
aggInfo = data.agg.info.cell[0];
|
|
275
|
+
self.setAlignment(th, aggInfo.colConfig[0], aggInfo.typeInfo[0], aggInfo.instance.getType());
|
|
276
|
+
}
|
|
277
|
+
else if ((df.cell.length || ai.cell.length) > 1) {
|
|
278
|
+
self.setAlignment(th, null, null, null, 'center');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (self.opts.drawInternalBorders || (df.cell.length || ai.cell.length) > 1) {
|
|
282
|
+
th.addClass('wcdv_pivot_colval_boundary');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
lastColValCount += 1;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Same logic as when the colVal changes.
|
|
291
|
+
|
|
292
|
+
var colSpan = lastColValCount;
|
|
293
|
+
|
|
294
|
+
if ((df.cell.length || ai.cell.length) >= 2) {
|
|
295
|
+
colSpan *= (df.cell.length || ai.cell.length);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (th != null) {
|
|
299
|
+
th.attr('colspan', colSpan);
|
|
300
|
+
tr.append(th);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (i = 0; i < colSpan - 1; i += 1) {
|
|
304
|
+
self.csv.addCol('');
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
309
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
310
|
+
// +---------------------------+------------+------------+------------+-----------+
|
|
311
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
312
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
313
|
+
// | GROUP FIELD | GROUP FIELD | // // // // // // // // // | GROUP AGG |
|
|
314
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
315
|
+
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
|
316
|
+
|
|
317
|
+
var displayCells_padding = function (tr) {
|
|
318
|
+
var ai = self._getAggInfo(data);
|
|
319
|
+
var df = self._getDisplayFormat();
|
|
320
|
+
|
|
321
|
+
var numCols = df.cell.length || ai.cell.length;
|
|
322
|
+
|
|
323
|
+
var hr = jQuery('<hr>', {
|
|
324
|
+
class: 'wcdv_hr_gradient'
|
|
325
|
+
});
|
|
326
|
+
var div = jQuery('<div> </div>');
|
|
327
|
+
var th = jQuery('<th>', {
|
|
328
|
+
class: 'wcdv_pivot_colval_boundary wcdv_cell_empty',
|
|
329
|
+
colspan: data.colVals.length * Math.max(numCols, 1)
|
|
330
|
+
});
|
|
331
|
+
div.appendTo(th);
|
|
332
|
+
th.appendTo(tr);
|
|
333
|
+
for (var i = 0; i < data.colVals.length * Math.max(numCols, 1); i += 1) {
|
|
334
|
+
self.csv.addCol('');
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
339
|
+
// +---------------------------+--------------------------------------+----------------------+
|
|
340
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
341
|
+
// +---------------------------+------------+------------+------------+----------------------+
|
|
342
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
343
|
+
// +-------------+-------------+------------+------------+------------+-----------+----------+
|
|
344
|
+
// | GROUP FIELD | GROUP FIELD | // // // // // // // // // | GROUP AGG | ADD COLS |
|
|
345
|
+
// +-------------+-------------+--------------------------------------+-----------+----------+
|
|
346
|
+
|
|
347
|
+
var displayGroupAggregates_padding = function (tr, displayOrderIndex, displayOrderMax) {
|
|
348
|
+
var ai = self._getAggInfo(data);
|
|
349
|
+
|
|
350
|
+
var numCols = ai.group.length + getPropDef(0, self.opts, 'addCols', 'length');
|
|
351
|
+
|
|
352
|
+
if (numCols > 0) {
|
|
353
|
+
var th = jQuery('<th>', { colspan: numCols });
|
|
354
|
+
if (displayOrderIndex > 0) {
|
|
355
|
+
th.addClass('wcdv_bld'); // border-left: double
|
|
356
|
+
}
|
|
357
|
+
if (displayOrderIndex < displayOrderMax - 1) {
|
|
358
|
+
th.addClass('wcdv_brd'); // border-right: double
|
|
359
|
+
}
|
|
360
|
+
tr.append(th);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
365
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
366
|
+
// +---------------------------+------------+------------+------------+-----------+
|
|
367
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
368
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
369
|
+
// | GROUP FIELD | GROUP FIELD | // // // // // // // // // | GROUP AGG |
|
|
370
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
371
|
+
// ↑↑↑↑↑↑↑↑↑↑↑
|
|
372
|
+
|
|
373
|
+
var displayGroupAggregates = function (tr, displayOrderIndex, displayOrderMax) {
|
|
374
|
+
self.drawHeader_aggregates(data, tr, displayOrderIndex, displayOrderMax);
|
|
375
|
+
self.drawHeader_addCols(tr, typeInfo, opts);
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
379
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | | ←---
|
|
380
|
+
// +---------------------------+------------+------------+------------+-----------+ ←---
|
|
381
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | | ←---
|
|
382
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
383
|
+
// | GROUP FIELD | GROUP FIELD | // // // // // // // // // | GROUP AGG |
|
|
384
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
385
|
+
|
|
386
|
+
for (var pivotFieldIdx = 0; pivotFieldIdx < data.pivotFields.length; pivotFieldIdx += 1) {
|
|
387
|
+
self.csv.addRow();
|
|
388
|
+
tr = jQuery('<tr>')
|
|
389
|
+
.dvAttr('pfi', pivotFieldIdx);
|
|
390
|
+
_.each(self.opts.displayOrder, function (what, displayOrderIndex) {
|
|
391
|
+
if (typeof what === 'string') {
|
|
392
|
+
switch (what) {
|
|
393
|
+
case 'rowVals':
|
|
394
|
+
displayRowVals_padding(tr);
|
|
395
|
+
break;
|
|
396
|
+
case 'cells':
|
|
397
|
+
displayCells(tr, pivotFieldIdx);
|
|
398
|
+
break;
|
|
399
|
+
case 'groupAggregates':
|
|
400
|
+
displayGroupAggregates_padding(tr, displayOrderIndex, self.opts.displayOrder.length);
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
tr.appendTo(self.ui.thead);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// +---------------------------+--------------------------------------+-----------+
|
|
409
|
+
// | | COLVAL 1.1 | COLVAL 1.2 | |
|
|
410
|
+
// +---------------------------+------------+------------+------------+-----------+
|
|
411
|
+
// | | COLVAL 2.1 | COLVAL 2.2 | COLVAL 2.1 | |
|
|
412
|
+
// +-------------+-------------+------------+------------+------------+-----------+
|
|
413
|
+
// | GROUP FIELD | GROUP FIELD | // // // // // // // // // | GROUP AGG | ←---
|
|
414
|
+
// +-------------+-------------+--------------------------------------+-----------+
|
|
415
|
+
|
|
416
|
+
self.csv.addRow();
|
|
417
|
+
tr = jQuery('<tr>');
|
|
418
|
+
_.each(self.opts.displayOrder, function (what, displayOrderIndex) {
|
|
419
|
+
if (typeof what === 'string') {
|
|
420
|
+
switch (what) {
|
|
421
|
+
case 'rowVals':
|
|
422
|
+
displayRowVals(tr);
|
|
423
|
+
break;
|
|
424
|
+
case 'cells':
|
|
425
|
+
displayCells_padding(tr);
|
|
426
|
+
break;
|
|
427
|
+
case 'groupAggregates':
|
|
428
|
+
displayGroupAggregates(tr, displayOrderIndex, self.opts.displayOrder.length);
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
tr.appendTo(self.ui.thead);
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// #drawBody {{{2
|
|
437
|
+
|
|
438
|
+
GridTablePivot.prototype.drawBody = function (data, typeInfo, columns, cont, opts) {
|
|
439
|
+
var self = this;
|
|
440
|
+
|
|
441
|
+
var aggType
|
|
442
|
+
, aggInfo;
|
|
443
|
+
|
|
444
|
+
opts = opts || {};
|
|
445
|
+
opts.pivotConfig = opts.pivotConfig || {};
|
|
446
|
+
|
|
447
|
+
var ai = self._getAggInfo(data);
|
|
448
|
+
var df = self._getDisplayFormat();
|
|
449
|
+
|
|
450
|
+
if (data.groupFields.length === 0) {
|
|
451
|
+
if (typeof cont === 'function') {
|
|
452
|
+
return cont();
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
self._setupFullValueWin(data);
|
|
460
|
+
|
|
461
|
+
// Setup the handlebars environment to reference our data.
|
|
462
|
+
|
|
463
|
+
var handlebarsEnv = handlebarsUtil.makeEnv();
|
|
464
|
+
handlebarsUtil.addHelpers(handlebarsEnv, self.data);
|
|
465
|
+
|
|
466
|
+
// Compile all templates; if there's an error then the template can still be used, it just
|
|
467
|
+
// produces the error message instead of doing something useful.
|
|
468
|
+
|
|
469
|
+
var templates = {};
|
|
470
|
+
|
|
471
|
+
_.each(df, function (tmplStrs, type) {
|
|
472
|
+
templates[type] = _.map(tmplStrs, function (str) {
|
|
473
|
+
var t;
|
|
474
|
+
try {
|
|
475
|
+
t = handlebarsEnv.compile(str);
|
|
476
|
+
}
|
|
477
|
+
catch (e) {
|
|
478
|
+
t = function () {
|
|
479
|
+
return e.message;
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return t;
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// ===========================================================================
|
|
487
|
+
// DATA AND GROUP AGGREGATES
|
|
488
|
+
// ===========================================================================
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
_.each(data.data, function (rowGroup, groupNum) {
|
|
492
|
+
self.csv.addRow();
|
|
493
|
+
|
|
494
|
+
var tr = document.createElement('tr');
|
|
495
|
+
tr.setAttribute('data-wcdv-rvi', groupNum);
|
|
496
|
+
|
|
497
|
+
_.each(self.opts.displayOrder, function (what, displayOrderIndex) {
|
|
498
|
+
if (typeof what === 'string') {
|
|
499
|
+
switch (what) {
|
|
500
|
+
case 'rowVals':
|
|
501
|
+
self.drawBody_rowVals(data, tr, groupNum);
|
|
502
|
+
break;
|
|
503
|
+
case 'cells':
|
|
504
|
+
var rowAgg = [];
|
|
505
|
+
|
|
506
|
+
// Create the cells that show the result of the aggregate function for all rows matching the
|
|
507
|
+
// column values at the same index.
|
|
508
|
+
//
|
|
509
|
+
// EXAMPLE
|
|
510
|
+
// -------
|
|
511
|
+
//
|
|
512
|
+
// pivotFields = ["State"]
|
|
513
|
+
// colVals = ["IL", "IN", "MI", "OH"]
|
|
514
|
+
//
|
|
515
|
+
// Column #1: agg(rowGroup[0]) - rows in the group w/ State = "IL"
|
|
516
|
+
// Column #2: agg(rowGroup[1]) - rows in the group w/ State = "IN"
|
|
517
|
+
// Column #3: agg(rowGroup[2]) - rows in the group w/ State = "MI"
|
|
518
|
+
// Column #4: agg(rowGroup[3]) - rows in the group w/ State = "OH"
|
|
519
|
+
|
|
520
|
+
_.each(rowGroup, function (colGroup, pivotNum) {
|
|
521
|
+
if (df.cell.length > 0) {
|
|
522
|
+
_.each(df.cell, function (dispFmt, dfCellIndex) {
|
|
523
|
+
var td = document.createElement('td');
|
|
524
|
+
td.classList.add('wcdv_pivot_cell');
|
|
525
|
+
td.setAttribute('data-wcdv-rvi', groupNum);
|
|
526
|
+
td.setAttribute('data-wcdv-cvi', pivotNum);
|
|
527
|
+
|
|
528
|
+
td.innerHTML = templates.cell[dfCellIndex]({
|
|
529
|
+
rowValIdx: groupNum,
|
|
530
|
+
colValIdx: pivotNum
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
if (_.every(data.groupSpec, function (gs) { return gs.fun == null; })
|
|
534
|
+
&& _.every(data.pivotSpec, function (ps) { return ps.fun == null; })) {
|
|
535
|
+
self._addDrillDownClass(td);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (self.opts.drawInternalBorders) {
|
|
539
|
+
td.classList.add('wcdv_pivot_colval_boundary');
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
tr.appendChild(td);
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
else if (ai.cell.length > 0) {
|
|
546
|
+
// Every cell aggregate function is going to make a separate cell.
|
|
547
|
+
_.each(ai.cell, function (aggInfo, aiCellIndex) {
|
|
548
|
+
var aggNum = aggInfo.aggNum;
|
|
549
|
+
var aggType = aggInfo.instance.getType();
|
|
550
|
+
var agg = data.agg.results.cell[aggNum];
|
|
551
|
+
var aggResult = agg[groupNum][pivotNum];
|
|
552
|
+
|
|
553
|
+
var td = document.createElement('td');
|
|
554
|
+
td.classList.add('wcdv_pivot_cell');
|
|
555
|
+
td.setAttribute('data-wcdv-rvi', groupNum);
|
|
556
|
+
td.setAttribute('data-wcdv-cvi', pivotNum);
|
|
557
|
+
td.setAttribute('data-wcdv-agg-scope', 'cell');
|
|
558
|
+
td.setAttribute('data-wcdv-agg-num', aggInfo.aggNum);
|
|
559
|
+
|
|
560
|
+
rowAgg.push(aggResult);
|
|
561
|
+
|
|
562
|
+
var text;
|
|
563
|
+
|
|
564
|
+
if (aggResult instanceof jQuery) {
|
|
565
|
+
aggResult = aggResult.get(0);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (aggResult instanceof Element) {
|
|
569
|
+
td.appendChild(aggResult);
|
|
570
|
+
self.csv.addCol(aggResult.innerText);
|
|
571
|
+
}
|
|
572
|
+
else if (self.opts.hideBottomValueAggResults && aggResult === aggInfo.instance.bottomValue) {
|
|
573
|
+
td.innerHTML = ' ';
|
|
574
|
+
self.csv.addCol('');
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
if (aggInfo.instance.inheritFormatting) {
|
|
578
|
+
text = format(aggInfo.colConfig[0], aggInfo.typeInfo[0], aggResult, {
|
|
579
|
+
overrideType: aggType
|
|
580
|
+
});
|
|
581
|
+
setTableCell(td, text, {
|
|
582
|
+
field: aggInfo.fields[0],
|
|
583
|
+
colConfig: aggInfo.colConfig[0],
|
|
584
|
+
typeInfo: aggInfo.typeInfo[0]
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
text = format(null, null, aggResult, {
|
|
589
|
+
overrideType: aggType,
|
|
590
|
+
decode: false
|
|
591
|
+
});
|
|
592
|
+
setTableCell(td, text);
|
|
593
|
+
}
|
|
594
|
+
self.csv.addCol(td.innerText);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (_.every(data.groupSpec, function (gs) { return gs.fun == null; })
|
|
598
|
+
&& _.every(data.pivotSpec, function (ps) { return ps.fun == null; })) {
|
|
599
|
+
self._addDrillDownClass(td);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if ((self.opts.drawInternalBorders || ai.cell.length > 1) && aiCellIndex === 0) {
|
|
603
|
+
td.classList.add('wcdv_pivot_colval_boundary');
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// REMOVED: How do we let the user set sizes &c. when doing a pivot table?
|
|
607
|
+
// self.setCss(td, col);
|
|
608
|
+
|
|
609
|
+
self.setAlignment(td, aggInfo.colConfig[0], aggInfo.typeInfo[0], aggType);
|
|
610
|
+
|
|
611
|
+
tr.appendChild(td);
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
// There's no cell aggregate functions, so there isn't anything to put in the cell.
|
|
616
|
+
tr.appendChild(document.createElement('td'));
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
break;
|
|
620
|
+
case 'groupAggregates':
|
|
621
|
+
self.drawBody_groupAggregates(data, tr, groupNum, displayOrderIndex, self.opts.displayOrder.length);
|
|
622
|
+
break;
|
|
623
|
+
case 'addCols':
|
|
624
|
+
// Generate the user's custom-defined additional columns. If the `value` function returns an
|
|
625
|
+
// Element or jQuery instance, we just put that in the <TD> that we make. Otherwise (e.g. it
|
|
626
|
+
// returns a string or number) we format it according to the type of the field that the pivot
|
|
627
|
+
// function was operating on.
|
|
628
|
+
//
|
|
629
|
+
// EXAMPLE:
|
|
630
|
+
//
|
|
631
|
+
// Aggregate Function = sum
|
|
632
|
+
// Aggregate Field = Amount : number -> $0,0.00
|
|
633
|
+
//
|
|
634
|
+
// If the `value` function adds up the sums, yielding a grand total of them all, then we format
|
|
635
|
+
// that using Numeral exactly as specified for the "Amount" field.
|
|
636
|
+
|
|
637
|
+
_.each(self.opts.addCols, function (addCol) {
|
|
638
|
+
var addColResult = addCol.value(data.data, groupNum, rowAgg, aggType);
|
|
639
|
+
var td = document.createElement('td');
|
|
640
|
+
var addColText;
|
|
641
|
+
|
|
642
|
+
if (addColResult instanceof jQuery) {
|
|
643
|
+
addColResult = addColResult.get(0);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (addColResult instanceof Element) {
|
|
647
|
+
td.appendChild(addColResult);
|
|
648
|
+
self.csv.addCol(addColResult.innerText);
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
if (false && aggInfo.instance.inheritFormatting) {
|
|
652
|
+
addColText = format(aggInfo.colConfig[0], aggInfo.typeInfo[0], addColResult, {
|
|
653
|
+
alwaysFormat: true
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
addColText = format(null, null, addColResult, {
|
|
658
|
+
alwaysFormat: true,
|
|
659
|
+
decode: false
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
td.innerText = addColText;
|
|
663
|
+
self.csv.addCol(addColText);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (getProp(opts, 'pivotConfig', 'aggField')) {
|
|
667
|
+
self.setAlignment(td, self.colConfig.get(opts.pivotConfig.aggField), typeInfo.get(opts.pivotConfig.aggField));
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
tr.appendChild(td);
|
|
671
|
+
});
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
self.ui.tbody.append(tr);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
// ===========================================================================
|
|
681
|
+
// PIVOT AGGREGATES
|
|
682
|
+
// ===========================================================================
|
|
683
|
+
|
|
684
|
+
_.each(ai.pivot, function (aggInfo, aiPivotIndex) {
|
|
685
|
+
var span,
|
|
686
|
+
text,
|
|
687
|
+
aggNum = aggInfo.aggNum,
|
|
688
|
+
aggResult,
|
|
689
|
+
headingThControls,
|
|
690
|
+
headingThContainer,
|
|
691
|
+
th,
|
|
692
|
+
tr,
|
|
693
|
+
i,
|
|
694
|
+
td;
|
|
695
|
+
|
|
696
|
+
tr = jQuery('<tr>');
|
|
697
|
+
self.csv.addRow();
|
|
698
|
+
|
|
699
|
+
// Add a class to the first row so it gets the double-bar outline.
|
|
700
|
+
|
|
701
|
+
if (aiPivotIndex === 0) {
|
|
702
|
+
tr.addClass('wcdv_btd'); // border-top: double
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
_.each(self.opts.displayOrder, function (what) {
|
|
706
|
+
if (typeof what === 'string') {
|
|
707
|
+
switch (what) {
|
|
708
|
+
case 'rowVals':
|
|
709
|
+
|
|
710
|
+
// Insert the name of the aggregate function in the header. This will take up as many columns
|
|
711
|
+
// as there are group fields.
|
|
712
|
+
|
|
713
|
+
if (data.groupFields.length > 1) {
|
|
714
|
+
for (i = 0; i < data.groupFields.length - 1; i += 1) {
|
|
715
|
+
self.csv.addCol('');
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
self.csv.addCol(aggInfo.instance.getFullName());
|
|
720
|
+
span = jQuery('<span>').addClass('wcdv_heading_title').text(aggInfo.instance.getFullName());
|
|
721
|
+
|
|
722
|
+
headingThControls = jQuery('<div>');
|
|
723
|
+
|
|
724
|
+
headingThContainer = jQuery('<div>')
|
|
725
|
+
.addClass('wcdv_heading_container')
|
|
726
|
+
.append(span, headingThControls);
|
|
727
|
+
|
|
728
|
+
th = jQuery('<th>')
|
|
729
|
+
.attr({'colspan': data.groupFields.length})
|
|
730
|
+
.append(headingThContainer)
|
|
731
|
+
.appendTo(tr);
|
|
732
|
+
|
|
733
|
+
// Add sorting to the header we just created.
|
|
734
|
+
|
|
735
|
+
self._addSortingToHeader(data, 'horizontal', {aggType: 'pivot', aggNum: aggNum}, headingThControls.get(0), getPropDef([], data, 'agg', 'info', 'cell'));
|
|
736
|
+
|
|
737
|
+
break;
|
|
738
|
+
case 'cells':
|
|
739
|
+
_.each(data.colVals, function (colVal, colValIdx) {
|
|
740
|
+
// Add padding cells in the CSV output so that the pivot aggregates appear staggered. Since
|
|
741
|
+
// we can't do rowspan in CSV like we can in HTML.
|
|
742
|
+
|
|
743
|
+
for (var i = 0; i < aiPivotIndex; i += 1) {
|
|
744
|
+
self.csv.addCol('');
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
var td = jQuery('<td>').dvAttr({
|
|
748
|
+
'cvi': colValIdx,
|
|
749
|
+
'agg-scope': 'pivot',
|
|
750
|
+
'agg-num': aggInfo.aggNum
|
|
751
|
+
});
|
|
752
|
+
var aggResult = data.agg.results.pivot[aggNum][colValIdx];
|
|
753
|
+
|
|
754
|
+
if (isElement(aggResult)) {
|
|
755
|
+
td.append(aggResult);
|
|
756
|
+
self.csv.addCol(getElement(aggResult).innerText);
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
if (aggInfo.instance.inheritFormatting) {
|
|
760
|
+
text = format(aggInfo.colConfig[0], aggInfo.typeInfo[0], aggResult, {
|
|
761
|
+
overrideType: aggInfo.instance.getType()
|
|
762
|
+
});
|
|
763
|
+
setTableCell(td, text, {
|
|
764
|
+
field: aggInfo.fields[0],
|
|
765
|
+
colConfig: aggInfo.colConfig[0],
|
|
766
|
+
typeInfo: aggInfo.typeInfo[0]
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
text = format(null, null, aggResult, {
|
|
771
|
+
overrideType: aggInfo.instance.getType(),
|
|
772
|
+
decode: false
|
|
773
|
+
});
|
|
774
|
+
setTableCell(td, text);
|
|
775
|
+
}
|
|
776
|
+
self.csv.addCol(td.text());
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
if (_.every(data.pivotSpec, function (ps) { return ps.fun == null; })) {
|
|
780
|
+
self._addDrillDownClass(td.get(0));
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if ((df.cell.length || ai.cell.length) > 1) {
|
|
784
|
+
td.attr('colspan', (df.cell.length || ai.cell.length));
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (self.opts.drawInternalBorders || ai.cell.length > 1) {
|
|
788
|
+
td.addClass('wcdv_pivot_colval_boundary');
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
self.setAlignment(td, aggInfo.colConfig[0], aggInfo.typeInfo[0], aggInfo.instance.getType());
|
|
792
|
+
td.appendTo(tr);
|
|
793
|
+
|
|
794
|
+
// Add padding cells in the CSV output so that the pivot aggregates appear staggered. Since
|
|
795
|
+
// we can't do rowspan in CSV like we can in HTML.
|
|
796
|
+
|
|
797
|
+
for (i = aiPivotIndex + 1; i < ai.pivot.length; i += 1) {
|
|
798
|
+
self.csv.addCol('');
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
break;
|
|
802
|
+
case 'groupAggregates':
|
|
803
|
+
|
|
804
|
+
// =========================================================================
|
|
805
|
+
// ALL AGGREGATES
|
|
806
|
+
// =========================================================================
|
|
807
|
+
|
|
808
|
+
if (getProp(data, 'agg', 'info', 'all', aggNum)) {
|
|
809
|
+
for (i = 0; i < aiPivotIndex; i += 1) {
|
|
810
|
+
td = jQuery('<td><div> </div></td>');
|
|
811
|
+
if (self.opts.drawInternalBorders || ai.cell.length > 1) {
|
|
812
|
+
td.addClass(i === 0 ? 'wcdv_pivot_aggregate_boundary' : 'wcdv_pivot_colval_boundary');
|
|
813
|
+
}
|
|
814
|
+
td.addClass('wcdv_cell_empty');
|
|
815
|
+
self.csv.addCol('');
|
|
816
|
+
td.appendTo(tr);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
aggInfo = data.agg.info.all[aggNum];
|
|
820
|
+
aggResult = data.agg.results.all[aggNum];
|
|
821
|
+
td = jQuery('<td>');
|
|
822
|
+
td.attr('data-wcdv-agg-scope', 'all');
|
|
823
|
+
td.attr('data-wcdv-agg-num', aggInfo.aggNum);
|
|
824
|
+
|
|
825
|
+
if (isElement(aggResult)) {
|
|
826
|
+
td.append(aggResult);
|
|
827
|
+
self.csv.addCol(getElement(aggResult).innerText);
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
if (aggInfo.instance.inheritFormatting) {
|
|
831
|
+
text = format(aggInfo.colConfig[0], aggInfo.typeInfo[0], aggResult, {
|
|
832
|
+
overrideType: aggInfo.instance.getType()
|
|
833
|
+
});
|
|
834
|
+
setTableCell(td, text, {
|
|
835
|
+
field: aggInfo.fields[0],
|
|
836
|
+
colConfig: aggInfo.colConfig[0],
|
|
837
|
+
typeInfo: aggInfo.typeInfo[0]
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
text = format(null, null, aggResult, {
|
|
842
|
+
overrideType: aggInfo.instance.getType(),
|
|
843
|
+
decode: false
|
|
844
|
+
});
|
|
845
|
+
setTableCell(td, text);
|
|
846
|
+
}
|
|
847
|
+
self.csv.addCol(td.text());
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
if (self.opts.drawInternalBorders || ai.cell.length > 1) {
|
|
851
|
+
td.addClass(aiPivotIndex === 0 ? 'wcdv_pivot_aggregate_boundary' : 'wcdv_pivot_colval_boundary');
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
self.setAlignment(td, aggInfo.colConfig[0], aggInfo.typeInfo[0], aggInfo.instance.getType());
|
|
855
|
+
td.appendTo(tr);
|
|
856
|
+
|
|
857
|
+
for (var i = aiPivotIndex + 1; i < ai.cell.length; i += 1) {
|
|
858
|
+
td = jQuery('<td><div> </div></td>');
|
|
859
|
+
if (self.opts.drawInternalBorders || ai.cell.length > 1) {
|
|
860
|
+
td.addClass('wcdv_pivot_colval_boundary');
|
|
861
|
+
}
|
|
862
|
+
td.addClass('wcdv_cell_empty');
|
|
863
|
+
self.csv.addCol('');
|
|
864
|
+
td.appendTo(tr);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
break;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
tr.appendTo(self.ui.tbody);
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
self.csv.finish(function () {
|
|
876
|
+
self.logDebug(self.makeLogTag() + ' Finished generating CSV file', self.toString());
|
|
877
|
+
self.csvLock.unlock();
|
|
878
|
+
self.fire('generateCsvProgress', null, 100);
|
|
879
|
+
self.fire('csvReady');
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
if (typeof cont === 'function') {
|
|
883
|
+
return cont();
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
// #addWorkHandler {{{2
|
|
888
|
+
|
|
889
|
+
GridTablePivot.prototype.addWorkHandler = function () {
|
|
890
|
+
var self = this;
|
|
891
|
+
|
|
892
|
+
self.view.on(ComputedView.events.workEnd, function (info, ops) {
|
|
893
|
+
if (self._destroyed) { return; }
|
|
894
|
+
self.logDebug(self.makeLogTag('handler(workEnd)') + ' ComputedView has finished doing work');
|
|
895
|
+
|
|
896
|
+
if (!ops.pivot) {
|
|
897
|
+
self.logDebug(self.makeLogTag('handler(workEnd)') + ' Unable to render this data: %O', ops);
|
|
898
|
+
self.fire('unableToRender', null, ops);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
self.logDebug(self.makeLogTag('handler(workEnd)') + ' Redrawing because the view has done work');
|
|
903
|
+
self.draw(self.root);
|
|
904
|
+
}, { who: self });
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
// Registry {{{1
|
|
908
|
+
|
|
909
|
+
GridRenderer.registry.set('table_pivot', GridTablePivot);
|
|
910
|
+
|
|
911
|
+
// Exports {{{1
|
|
912
|
+
|
|
913
|
+
export {
|
|
914
|
+
GridTablePivot
|
|
915
|
+
};
|