@datarailsshared/dr_renderer 1.1.40 → 1.2.1

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