@datarailsshared/dr_renderer 1.2.99 → 1.2.102-dev
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/.circleci/config.yml +41 -41
- package/README.md +18 -18
- package/package.json +28 -28
- package/src/dataformatter.js +1033 -1033
- package/src/dr_pivottable.js +2697 -2688
- package/src/highcharts_renderer.js +7730 -7730
- package/src/index.js +27 -27
- package/src/novix_renderer.js +901 -901
- package/src/pivot.css +410 -410
- package/src/pivottable.js +1874 -1874
- package/src/published_items_renderer.js +387 -387
- package/start_run.sh +3 -3
package/src/novix_renderer.js
CHANGED
|
@@ -1,901 +1,901 @@
|
|
|
1
|
-
let initNovixRenderer = function($, window, document, Handsontable){
|
|
2
|
-
//register custom editor for format numeric editor
|
|
3
|
-
(function (Handsontable) {
|
|
4
|
-
|
|
5
|
-
var GenericEditor = Handsontable.editors.NumericEditor.prototype.extend();
|
|
6
|
-
|
|
7
|
-
GenericEditor.prototype.beginEditing = function (initialValue) {
|
|
8
|
-
|
|
9
|
-
var BaseEditor = Handsontable.editors.NumericEditor.prototype;
|
|
10
|
-
|
|
11
|
-
if (typeof (initialValue) === 'undefined' && this.originalValue) {
|
|
12
|
-
|
|
13
|
-
var value = '' + this.originalValue;
|
|
14
|
-
if (!isNaN(parseFloat(value))) {
|
|
15
|
-
value = value.replace(",", "");
|
|
16
|
-
value = parseFloat(value).toFixed(10);
|
|
17
|
-
}
|
|
18
|
-
BaseEditor.beginEditing.apply(this, [value]);
|
|
19
|
-
} else {
|
|
20
|
-
BaseEditor.beginEditing.apply(this, arguments);
|
|
21
|
-
}
|
|
22
|
-
BaseEditor.beginEditing.apply(this, [initialValue]);
|
|
23
|
-
};
|
|
24
|
-
Handsontable.editors.GenericEditor = GenericEditor;
|
|
25
|
-
|
|
26
|
-
}(Handsontable));
|
|
27
|
-
|
|
28
|
-
const delim = " , ";
|
|
29
|
-
const subtotal = "subtotalDatarailsPlaceholder";
|
|
30
|
-
const replaceValue = "SubTotals";
|
|
31
|
-
const useNewUx = document.ReportHippo && document.ReportHippo && document.ReportHippo.user &&
|
|
32
|
-
document.ReportHippo.user.organization.settings && document.ReportHippo.user.organization.settings.use_new_ux;
|
|
33
|
-
|
|
34
|
-
$.pivotUtilities.novix_renderers = {
|
|
35
|
-
|
|
36
|
-
"Pivot Table": function (pvtData, opts) {
|
|
37
|
-
return $.pivotUtilities.novix_renderers["Input Table"](pvtData, $.extend({}, opts, { readOnly: true }));
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
"Input Table": function (pvtData, opts) {
|
|
41
|
-
|
|
42
|
-
// for (let i in pvtData.input) {
|
|
43
|
-
// pvtData.input[i].value = pvtData.processRecord(pvtData.input[i]);
|
|
44
|
-
// }
|
|
45
|
-
|
|
46
|
-
var table;
|
|
47
|
-
var def = {
|
|
48
|
-
$el: $(document),
|
|
49
|
-
showTotals: true,
|
|
50
|
-
header: {
|
|
51
|
-
className: "header"
|
|
52
|
-
},
|
|
53
|
-
total: {
|
|
54
|
-
className: "total",
|
|
55
|
-
format: "0,0.00"
|
|
56
|
-
},
|
|
57
|
-
subTotal: {
|
|
58
|
-
className: "subTotal",
|
|
59
|
-
format: "0,0.00"
|
|
60
|
-
},
|
|
61
|
-
data: {
|
|
62
|
-
className: "data",
|
|
63
|
-
format: "0,0.00"
|
|
64
|
-
},
|
|
65
|
-
getIndexContent: function (indexName) {
|
|
66
|
-
// to customize content index on table. For pivot implementation
|
|
67
|
-
return indexName;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
var minColWidth = 50;
|
|
72
|
-
var maxColWidth = 250;
|
|
73
|
-
|
|
74
|
-
var calculateMaxWidths = function(ds) {
|
|
75
|
-
const mc = findMergeCols(ds);
|
|
76
|
-
return ds.data
|
|
77
|
-
.reduce((acc, row, index) => {
|
|
78
|
-
for (let [col, value] of row.entries()) {
|
|
79
|
-
if (value === subtotal) value = "SubTotals";
|
|
80
|
-
value = typeof value === 'number' ? String(value) : value;
|
|
81
|
-
if (
|
|
82
|
-
typeof value !== "undefined" &&
|
|
83
|
-
(!acc[col] || acc[col].len <= value.length) &&
|
|
84
|
-
!(index === ds.totalRows - 1 && col < ds.fixedColumns)
|
|
85
|
-
) {
|
|
86
|
-
acc[col] = { str: value, len: value.length || 0, lastRow: index === ds.totalRows - 1 };
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
return acc;
|
|
90
|
-
}, new Array(ds.totalColumns).fill(null))
|
|
91
|
-
.map((item) => getTdWidth(item))
|
|
92
|
-
.reduce((acc, width, col, arr) => {
|
|
93
|
-
acc[col] = mc[col] ? getMergeColsWidth(arr, col, mc[col]) : width;
|
|
94
|
-
return acc;
|
|
95
|
-
}, {});
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
var getTdWidth = function(item) {
|
|
99
|
-
let tdStyles = {
|
|
100
|
-
borderLeft: 'solid 1px',
|
|
101
|
-
borderRight: 'solid 1px',
|
|
102
|
-
fontSize: '11px',
|
|
103
|
-
fontFamily: '"Open Sans",sans-serif',
|
|
104
|
-
fontWeight: item.lastRow && opts.chartOptions.table_options.show_row_total ? '700' : '400',
|
|
105
|
-
paddingRight: '4px',
|
|
106
|
-
paddingLeft: '4px',
|
|
107
|
-
wrap: 'nowrap',
|
|
108
|
-
visibility: 'hidden',
|
|
109
|
-
};
|
|
110
|
-
let td = document.createElement('td');
|
|
111
|
-
for (let [key, value] of _.entries(tdStyles)) {
|
|
112
|
-
td.style[key] = value;
|
|
113
|
-
};
|
|
114
|
-
td.innerHTML = item.str;
|
|
115
|
-
document.body.appendChild(td);
|
|
116
|
-
let width = Math.min(Math.max(td.offsetWidth, minColWidth), maxColWidth);
|
|
117
|
-
document.body.removeChild(td);
|
|
118
|
-
return width;
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
var findMergeCols = function(ds) {
|
|
122
|
-
return ds.mergeCells
|
|
123
|
-
.filter(cell => cell.row === ds.fixedRows - 1)
|
|
124
|
-
.reduce((acc, val) => {
|
|
125
|
-
if (!acc[val.col] && val.colspan > 1) acc[val.col] = val.colspan - 1;
|
|
126
|
-
return acc;
|
|
127
|
-
}, {});
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
var getMergeColsWidth = function(cw, col, m) {
|
|
131
|
-
let rightColsWidth = 0;
|
|
132
|
-
for (let _col = col + 1; _col <= col + m; _col++) {
|
|
133
|
-
rightColsWidth += cw[_col];
|
|
134
|
-
};
|
|
135
|
-
return rightColsWidth >= cw[col] ? 0 : cw[col] - rightColsWidth;
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
opts = $.extend(def, opts, true);
|
|
139
|
-
|
|
140
|
-
var headerRenderer = function (cellProperties) {
|
|
141
|
-
cellProperties.readOnly = true;
|
|
142
|
-
cellProperties.className = opts.header.className;
|
|
143
|
-
};
|
|
144
|
-
var totalRenderer = function (cellProperties) {
|
|
145
|
-
cellProperties.readOnly = opts.showTotals;
|
|
146
|
-
cellProperties.format = opts.total.format;
|
|
147
|
-
cellProperties.className = opts.total.className;
|
|
148
|
-
};
|
|
149
|
-
var subTotalRenderer = function (cellProperties) {
|
|
150
|
-
cellProperties.readOnly = true;
|
|
151
|
-
cellProperties.format = opts.subTotal.format;
|
|
152
|
-
cellProperties.className = opts.subTotal.className;
|
|
153
|
-
};
|
|
154
|
-
var dataRenderer = function (cellProperties) {
|
|
155
|
-
cellProperties.readOnly = opts.readOnly;
|
|
156
|
-
cellProperties.className = opts.data.className;
|
|
157
|
-
cellProperties.format = opts.data.format;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// get changes on pivot table
|
|
161
|
-
var getPivotChange = function (change, pvtData, dataSource) {
|
|
162
|
-
var rowIdx = change[0] - dataSource.fixedRows;
|
|
163
|
-
var colIdx = change[1] - dataSource.fixedColumns;
|
|
164
|
-
var dataFilter = {
|
|
165
|
-
filterList: [],
|
|
166
|
-
oldValue: change[2],
|
|
167
|
-
newValue: change[3]
|
|
168
|
-
};
|
|
169
|
-
if (colIdx >= 0) {
|
|
170
|
-
var colKeys = pvtData.getColKeys();
|
|
171
|
-
for (var cAttrIdx = 0; cAttrIdx < pvtData.colAttrs.length; cAttrIdx++) {
|
|
172
|
-
if (colIdx < colKeys.length) {
|
|
173
|
-
var cValues = colKeys[colIdx];
|
|
174
|
-
dataFilter.filterList.push({
|
|
175
|
-
Key: pvtData.colAttrs[cAttrIdx],
|
|
176
|
-
Value: cValues[cAttrIdx]
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (rowIdx >= 0) {
|
|
182
|
-
var rowKeys = pvtData.getRowKeys();
|
|
183
|
-
for (var rAttrIdx = 0; rAttrIdx < pvtData.rowAttrs.length; rAttrIdx++) {
|
|
184
|
-
if (rowIdx < rowKeys.length) {
|
|
185
|
-
var rValues = rowKeys[rowIdx];
|
|
186
|
-
dataFilter.filterList.push({
|
|
187
|
-
Key: pvtData.rowAttrs[rAttrIdx],
|
|
188
|
-
Value: rValues[rAttrIdx]
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return dataFilter;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Parse the pvtData and create datasource to handsontable
|
|
197
|
-
var parsePivotData = function (pvtData) {
|
|
198
|
-
var dataSource = {
|
|
199
|
-
data: [],
|
|
200
|
-
columns: [],
|
|
201
|
-
fixedColumns: 0,
|
|
202
|
-
fixedRows: 0,
|
|
203
|
-
mergeCells: [],
|
|
204
|
-
totalColumns: 0,
|
|
205
|
-
totalRows: 0,
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
// add rows subtotals
|
|
209
|
-
var addRowSubTotals = function (pvtData) {
|
|
210
|
-
|
|
211
|
-
const tmpNewRows = [];
|
|
212
|
-
const newRowsKeys = [];
|
|
213
|
-
for (let i = 1; i < pvtData.rowAttrs.length; i++) {
|
|
214
|
-
for (let rowKeyArr of pvtData.rowKeys) {
|
|
215
|
-
|
|
216
|
-
let tmpRowKeyArr = rowKeyArr.slice(0, i);
|
|
217
|
-
let tmpRowKey = tmpRowKeyArr.join(delim);
|
|
218
|
-
|
|
219
|
-
let newKeyArr = tmpRowKeyArr.concat(subtotal);
|
|
220
|
-
let newKey = newKeyArr.join(delim);
|
|
221
|
-
|
|
222
|
-
if (!pvtData.rowTotals[newKey]) {
|
|
223
|
-
pvtData.rowTotals[newKey] = pvtData.rowTotals[tmpRowKey];
|
|
224
|
-
newRowsKeys.push(newKeyArr);
|
|
225
|
-
|
|
226
|
-
pvtData.tree[newKey] = {};
|
|
227
|
-
for (let colKeyArr of pvtData.colKeys) {
|
|
228
|
-
let colKey = colKeyArr.join(delim);
|
|
229
|
-
if (pvtData.tree[tmpRowKey][colKey]) {
|
|
230
|
-
pvtData.tree[newKey][colKey] = pvtData.tree[tmpRowKey][colKey];
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
for (let j = 1; j < pvtData.colAttrs.length; j++) {
|
|
234
|
-
let tmpColKeyArr = colKeyArr.slice(0, j);
|
|
235
|
-
let tmpColKeyStr = tmpColKeyArr.join(delim);
|
|
236
|
-
|
|
237
|
-
let grandSubTotal = pvtData.tree[tmpRowKey][tmpColKeyStr];
|
|
238
|
-
pvtData.tree[newKey][tmpColKeyStr + delim + subtotal] = grandSubTotal;
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
pvtData.rowKeys = pvtData.rowKeys.concat(newRowsKeys);
|
|
246
|
-
return pvtData;
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// add cols subtotals
|
|
250
|
-
var addColSubTotals = function (pvtData) {
|
|
251
|
-
// console.log("handson col data", pvtData);
|
|
252
|
-
const tmpNewColumns = [];
|
|
253
|
-
const newColumnKeys = [];
|
|
254
|
-
for (let i = 1; i < pvtData.colAttrs.length; i++) {
|
|
255
|
-
for (let colKeyArr of pvtData.colKeys) {
|
|
256
|
-
|
|
257
|
-
let tmpColKeyArr = colKeyArr.slice(0, i);
|
|
258
|
-
let tmpColKey = tmpColKeyArr.join(delim);
|
|
259
|
-
|
|
260
|
-
let newKeyArr = tmpColKeyArr.concat(subtotal);
|
|
261
|
-
let newKey = newKeyArr.join(delim);
|
|
262
|
-
|
|
263
|
-
if (!pvtData.colTotals[newKey]) {
|
|
264
|
-
pvtData.colTotals[newKey] = pvtData.colTotals[tmpColKey];
|
|
265
|
-
newColumnKeys.push(newKeyArr);
|
|
266
|
-
|
|
267
|
-
for (let rowKeyArr of pvtData.rowKeys) {
|
|
268
|
-
let rowKey = rowKeyArr.join(delim);
|
|
269
|
-
if (pvtData.tree[rowKey][tmpColKey]) {
|
|
270
|
-
pvtData.tree[rowKey][newKey] = pvtData.tree[rowKey][tmpColKey];
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
pvtData.colKeys = pvtData.colKeys.concat(newColumnKeys);
|
|
277
|
-
// console.log("handson data2", pvtData);
|
|
278
|
-
return pvtData;
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
if (opts.chartOptions.table_options.show_subtotals_for_rows) {
|
|
282
|
-
pvtData = addRowSubTotals(pvtData);
|
|
283
|
-
}
|
|
284
|
-
if (opts.chartOptions.table_options.show_subtotals_for_columns) {
|
|
285
|
-
pvtData = addColSubTotals(pvtData);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
var colKeys = pvtData.getColKeys();
|
|
290
|
-
var rowKeys = pvtData.getRowKeys();
|
|
291
|
-
var hasColumnAttr = (pvtData.colAttrs.length > 0 ? true : false);
|
|
292
|
-
var hasRowAttr = (pvtData.rowAttrs.length > 0 ? true : false);
|
|
293
|
-
|
|
294
|
-
var addMergeCell = function (row, col, rows, columns, noHAlign, noVAlign) {
|
|
295
|
-
dataSource.mergeCells.push({
|
|
296
|
-
row: row,
|
|
297
|
-
col: col,
|
|
298
|
-
rowspan: rows,
|
|
299
|
-
colspan: columns
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
//fixed columns and rows
|
|
304
|
-
dataSource.fixedColumns = pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0);
|
|
305
|
-
dataSource.fixedRows = pvtData.colAttrs.length + (hasRowAttr ? 1 : 0);
|
|
306
|
-
|
|
307
|
-
for (i = 0; i < pvtData.rowAttrs.length; i++) {
|
|
308
|
-
rowKeys.sort((a,b) => {
|
|
309
|
-
if (_.isEqual(a.slice(0, i), b.slice(0,i)) && a[i] && a[i] === subtotal) return -1;
|
|
310
|
-
if (_.isEqual(a.slice(0, i), b.slice(0,i)) && b[i] && b[i] === subtotal) return 1;
|
|
311
|
-
return 0;
|
|
312
|
-
});
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// for extra rows on edit mode. Where show only one dimension on row o column.
|
|
316
|
-
var extraColumnLabel = "Grand Totals";
|
|
317
|
-
var extraRowLabel = "Grand Totals";
|
|
318
|
-
if (opts.totalFilterElements && opts.totalFilterElements.row_total) {
|
|
319
|
-
extraColumnLabel = opts.totalFilterElements.row_total.innerHTML;
|
|
320
|
-
}
|
|
321
|
-
if (opts.totalFilterElements && opts.totalFilterElements.col_total) {
|
|
322
|
-
extraRowLabel = opts.totalFilterElements.col_total.innerHTML;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
var addExtraColumn = false;
|
|
326
|
-
var addExtraRow = false;
|
|
327
|
-
if (pvtData.colKeys.length == 0) {
|
|
328
|
-
addExtraColumn = true;
|
|
329
|
-
}
|
|
330
|
-
if (pvtData.rowKeys.length == 0) {
|
|
331
|
-
addExtraRow = true;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
//columns
|
|
335
|
-
var totalColumns = dataSource.totalColumns = pvtData.colKeys.length + pvtData.rowAttrs.length +
|
|
336
|
-
(pvtData.colAttrs.length > 0 ? 1 : 0) +
|
|
337
|
-
(opts.showTotals || addExtraColumn ? 1 : 0);
|
|
338
|
-
|
|
339
|
-
if (!opts.chartOptions.table_options.show_column_total) {
|
|
340
|
-
totalColumns--;
|
|
341
|
-
}
|
|
342
|
-
for (var cc = 0; cc < totalColumns; cc++) {
|
|
343
|
-
|
|
344
|
-
if (cc < dataSource.fixedColumns) {
|
|
345
|
-
dataSource.columns.push({
|
|
346
|
-
type: 'text',
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
dataSource.columns.push({
|
|
351
|
-
type: 'text',
|
|
352
|
-
editor: Handsontable.editors.GenericEditor
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
//first merge cells
|
|
358
|
-
if (hasRowAttr && hasColumnAttr) {
|
|
359
|
-
addMergeCell(0, 0, hasColumnAttr ? pvtData.colAttrs.length : 1, (hasRowAttr ? pvtData.rowAttrs.length : 1));
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// ##
|
|
363
|
-
// HEADERS (columns)
|
|
364
|
-
for (var nn = 0; nn < pvtData.colAttrs.length + (hasRowAttr ? 1 : 0) ; nn++) {
|
|
365
|
-
var rowData = [];
|
|
366
|
-
|
|
367
|
-
// rows with dimensions on columns
|
|
368
|
-
if (nn < pvtData.colAttrs.length) {
|
|
369
|
-
|
|
370
|
-
// columns for row attrs
|
|
371
|
-
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
372
|
-
rowData.push("");
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
//column for colum attr,
|
|
376
|
-
rowData.push(opts.getIndexContent(pvtData.colAttrs[nn]));
|
|
377
|
-
|
|
378
|
-
//data columns
|
|
379
|
-
if (pvtData.colKeys.length > 0) {
|
|
380
|
-
|
|
381
|
-
var aux = rowData.length;
|
|
382
|
-
var startCol = aux;
|
|
383
|
-
var prior = colKeys[0][nn];
|
|
384
|
-
var toMerge = 0;
|
|
385
|
-
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
386
|
-
|
|
387
|
-
var textHeader = colKeys[cc][nn];
|
|
388
|
-
|
|
389
|
-
if (nn < pvtData.colAttrs.length - 1 && prior != textHeader) {
|
|
390
|
-
rowData.push(textHeader);
|
|
391
|
-
prior = textHeader;
|
|
392
|
-
// merge cell
|
|
393
|
-
addMergeCell(nn, aux, 1, toMerge);
|
|
394
|
-
aux = aux + toMerge;
|
|
395
|
-
toMerge = 1;
|
|
396
|
-
}
|
|
397
|
-
else {
|
|
398
|
-
toMerge++;
|
|
399
|
-
rowData.push(textHeader);
|
|
400
|
-
|
|
401
|
-
// vertical merge on last row of header columns. Disabled for performance analysis
|
|
402
|
-
//if (nn == pvtData.colAttrs.length - 1 && hasRowAttr) {
|
|
403
|
-
//addMergeCell(nn,startCol+cc ,2,1);
|
|
404
|
-
//}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
//merge last cell
|
|
409
|
-
if (nn < pvtData.colAttrs.length - 1) {
|
|
410
|
-
addMergeCell(nn, aux, 1, toMerge);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// total column
|
|
416
|
-
if (opts.showTotals || addExtraColumn) {
|
|
417
|
-
rowData.push(extraColumnLabel);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
else { // rows with dimensions on columns
|
|
421
|
-
|
|
422
|
-
// columns for row attrs
|
|
423
|
-
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
424
|
-
|
|
425
|
-
rowData.push(opts.getIndexContent(pvtData.rowAttrs[cc]));
|
|
426
|
-
//merge cell
|
|
427
|
-
if (cc == pvtData.rowAttrs.length - 1 && hasColumnAttr) {
|
|
428
|
-
addMergeCell(nn, cc, 1, 2);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
//empty column for colum attr,
|
|
434
|
-
if (hasColumnAttr > 0) {
|
|
435
|
-
rowData.push("");
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
//data columns (empty)
|
|
439
|
-
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
440
|
-
rowData.push("");
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// total column
|
|
444
|
-
if (opts.showTotals || addExtraColumn) {
|
|
445
|
-
rowData.push(extraColumnLabel);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
dataSource.data.push(rowData);
|
|
451
|
-
}
|
|
452
|
-
// END HEADER
|
|
453
|
-
// ######
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
// ######
|
|
458
|
-
// DATA
|
|
459
|
-
|
|
460
|
-
var mergeDic = {};
|
|
461
|
-
|
|
462
|
-
for (var rr = 0; rr < rowKeys.length; rr++) {
|
|
463
|
-
|
|
464
|
-
var rowData = [];
|
|
465
|
-
|
|
466
|
-
if (rr == 0) {
|
|
467
|
-
for (var cc = 0; cc < dataSource.fixedColumns; cc++) {
|
|
468
|
-
mergeDic[cc] = {
|
|
469
|
-
toMerge: 1,
|
|
470
|
-
row: 0,
|
|
471
|
-
priorText: rowKeys[rr][cc]
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
//column for row atts
|
|
477
|
-
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
478
|
-
rowData.push(rowKeys[rr][cc]);
|
|
479
|
-
if (rowKeys[rr][cc] === subtotal) {
|
|
480
|
-
addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, dataSource.fixedColumns - cc, true, true);
|
|
481
|
-
} else if (cc === rowKeys[rr].length - 1 && hasColumnAttr) {
|
|
482
|
-
addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, 2, true, true);
|
|
483
|
-
}
|
|
484
|
-
// merge cell (last column)
|
|
485
|
-
if (opts.chartOptions.table_options.show_column_total && rr != 0 && mergeDic[cc]) { // check for merge dic
|
|
486
|
-
if (rowKeys[rr][cc] == mergeDic[cc].priorText) {
|
|
487
|
-
mergeDic[cc].toMerge++;
|
|
488
|
-
} else if (cc < rowKeys[rr].length - 1) {
|
|
489
|
-
//create merge cell for this column
|
|
490
|
-
addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
|
|
491
|
-
mergeDic[cc].row = rr;
|
|
492
|
-
mergeDic[cc].toMerge = 1;
|
|
493
|
-
mergeDic[cc].priorText = rowKeys[rr][cc];
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// empty column (for colum atts)
|
|
499
|
-
if (hasColumnAttr) {
|
|
500
|
-
rowData.push("");
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// columns data
|
|
504
|
-
var agg;
|
|
505
|
-
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
506
|
-
agg = pvtData.getAggregator(rowKeys[rr], colKeys[cc])
|
|
507
|
-
|
|
508
|
-
var cellValue = $.pivotUtilities.getFormattedNumber(agg.value(), agg, opts);
|
|
509
|
-
// var cellValue = agg.value();
|
|
510
|
-
|
|
511
|
-
if (cellValue) {
|
|
512
|
-
rowData.push(cellValue);
|
|
513
|
-
}
|
|
514
|
-
else if (cellValue === 0) {
|
|
515
|
-
rowData.push("0");
|
|
516
|
-
}
|
|
517
|
-
else {
|
|
518
|
-
rowData.push("");
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// column total
|
|
524
|
-
if (opts.showTotals || addExtraColumn) {
|
|
525
|
-
// var rowKeyAtt = rowKeys[rr].join(String.fromCharCode(0));
|
|
526
|
-
var rowKeyAtt = rowKeys[rr].join(delim);
|
|
527
|
-
if (pvtData.rowTotals[rowKeyAtt]) {
|
|
528
|
-
let agg = pvtData.getAggregator(rowKeys[rr], []);
|
|
529
|
-
let preValue = pvtData.rowTotals[rowKeyAtt].value();
|
|
530
|
-
let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
|
|
531
|
-
rowData.push(cellValue);
|
|
532
|
-
// rowData.push(pvtData.rowTotals[rowKeyAtt].value());
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
rowData.push("");
|
|
536
|
-
// rowData.push(0);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
dataSource.data.push(rowData);
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// add last rows merge cells for each column
|
|
545
|
-
if (opts.chartOptions.table_options.show_column_total) {
|
|
546
|
-
|
|
547
|
-
for (var cc = 0; cc < pvtData.rowAttrs.length - 1; cc++) {
|
|
548
|
-
|
|
549
|
-
if (mergeDic[cc] && mergeDic[cc].toMerge > 1) {
|
|
550
|
-
addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// END DATA
|
|
556
|
-
// ######
|
|
557
|
-
|
|
558
|
-
// ######
|
|
559
|
-
// TOTAL
|
|
560
|
-
// colums totals area
|
|
561
|
-
if (opts.showTotals || addExtraRow) {
|
|
562
|
-
|
|
563
|
-
var rowData = [];
|
|
564
|
-
|
|
565
|
-
// columns for row attrs
|
|
566
|
-
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
567
|
-
rowData.push(extraRowLabel);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
//empty column for colum attr,
|
|
571
|
-
if (hasColumnAttr) {
|
|
572
|
-
rowData.push(extraRowLabel);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
//column totals
|
|
577
|
-
if (opts.chartOptions.table_options.show_row_total) {
|
|
578
|
-
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
579
|
-
|
|
580
|
-
var colKeyAtt = colKeys[cc].join(delim);
|
|
581
|
-
if (pvtData.colTotals[colKeyAtt]) {
|
|
582
|
-
let agg = pvtData.getAggregator([], colKeys[cc]);
|
|
583
|
-
let preValue = pvtData.colTotals[colKeyAtt].value();
|
|
584
|
-
let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
|
|
585
|
-
rowData.push(cellValue);
|
|
586
|
-
}
|
|
587
|
-
else {
|
|
588
|
-
rowData.push(0);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
//all total column
|
|
594
|
-
rowData.push($.pivotUtilities.getFormattedNumber(pvtData.allTotal.value(), pvtData.allTotal, opts));
|
|
595
|
-
|
|
596
|
-
// END TOTAL
|
|
597
|
-
// ######
|
|
598
|
-
|
|
599
|
-
if (opts.chartOptions.table_options.show_row_total) {
|
|
600
|
-
|
|
601
|
-
dataSource.data.push(rowData);
|
|
602
|
-
}
|
|
603
|
-
// end total columns
|
|
604
|
-
}
|
|
605
|
-
dataSource.totalRows = dataSource.data.length;
|
|
606
|
-
|
|
607
|
-
if (opts.showTotals || addExtraRow) {
|
|
608
|
-
|
|
609
|
-
// columns total merge cell
|
|
610
|
-
if (opts.chartOptions.table_options.show_row_total) {
|
|
611
|
-
if (pvtData.rowAttrs.length > 0) {
|
|
612
|
-
addMergeCell(dataSource.totalRows - 1, 0, 1, pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0));
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if (opts.chartOptions.table_options.show_column_total) {
|
|
617
|
-
// rows total merge cell
|
|
618
|
-
if (pvtData.colAttrs.length > 0) {
|
|
619
|
-
addMergeCell(0, totalColumns - 1, pvtData.colAttrs.length + (hasRowAttr ? 1 : 0), 1);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return dataSource;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// render the table
|
|
627
|
-
var renderTable = function (pvtData, opts) {
|
|
628
|
-
var dataSource = parsePivotData(pvtData);
|
|
629
|
-
|
|
630
|
-
// function to data render
|
|
631
|
-
var genericRenderer = function (instance, td, row, col, prop, value, cellProperties) {
|
|
632
|
-
|
|
633
|
-
var newValue = '' + value;
|
|
634
|
-
td.innerHTML = opts.labelsConvertFunction(newValue);
|
|
635
|
-
|
|
636
|
-
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
637
|
-
// header
|
|
638
|
-
td.className = opts.header.className;
|
|
639
|
-
|
|
640
|
-
if (opts.chartOptions.table_options.colorize_headers == true && opts.defaults_colors) {
|
|
641
|
-
let color_to_set;
|
|
642
|
-
if (row < dataSource.fixedRows) {
|
|
643
|
-
if (row < 1) {
|
|
644
|
-
color_to_set = opts.defaults_colors[row];
|
|
645
|
-
} else {
|
|
646
|
-
color_to_set = opts.defaults_colors[1];
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
if (col < dataSource.fixedColumns) {
|
|
650
|
-
td.className = opts.header.className + " sideHeader";
|
|
651
|
-
if (row < dataSource.fixedRows) {
|
|
652
|
-
color_to_set = opts.defaults_colors[row];
|
|
653
|
-
} else {
|
|
654
|
-
// color_to_set = "#fff";
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
if(color_to_set){
|
|
659
|
-
td.style.setProperty("background-color", color_to_set, "important");
|
|
660
|
-
// td.style.setProperty("border-color", color_to_set, "important");
|
|
661
|
-
td.style.color = "#FFFFFF";
|
|
662
|
-
// td.style.fontWeight = "bold";
|
|
663
|
-
} else {
|
|
664
|
-
td.style.setProperty("background-color", "#fff", "important");
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
else if (col < dataSource.fixedColumns) {
|
|
670
|
-
if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
|
|
671
|
-
(dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
|
|
672
|
-
td.className = opts.subTotal.className;
|
|
673
|
-
} else if (dataSource.data[row] && dataSource.data[row].indexOf(subtotal) !== -1 &&
|
|
674
|
-
dataSource.data[row].indexOf(subtotal) < 3) {
|
|
675
|
-
td.className = opts.subTotal.className;
|
|
676
|
-
}
|
|
677
|
-
if (newValue === subtotal) {
|
|
678
|
-
td.innerHTML = replaceValue;
|
|
679
|
-
} else if (opts.chartOptions.table_options.remove_underscores == true) {
|
|
680
|
-
td.innerHTML = newValue.replace("_", " ");
|
|
681
|
-
}
|
|
682
|
-
} else if (opts.chartOptions.table_options.show_row_total && opts.showTotals && row == dataSource.totalRows - 1) {
|
|
683
|
-
//total row
|
|
684
|
-
td.className = opts.total.className;
|
|
685
|
-
} else if (opts.chartOptions.table_options.show_column_total && opts.showTotals && col == dataSource.totalColumns - 1) {
|
|
686
|
-
//total col
|
|
687
|
-
td.className = opts.total.className;
|
|
688
|
-
} else if (dataSource.data[row] && dataSource.data[row].includes(subtotal)) {
|
|
689
|
-
//subTotal row class
|
|
690
|
-
td.className = opts.subTotal.className;
|
|
691
|
-
} else if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
|
|
692
|
-
(dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
|
|
693
|
-
//subTotal col class
|
|
694
|
-
td.className = opts.subTotal.className;
|
|
695
|
-
} else {
|
|
696
|
-
//data
|
|
697
|
-
td.className = opts.data.className;
|
|
698
|
-
}
|
|
699
|
-
td.className += " __" + row + "," + col + "__";
|
|
700
|
-
|
|
701
|
-
if (opts.chartOptions.table_options.colorize_headers == true) {
|
|
702
|
-
td.className += " colorized";
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
if (opts.chartOptions.table_options.show_row_total && row == dataSource.totalRows-1) {
|
|
706
|
-
td.className += " withTopBorder";
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
if (td.innerHTML === subtotal) {
|
|
710
|
-
td.innerHTML = replaceValue;
|
|
711
|
-
}
|
|
712
|
-
if (td.innerHTML === "undefined") {
|
|
713
|
-
td.innerHTML = "";
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
if (opts.chartOptions.table_options.hide_nulls_in_headers && td.innerHTML === '[null]') {
|
|
717
|
-
td.innerHTML = '';
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (opts.chartOptions.table_options.styles) {
|
|
721
|
-
for (let rule of opts.chartOptions.table_options.styles) {
|
|
722
|
-
|
|
723
|
-
if (!rule.styles || rule.styles.length === 0) {
|
|
724
|
-
continue;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
if (rule.row && rule.col) {
|
|
728
|
-
if (row === parseInt(rule.row) && col === parseInt(rule.col)) {
|
|
729
|
-
for (let style of rule.styles) {
|
|
730
|
-
td.style.setProperty(style.name, style.val, "important");
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
} else if (rule.row && row !== 0 && col !== 0) {
|
|
734
|
-
if (rule.repeat) {
|
|
735
|
-
const offset = rule.offset || 0;
|
|
736
|
-
if (row > offset && (row - offset) % rule.row === 0) {
|
|
737
|
-
for (let style of rule.styles) {
|
|
738
|
-
td.style.setProperty(style.name, style.val, "important");
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
} else if (row === parseInt(rule.row)) {
|
|
742
|
-
for (let style of rule.styles) {
|
|
743
|
-
td.style.setProperty(style.name, style.val, "important");
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
} else if (rule.col && col !== 0 && row !== 0) {
|
|
747
|
-
if (rule.repeat) {
|
|
748
|
-
const offset = rule.offset || 0;
|
|
749
|
-
if (col > offset && (col - offset) % rule.col === 0) {
|
|
750
|
-
for (let style of rule.styles) {
|
|
751
|
-
td.style.setProperty(style.name, style.val, "important");
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
} else if (col === parseInt(rule.col)) {
|
|
755
|
-
for (let style of rule.styles) {
|
|
756
|
-
td.style.setProperty(style.name, style.val, "important");
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
return td;
|
|
763
|
-
};
|
|
764
|
-
|
|
765
|
-
var _this = this;
|
|
766
|
-
if (table) {
|
|
767
|
-
table.destroy();
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
var contextMenu = null;
|
|
771
|
-
|
|
772
|
-
if(opts.value_drill_down_fn){
|
|
773
|
-
let calBackFn = function(key, selection, clickEvent) {
|
|
774
|
-
let row = selection[0].start.row;
|
|
775
|
-
let col = selection[0].start.col;
|
|
776
|
-
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
else{
|
|
780
|
-
let cols = [];
|
|
781
|
-
let rows = [];
|
|
782
|
-
|
|
783
|
-
for(let i=0; i< pvtData.rowAttrs.length; i++){
|
|
784
|
-
rows.push(dataSource.data[row][i]);
|
|
785
|
-
}
|
|
786
|
-
for(let i=0; i< pvtData.colAttrs.length; i++){
|
|
787
|
-
cols.push(dataSource.data[i][col]);
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (opts.showTotals && row == dataSource.totalRows - 1) {
|
|
791
|
-
rows = [];
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
if (opts.showTotals && col == dataSource.totalColumns - 1) {
|
|
795
|
-
cols = [];
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
opts.value_drill_down_fn(clickEvent, rows, cols, key);
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
|
|
802
|
-
let disableFn = function () {
|
|
803
|
-
let selection = this.getSelectedLast();
|
|
804
|
-
if (selection[0] < dataSource.fixedRows || selection[1] < dataSource.fixedColumns) {
|
|
805
|
-
return true;
|
|
806
|
-
}
|
|
807
|
-
return false;
|
|
808
|
-
};
|
|
809
|
-
|
|
810
|
-
contextMenu = {
|
|
811
|
-
items: {
|
|
812
|
-
"open_drill_down_view": {
|
|
813
|
-
name: 'Open drill down view',
|
|
814
|
-
callback: calBackFn,
|
|
815
|
-
disabled: disableFn
|
|
816
|
-
},
|
|
817
|
-
"export_drill_down": {
|
|
818
|
-
name: 'Export drill down to excel',
|
|
819
|
-
callback: calBackFn,
|
|
820
|
-
disabled: disableFn
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
var $tableArea = opts.$el.find(".widget-id-" + opts.widgetId);
|
|
827
|
-
$tableArea.empty();
|
|
828
|
-
console.log('Handsontable data', dataSource);
|
|
829
|
-
var maxWidths = calculateMaxWidths(dataSource);
|
|
830
|
-
table = new Handsontable($tableArea.get(0), {
|
|
831
|
-
licenseKey: 'b0eda-7220b-32d15-e4128-c2f4c', //98463-b132b-fcea0-24f22-da020
|
|
832
|
-
data: dataSource.data,
|
|
833
|
-
contextMenu: contextMenu,
|
|
834
|
-
selectionMode: "single",
|
|
835
|
-
colHeaders: false,
|
|
836
|
-
allowInsertColumn: false,
|
|
837
|
-
allowInsertRow: false,
|
|
838
|
-
columns: dataSource.columns,
|
|
839
|
-
fixedColumnsLeft: dataSource.fixedColumns,
|
|
840
|
-
fixedRowsTop: dataSource.fixedRows,
|
|
841
|
-
mergeCells: dataSource.mergeCells,
|
|
842
|
-
colWidths: function(index) {
|
|
843
|
-
return maxWidths[index];
|
|
844
|
-
},
|
|
845
|
-
cells: function (row, col, prop) {
|
|
846
|
-
var cellProperties = {};
|
|
847
|
-
cellProperties.renderer = genericRenderer;
|
|
848
|
-
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
849
|
-
headerRenderer(cellProperties);
|
|
850
|
-
} else {
|
|
851
|
-
if (opts.showTotals && (row == dataSource.totalRows - 1 || col == dataSource.totalColumns - 1)) {
|
|
852
|
-
totalRenderer(cellProperties);
|
|
853
|
-
} else {
|
|
854
|
-
dataRenderer(cellProperties);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
return cellProperties;
|
|
858
|
-
}
|
|
859
|
-
});
|
|
860
|
-
|
|
861
|
-
setTimeout(function () {
|
|
862
|
-
|
|
863
|
-
var currentState = opts.$el.data("currentState");
|
|
864
|
-
|
|
865
|
-
if (currentState) {
|
|
866
|
-
if (currentState && currentState.lastRowChanged) {
|
|
867
|
-
table.selectCell(currentState.lastRowChanged + 1, currentState.lasColChanged, currentState.lastRowChanged + 1, currentState.lasColChanged);
|
|
868
|
-
currentState.lastRowChanged = null;
|
|
869
|
-
if (currentState.scrollX && currentState.scrollX > 0) {
|
|
870
|
-
opts.$el.scrollLeft(currentState.scrollX);
|
|
871
|
-
}
|
|
872
|
-
if (currentState.scrollY && currentState.scrollY > 0) {
|
|
873
|
-
opts.$el.scrollTop(currentState.scrollY);
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
currentState = null;
|
|
877
|
-
opts.$el.data("currentState", null);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
}, 5);
|
|
882
|
-
return false;
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
var _this = this;
|
|
886
|
-
setTimeout(function () {
|
|
887
|
-
renderTable(pvtData, opts);
|
|
888
|
-
}, 10);
|
|
889
|
-
|
|
890
|
-
// inject the widgetId to the class name so we can separate the tables by it
|
|
891
|
-
// look for the search side on line 653 "opts.$el.find(".widget-id-" + opts.widgetId);"
|
|
892
|
-
return `<div class='novixPivot widget-id-${opts.widgetId} ${
|
|
893
|
-
useNewUx && opts.chartOptions.table_options.use_new_table_design ? 'handsontable-new' : ''
|
|
894
|
-
}' style='overflow:auto'></div>`;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
};
|
|
898
|
-
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
module.exports = initNovixRenderer;
|
|
1
|
+
let initNovixRenderer = function($, window, document, Handsontable){
|
|
2
|
+
//register custom editor for format numeric editor
|
|
3
|
+
(function (Handsontable) {
|
|
4
|
+
|
|
5
|
+
var GenericEditor = Handsontable.editors.NumericEditor.prototype.extend();
|
|
6
|
+
|
|
7
|
+
GenericEditor.prototype.beginEditing = function (initialValue) {
|
|
8
|
+
|
|
9
|
+
var BaseEditor = Handsontable.editors.NumericEditor.prototype;
|
|
10
|
+
|
|
11
|
+
if (typeof (initialValue) === 'undefined' && this.originalValue) {
|
|
12
|
+
|
|
13
|
+
var value = '' + this.originalValue;
|
|
14
|
+
if (!isNaN(parseFloat(value))) {
|
|
15
|
+
value = value.replace(",", "");
|
|
16
|
+
value = parseFloat(value).toFixed(10);
|
|
17
|
+
}
|
|
18
|
+
BaseEditor.beginEditing.apply(this, [value]);
|
|
19
|
+
} else {
|
|
20
|
+
BaseEditor.beginEditing.apply(this, arguments);
|
|
21
|
+
}
|
|
22
|
+
BaseEditor.beginEditing.apply(this, [initialValue]);
|
|
23
|
+
};
|
|
24
|
+
Handsontable.editors.GenericEditor = GenericEditor;
|
|
25
|
+
|
|
26
|
+
}(Handsontable));
|
|
27
|
+
|
|
28
|
+
const delim = " , ";
|
|
29
|
+
const subtotal = "subtotalDatarailsPlaceholder";
|
|
30
|
+
const replaceValue = "SubTotals";
|
|
31
|
+
const useNewUx = document.ReportHippo && document.ReportHippo && document.ReportHippo.user &&
|
|
32
|
+
document.ReportHippo.user.organization.settings && document.ReportHippo.user.organization.settings.use_new_ux;
|
|
33
|
+
|
|
34
|
+
$.pivotUtilities.novix_renderers = {
|
|
35
|
+
|
|
36
|
+
"Pivot Table": function (pvtData, opts) {
|
|
37
|
+
return $.pivotUtilities.novix_renderers["Input Table"](pvtData, $.extend({}, opts, { readOnly: true }));
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"Input Table": function (pvtData, opts) {
|
|
41
|
+
|
|
42
|
+
// for (let i in pvtData.input) {
|
|
43
|
+
// pvtData.input[i].value = pvtData.processRecord(pvtData.input[i]);
|
|
44
|
+
// }
|
|
45
|
+
|
|
46
|
+
var table;
|
|
47
|
+
var def = {
|
|
48
|
+
$el: $(document),
|
|
49
|
+
showTotals: true,
|
|
50
|
+
header: {
|
|
51
|
+
className: "header"
|
|
52
|
+
},
|
|
53
|
+
total: {
|
|
54
|
+
className: "total",
|
|
55
|
+
format: "0,0.00"
|
|
56
|
+
},
|
|
57
|
+
subTotal: {
|
|
58
|
+
className: "subTotal",
|
|
59
|
+
format: "0,0.00"
|
|
60
|
+
},
|
|
61
|
+
data: {
|
|
62
|
+
className: "data",
|
|
63
|
+
format: "0,0.00"
|
|
64
|
+
},
|
|
65
|
+
getIndexContent: function (indexName) {
|
|
66
|
+
// to customize content index on table. For pivot implementation
|
|
67
|
+
return indexName;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
var minColWidth = 50;
|
|
72
|
+
var maxColWidth = 250;
|
|
73
|
+
|
|
74
|
+
var calculateMaxWidths = function(ds) {
|
|
75
|
+
const mc = findMergeCols(ds);
|
|
76
|
+
return ds.data
|
|
77
|
+
.reduce((acc, row, index) => {
|
|
78
|
+
for (let [col, value] of row.entries()) {
|
|
79
|
+
if (value === subtotal) value = "SubTotals";
|
|
80
|
+
value = typeof value === 'number' ? String(value) : value;
|
|
81
|
+
if (
|
|
82
|
+
typeof value !== "undefined" &&
|
|
83
|
+
(!acc[col] || acc[col].len <= value.length) &&
|
|
84
|
+
!(index === ds.totalRows - 1 && col < ds.fixedColumns)
|
|
85
|
+
) {
|
|
86
|
+
acc[col] = { str: value, len: value.length || 0, lastRow: index === ds.totalRows - 1 };
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
return acc;
|
|
90
|
+
}, new Array(ds.totalColumns).fill(null))
|
|
91
|
+
.map((item) => getTdWidth(item))
|
|
92
|
+
.reduce((acc, width, col, arr) => {
|
|
93
|
+
acc[col] = mc[col] ? getMergeColsWidth(arr, col, mc[col]) : width;
|
|
94
|
+
return acc;
|
|
95
|
+
}, {});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
var getTdWidth = function(item) {
|
|
99
|
+
let tdStyles = {
|
|
100
|
+
borderLeft: 'solid 1px',
|
|
101
|
+
borderRight: 'solid 1px',
|
|
102
|
+
fontSize: '11px',
|
|
103
|
+
fontFamily: '"Open Sans",sans-serif',
|
|
104
|
+
fontWeight: item.lastRow && opts.chartOptions.table_options.show_row_total ? '700' : '400',
|
|
105
|
+
paddingRight: '4px',
|
|
106
|
+
paddingLeft: '4px',
|
|
107
|
+
wrap: 'nowrap',
|
|
108
|
+
visibility: 'hidden',
|
|
109
|
+
};
|
|
110
|
+
let td = document.createElement('td');
|
|
111
|
+
for (let [key, value] of _.entries(tdStyles)) {
|
|
112
|
+
td.style[key] = value;
|
|
113
|
+
};
|
|
114
|
+
td.innerHTML = item.str;
|
|
115
|
+
document.body.appendChild(td);
|
|
116
|
+
let width = Math.min(Math.max(td.offsetWidth, minColWidth), maxColWidth);
|
|
117
|
+
document.body.removeChild(td);
|
|
118
|
+
return width;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
var findMergeCols = function(ds) {
|
|
122
|
+
return ds.mergeCells
|
|
123
|
+
.filter(cell => cell.row === ds.fixedRows - 1)
|
|
124
|
+
.reduce((acc, val) => {
|
|
125
|
+
if (!acc[val.col] && val.colspan > 1) acc[val.col] = val.colspan - 1;
|
|
126
|
+
return acc;
|
|
127
|
+
}, {});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
var getMergeColsWidth = function(cw, col, m) {
|
|
131
|
+
let rightColsWidth = 0;
|
|
132
|
+
for (let _col = col + 1; _col <= col + m; _col++) {
|
|
133
|
+
rightColsWidth += cw[_col];
|
|
134
|
+
};
|
|
135
|
+
return rightColsWidth >= cw[col] ? 0 : cw[col] - rightColsWidth;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
opts = $.extend(def, opts, true);
|
|
139
|
+
|
|
140
|
+
var headerRenderer = function (cellProperties) {
|
|
141
|
+
cellProperties.readOnly = true;
|
|
142
|
+
cellProperties.className = opts.header.className;
|
|
143
|
+
};
|
|
144
|
+
var totalRenderer = function (cellProperties) {
|
|
145
|
+
cellProperties.readOnly = opts.showTotals;
|
|
146
|
+
cellProperties.format = opts.total.format;
|
|
147
|
+
cellProperties.className = opts.total.className;
|
|
148
|
+
};
|
|
149
|
+
var subTotalRenderer = function (cellProperties) {
|
|
150
|
+
cellProperties.readOnly = true;
|
|
151
|
+
cellProperties.format = opts.subTotal.format;
|
|
152
|
+
cellProperties.className = opts.subTotal.className;
|
|
153
|
+
};
|
|
154
|
+
var dataRenderer = function (cellProperties) {
|
|
155
|
+
cellProperties.readOnly = opts.readOnly;
|
|
156
|
+
cellProperties.className = opts.data.className;
|
|
157
|
+
cellProperties.format = opts.data.format;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// get changes on pivot table
|
|
161
|
+
var getPivotChange = function (change, pvtData, dataSource) {
|
|
162
|
+
var rowIdx = change[0] - dataSource.fixedRows;
|
|
163
|
+
var colIdx = change[1] - dataSource.fixedColumns;
|
|
164
|
+
var dataFilter = {
|
|
165
|
+
filterList: [],
|
|
166
|
+
oldValue: change[2],
|
|
167
|
+
newValue: change[3]
|
|
168
|
+
};
|
|
169
|
+
if (colIdx >= 0) {
|
|
170
|
+
var colKeys = pvtData.getColKeys();
|
|
171
|
+
for (var cAttrIdx = 0; cAttrIdx < pvtData.colAttrs.length; cAttrIdx++) {
|
|
172
|
+
if (colIdx < colKeys.length) {
|
|
173
|
+
var cValues = colKeys[colIdx];
|
|
174
|
+
dataFilter.filterList.push({
|
|
175
|
+
Key: pvtData.colAttrs[cAttrIdx],
|
|
176
|
+
Value: cValues[cAttrIdx]
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (rowIdx >= 0) {
|
|
182
|
+
var rowKeys = pvtData.getRowKeys();
|
|
183
|
+
for (var rAttrIdx = 0; rAttrIdx < pvtData.rowAttrs.length; rAttrIdx++) {
|
|
184
|
+
if (rowIdx < rowKeys.length) {
|
|
185
|
+
var rValues = rowKeys[rowIdx];
|
|
186
|
+
dataFilter.filterList.push({
|
|
187
|
+
Key: pvtData.rowAttrs[rAttrIdx],
|
|
188
|
+
Value: rValues[rAttrIdx]
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return dataFilter;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Parse the pvtData and create datasource to handsontable
|
|
197
|
+
var parsePivotData = function (pvtData) {
|
|
198
|
+
var dataSource = {
|
|
199
|
+
data: [],
|
|
200
|
+
columns: [],
|
|
201
|
+
fixedColumns: 0,
|
|
202
|
+
fixedRows: 0,
|
|
203
|
+
mergeCells: [],
|
|
204
|
+
totalColumns: 0,
|
|
205
|
+
totalRows: 0,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// add rows subtotals
|
|
209
|
+
var addRowSubTotals = function (pvtData) {
|
|
210
|
+
|
|
211
|
+
const tmpNewRows = [];
|
|
212
|
+
const newRowsKeys = [];
|
|
213
|
+
for (let i = 1; i < pvtData.rowAttrs.length; i++) {
|
|
214
|
+
for (let rowKeyArr of pvtData.rowKeys) {
|
|
215
|
+
|
|
216
|
+
let tmpRowKeyArr = rowKeyArr.slice(0, i);
|
|
217
|
+
let tmpRowKey = tmpRowKeyArr.join(delim);
|
|
218
|
+
|
|
219
|
+
let newKeyArr = tmpRowKeyArr.concat(subtotal);
|
|
220
|
+
let newKey = newKeyArr.join(delim);
|
|
221
|
+
|
|
222
|
+
if (!pvtData.rowTotals[newKey]) {
|
|
223
|
+
pvtData.rowTotals[newKey] = pvtData.rowTotals[tmpRowKey];
|
|
224
|
+
newRowsKeys.push(newKeyArr);
|
|
225
|
+
|
|
226
|
+
pvtData.tree[newKey] = {};
|
|
227
|
+
for (let colKeyArr of pvtData.colKeys) {
|
|
228
|
+
let colKey = colKeyArr.join(delim);
|
|
229
|
+
if (pvtData.tree[tmpRowKey][colKey]) {
|
|
230
|
+
pvtData.tree[newKey][colKey] = pvtData.tree[tmpRowKey][colKey];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (let j = 1; j < pvtData.colAttrs.length; j++) {
|
|
234
|
+
let tmpColKeyArr = colKeyArr.slice(0, j);
|
|
235
|
+
let tmpColKeyStr = tmpColKeyArr.join(delim);
|
|
236
|
+
|
|
237
|
+
let grandSubTotal = pvtData.tree[tmpRowKey][tmpColKeyStr];
|
|
238
|
+
pvtData.tree[newKey][tmpColKeyStr + delim + subtotal] = grandSubTotal;
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
pvtData.rowKeys = pvtData.rowKeys.concat(newRowsKeys);
|
|
246
|
+
return pvtData;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// add cols subtotals
|
|
250
|
+
var addColSubTotals = function (pvtData) {
|
|
251
|
+
// console.log("handson col data", pvtData);
|
|
252
|
+
const tmpNewColumns = [];
|
|
253
|
+
const newColumnKeys = [];
|
|
254
|
+
for (let i = 1; i < pvtData.colAttrs.length; i++) {
|
|
255
|
+
for (let colKeyArr of pvtData.colKeys) {
|
|
256
|
+
|
|
257
|
+
let tmpColKeyArr = colKeyArr.slice(0, i);
|
|
258
|
+
let tmpColKey = tmpColKeyArr.join(delim);
|
|
259
|
+
|
|
260
|
+
let newKeyArr = tmpColKeyArr.concat(subtotal);
|
|
261
|
+
let newKey = newKeyArr.join(delim);
|
|
262
|
+
|
|
263
|
+
if (!pvtData.colTotals[newKey]) {
|
|
264
|
+
pvtData.colTotals[newKey] = pvtData.colTotals[tmpColKey];
|
|
265
|
+
newColumnKeys.push(newKeyArr);
|
|
266
|
+
|
|
267
|
+
for (let rowKeyArr of pvtData.rowKeys) {
|
|
268
|
+
let rowKey = rowKeyArr.join(delim);
|
|
269
|
+
if (pvtData.tree[rowKey][tmpColKey]) {
|
|
270
|
+
pvtData.tree[rowKey][newKey] = pvtData.tree[rowKey][tmpColKey];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
pvtData.colKeys = pvtData.colKeys.concat(newColumnKeys);
|
|
277
|
+
// console.log("handson data2", pvtData);
|
|
278
|
+
return pvtData;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
if (opts.chartOptions.table_options.show_subtotals_for_rows) {
|
|
282
|
+
pvtData = addRowSubTotals(pvtData);
|
|
283
|
+
}
|
|
284
|
+
if (opts.chartOptions.table_options.show_subtotals_for_columns) {
|
|
285
|
+
pvtData = addColSubTotals(pvtData);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
var colKeys = pvtData.getColKeys();
|
|
290
|
+
var rowKeys = pvtData.getRowKeys();
|
|
291
|
+
var hasColumnAttr = (pvtData.colAttrs.length > 0 ? true : false);
|
|
292
|
+
var hasRowAttr = (pvtData.rowAttrs.length > 0 ? true : false);
|
|
293
|
+
|
|
294
|
+
var addMergeCell = function (row, col, rows, columns, noHAlign, noVAlign) {
|
|
295
|
+
dataSource.mergeCells.push({
|
|
296
|
+
row: row,
|
|
297
|
+
col: col,
|
|
298
|
+
rowspan: rows,
|
|
299
|
+
colspan: columns
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
//fixed columns and rows
|
|
304
|
+
dataSource.fixedColumns = pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0);
|
|
305
|
+
dataSource.fixedRows = pvtData.colAttrs.length + (hasRowAttr ? 1 : 0);
|
|
306
|
+
|
|
307
|
+
for (let i = 0; i < pvtData.rowAttrs.length; i++) {
|
|
308
|
+
rowKeys.sort((a,b) => {
|
|
309
|
+
if (_.isEqual(a.slice(0, i), b.slice(0,i)) && a[i] && a[i] === subtotal) return -1;
|
|
310
|
+
if (_.isEqual(a.slice(0, i), b.slice(0,i)) && b[i] && b[i] === subtotal) return 1;
|
|
311
|
+
return 0;
|
|
312
|
+
});
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// for extra rows on edit mode. Where show only one dimension on row o column.
|
|
316
|
+
var extraColumnLabel = "Grand Totals";
|
|
317
|
+
var extraRowLabel = "Grand Totals";
|
|
318
|
+
if (opts.totalFilterElements && opts.totalFilterElements.row_total) {
|
|
319
|
+
extraColumnLabel = opts.totalFilterElements.row_total.innerHTML;
|
|
320
|
+
}
|
|
321
|
+
if (opts.totalFilterElements && opts.totalFilterElements.col_total) {
|
|
322
|
+
extraRowLabel = opts.totalFilterElements.col_total.innerHTML;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
var addExtraColumn = false;
|
|
326
|
+
var addExtraRow = false;
|
|
327
|
+
if (pvtData.colKeys.length == 0) {
|
|
328
|
+
addExtraColumn = true;
|
|
329
|
+
}
|
|
330
|
+
if (pvtData.rowKeys.length == 0) {
|
|
331
|
+
addExtraRow = true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
//columns
|
|
335
|
+
var totalColumns = dataSource.totalColumns = pvtData.colKeys.length + pvtData.rowAttrs.length +
|
|
336
|
+
(pvtData.colAttrs.length > 0 ? 1 : 0) +
|
|
337
|
+
(opts.showTotals || addExtraColumn ? 1 : 0);
|
|
338
|
+
|
|
339
|
+
if (!opts.chartOptions.table_options.show_column_total) {
|
|
340
|
+
totalColumns--;
|
|
341
|
+
}
|
|
342
|
+
for (var cc = 0; cc < totalColumns; cc++) {
|
|
343
|
+
|
|
344
|
+
if (cc < dataSource.fixedColumns) {
|
|
345
|
+
dataSource.columns.push({
|
|
346
|
+
type: 'text',
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
dataSource.columns.push({
|
|
351
|
+
type: 'text',
|
|
352
|
+
editor: Handsontable.editors.GenericEditor
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
//first merge cells
|
|
358
|
+
if (hasRowAttr && hasColumnAttr) {
|
|
359
|
+
addMergeCell(0, 0, hasColumnAttr ? pvtData.colAttrs.length : 1, (hasRowAttr ? pvtData.rowAttrs.length : 1));
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ##
|
|
363
|
+
// HEADERS (columns)
|
|
364
|
+
for (var nn = 0; nn < pvtData.colAttrs.length + (hasRowAttr ? 1 : 0) ; nn++) {
|
|
365
|
+
var rowData = [];
|
|
366
|
+
|
|
367
|
+
// rows with dimensions on columns
|
|
368
|
+
if (nn < pvtData.colAttrs.length) {
|
|
369
|
+
|
|
370
|
+
// columns for row attrs
|
|
371
|
+
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
372
|
+
rowData.push("");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
//column for colum attr,
|
|
376
|
+
rowData.push(opts.getIndexContent(pvtData.colAttrs[nn]));
|
|
377
|
+
|
|
378
|
+
//data columns
|
|
379
|
+
if (pvtData.colKeys.length > 0) {
|
|
380
|
+
|
|
381
|
+
var aux = rowData.length;
|
|
382
|
+
var startCol = aux;
|
|
383
|
+
var prior = colKeys[0][nn];
|
|
384
|
+
var toMerge = 0;
|
|
385
|
+
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
386
|
+
|
|
387
|
+
var textHeader = colKeys[cc][nn];
|
|
388
|
+
|
|
389
|
+
if (nn < pvtData.colAttrs.length - 1 && prior != textHeader) {
|
|
390
|
+
rowData.push(textHeader);
|
|
391
|
+
prior = textHeader;
|
|
392
|
+
// merge cell
|
|
393
|
+
addMergeCell(nn, aux, 1, toMerge);
|
|
394
|
+
aux = aux + toMerge;
|
|
395
|
+
toMerge = 1;
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
toMerge++;
|
|
399
|
+
rowData.push(textHeader);
|
|
400
|
+
|
|
401
|
+
// vertical merge on last row of header columns. Disabled for performance analysis
|
|
402
|
+
//if (nn == pvtData.colAttrs.length - 1 && hasRowAttr) {
|
|
403
|
+
//addMergeCell(nn,startCol+cc ,2,1);
|
|
404
|
+
//}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
//merge last cell
|
|
409
|
+
if (nn < pvtData.colAttrs.length - 1) {
|
|
410
|
+
addMergeCell(nn, aux, 1, toMerge);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// total column
|
|
416
|
+
if (opts.showTotals || addExtraColumn) {
|
|
417
|
+
rowData.push(extraColumnLabel);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else { // rows with dimensions on columns
|
|
421
|
+
|
|
422
|
+
// columns for row attrs
|
|
423
|
+
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
424
|
+
|
|
425
|
+
rowData.push(opts.getIndexContent(pvtData.rowAttrs[cc]));
|
|
426
|
+
//merge cell
|
|
427
|
+
if (cc == pvtData.rowAttrs.length - 1 && hasColumnAttr) {
|
|
428
|
+
addMergeCell(nn, cc, 1, 2);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
//empty column for colum attr,
|
|
434
|
+
if (hasColumnAttr > 0) {
|
|
435
|
+
rowData.push("");
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
//data columns (empty)
|
|
439
|
+
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
440
|
+
rowData.push("");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// total column
|
|
444
|
+
if (opts.showTotals || addExtraColumn) {
|
|
445
|
+
rowData.push(extraColumnLabel);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
dataSource.data.push(rowData);
|
|
451
|
+
}
|
|
452
|
+
// END HEADER
|
|
453
|
+
// ######
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
// ######
|
|
458
|
+
// DATA
|
|
459
|
+
|
|
460
|
+
var mergeDic = {};
|
|
461
|
+
|
|
462
|
+
for (var rr = 0; rr < rowKeys.length; rr++) {
|
|
463
|
+
|
|
464
|
+
var rowData = [];
|
|
465
|
+
|
|
466
|
+
if (rr == 0) {
|
|
467
|
+
for (var cc = 0; cc < dataSource.fixedColumns; cc++) {
|
|
468
|
+
mergeDic[cc] = {
|
|
469
|
+
toMerge: 1,
|
|
470
|
+
row: 0,
|
|
471
|
+
priorText: rowKeys[rr][cc]
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
//column for row atts
|
|
477
|
+
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
478
|
+
rowData.push(rowKeys[rr][cc]);
|
|
479
|
+
if (rowKeys[rr][cc] === subtotal) {
|
|
480
|
+
addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, dataSource.fixedColumns - cc, true, true);
|
|
481
|
+
} else if (cc === rowKeys[rr].length - 1 && hasColumnAttr) {
|
|
482
|
+
addMergeCell(rr + pvtData.colAttrs.length + 1, cc, 1, 2, true, true);
|
|
483
|
+
}
|
|
484
|
+
// merge cell (last column)
|
|
485
|
+
if (opts.chartOptions.table_options.show_column_total && rr != 0 && mergeDic[cc]) { // check for merge dic
|
|
486
|
+
if (rowKeys[rr][cc] == mergeDic[cc].priorText) {
|
|
487
|
+
mergeDic[cc].toMerge++;
|
|
488
|
+
} else if (cc < rowKeys[rr].length - 1) {
|
|
489
|
+
//create merge cell for this column
|
|
490
|
+
addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
|
|
491
|
+
mergeDic[cc].row = rr;
|
|
492
|
+
mergeDic[cc].toMerge = 1;
|
|
493
|
+
mergeDic[cc].priorText = rowKeys[rr][cc];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// empty column (for colum atts)
|
|
499
|
+
if (hasColumnAttr) {
|
|
500
|
+
rowData.push("");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// columns data
|
|
504
|
+
var agg;
|
|
505
|
+
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
506
|
+
agg = pvtData.getAggregator(rowKeys[rr], colKeys[cc])
|
|
507
|
+
|
|
508
|
+
var cellValue = $.pivotUtilities.getFormattedNumber(agg.value(), agg, opts);
|
|
509
|
+
// var cellValue = agg.value();
|
|
510
|
+
|
|
511
|
+
if (cellValue) {
|
|
512
|
+
rowData.push(cellValue);
|
|
513
|
+
}
|
|
514
|
+
else if (cellValue === 0) {
|
|
515
|
+
rowData.push("0");
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
rowData.push("");
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// column total
|
|
524
|
+
if (opts.showTotals || addExtraColumn) {
|
|
525
|
+
// var rowKeyAtt = rowKeys[rr].join(String.fromCharCode(0));
|
|
526
|
+
var rowKeyAtt = rowKeys[rr].join(delim);
|
|
527
|
+
if (pvtData.rowTotals[rowKeyAtt]) {
|
|
528
|
+
let agg = pvtData.getAggregator(rowKeys[rr], []);
|
|
529
|
+
let preValue = pvtData.rowTotals[rowKeyAtt].value();
|
|
530
|
+
let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
|
|
531
|
+
rowData.push(cellValue);
|
|
532
|
+
// rowData.push(pvtData.rowTotals[rowKeyAtt].value());
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
rowData.push("");
|
|
536
|
+
// rowData.push(0);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
dataSource.data.push(rowData);
|
|
541
|
+
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// add last rows merge cells for each column
|
|
545
|
+
if (opts.chartOptions.table_options.show_column_total) {
|
|
546
|
+
|
|
547
|
+
for (var cc = 0; cc < pvtData.rowAttrs.length - 1; cc++) {
|
|
548
|
+
|
|
549
|
+
if (mergeDic[cc] && mergeDic[cc].toMerge > 1) {
|
|
550
|
+
addMergeCell(mergeDic[cc].row + pvtData.colAttrs.length + 1, cc, mergeDic[cc].toMerge, 1);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// END DATA
|
|
556
|
+
// ######
|
|
557
|
+
|
|
558
|
+
// ######
|
|
559
|
+
// TOTAL
|
|
560
|
+
// colums totals area
|
|
561
|
+
if (opts.showTotals || addExtraRow) {
|
|
562
|
+
|
|
563
|
+
var rowData = [];
|
|
564
|
+
|
|
565
|
+
// columns for row attrs
|
|
566
|
+
for (var cc = 0; cc < pvtData.rowAttrs.length; cc++) {
|
|
567
|
+
rowData.push(extraRowLabel);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
//empty column for colum attr,
|
|
571
|
+
if (hasColumnAttr) {
|
|
572
|
+
rowData.push(extraRowLabel);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
//column totals
|
|
577
|
+
if (opts.chartOptions.table_options.show_row_total) {
|
|
578
|
+
for (var cc = 0; cc < colKeys.length; cc++) {
|
|
579
|
+
|
|
580
|
+
var colKeyAtt = colKeys[cc].join(delim);
|
|
581
|
+
if (pvtData.colTotals[colKeyAtt]) {
|
|
582
|
+
let agg = pvtData.getAggregator([], colKeys[cc]);
|
|
583
|
+
let preValue = pvtData.colTotals[colKeyAtt].value();
|
|
584
|
+
let cellValue = $.pivotUtilities.getFormattedNumber(preValue, agg, opts);
|
|
585
|
+
rowData.push(cellValue);
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
rowData.push(0);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
//all total column
|
|
594
|
+
rowData.push($.pivotUtilities.getFormattedNumber(pvtData.allTotal.value(), pvtData.allTotal, opts));
|
|
595
|
+
|
|
596
|
+
// END TOTAL
|
|
597
|
+
// ######
|
|
598
|
+
|
|
599
|
+
if (opts.chartOptions.table_options.show_row_total) {
|
|
600
|
+
|
|
601
|
+
dataSource.data.push(rowData);
|
|
602
|
+
}
|
|
603
|
+
// end total columns
|
|
604
|
+
}
|
|
605
|
+
dataSource.totalRows = dataSource.data.length;
|
|
606
|
+
|
|
607
|
+
if (opts.showTotals || addExtraRow) {
|
|
608
|
+
|
|
609
|
+
// columns total merge cell
|
|
610
|
+
if (opts.chartOptions.table_options.show_row_total) {
|
|
611
|
+
if (pvtData.rowAttrs.length > 0) {
|
|
612
|
+
addMergeCell(dataSource.totalRows - 1, 0, 1, pvtData.rowAttrs.length + (hasColumnAttr ? 1 : 0));
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (opts.chartOptions.table_options.show_column_total) {
|
|
617
|
+
// rows total merge cell
|
|
618
|
+
if (pvtData.colAttrs.length > 0) {
|
|
619
|
+
addMergeCell(0, totalColumns - 1, pvtData.colAttrs.length + (hasRowAttr ? 1 : 0), 1);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return dataSource;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// render the table
|
|
627
|
+
var renderTable = function (pvtData, opts) {
|
|
628
|
+
var dataSource = parsePivotData(pvtData);
|
|
629
|
+
|
|
630
|
+
// function to data render
|
|
631
|
+
var genericRenderer = function (instance, td, row, col, prop, value, cellProperties) {
|
|
632
|
+
|
|
633
|
+
var newValue = '' + value;
|
|
634
|
+
td.innerHTML = opts.labelsConvertFunction(newValue);
|
|
635
|
+
|
|
636
|
+
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
637
|
+
// header
|
|
638
|
+
td.className = opts.header.className;
|
|
639
|
+
|
|
640
|
+
if (opts.chartOptions.table_options.colorize_headers == true && opts.defaults_colors) {
|
|
641
|
+
let color_to_set;
|
|
642
|
+
if (row < dataSource.fixedRows) {
|
|
643
|
+
if (row < 1) {
|
|
644
|
+
color_to_set = opts.defaults_colors[row];
|
|
645
|
+
} else {
|
|
646
|
+
color_to_set = opts.defaults_colors[1];
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
if (col < dataSource.fixedColumns) {
|
|
650
|
+
td.className = opts.header.className + " sideHeader";
|
|
651
|
+
if (row < dataSource.fixedRows) {
|
|
652
|
+
color_to_set = opts.defaults_colors[row];
|
|
653
|
+
} else {
|
|
654
|
+
// color_to_set = "#fff";
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if(color_to_set){
|
|
659
|
+
td.style.setProperty("background-color", color_to_set, "important");
|
|
660
|
+
// td.style.setProperty("border-color", color_to_set, "important");
|
|
661
|
+
td.style.color = "#FFFFFF";
|
|
662
|
+
// td.style.fontWeight = "bold";
|
|
663
|
+
} else {
|
|
664
|
+
td.style.setProperty("background-color", "#fff", "important");
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
else if (col < dataSource.fixedColumns) {
|
|
670
|
+
if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
|
|
671
|
+
(dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
|
|
672
|
+
td.className = opts.subTotal.className;
|
|
673
|
+
} else if (dataSource.data[row] && dataSource.data[row].indexOf(subtotal) !== -1 &&
|
|
674
|
+
dataSource.data[row].indexOf(subtotal) < 3) {
|
|
675
|
+
td.className = opts.subTotal.className;
|
|
676
|
+
}
|
|
677
|
+
if (newValue === subtotal) {
|
|
678
|
+
td.innerHTML = replaceValue;
|
|
679
|
+
} else if (opts.chartOptions.table_options.remove_underscores == true) {
|
|
680
|
+
td.innerHTML = newValue.replace("_", " ");
|
|
681
|
+
}
|
|
682
|
+
} else if (opts.chartOptions.table_options.show_row_total && opts.showTotals && row == dataSource.totalRows - 1) {
|
|
683
|
+
//total row
|
|
684
|
+
td.className = opts.total.className;
|
|
685
|
+
} else if (opts.chartOptions.table_options.show_column_total && opts.showTotals && col == dataSource.totalColumns - 1) {
|
|
686
|
+
//total col
|
|
687
|
+
td.className = opts.total.className;
|
|
688
|
+
} else if (dataSource.data[row] && dataSource.data[row].includes(subtotal)) {
|
|
689
|
+
//subTotal row class
|
|
690
|
+
td.className = opts.subTotal.className;
|
|
691
|
+
} else if ((dataSource.data[0] && dataSource.data[0][col] == subtotal) ||
|
|
692
|
+
(dataSource.data[1] && dataSource.data[1][col] == subtotal)) {
|
|
693
|
+
//subTotal col class
|
|
694
|
+
td.className = opts.subTotal.className;
|
|
695
|
+
} else {
|
|
696
|
+
//data
|
|
697
|
+
td.className = opts.data.className;
|
|
698
|
+
}
|
|
699
|
+
td.className += " __" + row + "," + col + "__";
|
|
700
|
+
|
|
701
|
+
if (opts.chartOptions.table_options.colorize_headers == true) {
|
|
702
|
+
td.className += " colorized";
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
if (opts.chartOptions.table_options.show_row_total && row == dataSource.totalRows-1) {
|
|
706
|
+
td.className += " withTopBorder";
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
if (td.innerHTML === subtotal) {
|
|
710
|
+
td.innerHTML = replaceValue;
|
|
711
|
+
}
|
|
712
|
+
if (td.innerHTML === "undefined") {
|
|
713
|
+
td.innerHTML = "";
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
if (opts.chartOptions.table_options.hide_nulls_in_headers && td.innerHTML === '[null]') {
|
|
717
|
+
td.innerHTML = '';
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (opts.chartOptions.table_options.styles) {
|
|
721
|
+
for (let rule of opts.chartOptions.table_options.styles) {
|
|
722
|
+
|
|
723
|
+
if (!rule.styles || rule.styles.length === 0) {
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (rule.row && rule.col) {
|
|
728
|
+
if (row === parseInt(rule.row) && col === parseInt(rule.col)) {
|
|
729
|
+
for (let style of rule.styles) {
|
|
730
|
+
td.style.setProperty(style.name, style.val, "important");
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
} else if (rule.row && row !== 0 && col !== 0) {
|
|
734
|
+
if (rule.repeat) {
|
|
735
|
+
const offset = rule.offset || 0;
|
|
736
|
+
if (row > offset && (row - offset) % rule.row === 0) {
|
|
737
|
+
for (let style of rule.styles) {
|
|
738
|
+
td.style.setProperty(style.name, style.val, "important");
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
} else if (row === parseInt(rule.row)) {
|
|
742
|
+
for (let style of rule.styles) {
|
|
743
|
+
td.style.setProperty(style.name, style.val, "important");
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
} else if (rule.col && col !== 0 && row !== 0) {
|
|
747
|
+
if (rule.repeat) {
|
|
748
|
+
const offset = rule.offset || 0;
|
|
749
|
+
if (col > offset && (col - offset) % rule.col === 0) {
|
|
750
|
+
for (let style of rule.styles) {
|
|
751
|
+
td.style.setProperty(style.name, style.val, "important");
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
} else if (col === parseInt(rule.col)) {
|
|
755
|
+
for (let style of rule.styles) {
|
|
756
|
+
td.style.setProperty(style.name, style.val, "important");
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return td;
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
var _this = this;
|
|
766
|
+
if (table) {
|
|
767
|
+
table.destroy();
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
var contextMenu = null;
|
|
771
|
+
|
|
772
|
+
if(opts.value_drill_down_fn){
|
|
773
|
+
let calBackFn = function(key, selection, clickEvent) {
|
|
774
|
+
let row = selection[0].start.row;
|
|
775
|
+
let col = selection[0].start.col;
|
|
776
|
+
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
else{
|
|
780
|
+
let cols = [];
|
|
781
|
+
let rows = [];
|
|
782
|
+
|
|
783
|
+
for(let i=0; i< pvtData.rowAttrs.length; i++){
|
|
784
|
+
rows.push(dataSource.data[row][i]);
|
|
785
|
+
}
|
|
786
|
+
for(let i=0; i< pvtData.colAttrs.length; i++){
|
|
787
|
+
cols.push(dataSource.data[i][col]);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (opts.showTotals && row == dataSource.totalRows - 1) {
|
|
791
|
+
rows = [];
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (opts.showTotals && col == dataSource.totalColumns - 1) {
|
|
795
|
+
cols = [];
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
opts.value_drill_down_fn(clickEvent, rows, cols, key);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
let disableFn = function () {
|
|
803
|
+
let selection = this.getSelectedLast();
|
|
804
|
+
if (selection[0] < dataSource.fixedRows || selection[1] < dataSource.fixedColumns) {
|
|
805
|
+
return true;
|
|
806
|
+
}
|
|
807
|
+
return false;
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
contextMenu = {
|
|
811
|
+
items: {
|
|
812
|
+
"open_drill_down_view": {
|
|
813
|
+
name: 'Open drill down view',
|
|
814
|
+
callback: calBackFn,
|
|
815
|
+
disabled: disableFn
|
|
816
|
+
},
|
|
817
|
+
"export_drill_down": {
|
|
818
|
+
name: 'Export drill down to excel',
|
|
819
|
+
callback: calBackFn,
|
|
820
|
+
disabled: disableFn
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
var $tableArea = opts.$el.find(".widget-id-" + opts.widgetId);
|
|
827
|
+
$tableArea.empty();
|
|
828
|
+
console.log('Handsontable data', dataSource);
|
|
829
|
+
var maxWidths = calculateMaxWidths(dataSource);
|
|
830
|
+
table = new Handsontable($tableArea.get(0), {
|
|
831
|
+
licenseKey: 'b0eda-7220b-32d15-e4128-c2f4c', //98463-b132b-fcea0-24f22-da020
|
|
832
|
+
data: dataSource.data,
|
|
833
|
+
contextMenu: contextMenu,
|
|
834
|
+
selectionMode: "single",
|
|
835
|
+
colHeaders: false,
|
|
836
|
+
allowInsertColumn: false,
|
|
837
|
+
allowInsertRow: false,
|
|
838
|
+
columns: dataSource.columns,
|
|
839
|
+
fixedColumnsLeft: dataSource.fixedColumns,
|
|
840
|
+
fixedRowsTop: dataSource.fixedRows,
|
|
841
|
+
mergeCells: dataSource.mergeCells,
|
|
842
|
+
colWidths: function(index) {
|
|
843
|
+
return maxWidths[index];
|
|
844
|
+
},
|
|
845
|
+
cells: function (row, col, prop) {
|
|
846
|
+
var cellProperties = {};
|
|
847
|
+
cellProperties.renderer = genericRenderer;
|
|
848
|
+
if (row < dataSource.fixedRows || col < dataSource.fixedColumns) {
|
|
849
|
+
headerRenderer(cellProperties);
|
|
850
|
+
} else {
|
|
851
|
+
if (opts.showTotals && (row == dataSource.totalRows - 1 || col == dataSource.totalColumns - 1)) {
|
|
852
|
+
totalRenderer(cellProperties);
|
|
853
|
+
} else {
|
|
854
|
+
dataRenderer(cellProperties);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
return cellProperties;
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
setTimeout(function () {
|
|
862
|
+
|
|
863
|
+
var currentState = opts.$el.data("currentState");
|
|
864
|
+
|
|
865
|
+
if (currentState) {
|
|
866
|
+
if (currentState && currentState.lastRowChanged) {
|
|
867
|
+
table.selectCell(currentState.lastRowChanged + 1, currentState.lasColChanged, currentState.lastRowChanged + 1, currentState.lasColChanged);
|
|
868
|
+
currentState.lastRowChanged = null;
|
|
869
|
+
if (currentState.scrollX && currentState.scrollX > 0) {
|
|
870
|
+
opts.$el.scrollLeft(currentState.scrollX);
|
|
871
|
+
}
|
|
872
|
+
if (currentState.scrollY && currentState.scrollY > 0) {
|
|
873
|
+
opts.$el.scrollTop(currentState.scrollY);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
currentState = null;
|
|
877
|
+
opts.$el.data("currentState", null);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
}, 5);
|
|
882
|
+
return false;
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
var _this = this;
|
|
886
|
+
setTimeout(function () {
|
|
887
|
+
renderTable(pvtData, opts);
|
|
888
|
+
}, 10);
|
|
889
|
+
|
|
890
|
+
// inject the widgetId to the class name so we can separate the tables by it
|
|
891
|
+
// look for the search side on line 653 "opts.$el.find(".widget-id-" + opts.widgetId);"
|
|
892
|
+
return `<div class='novixPivot widget-id-${opts.widgetId} ${
|
|
893
|
+
useNewUx && opts.chartOptions.table_options.use_new_table_design ? 'handsontable-new' : ''
|
|
894
|
+
}' style='overflow:auto'></div>`;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
module.exports = initNovixRenderer;
|