jsl-ui 9.28.2 → 9.28.3

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.
Files changed (170) hide show
  1. package/lib/components/IntervalComponent.d.ts +17 -17
  2. package/lib/components/IntervalComponent.js +65 -68
  3. package/lib/components/auto-suggest/AutoSuggestComponent.d.ts +22 -22
  4. package/lib/components/auto-suggest/AutoSuggestComponent.js +47 -49
  5. package/lib/components/button/ButtonComponent.d.ts +18 -18
  6. package/lib/components/button/ButtonComponent.js +29 -46
  7. package/lib/components/checkbox/CheckBoxComponent.d.ts +28 -28
  8. package/lib/components/checkbox/CheckBoxComponent.js +81 -98
  9. package/lib/components/date/DateComponent.d.ts +32 -32
  10. package/lib/components/date/DateComponent.js +89 -106
  11. package/lib/components/date-range/DateRangeComponent.d.ts +35 -35
  12. package/lib/components/date-range/DateRangeComponent.js +123 -136
  13. package/lib/components/date-time/DateTimeComponent.d.ts +15 -15
  14. package/lib/components/date-time/DateTimeComponent.js +39 -53
  15. package/lib/components/dialog/DialogComponent.d.ts +67 -67
  16. package/lib/components/dialog/DialogComponent.js +198 -251
  17. package/lib/components/drop-down/DropDownComponent.d.ts +27 -27
  18. package/lib/components/drop-down/DropDownComponent.js +60 -74
  19. package/lib/components/expander/ExpanderComponent.d.ts +27 -27
  20. package/lib/components/expander/ExpanderComponent.js +89 -90
  21. package/lib/components/form-field/FormComponent.d.ts +12 -12
  22. package/lib/components/form-field/FormComponent.js +23 -26
  23. package/lib/components/form-field/FormFieldComponent.d.ts +39 -39
  24. package/lib/components/form-field/FormFieldComponent.js +138 -140
  25. package/lib/components/grid/GridComponent.d.ts +26 -26
  26. package/lib/components/grid/GridComponent.js +110 -116
  27. package/lib/components/input/InputComponent.d.ts +33 -33
  28. package/lib/components/input/InputComponent.js +126 -147
  29. package/lib/components/loading/LoadingComponent.d.ts +8 -8
  30. package/lib/components/loading/LoadingComponent.js +20 -22
  31. package/lib/components/navigation/NavigationComponent.d.ts +34 -34
  32. package/lib/components/navigation/NavigationComponent.js +45 -70
  33. package/lib/components/notification/Notification.d.ts +19 -19
  34. package/lib/components/notification/Notification.js +65 -69
  35. package/lib/components/number/NumberComponent.d.ts +26 -26
  36. package/lib/components/number/NumberComponent.js +80 -98
  37. package/lib/components/overlay/OverlayComponent.d.ts +27 -27
  38. package/lib/components/overlay/OverlayComponent.js +137 -149
  39. package/lib/components/progress/ProgressComponent.d.ts +18 -18
  40. package/lib/components/progress/ProgressComponent.js +40 -42
  41. package/lib/components/ribbon-menu/RibbonMenuComponent.d.ts +12 -12
  42. package/lib/components/ribbon-menu/RibbonMenuComponent.js +23 -34
  43. package/lib/components/select/SelectComponent.d.ts +79 -79
  44. package/lib/components/select/SelectComponent.js +356 -369
  45. package/lib/components/select/SelectDDAreaComponent.d.ts +32 -32
  46. package/lib/components/select/SelectDDAreaComponent.js +303 -317
  47. package/lib/components/slider/nouislider.d.ts +44 -44
  48. package/lib/components/slider/nouislider.js +2158 -2158
  49. package/lib/components/stack-panel/SplitterComponent.d.ts +21 -21
  50. package/lib/components/stack-panel/SplitterComponent.js +124 -126
  51. package/lib/components/stack-panel/StackPanelComponent.d.ts +20 -20
  52. package/lib/components/stack-panel/StackPanelComponent.js +50 -64
  53. package/lib/components/tabs/TabsComponent.d.ts +40 -40
  54. package/lib/components/tabs/TabsComponent.js +200 -204
  55. package/lib/components/time/TimeComponent.d.ts +29 -29
  56. package/lib/components/time/TimeComponent.js +104 -113
  57. package/lib/components/tree-view/TreeViewComponent.d.ts +23 -23
  58. package/lib/components/tree-view/TreeViewComponent.js +43 -45
  59. package/lib/components/virtual-render/VirtualRenderComponent.d.ts +30 -30
  60. package/lib/components/virtual-render/VirtualRenderComponent.js +92 -104
  61. package/lib/core/culture.d.ts +5 -5
  62. package/lib/core/culture.js +385 -385
  63. package/lib/core/date.d.ts +14 -14
  64. package/lib/core/date.js +346 -350
  65. package/lib/core/helper.d.ts +13 -13
  66. package/lib/core/helper.js +100 -104
  67. package/lib/core/jq.d.ts +37 -37
  68. package/lib/core/jq.js +362 -371
  69. package/lib/core/lang.d.ts +24 -24
  70. package/lib/core/lang.js +24 -28
  71. package/lib/core/numeric.d.ts +7 -7
  72. package/lib/core/numeric.js +139 -143
  73. package/lib/core/polyfills.js +22 -22
  74. package/lib/core.d.ts +6 -6
  75. package/lib/core.js +6 -6
  76. package/lib/grid/filterDialogs/dateRangeFilter.d.ts +7 -7
  77. package/lib/grid/filterDialogs/dateRangeFilter.js +106 -156
  78. package/lib/grid/filterDialogs/excelFilter.d.ts +9 -9
  79. package/lib/grid/filterDialogs/excelFilter.js +250 -316
  80. package/lib/grid/plugins/ext.overlay.d.ts +2 -2
  81. package/lib/grid/plugins/ext.overlay.js +295 -295
  82. package/lib/grid/plugins/slick.cellrangedecorator.d.ts +12 -12
  83. package/lib/grid/plugins/slick.cellrangedecorator.js +68 -68
  84. package/lib/grid/plugins/slick.cellrangeselector.d.ts +1 -1
  85. package/lib/grid/plugins/slick.cellrangeselector.js +144 -144
  86. package/lib/grid/plugins/slick.cellselectionmodel.d.ts +1 -1
  87. package/lib/grid/plugins/slick.cellselectionmodel.js +194 -194
  88. package/lib/grid/plugins/slick.headerbuttons.d.ts +55 -55
  89. package/lib/grid/plugins/slick.headerbuttons.js +156 -156
  90. package/lib/grid/plugins/slick.headermenu.d.ts +74 -74
  91. package/lib/grid/plugins/slick.headermenu.js +260 -260
  92. package/lib/grid/plugins/slick.rowmovemanager.d.ts +18 -18
  93. package/lib/grid/plugins/slick.rowmovemanager.js +249 -249
  94. package/lib/grid/plugins/slick.rowselectionmodel.d.ts +1 -1
  95. package/lib/grid/plugins/slick.rowselectionmodel.js +167 -167
  96. package/lib/grid/slick.core.d.ts +91 -91
  97. package/lib/grid/slick.core.js +574 -574
  98. package/lib/grid/slick.creator.d.ts +81 -81
  99. package/lib/grid/slick.creator.js +726 -726
  100. package/lib/grid/slick.dataview.d.ts +71 -71
  101. package/lib/grid/slick.dataview.js +1069 -1080
  102. package/lib/grid/slick.editors.core.d.ts +4 -4
  103. package/lib/grid/slick.editors.core.js +235 -235
  104. package/lib/grid/slick.editors.date.d.ts +2 -2
  105. package/lib/grid/slick.editors.date.js +125 -125
  106. package/lib/grid/slick.editors.lookup.d.ts +14 -14
  107. package/lib/grid/slick.editors.lookup.js +352 -353
  108. package/lib/grid/slick.editors.nav.d.ts +6 -6
  109. package/lib/grid/slick.editors.nav.js +22 -22
  110. package/lib/grid/slick.formatters.d.ts +17 -17
  111. package/lib/grid/slick.formatters.js +144 -144
  112. package/lib/grid/slick.grid.d.ts +285 -285
  113. package/lib/grid/slick.grid.js +5409 -5412
  114. package/lib/grid/slick.groupitemmetadataprovider.d.ts +39 -39
  115. package/lib/grid/slick.groupitemmetadataprovider.js +165 -165
  116. package/lib/grid/slick.tree.d.ts +33 -33
  117. package/lib/grid/slick.tree.js +208 -220
  118. package/lib/grid.css +1 -705
  119. package/lib/grid.d.ts +13 -13
  120. package/lib/grid.js +13 -13
  121. package/lib/index.css +8 -2195
  122. package/lib/index.css.map +1 -1
  123. package/lib/index.d.ts +56 -55
  124. package/lib/index.js +61 -61
  125. package/lib/index.js.map +1 -1
  126. package/lib/interaction/dataconverter.d.ts +4 -4
  127. package/lib/interaction/dataconverter.js +0 -1
  128. package/lib/interaction/eventhandler.d.ts +13 -13
  129. package/lib/interaction/eventhandler.js +39 -42
  130. package/lib/interaction/moveable.d.ts +39 -39
  131. package/lib/interaction/moveable.js +160 -174
  132. package/lib/interaction/resizable.d.ts +37 -37
  133. package/lib/interaction/resizable.js +109 -123
  134. package/lib/ui/auto.suggest.d.ts +18 -18
  135. package/lib/ui/auto.suggest.js +244 -259
  136. package/lib/ui/date.picker/date-picker-options.d.ts +11 -11
  137. package/lib/ui/date.picker/date-picker-options.js +76 -76
  138. package/lib/ui/date.picker/lib/date-manip.d.ts +74 -74
  139. package/lib/ui/date.picker/lib/date-manip.js +120 -120
  140. package/lib/ui/date.picker/lib/dom.d.ts +23 -23
  141. package/lib/ui/date.picker/lib/dom.js +28 -28
  142. package/lib/ui/date.picker/lib/emitter.d.ts +13 -13
  143. package/lib/ui/date.picker/lib/emitter.js +49 -49
  144. package/lib/ui/date.picker/lib/fns.d.ts +23 -23
  145. package/lib/ui/date.picker/lib/fns.js +39 -43
  146. package/lib/ui/date.picker/mode/base-mode.d.ts +26 -26
  147. package/lib/ui/date.picker/mode/base-mode.js +248 -248
  148. package/lib/ui/date.picker/mode/dropdown-mode.d.ts +28 -28
  149. package/lib/ui/date.picker/mode/dropdown-mode.js +50 -50
  150. package/lib/ui/date.picker/mode/index.d.ts +28 -28
  151. package/lib/ui/date.picker/mode/index.js +18 -18
  152. package/lib/ui/date.picker/mode/modal-mode.d.ts +25 -25
  153. package/lib/ui/date.picker/mode/modal-mode.js +17 -17
  154. package/lib/ui/date.picker/mode/permanent-mode.d.ts +29 -29
  155. package/lib/ui/date.picker/mode/permanent-mode.js +19 -19
  156. package/lib/ui/date.picker/views/day-picker.d.ts +40 -40
  157. package/lib/ui/date.picker/views/day-picker.js +155 -155
  158. package/lib/ui/date.picker/views/month-picker.d.ts +26 -26
  159. package/lib/ui/date.picker/views/month-picker.js +65 -65
  160. package/lib/ui/date.picker/views/year-picker.d.ts +20 -20
  161. package/lib/ui/date.picker/views/year-picker.js +66 -66
  162. package/lib/ui/date.picker.d.ts +66 -66
  163. package/lib/ui/date.picker.js +32 -32
  164. package/lib/ui/dialog.d.ts +22 -22
  165. package/lib/ui/dialog.js +98 -113
  166. package/lib/ui/drop.down.d.ts +52 -52
  167. package/lib/ui/drop.down.js +2112 -2112
  168. package/lib/ui/number.input.d.ts +13 -13
  169. package/lib/ui/number.input.js +56 -67
  170. package/package.json +1 -1
@@ -1,1080 +1,1069 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- import { jQueryReplacement } from "../core/jq";
13
- import { Slick } from "./slick.core";
14
- var $ = jQueryReplacement;
15
- /***
16
- * A sample Model implementation.
17
- * Provides a filtered view of the underlying data.
18
- *
19
- * Relies on the data item having an "id" property uniquely identifying it.
20
- */
21
- export function DataView(options) {
22
- var self = this;
23
- var defaults = {
24
- groupItemMetadataProvider: null,
25
- inlineFilters: false
26
- };
27
- // private
28
- var idProperty = "id"; // property holding a unique row id
29
- var items = []; // data by index
30
- var rows = []; // data by row
31
- var idxById = {}; // indexes by id
32
- var rowsById = null; // rows by id; lazy-calculated
33
- var filter = null; // filter function
34
- var updated = null; // updated item ids
35
- var suspend = false; // suspends the recalculation
36
- var sortAsc = true;
37
- // var fastSortField;
38
- var sortComparer;
39
- var refreshHints = {};
40
- var prevRefreshHints = {};
41
- var filterArgs;
42
- var filteredItems = [];
43
- // let compiledFilter;
44
- // let compiledFilterWithCaching;
45
- var filterCache = [];
46
- // grouping
47
- var groupingInfoDefaults = {
48
- getter: null,
49
- formatter: null,
50
- comparer: function (a, b) {
51
- return (a.value === b.value ? 0 :
52
- (a.value > b.value ? 1 : -1));
53
- },
54
- predefinedValues: [],
55
- aggregators: [],
56
- aggregateEmpty: false,
57
- aggregateCollapsed: false,
58
- aggregateChildGroups: false,
59
- collapsed: false,
60
- displayTotalsRow: true,
61
- lazyTotalsCalculation: false
62
- };
63
- var groupingInfos = [];
64
- var groups = [];
65
- var toggledGroupsByLevel = [];
66
- var groupingDelimiter = ":|:";
67
- var pagesize = 0;
68
- var pagenum = 0;
69
- var totalRows = 0;
70
- // events
71
- var onRowCountChanged = new Slick.Event();
72
- var onRowsChanged = new Slick.Event();
73
- var onRowsOrCountChanged = new Slick.Event();
74
- var onPagingInfoChanged = new Slick.Event();
75
- options = $.deepExtend({}, defaults, options);
76
- function beginUpdate() {
77
- suspend = true;
78
- }
79
- function endUpdate() {
80
- suspend = false;
81
- refresh();
82
- }
83
- function setRefreshHints(hints) {
84
- refreshHints = hints;
85
- }
86
- function setFilterArgs(args) {
87
- filterArgs = args;
88
- }
89
- function updateIdxById(startingIndex) {
90
- startingIndex = startingIndex || 0;
91
- var id;
92
- for (var i = startingIndex, l = items.length; i < l; i++) {
93
- id = items[i][idProperty];
94
- if (id === undefined) {
95
- // throw new Error("Each data element must implement a unique 'id' property");
96
- throw new Error("Id (" + idProperty + ") of element at index " + i + " was undefined");
97
- }
98
- idxById[id] = i;
99
- }
100
- }
101
- function ensureIdUniqueness() {
102
- var id;
103
- for (var i = 0, l = items.length; i < l; i++) {
104
- id = items[i][idProperty];
105
- if (id === undefined) {
106
- throw new Error("Id (" + idProperty + ") of element at index " + i + " was undefined");
107
- }
108
- else if (idxById[id] !== i) {
109
- throw new Error("Duplicate id (" + idProperty + ") for " + id + " found at index (" + idxById[id] + ", " + i + ")");
110
- }
111
- }
112
- }
113
- function getItems() {
114
- return items;
115
- }
116
- function setItems(data, objectIdProperty) {
117
- if (objectIdProperty !== undefined) {
118
- idProperty = objectIdProperty;
119
- }
120
- items = filteredItems = data;
121
- idxById = {};
122
- updateIdxById();
123
- ensureIdUniqueness();
124
- refresh();
125
- }
126
- function setPagingOptions(args) {
127
- if (args.pageSize != undefined) {
128
- pagesize = args.pageSize;
129
- pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
130
- }
131
- if (args.pageNum != undefined) {
132
- pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
133
- }
134
- onPagingInfoChanged.notify(getPagingInfo(), null, self);
135
- refresh();
136
- }
137
- function getPagingInfo() {
138
- var totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
139
- return { pageSize: pagesize, pageNum: pagenum, totalRows: totalRows, totalPages: totalPages, dataView: self };
140
- }
141
- function sort(comparer, ascending) {
142
- sortAsc = ascending;
143
- sortComparer = comparer;
144
- // fastSortField = null;
145
- if (ascending === false) {
146
- items.reverse();
147
- }
148
- items.sort(comparer);
149
- if (ascending === false) {
150
- items.reverse();
151
- }
152
- idxById = {};
153
- updateIdxById();
154
- refresh();
155
- }
156
- function reSort() {
157
- if (sortComparer) {
158
- sort(sortComparer, sortAsc);
159
- }
160
- }
161
- function getFilteredItems() {
162
- return filteredItems;
163
- }
164
- function getFilter() {
165
- return filter;
166
- }
167
- function setFilter(filterFn) {
168
- filter = filterFn;
169
- // if (options.inlineFilters) {
170
- // compiledFilter = compileFilter();
171
- // compiledFilterWithCaching = compileFilterWithCaching();
172
- // }
173
- refresh();
174
- }
175
- function getGrouping() {
176
- return groupingInfos;
177
- }
178
- function setGrouping(groupingInfo) {
179
- if (!options.groupItemMetadataProvider) {
180
- options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
181
- }
182
- groups = [];
183
- toggledGroupsByLevel = [];
184
- groupingInfo = groupingInfo || [];
185
- groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
186
- for (var i = 0; i < groupingInfos.length; i++) {
187
- var gi = groupingInfos[i] = $.deepExtend({}, groupingInfoDefaults, groupingInfos[i]);
188
- gi.getterIsAFn = typeof gi.getter === "function";
189
- // pre-compile accumulator loops
190
- gi.compiledAccumulators = [];
191
- var idx = gi.aggregators.length;
192
- while (idx--) {
193
- gi.compiledAccumulators[idx] = compileAccumulatorLoop(gi.aggregators[idx]);
194
- }
195
- toggledGroupsByLevel[i] = {};
196
- }
197
- refresh();
198
- }
199
- /**
200
- * @deprecated Please use {@link setGrouping}.
201
- */
202
- function groupBy(valueGetter, valueFormatter, sortComparer) {
203
- if (valueGetter == null) {
204
- setGrouping([]);
205
- return;
206
- }
207
- setGrouping({
208
- getter: valueGetter,
209
- formatter: valueFormatter,
210
- comparer: sortComparer
211
- });
212
- }
213
- /**
214
- * @deprecated Please use {@link setGrouping}.
215
- */
216
- function setAggregators(groupAggregators, includeCollapsed) {
217
- if (!groupingInfos.length) {
218
- throw new Error("At least one grouping must be specified before calling setAggregators().");
219
- }
220
- groupingInfos[0].aggregators = groupAggregators;
221
- groupingInfos[0].aggregateCollapsed = includeCollapsed;
222
- setGrouping(groupingInfos);
223
- }
224
- function getItemByIdx(i) {
225
- return items[i];
226
- }
227
- function getIdxById(id) {
228
- return idxById[id];
229
- }
230
- function getIdxByItem(item) {
231
- return idxById[item[idProperty]];
232
- }
233
- function ensureRowsByIdCache() {
234
- if (!rowsById) {
235
- rowsById = {};
236
- for (var i = 0, l = rows.length; i < l; i++) {
237
- rowsById[rows[i][idProperty]] = i;
238
- }
239
- }
240
- }
241
- function getRowByItem(item) {
242
- ensureRowsByIdCache();
243
- return rowsById[item[idProperty]];
244
- }
245
- function getRowById(id) {
246
- ensureRowsByIdCache();
247
- return rowsById[id];
248
- }
249
- function getItemById(id) {
250
- return items[idxById[id]];
251
- }
252
- function mapItemsToRows(itemArray) {
253
- var rows = [];
254
- ensureRowsByIdCache();
255
- for (var i = 0, l = itemArray.length; i < l; i++) {
256
- var row = rowsById[itemArray[i][idProperty]];
257
- if (row != null) {
258
- rows[rows.length] = row;
259
- }
260
- }
261
- return rows;
262
- }
263
- function mapIdsToRows(idArray) {
264
- var rows = [];
265
- ensureRowsByIdCache();
266
- for (var i = 0, l = idArray.length; i < l; i++) {
267
- var row = rowsById[idArray[i]];
268
- if (row != null) {
269
- rows[rows.length] = row;
270
- }
271
- }
272
- return rows;
273
- }
274
- function mapRowsToIds(rowArray) {
275
- var ids = [];
276
- for (var i = 0, l = rowArray.length; i < l; i++) {
277
- if (rowArray[i] < rows.length) {
278
- ids[ids.length] = rows[rowArray[i]][idProperty];
279
- }
280
- }
281
- return ids;
282
- }
283
- function updateItem(id, item) {
284
- // see also https://github.com/mleibman/SlickGrid/issues/1082
285
- if (idxById[id] === undefined) {
286
- throw new Error("Invalid id");
287
- }
288
- // what if the specified item also has an updated idProperty?
289
- // then we'll have to update the index as well, and possibly the `updated` cache too.
290
- if (id !== item[idProperty]) {
291
- // make sure the new id is unique:
292
- var newId = item[idProperty];
293
- if (newId == null) {
294
- throw new Error("Cannot update item to associate with a null id");
295
- }
296
- if (idxById[newId] !== undefined) {
297
- throw new Error("Cannot update item to associate with a non-unique id");
298
- }
299
- idxById[newId] = idxById[id];
300
- delete idxById[id];
301
- // also update the `updated` hashtable/markercache? Yes, `recalc()` inside `refresh()` needs that one!
302
- if (updated && updated[id]) {
303
- delete updated[id];
304
- }
305
- // also update the row indexes? no need since the `refresh()`, further down, blows away the `rowsById[]` cache!
306
- id = newId;
307
- }
308
- items[idxById[id]] = item;
309
- // also update the rows? no need since the `refresh()`, further down, blows away the `rows[]` cache and recalculates it via `recalc()`!
310
- if (!updated) {
311
- updated = {};
312
- }
313
- updated[id] = true;
314
- refresh();
315
- }
316
- function insertItem(insertBefore, item) {
317
- items.splice(insertBefore, 0, item);
318
- updateIdxById(insertBefore);
319
- refresh();
320
- }
321
- function addItem(item) {
322
- items.push(item);
323
- updateIdxById(items.length - 1);
324
- refresh();
325
- }
326
- function deleteItem(id) {
327
- var idx = idxById[id];
328
- if (idx === undefined) {
329
- throw new Error("Invalid id");
330
- }
331
- delete idxById[id];
332
- items.splice(idx, 1);
333
- updateIdxById(idx);
334
- refresh();
335
- }
336
- function sortedAddItem(item) {
337
- if (!sortComparer) {
338
- throw new Error("sortedAddItem() requires a sort comparer, use sort()");
339
- }
340
- insertItem(sortedIndex(item), item);
341
- }
342
- function sortedUpdateItem(id, item) {
343
- if (idxById[id] === undefined || id !== item[idProperty]) {
344
- throw new Error("Invalid or non-matching id " + idxById[id]);
345
- }
346
- if (!sortComparer) {
347
- throw new Error("sortedUpdateItem() requires a sort comparer, use sort()");
348
- }
349
- var oldItem = getItemById(id);
350
- if (sortComparer(oldItem, item) !== 0) {
351
- // item affects sorting -> must use sorted add
352
- deleteItem(id);
353
- sortedAddItem(item);
354
- }
355
- else { // update does not affect sorting -> regular update works fine
356
- updateItem(id, item);
357
- }
358
- }
359
- function sortedIndex(searchItem) {
360
- var low = 0, high = items.length;
361
- while (low < high) {
362
- var mid = low + high >>> 1;
363
- if (sortComparer(items[mid], searchItem) === -1) {
364
- low = mid + 1;
365
- }
366
- else {
367
- high = mid;
368
- }
369
- }
370
- return low;
371
- }
372
- function getLength() {
373
- return rows.length;
374
- }
375
- function getItem(i) {
376
- var item = rows[i];
377
- // if this is a group row, make sure totals are calculated and update the title
378
- if (item && item.__group && item.totals && !item.totals.initialized) {
379
- var gi = groupingInfos[item.level];
380
- if (!gi.displayTotalsRow) {
381
- calculateTotals(item.totals);
382
- item.title = gi.formatter ? gi.formatter(item) : item.value;
383
- }
384
- }
385
- else if (item && item.__groupTotals && !item.initialized) {
386
- calculateTotals(item);
387
- }
388
- return item;
389
- }
390
- function getItemMetadata(i) {
391
- var item = rows[i];
392
- if (item === undefined) {
393
- return null;
394
- }
395
- // overrides for grouping rows
396
- if (item.__group) {
397
- return options.groupItemMetadataProvider.getGroupRowMetadata(item);
398
- }
399
- // overrides for totals rows
400
- if (item.__groupTotals) {
401
- return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
402
- }
403
- if (item.__height) {
404
- if (item.getItemMetadata != null) {
405
- return __assign({ height: item.__height }, (item.getItemMetadata || {}));
406
- }
407
- return { height: item.__height };
408
- }
409
- return item.getItemMetadata != null ? item.getItemMetadata(i, item) : null;
410
- }
411
- function expandCollapseAllGroups(level, collapse) {
412
- if (level == null) {
413
- for (var i = 0; i < groupingInfos.length; i++) {
414
- toggledGroupsByLevel[i] = {};
415
- groupingInfos[i].collapsed = collapse;
416
- }
417
- }
418
- else {
419
- toggledGroupsByLevel[level] = {};
420
- groupingInfos[level].collapsed = collapse;
421
- }
422
- refresh();
423
- }
424
- /**
425
- * @param level {Number} Optional level to collapse. If not specified, applies to all levels.
426
- */
427
- function collapseAllGroups(level) {
428
- expandCollapseAllGroups(level, true);
429
- }
430
- /**
431
- * @param level {Number} Optional level to expand. If not specified, applies to all levels.
432
- */
433
- function expandAllGroups(level) {
434
- expandCollapseAllGroups(level, false);
435
- }
436
- function expandCollapseGroup(level, groupingKey, collapse) {
437
- toggledGroupsByLevel[level][groupingKey] = groupingInfos[level].collapsed ^ collapse;
438
- refresh();
439
- }
440
- /**
441
- * @param varArgs Either a Slick.Group's "groupingKey" property, or a
442
- * variable argument list of grouping values denoting a unique path to the row. For
443
- * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of
444
- * the 'high' group.
445
- */
446
- function collapseGroup(varArgs) {
447
- var args = Array.prototype.slice.call(arguments);
448
- var arg0 = args[0];
449
- if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
450
- expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, true);
451
- }
452
- else {
453
- expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), true);
454
- }
455
- }
456
- /**
457
- * @param varArgs Either a Slick.Group's "groupingKey" property, or a
458
- * variable argument list of grouping values denoting a unique path to the row. For
459
- * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of
460
- * the 'high' group.
461
- */
462
- function expandGroup(varArgs) {
463
- var args = Array.prototype.slice.call(arguments);
464
- var arg0 = args[0];
465
- if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
466
- expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, false);
467
- }
468
- else {
469
- expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), false);
470
- }
471
- }
472
- function getGroups() {
473
- return groups;
474
- }
475
- function extractGroups(rows, parentGroup) {
476
- var group;
477
- var val;
478
- var groups = [];
479
- var groupsByVal = {};
480
- var r;
481
- var level = parentGroup ? parentGroup.level + 1 : 0;
482
- var gi = groupingInfos[level];
483
- for (var i = 0, l = gi.predefinedValues.length; i < l; i++) {
484
- val = gi.predefinedValues[i];
485
- group = groupsByVal[val];
486
- if (!group) {
487
- group = new Slick.Group();
488
- group.value = val;
489
- group.level = level;
490
- group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : "") + val;
491
- groups[groups.length] = group;
492
- groupsByVal[val] = group;
493
- }
494
- }
495
- for (var i = 0, l = rows.length; i < l; i++) {
496
- r = rows[i];
497
- val = gi.getterIsAFn ? gi.getter(r) : r[gi.getter];
498
- group = groupsByVal[val];
499
- if (!group) {
500
- group = new Slick.Group();
501
- group.value = val;
502
- group.level = level;
503
- group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : "") + val;
504
- groups[groups.length] = group;
505
- groupsByVal[val] = group;
506
- }
507
- group.rows[group.count++] = r;
508
- }
509
- if (level < groupingInfos.length - 1) {
510
- for (var i = 0; i < groups.length; i++) {
511
- group = groups[i];
512
- group.groups = extractGroups(group.rows, group);
513
- }
514
- }
515
- groups.sort(groupingInfos[level].comparer);
516
- return groups;
517
- }
518
- function calculateTotals(totals) {
519
- var group = totals.group;
520
- var gi = groupingInfos[group.level];
521
- var isLeafLevel = (group.level == groupingInfos.length);
522
- var agg, idx = gi.aggregators.length;
523
- if (!isLeafLevel && gi.aggregateChildGroups) {
524
- // make sure all the subgroups are calculated
525
- var i = group.groups.length;
526
- while (i--) {
527
- if (!group.groups[i].totals.initialized) {
528
- calculateTotals(group.groups[i].totals);
529
- }
530
- }
531
- }
532
- while (idx--) {
533
- agg = gi.aggregators[idx];
534
- agg.init();
535
- if (!isLeafLevel && gi.aggregateChildGroups) {
536
- gi.compiledAccumulators[idx].call(agg, group.groups);
537
- }
538
- else {
539
- gi.compiledAccumulators[idx].call(agg, group.rows);
540
- }
541
- agg.storeResult(totals);
542
- }
543
- totals.initialized = true;
544
- }
545
- function addGroupTotals(group) {
546
- var gi = groupingInfos[group.level];
547
- var totals = new Slick.GroupTotals();
548
- totals.group = group;
549
- group.totals = totals;
550
- if (!gi.lazyTotalsCalculation) {
551
- calculateTotals(totals);
552
- }
553
- }
554
- function addTotals(groups, level) {
555
- level = level || 0;
556
- var gi = groupingInfos[level];
557
- var groupCollapsed = gi.collapsed;
558
- var toggledGroups = toggledGroupsByLevel[level];
559
- var idx = groups.length, g;
560
- while (idx--) {
561
- g = groups[idx];
562
- if (g.collapsed && !gi.aggregateCollapsed) {
563
- continue;
564
- }
565
- // do a depth-first aggregation so that parent group aggregators can access subgroup totals.
566
- if (g.groups) {
567
- addTotals(g.groups, level + 1);
568
- }
569
- if (gi.aggregators.length && (gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
570
- addGroupTotals(g);
571
- }
572
- g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
573
- g.title = gi.formatter ? gi.formatter(g) : g.value;
574
- }
575
- }
576
- function flattenGroupedRows(groups, level) {
577
- level = level || 0;
578
- var gi = groupingInfos[level];
579
- var groupedRows = [], rows, gl = 0, g;
580
- for (var i = 0, l = groups.length; i < l; i++) {
581
- g = groups[i];
582
- groupedRows[gl++] = g;
583
- if (!g.collapsed) {
584
- rows = g.groups ? flattenGroupedRows(g.groups, level + 1) : g.rows;
585
- for (var j = 0, jj = rows.length; j < jj; j++) {
586
- groupedRows[gl++] = rows[j];
587
- }
588
- }
589
- if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {
590
- groupedRows[gl++] = g.totals;
591
- }
592
- }
593
- return groupedRows;
594
- }
595
- function getFunctionInfo(fn) {
596
- var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
597
- var matches = fn.toString().match(fnRegex);
598
- return {
599
- params: matches[1].split(","),
600
- body: matches[2]
601
- };
602
- }
603
- function compileAccumulatorLoop(aggregator) {
604
- var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
605
- var fn = new Function("_items", "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
606
- accumulatorInfo.params[0] + " = _items[_i]; " +
607
- accumulatorInfo.body +
608
- "}");
609
- fn.displayName /*= fn.name*/ = "compiledAccumulatorLoop";
610
- return fn;
611
- }
612
- // function compileFilter() {
613
- // let filterInfo = getFunctionInfo(filter);
614
- // let filterPath1 = "{ continue _coreloop; }$1";
615
- // let filterPath2 = "{ _retval[_idx++] = $item$; continue _coreloop; }$1";
616
- // // make some allowances for minification - there's only so far we can go with RegEx
617
- // let filterBody = filterInfo.body
618
- // .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
619
- // .replace(/return!1([;}]|\}|$)/gi, filterPath1)
620
- // .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
621
- // .replace(/return!0([;}]|\}|$)/gi, filterPath2)
622
- // .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
623
- // "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
624
- // // This preserves the function template code after JS compression,
625
- // // so that replace() commands still work as expected.
626
- // let tpl = [
627
- // // "function(_items, _args) { ",
628
- // "var _retval = [], _idx = 0; ",
629
- // "var $item$, $args$ = _args; ",
630
- // "_coreloop: ",
631
- // "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
632
- // "$item$ = _items[_i]; ",
633
- // "$filter$; ",
634
- // "} ",
635
- // "return _retval; "
636
- // // "}"
637
- // ].join("");
638
- // tpl = tpl.replace(/\$filter\$/gi, filterBody);
639
- // tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
640
- // tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
641
- // let fn: any = new Function("_items,_args", tpl);
642
- // fn.displayName = /*fn.name =*/ "compiledFilter";
643
- // return fn;
644
- // }
645
- // function compileFilterWithCaching() {
646
- // let filterInfo = getFunctionInfo(filter);
647
- // let filterPath1 = "{ continue _coreloop; }$1";
648
- // let filterPath2 = "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1";
649
- // // make some allowances for minification - there's only so far we can go with RegEx
650
- // let filterBody = filterInfo.body
651
- // .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
652
- // .replace(/return!1([;}]|\}|$)/gi, filterPath1)
653
- // .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
654
- // .replace(/return!0([;}]|\}|$)/gi, filterPath2)
655
- // .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
656
- // "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
657
- // // This preserves the function template code after JS compression,
658
- // // so that replace() commands still work as expected.
659
- // let tpl = [
660
- // // "function(_items, _args, _cache) { ",
661
- // "var _retval = [], _idx = 0; ",
662
- // "var $item$, $args$ = _args; ",
663
- // "_coreloop: ",
664
- // "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
665
- // "$item$ = _items[_i]; ",
666
- // "if (_cache[_i]) { ",
667
- // "_retval[_idx++] = $item$; ",
668
- // "continue _coreloop; ",
669
- // "} ",
670
- // "$filter$; ",
671
- // "} ",
672
- // "return _retval; "
673
- // // "}"
674
- // ].join("");
675
- // tpl = tpl.replace(/\$filter\$/gi, filterBody);
676
- // tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
677
- // tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
678
- // let fn: any = new Function("_items,_args,_cache", tpl);
679
- // fn.displayName /*= fn.name*/ = "compiledFilterWithCaching";
680
- // return fn;
681
- // }
682
- function uncompiledFilter(items, args) {
683
- var retval = [], idx = 0;
684
- for (var i = 0, ii = items.length; i < ii; i++) {
685
- if (filter(items[i], args)) {
686
- retval[idx++] = items[i];
687
- }
688
- }
689
- return retval;
690
- }
691
- function uncompiledFilterWithCaching(items, args, cache) {
692
- var retval = [], idx = 0, item;
693
- for (var i = 0, ii = items.length; i < ii; i++) {
694
- item = items[i];
695
- if (cache[i]) {
696
- retval[idx++] = item;
697
- }
698
- else if (filter(item, args)) {
699
- retval[idx++] = item;
700
- cache[i] = true;
701
- }
702
- }
703
- return retval;
704
- }
705
- function getFilteredAndPagedItems(items) {
706
- if (filter) {
707
- var batchFilter = uncompiledFilter; // options.inlineFilters ? compiledFilter : uncompiledFilter;
708
- var batchFilterWithCaching = uncompiledFilterWithCaching; // options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
709
- if (refreshHints.isFilterNarrowing) {
710
- filteredItems = batchFilter(filteredItems, filterArgs);
711
- }
712
- else if (refreshHints.isFilterExpanding) {
713
- filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
714
- }
715
- else if (!refreshHints.isFilterUnchanged) {
716
- filteredItems = batchFilter(items, filterArgs);
717
- }
718
- }
719
- else {
720
- // special case: if not filtering and not paging, the resulting
721
- // rows collection needs to be a copy so that changes due to sort
722
- // can be caught
723
- filteredItems = pagesize ? items : items.concat();
724
- }
725
- // get the current page
726
- var paged;
727
- if (pagesize) {
728
- if (filteredItems.length <= pagenum * pagesize) {
729
- if (filteredItems.length === 0) {
730
- pagenum = 0;
731
- }
732
- else {
733
- pagenum = Math.floor((filteredItems.length - 1) / pagesize);
734
- }
735
- }
736
- paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
737
- }
738
- else {
739
- paged = filteredItems;
740
- }
741
- return { totalRows: filteredItems.length, rows: paged };
742
- }
743
- function getRowDiffs(rows, newRows) {
744
- var item, r, eitherIsNonData, diff = [];
745
- var from = 0, to = newRows.length;
746
- if (refreshHints && refreshHints.ignoreDiffsBefore) {
747
- from = Math.max(0, Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
748
- }
749
- if (refreshHints && refreshHints.ignoreDiffsAfter) {
750
- to = Math.min(newRows.length, Math.max(0, refreshHints.ignoreDiffsAfter));
751
- }
752
- for (var i = from, rl = rows.length; i < to; i++) {
753
- if (i >= rl) {
754
- diff[diff.length] = i;
755
- }
756
- else {
757
- item = newRows[i];
758
- r = rows[i];
759
- if ((groupingInfos.length && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
760
- item.__group !== r.__group ||
761
- item.__group && !item.equals(r))
762
- || (eitherIsNonData &&
763
- // no good way to compare totals since they are arbitrary DTOs
764
- // deep object comparison is pretty expensive
765
- // always considering them 'dirty' seems easier for the time being
766
- (item.__groupTotals || r.__groupTotals))
767
- || item[idProperty] != r[idProperty]
768
- || (updated && updated[item[idProperty]])) {
769
- diff[diff.length] = i;
770
- }
771
- }
772
- }
773
- return diff;
774
- }
775
- function recalc(_items, second) {
776
- rowsById = null;
777
- if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
778
- refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
779
- filterCache = [];
780
- }
781
- var filteredItems = getFilteredAndPagedItems(_items);
782
- totalRows = filteredItems.totalRows;
783
- var newRows = filteredItems.rows;
784
- groups = [];
785
- if (groupingInfos.length) {
786
- groups = extractGroups(newRows);
787
- if (groups.length) {
788
- addTotals(groups);
789
- newRows = flattenGroupedRows(groups);
790
- }
791
- }
792
- var diff = getRowDiffs(rows, newRows);
793
- rows = newRows;
794
- return diff;
795
- }
796
- function refresh() {
797
- if (suspend) {
798
- return;
799
- }
800
- var countBefore = rows.length;
801
- var totalRowsBefore = totalRows;
802
- var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
803
- // if the current page is no longer valid, go to last page and recalc
804
- // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
805
- if (pagesize && totalRows < pagenum * pagesize) {
806
- pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
807
- diff = recalc(items, filter);
808
- }
809
- updated = null;
810
- prevRefreshHints = refreshHints;
811
- refreshHints = {};
812
- if (totalRowsBefore !== totalRows) {
813
- onPagingInfoChanged.notify(getPagingInfo(), null, self);
814
- }
815
- if (countBefore !== rows.length) {
816
- onRowCountChanged.notify({ previous: countBefore, current: rows.length, dataView: self, callingOnRowsChanged: (diff.length > 0) }, null, self);
817
- }
818
- if (diff.length > 0) {
819
- onRowsChanged.notify({ rows: diff, dataView: self, calledOnRowCountChanged: (countBefore !== rows.length) }, null, self);
820
- }
821
- if (countBefore !== rows.length || diff.length > 0) {
822
- onRowsOrCountChanged.notify({
823
- rowsDiff: diff, previousRowCount: countBefore, currentRowCount: rows.length,
824
- rowCountChanged: countBefore !== rows.length, rowsChanged: diff.length > 0, dataView: self
825
- }, null, self);
826
- }
827
- }
828
- /***
829
- * Wires the grid and the DataView together to keep row selection tied to item ids.
830
- * This is useful since, without it, the grid only knows about rows, so if the items
831
- * move around, the same rows stay selected instead of the selection moving along
832
- * with the items.
833
- *
834
- * NOTE: This doesn't work with cell selection model.
835
- *
836
- * @param grid {Slick.Grid} The grid to sync selection with.
837
- * @param preserveHidden {Boolean} Whether to keep selected items that go out of the
838
- * view due to them getting filtered out.
839
- * @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items
840
- * that are currently out of the view (see preserveHidden) as selected when selection
841
- * changes.
842
- * @return {Slick.Event} An event that notifies when an internal list of selected row ids
843
- * changes. This is useful since, in combination with the above two options, it allows
844
- * access to the full list selected row ids, and not just the ones visible to the grid.
845
- * @method syncGridSelection
846
- */
847
- function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
848
- var self = this;
849
- var inHandler;
850
- var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
851
- var onSelectedRowIdsChanged = new Slick.Event();
852
- function setSelectedRowIds(rowIds) {
853
- if (selectedRowIds.join(",") == rowIds.join(",")) {
854
- return;
855
- }
856
- selectedRowIds = rowIds;
857
- onSelectedRowIdsChanged.notify({
858
- grid: grid,
859
- ids: selectedRowIds,
860
- dataView: self
861
- }, new Slick.EventData(), self);
862
- }
863
- function update() {
864
- if (selectedRowIds.length > 0) {
865
- inHandler = true;
866
- var selectedRows = self.mapIdsToRows(selectedRowIds);
867
- if (!preserveHidden) {
868
- setSelectedRowIds(self.mapRowsToIds(selectedRows));
869
- }
870
- grid.setSelectedRows(selectedRows);
871
- inHandler = false;
872
- }
873
- }
874
- grid.onSelectedRowsChanged.subscribe(function (e, args) {
875
- if (inHandler) {
876
- return;
877
- }
878
- var newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
879
- if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
880
- setSelectedRowIds(newSelectedRowIds);
881
- }
882
- else {
883
- // keep the ones that are hidden
884
- var existing = [];
885
- for (var i = 0; i < selectedRowIds.length; i++) {
886
- if (self.getRowById(selectedRowIds[i]) === undefined) {
887
- existing.push(selectedRowIds[i]);
888
- }
889
- }
890
- // $.grep(selectedRowIds, function(id) { return self.getRowById(id) === undefined; });
891
- // add the newly selected ones
892
- setSelectedRowIds(existing.concat(newSelectedRowIds));
893
- }
894
- });
895
- this.onRowsOrCountChanged.subscribe(update);
896
- return onSelectedRowIdsChanged;
897
- }
898
- function syncGridCellCssStyles(grid, key) {
899
- var hashById;
900
- var inHandler;
901
- // since this method can be called after the cell styles have been set,
902
- // get the existing ones right away
903
- storeCellCssStyles(grid.getCellCssStyles(key));
904
- function storeCellCssStyles(hash) {
905
- hashById = {};
906
- for (var row in hash) {
907
- var id = rows[row][idProperty];
908
- hashById[id] = hash[row];
909
- }
910
- }
911
- function update() {
912
- if (hashById) {
913
- inHandler = true;
914
- ensureRowsByIdCache();
915
- var newHash = {};
916
- for (var id in hashById) {
917
- var row = rowsById[id];
918
- if (row != undefined) {
919
- newHash[row] = hashById[id];
920
- }
921
- }
922
- grid.setCellCssStyles(key, newHash);
923
- inHandler = false;
924
- }
925
- }
926
- grid.onCellCssStylesChanged.subscribe(function (e, args) {
927
- if (inHandler) {
928
- return;
929
- }
930
- if (key != args.key) {
931
- return;
932
- }
933
- if (args.hash) {
934
- storeCellCssStyles(args.hash);
935
- }
936
- else {
937
- // grid.onCellCssStylesChanged.unsubscribe(styleChanged); //styleChanged not declared
938
- self.onRowsOrCountChanged.unsubscribe(update);
939
- }
940
- });
941
- this.onRowsOrCountChanged.subscribe(update);
942
- }
943
- $.shallowExtend(this, {
944
- // methods
945
- beginUpdate: beginUpdate,
946
- endUpdate: endUpdate,
947
- setPagingOptions: setPagingOptions,
948
- getPagingInfo: getPagingInfo,
949
- getItems: getItems,
950
- setItems: setItems,
951
- setFilter: setFilter,
952
- getFilter: getFilter,
953
- getFilteredItems: getFilteredItems,
954
- sort: sort,
955
- // "fastSort": fastSort,
956
- reSort: reSort,
957
- setGrouping: setGrouping,
958
- getGrouping: getGrouping,
959
- groupBy: groupBy,
960
- setAggregators: setAggregators,
961
- collapseAllGroups: collapseAllGroups,
962
- expandAllGroups: expandAllGroups,
963
- collapseGroup: collapseGroup,
964
- expandGroup: expandGroup,
965
- getGroups: getGroups,
966
- getIdxById: getIdxById,
967
- getIdxByItem: getIdxByItem,
968
- getRowByItem: getRowByItem,
969
- getRowById: getRowById,
970
- getItemById: getItemById,
971
- getItemByIdx: getItemByIdx,
972
- mapItemsToRows: mapItemsToRows,
973
- mapRowsToIds: mapRowsToIds,
974
- mapIdsToRows: mapIdsToRows,
975
- setRefreshHints: setRefreshHints,
976
- setFilterArgs: setFilterArgs,
977
- refresh: refresh,
978
- updateItem: updateItem,
979
- insertItem: insertItem,
980
- addItem: addItem,
981
- deleteItem: deleteItem,
982
- sortedAddItem: sortedAddItem,
983
- sortedUpdateItem: sortedUpdateItem,
984
- syncGridSelection: syncGridSelection,
985
- syncGridCellCssStyles: syncGridCellCssStyles,
986
- // data provider methods
987
- getLength: getLength,
988
- getItem: getItem,
989
- getItemMetadata: getItemMetadata,
990
- // events
991
- onRowCountChanged: onRowCountChanged,
992
- onRowsChanged: onRowsChanged,
993
- onRowsOrCountChanged: onRowsOrCountChanged,
994
- onPagingInfoChanged: onPagingInfoChanged
995
- });
996
- }
997
- export function AvgAggregator(field) {
998
- this.field_ = field;
999
- this.init = function () {
1000
- this.count_ = 0;
1001
- this.nonNullCount_ = 0;
1002
- this.sum_ = 0;
1003
- };
1004
- this.accumulate = function (item) {
1005
- var val = item[this.field_];
1006
- this.count_++;
1007
- if (val != null && val !== "" && !isNaN(val)) {
1008
- this.nonNullCount_++;
1009
- this.sum_ += parseFloat(val);
1010
- }
1011
- };
1012
- this.storeResult = function (groupTotals) {
1013
- if (!groupTotals.avg) {
1014
- groupTotals.avg = {};
1015
- }
1016
- if (this.nonNullCount_ != 0) {
1017
- groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
1018
- }
1019
- };
1020
- }
1021
- export function MinAggregator(field) {
1022
- this.field_ = field;
1023
- this.init = function () {
1024
- this.min_ = null;
1025
- };
1026
- this.accumulate = function (item) {
1027
- var val = item[this.field_];
1028
- if (val != null && val !== "" && !isNaN(val)) {
1029
- if (this.min_ == null || val < this.min_) {
1030
- this.min_ = val;
1031
- }
1032
- }
1033
- };
1034
- this.storeResult = function (groupTotals) {
1035
- if (!groupTotals.min) {
1036
- groupTotals.min = {};
1037
- }
1038
- groupTotals.min[this.field_] = this.min_;
1039
- };
1040
- }
1041
- export function MaxAggregator(field) {
1042
- this.field_ = field;
1043
- this.init = function () {
1044
- this.max_ = null;
1045
- };
1046
- this.accumulate = function (item) {
1047
- var val = item[this.field_];
1048
- if (val != null && val !== "" && !isNaN(val)) {
1049
- if (this.max_ == null || val > this.max_) {
1050
- this.max_ = val;
1051
- }
1052
- }
1053
- };
1054
- this.storeResult = function (groupTotals) {
1055
- if (!groupTotals.max) {
1056
- groupTotals.max = {};
1057
- }
1058
- groupTotals.max[this.field_] = this.max_;
1059
- };
1060
- }
1061
- export function SumAggregator(field) {
1062
- this.field_ = field;
1063
- this.init = function () {
1064
- this.sum_ = null;
1065
- };
1066
- this.accumulate = function (item) {
1067
- var val = item[this.field_];
1068
- if (val != null && val !== "" && !isNaN(val)) {
1069
- this.sum_ += parseFloat(val);
1070
- }
1071
- };
1072
- this.storeResult = function (groupTotals) {
1073
- if (!groupTotals.sum) {
1074
- groupTotals.sum = {};
1075
- }
1076
- groupTotals.sum[this.field_] = this.sum_;
1077
- };
1078
- }
1079
- // tODO: add more built-in aggregators
1080
- // tODO: merge common aggregators in one to prevent needles iterating
1
+ import { jQueryReplacement } from "../core/jq";
2
+ import { Slick } from "./slick.core";
3
+ const $ = jQueryReplacement;
4
+ /***
5
+ * A sample Model implementation.
6
+ * Provides a filtered view of the underlying data.
7
+ *
8
+ * Relies on the data item having an "id" property uniquely identifying it.
9
+ */
10
+ export function DataView(options) {
11
+ let self = this;
12
+ let defaults = {
13
+ groupItemMetadataProvider: null,
14
+ inlineFilters: false
15
+ };
16
+ // private
17
+ let idProperty = "id"; // property holding a unique row id
18
+ let items = []; // data by index
19
+ let rows = []; // data by row
20
+ let idxById = {}; // indexes by id
21
+ let rowsById = null; // rows by id; lazy-calculated
22
+ let filter = null; // filter function
23
+ let updated = null; // updated item ids
24
+ let suspend = false; // suspends the recalculation
25
+ let sortAsc = true;
26
+ // var fastSortField;
27
+ let sortComparer;
28
+ let refreshHints = {};
29
+ let prevRefreshHints = {};
30
+ let filterArgs;
31
+ let filteredItems = [];
32
+ // let compiledFilter;
33
+ // let compiledFilterWithCaching;
34
+ let filterCache = [];
35
+ // grouping
36
+ let groupingInfoDefaults = {
37
+ getter: null,
38
+ formatter: null,
39
+ comparer(a, b) {
40
+ return (a.value === b.value ? 0 :
41
+ (a.value > b.value ? 1 : -1));
42
+ },
43
+ predefinedValues: [],
44
+ aggregators: [],
45
+ aggregateEmpty: false,
46
+ aggregateCollapsed: false,
47
+ aggregateChildGroups: false,
48
+ collapsed: false,
49
+ displayTotalsRow: true,
50
+ lazyTotalsCalculation: false
51
+ };
52
+ let groupingInfos = [];
53
+ let groups = [];
54
+ let toggledGroupsByLevel = [];
55
+ let groupingDelimiter = ":|:";
56
+ let pagesize = 0;
57
+ let pagenum = 0;
58
+ let totalRows = 0;
59
+ // events
60
+ let onRowCountChanged = new Slick.Event();
61
+ let onRowsChanged = new Slick.Event();
62
+ let onRowsOrCountChanged = new Slick.Event();
63
+ let onPagingInfoChanged = new Slick.Event();
64
+ options = $.deepExtend({}, defaults, options);
65
+ function beginUpdate() {
66
+ suspend = true;
67
+ }
68
+ function endUpdate() {
69
+ suspend = false;
70
+ refresh();
71
+ }
72
+ function setRefreshHints(hints) {
73
+ refreshHints = hints;
74
+ }
75
+ function setFilterArgs(args) {
76
+ filterArgs = args;
77
+ }
78
+ function updateIdxById(startingIndex) {
79
+ startingIndex = startingIndex || 0;
80
+ let id;
81
+ for (let i = startingIndex, l = items.length; i < l; i++) {
82
+ id = items[i][idProperty];
83
+ if (id === undefined) {
84
+ // throw new Error("Each data element must implement a unique 'id' property");
85
+ throw new Error("Id (" + idProperty + ") of element at index " + i + " was undefined");
86
+ }
87
+ idxById[id] = i;
88
+ }
89
+ }
90
+ function ensureIdUniqueness() {
91
+ let id;
92
+ for (let i = 0, l = items.length; i < l; i++) {
93
+ id = items[i][idProperty];
94
+ if (id === undefined) {
95
+ throw new Error("Id (" + idProperty + ") of element at index " + i + " was undefined");
96
+ }
97
+ else if (idxById[id] !== i) {
98
+ throw new Error("Duplicate id (" + idProperty + ") for " + id + " found at index (" + idxById[id] + ", " + i + ")");
99
+ }
100
+ }
101
+ }
102
+ function getItems() {
103
+ return items;
104
+ }
105
+ function setItems(data, objectIdProperty) {
106
+ if (objectIdProperty !== undefined) {
107
+ idProperty = objectIdProperty;
108
+ }
109
+ items = filteredItems = data;
110
+ idxById = {};
111
+ updateIdxById();
112
+ ensureIdUniqueness();
113
+ refresh();
114
+ }
115
+ function setPagingOptions(args) {
116
+ if (args.pageSize != undefined) {
117
+ pagesize = args.pageSize;
118
+ pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
119
+ }
120
+ if (args.pageNum != undefined) {
121
+ pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
122
+ }
123
+ onPagingInfoChanged.notify(getPagingInfo(), null, self);
124
+ refresh();
125
+ }
126
+ function getPagingInfo() {
127
+ let totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
128
+ return { pageSize: pagesize, pageNum: pagenum, totalRows, totalPages, dataView: self };
129
+ }
130
+ function sort(comparer, ascending) {
131
+ sortAsc = ascending;
132
+ sortComparer = comparer;
133
+ // fastSortField = null;
134
+ if (ascending === false) {
135
+ items.reverse();
136
+ }
137
+ items.sort(comparer);
138
+ if (ascending === false) {
139
+ items.reverse();
140
+ }
141
+ idxById = {};
142
+ updateIdxById();
143
+ refresh();
144
+ }
145
+ function reSort() {
146
+ if (sortComparer) {
147
+ sort(sortComparer, sortAsc);
148
+ }
149
+ }
150
+ function getFilteredItems() {
151
+ return filteredItems;
152
+ }
153
+ function getFilter() {
154
+ return filter;
155
+ }
156
+ function setFilter(filterFn) {
157
+ filter = filterFn;
158
+ // if (options.inlineFilters) {
159
+ // compiledFilter = compileFilter();
160
+ // compiledFilterWithCaching = compileFilterWithCaching();
161
+ // }
162
+ refresh();
163
+ }
164
+ function getGrouping() {
165
+ return groupingInfos;
166
+ }
167
+ function setGrouping(groupingInfo) {
168
+ if (!options.groupItemMetadataProvider) {
169
+ options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
170
+ }
171
+ groups = [];
172
+ toggledGroupsByLevel = [];
173
+ groupingInfo = groupingInfo || [];
174
+ groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
175
+ for (let i = 0; i < groupingInfos.length; i++) {
176
+ const gi = groupingInfos[i] = $.deepExtend({}, groupingInfoDefaults, groupingInfos[i]);
177
+ gi.getterIsAFn = typeof gi.getter === "function";
178
+ // pre-compile accumulator loops
179
+ gi.compiledAccumulators = [];
180
+ let idx = gi.aggregators.length;
181
+ while (idx--) {
182
+ gi.compiledAccumulators[idx] = compileAccumulatorLoop(gi.aggregators[idx]);
183
+ }
184
+ toggledGroupsByLevel[i] = {};
185
+ }
186
+ refresh();
187
+ }
188
+ /**
189
+ * @deprecated Please use {@link setGrouping}.
190
+ */
191
+ function groupBy(valueGetter, valueFormatter, sortComparer) {
192
+ if (valueGetter == null) {
193
+ setGrouping([]);
194
+ return;
195
+ }
196
+ setGrouping({
197
+ getter: valueGetter,
198
+ formatter: valueFormatter,
199
+ comparer: sortComparer
200
+ });
201
+ }
202
+ /**
203
+ * @deprecated Please use {@link setGrouping}.
204
+ */
205
+ function setAggregators(groupAggregators, includeCollapsed) {
206
+ if (!groupingInfos.length) {
207
+ throw new Error("At least one grouping must be specified before calling setAggregators().");
208
+ }
209
+ groupingInfos[0].aggregators = groupAggregators;
210
+ groupingInfos[0].aggregateCollapsed = includeCollapsed;
211
+ setGrouping(groupingInfos);
212
+ }
213
+ function getItemByIdx(i) {
214
+ return items[i];
215
+ }
216
+ function getIdxById(id) {
217
+ return idxById[id];
218
+ }
219
+ function getIdxByItem(item) {
220
+ return idxById[item[idProperty]];
221
+ }
222
+ function ensureRowsByIdCache() {
223
+ if (!rowsById) {
224
+ rowsById = {};
225
+ for (let i = 0, l = rows.length; i < l; i++) {
226
+ rowsById[rows[i][idProperty]] = i;
227
+ }
228
+ }
229
+ }
230
+ function getRowByItem(item) {
231
+ ensureRowsByIdCache();
232
+ return rowsById[item[idProperty]];
233
+ }
234
+ function getRowById(id) {
235
+ ensureRowsByIdCache();
236
+ return rowsById[id];
237
+ }
238
+ function getItemById(id) {
239
+ return items[idxById[id]];
240
+ }
241
+ function mapItemsToRows(itemArray) {
242
+ let rows = [];
243
+ ensureRowsByIdCache();
244
+ for (let i = 0, l = itemArray.length; i < l; i++) {
245
+ let row = rowsById[itemArray[i][idProperty]];
246
+ if (row != null) {
247
+ rows[rows.length] = row;
248
+ }
249
+ }
250
+ return rows;
251
+ }
252
+ function mapIdsToRows(idArray) {
253
+ let rows = [];
254
+ ensureRowsByIdCache();
255
+ for (let i = 0, l = idArray.length; i < l; i++) {
256
+ let row = rowsById[idArray[i]];
257
+ if (row != null) {
258
+ rows[rows.length] = row;
259
+ }
260
+ }
261
+ return rows;
262
+ }
263
+ function mapRowsToIds(rowArray) {
264
+ let ids = [];
265
+ for (let i = 0, l = rowArray.length; i < l; i++) {
266
+ if (rowArray[i] < rows.length) {
267
+ ids[ids.length] = rows[rowArray[i]][idProperty];
268
+ }
269
+ }
270
+ return ids;
271
+ }
272
+ function updateItem(id, item) {
273
+ // see also https://github.com/mleibman/SlickGrid/issues/1082
274
+ if (idxById[id] === undefined) {
275
+ throw new Error("Invalid id");
276
+ }
277
+ // what if the specified item also has an updated idProperty?
278
+ // then we'll have to update the index as well, and possibly the `updated` cache too.
279
+ if (id !== item[idProperty]) {
280
+ // make sure the new id is unique:
281
+ let newId = item[idProperty];
282
+ if (newId == null) {
283
+ throw new Error("Cannot update item to associate with a null id");
284
+ }
285
+ if (idxById[newId] !== undefined) {
286
+ throw new Error("Cannot update item to associate with a non-unique id");
287
+ }
288
+ idxById[newId] = idxById[id];
289
+ delete idxById[id];
290
+ // also update the `updated` hashtable/markercache? Yes, `recalc()` inside `refresh()` needs that one!
291
+ if (updated && updated[id]) {
292
+ delete updated[id];
293
+ }
294
+ // also update the row indexes? no need since the `refresh()`, further down, blows away the `rowsById[]` cache!
295
+ id = newId;
296
+ }
297
+ items[idxById[id]] = item;
298
+ // also update the rows? no need since the `refresh()`, further down, blows away the `rows[]` cache and recalculates it via `recalc()`!
299
+ if (!updated) {
300
+ updated = {};
301
+ }
302
+ updated[id] = true;
303
+ refresh();
304
+ }
305
+ function insertItem(insertBefore, item) {
306
+ items.splice(insertBefore, 0, item);
307
+ updateIdxById(insertBefore);
308
+ refresh();
309
+ }
310
+ function addItem(item) {
311
+ items.push(item);
312
+ updateIdxById(items.length - 1);
313
+ refresh();
314
+ }
315
+ function deleteItem(id) {
316
+ let idx = idxById[id];
317
+ if (idx === undefined) {
318
+ throw new Error("Invalid id");
319
+ }
320
+ delete idxById[id];
321
+ items.splice(idx, 1);
322
+ updateIdxById(idx);
323
+ refresh();
324
+ }
325
+ function sortedAddItem(item) {
326
+ if (!sortComparer) {
327
+ throw new Error("sortedAddItem() requires a sort comparer, use sort()");
328
+ }
329
+ insertItem(sortedIndex(item), item);
330
+ }
331
+ function sortedUpdateItem(id, item) {
332
+ if (idxById[id] === undefined || id !== item[idProperty]) {
333
+ throw new Error("Invalid or non-matching id " + idxById[id]);
334
+ }
335
+ if (!sortComparer) {
336
+ throw new Error("sortedUpdateItem() requires a sort comparer, use sort()");
337
+ }
338
+ let oldItem = getItemById(id);
339
+ if (sortComparer(oldItem, item) !== 0) {
340
+ // item affects sorting -> must use sorted add
341
+ deleteItem(id);
342
+ sortedAddItem(item);
343
+ }
344
+ else { // update does not affect sorting -> regular update works fine
345
+ updateItem(id, item);
346
+ }
347
+ }
348
+ function sortedIndex(searchItem) {
349
+ let low = 0, high = items.length;
350
+ while (low < high) {
351
+ let mid = low + high >>> 1;
352
+ if (sortComparer(items[mid], searchItem) === -1) {
353
+ low = mid + 1;
354
+ }
355
+ else {
356
+ high = mid;
357
+ }
358
+ }
359
+ return low;
360
+ }
361
+ function getLength() {
362
+ return rows.length;
363
+ }
364
+ function getItem(i) {
365
+ let item = rows[i];
366
+ // if this is a group row, make sure totals are calculated and update the title
367
+ if (item && item.__group && item.totals && !item.totals.initialized) {
368
+ let gi = groupingInfos[item.level];
369
+ if (!gi.displayTotalsRow) {
370
+ calculateTotals(item.totals);
371
+ item.title = gi.formatter ? gi.formatter(item) : item.value;
372
+ }
373
+ }
374
+ else if (item && item.__groupTotals && !item.initialized) {
375
+ calculateTotals(item);
376
+ }
377
+ return item;
378
+ }
379
+ function getItemMetadata(i) {
380
+ let item = rows[i];
381
+ if (item === undefined) {
382
+ return null;
383
+ }
384
+ // overrides for grouping rows
385
+ if (item.__group) {
386
+ return options.groupItemMetadataProvider.getGroupRowMetadata(item);
387
+ }
388
+ // overrides for totals rows
389
+ if (item.__groupTotals) {
390
+ return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
391
+ }
392
+ if (item.__height) {
393
+ if (item.getItemMetadata != null) {
394
+ return { height: item.__height, ...(item.getItemMetadata || {}) };
395
+ }
396
+ return { height: item.__height };
397
+ }
398
+ return item.getItemMetadata != null ? item.getItemMetadata(i, item) : null;
399
+ }
400
+ function expandCollapseAllGroups(level, collapse) {
401
+ if (level == null) {
402
+ for (let i = 0; i < groupingInfos.length; i++) {
403
+ toggledGroupsByLevel[i] = {};
404
+ groupingInfos[i].collapsed = collapse;
405
+ }
406
+ }
407
+ else {
408
+ toggledGroupsByLevel[level] = {};
409
+ groupingInfos[level].collapsed = collapse;
410
+ }
411
+ refresh();
412
+ }
413
+ /**
414
+ * @param level {Number} Optional level to collapse. If not specified, applies to all levels.
415
+ */
416
+ function collapseAllGroups(level) {
417
+ expandCollapseAllGroups(level, true);
418
+ }
419
+ /**
420
+ * @param level {Number} Optional level to expand. If not specified, applies to all levels.
421
+ */
422
+ function expandAllGroups(level) {
423
+ expandCollapseAllGroups(level, false);
424
+ }
425
+ function expandCollapseGroup(level, groupingKey, collapse) {
426
+ toggledGroupsByLevel[level][groupingKey] = groupingInfos[level].collapsed ^ collapse;
427
+ refresh();
428
+ }
429
+ /**
430
+ * @param varArgs Either a Slick.Group's "groupingKey" property, or a
431
+ * variable argument list of grouping values denoting a unique path to the row. For
432
+ * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of
433
+ * the 'high' group.
434
+ */
435
+ function collapseGroup(varArgs) {
436
+ let args = Array.prototype.slice.call(arguments);
437
+ let arg0 = args[0];
438
+ if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
439
+ expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, true);
440
+ }
441
+ else {
442
+ expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), true);
443
+ }
444
+ }
445
+ /**
446
+ * @param varArgs Either a Slick.Group's "groupingKey" property, or a
447
+ * variable argument list of grouping values denoting a unique path to the row. For
448
+ * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of
449
+ * the 'high' group.
450
+ */
451
+ function expandGroup(varArgs) {
452
+ let args = Array.prototype.slice.call(arguments);
453
+ let arg0 = args[0];
454
+ if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
455
+ expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, false);
456
+ }
457
+ else {
458
+ expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), false);
459
+ }
460
+ }
461
+ function getGroups() {
462
+ return groups;
463
+ }
464
+ function extractGroups(rows, parentGroup) {
465
+ let group;
466
+ let val;
467
+ let groups = [];
468
+ let groupsByVal = {};
469
+ let r;
470
+ let level = parentGroup ? parentGroup.level + 1 : 0;
471
+ let gi = groupingInfos[level];
472
+ for (let i = 0, l = gi.predefinedValues.length; i < l; i++) {
473
+ val = gi.predefinedValues[i];
474
+ group = groupsByVal[val];
475
+ if (!group) {
476
+ group = new Slick.Group();
477
+ group.value = val;
478
+ group.level = level;
479
+ group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : "") + val;
480
+ groups[groups.length] = group;
481
+ groupsByVal[val] = group;
482
+ }
483
+ }
484
+ for (let i = 0, l = rows.length; i < l; i++) {
485
+ r = rows[i];
486
+ val = gi.getterIsAFn ? gi.getter(r) : r[gi.getter];
487
+ group = groupsByVal[val];
488
+ if (!group) {
489
+ group = new Slick.Group();
490
+ group.value = val;
491
+ group.level = level;
492
+ group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : "") + val;
493
+ groups[groups.length] = group;
494
+ groupsByVal[val] = group;
495
+ }
496
+ group.rows[group.count++] = r;
497
+ }
498
+ if (level < groupingInfos.length - 1) {
499
+ for (let i = 0; i < groups.length; i++) {
500
+ group = groups[i];
501
+ group.groups = extractGroups(group.rows, group);
502
+ }
503
+ }
504
+ groups.sort(groupingInfos[level].comparer);
505
+ return groups;
506
+ }
507
+ function calculateTotals(totals) {
508
+ let group = totals.group;
509
+ let gi = groupingInfos[group.level];
510
+ let isLeafLevel = (group.level == groupingInfos.length);
511
+ let agg, idx = gi.aggregators.length;
512
+ if (!isLeafLevel && gi.aggregateChildGroups) {
513
+ // make sure all the subgroups are calculated
514
+ let i = group.groups.length;
515
+ while (i--) {
516
+ if (!group.groups[i].totals.initialized) {
517
+ calculateTotals(group.groups[i].totals);
518
+ }
519
+ }
520
+ }
521
+ while (idx--) {
522
+ agg = gi.aggregators[idx];
523
+ agg.init();
524
+ if (!isLeafLevel && gi.aggregateChildGroups) {
525
+ gi.compiledAccumulators[idx].call(agg, group.groups);
526
+ }
527
+ else {
528
+ gi.compiledAccumulators[idx].call(agg, group.rows);
529
+ }
530
+ agg.storeResult(totals);
531
+ }
532
+ totals.initialized = true;
533
+ }
534
+ function addGroupTotals(group) {
535
+ let gi = groupingInfos[group.level];
536
+ let totals = new Slick.GroupTotals();
537
+ totals.group = group;
538
+ group.totals = totals;
539
+ if (!gi.lazyTotalsCalculation) {
540
+ calculateTotals(totals);
541
+ }
542
+ }
543
+ function addTotals(groups, level) {
544
+ level = level || 0;
545
+ let gi = groupingInfos[level];
546
+ let groupCollapsed = gi.collapsed;
547
+ let toggledGroups = toggledGroupsByLevel[level];
548
+ let idx = groups.length, g;
549
+ while (idx--) {
550
+ g = groups[idx];
551
+ if (g.collapsed && !gi.aggregateCollapsed) {
552
+ continue;
553
+ }
554
+ // do a depth-first aggregation so that parent group aggregators can access subgroup totals.
555
+ if (g.groups) {
556
+ addTotals(g.groups, level + 1);
557
+ }
558
+ if (gi.aggregators.length && (gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
559
+ addGroupTotals(g);
560
+ }
561
+ g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
562
+ g.title = gi.formatter ? gi.formatter(g) : g.value;
563
+ }
564
+ }
565
+ function flattenGroupedRows(groups, level) {
566
+ level = level || 0;
567
+ let gi = groupingInfos[level];
568
+ let groupedRows = [], rows, gl = 0, g;
569
+ for (let i = 0, l = groups.length; i < l; i++) {
570
+ g = groups[i];
571
+ groupedRows[gl++] = g;
572
+ if (!g.collapsed) {
573
+ rows = g.groups ? flattenGroupedRows(g.groups, level + 1) : g.rows;
574
+ for (let j = 0, jj = rows.length; j < jj; j++) {
575
+ groupedRows[gl++] = rows[j];
576
+ }
577
+ }
578
+ if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {
579
+ groupedRows[gl++] = g.totals;
580
+ }
581
+ }
582
+ return groupedRows;
583
+ }
584
+ function getFunctionInfo(fn) {
585
+ let fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
586
+ let matches = fn.toString().match(fnRegex);
587
+ return {
588
+ params: matches[1].split(","),
589
+ body: matches[2]
590
+ };
591
+ }
592
+ function compileAccumulatorLoop(aggregator) {
593
+ let accumulatorInfo = getFunctionInfo(aggregator.accumulate);
594
+ let fn = new Function("_items", "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
595
+ accumulatorInfo.params[0] + " = _items[_i]; " +
596
+ accumulatorInfo.body +
597
+ "}");
598
+ fn.displayName /*= fn.name*/ = "compiledAccumulatorLoop";
599
+ return fn;
600
+ }
601
+ // function compileFilter() {
602
+ // let filterInfo = getFunctionInfo(filter);
603
+ // let filterPath1 = "{ continue _coreloop; }$1";
604
+ // let filterPath2 = "{ _retval[_idx++] = $item$; continue _coreloop; }$1";
605
+ // // make some allowances for minification - there's only so far we can go with RegEx
606
+ // let filterBody = filterInfo.body
607
+ // .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
608
+ // .replace(/return!1([;}]|\}|$)/gi, filterPath1)
609
+ // .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
610
+ // .replace(/return!0([;}]|\}|$)/gi, filterPath2)
611
+ // .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
612
+ // "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
613
+ // // This preserves the function template code after JS compression,
614
+ // // so that replace() commands still work as expected.
615
+ // let tpl = [
616
+ // // "function(_items, _args) { ",
617
+ // "var _retval = [], _idx = 0; ",
618
+ // "var $item$, $args$ = _args; ",
619
+ // "_coreloop: ",
620
+ // "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
621
+ // "$item$ = _items[_i]; ",
622
+ // "$filter$; ",
623
+ // "} ",
624
+ // "return _retval; "
625
+ // // "}"
626
+ // ].join("");
627
+ // tpl = tpl.replace(/\$filter\$/gi, filterBody);
628
+ // tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
629
+ // tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
630
+ // let fn: any = new Function("_items,_args", tpl);
631
+ // fn.displayName = /*fn.name =*/ "compiledFilter";
632
+ // return fn;
633
+ // }
634
+ // function compileFilterWithCaching() {
635
+ // let filterInfo = getFunctionInfo(filter);
636
+ // let filterPath1 = "{ continue _coreloop; }$1";
637
+ // let filterPath2 = "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1";
638
+ // // make some allowances for minification - there's only so far we can go with RegEx
639
+ // let filterBody = filterInfo.body
640
+ // .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
641
+ // .replace(/return!1([;}]|\}|$)/gi, filterPath1)
642
+ // .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
643
+ // .replace(/return!0([;}]|\}|$)/gi, filterPath2)
644
+ // .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
645
+ // "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
646
+ // // This preserves the function template code after JS compression,
647
+ // // so that replace() commands still work as expected.
648
+ // let tpl = [
649
+ // // "function(_items, _args, _cache) { ",
650
+ // "var _retval = [], _idx = 0; ",
651
+ // "var $item$, $args$ = _args; ",
652
+ // "_coreloop: ",
653
+ // "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
654
+ // "$item$ = _items[_i]; ",
655
+ // "if (_cache[_i]) { ",
656
+ // "_retval[_idx++] = $item$; ",
657
+ // "continue _coreloop; ",
658
+ // "} ",
659
+ // "$filter$; ",
660
+ // "} ",
661
+ // "return _retval; "
662
+ // // "}"
663
+ // ].join("");
664
+ // tpl = tpl.replace(/\$filter\$/gi, filterBody);
665
+ // tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
666
+ // tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
667
+ // let fn: any = new Function("_items,_args,_cache", tpl);
668
+ // fn.displayName /*= fn.name*/ = "compiledFilterWithCaching";
669
+ // return fn;
670
+ // }
671
+ function uncompiledFilter(items, args) {
672
+ let retval = [], idx = 0;
673
+ for (let i = 0, ii = items.length; i < ii; i++) {
674
+ if (filter(items[i], args)) {
675
+ retval[idx++] = items[i];
676
+ }
677
+ }
678
+ return retval;
679
+ }
680
+ function uncompiledFilterWithCaching(items, args, cache) {
681
+ let retval = [], idx = 0, item;
682
+ for (let i = 0, ii = items.length; i < ii; i++) {
683
+ item = items[i];
684
+ if (cache[i]) {
685
+ retval[idx++] = item;
686
+ }
687
+ else if (filter(item, args)) {
688
+ retval[idx++] = item;
689
+ cache[i] = true;
690
+ }
691
+ }
692
+ return retval;
693
+ }
694
+ function getFilteredAndPagedItems(items) {
695
+ if (filter) {
696
+ let batchFilter = uncompiledFilter; // options.inlineFilters ? compiledFilter : uncompiledFilter;
697
+ let batchFilterWithCaching = uncompiledFilterWithCaching; // options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
698
+ if (refreshHints.isFilterNarrowing) {
699
+ filteredItems = batchFilter(filteredItems, filterArgs);
700
+ }
701
+ else if (refreshHints.isFilterExpanding) {
702
+ filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
703
+ }
704
+ else if (!refreshHints.isFilterUnchanged) {
705
+ filteredItems = batchFilter(items, filterArgs);
706
+ }
707
+ }
708
+ else {
709
+ // special case: if not filtering and not paging, the resulting
710
+ // rows collection needs to be a copy so that changes due to sort
711
+ // can be caught
712
+ filteredItems = pagesize ? items : items.concat();
713
+ }
714
+ // get the current page
715
+ let paged;
716
+ if (pagesize) {
717
+ if (filteredItems.length <= pagenum * pagesize) {
718
+ if (filteredItems.length === 0) {
719
+ pagenum = 0;
720
+ }
721
+ else {
722
+ pagenum = Math.floor((filteredItems.length - 1) / pagesize);
723
+ }
724
+ }
725
+ paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
726
+ }
727
+ else {
728
+ paged = filteredItems;
729
+ }
730
+ return { totalRows: filteredItems.length, rows: paged };
731
+ }
732
+ function getRowDiffs(rows, newRows) {
733
+ let item, r, eitherIsNonData, diff = [];
734
+ let from = 0, to = newRows.length;
735
+ if (refreshHints && refreshHints.ignoreDiffsBefore) {
736
+ from = Math.max(0, Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
737
+ }
738
+ if (refreshHints && refreshHints.ignoreDiffsAfter) {
739
+ to = Math.min(newRows.length, Math.max(0, refreshHints.ignoreDiffsAfter));
740
+ }
741
+ for (let i = from, rl = rows.length; i < to; i++) {
742
+ if (i >= rl) {
743
+ diff[diff.length] = i;
744
+ }
745
+ else {
746
+ item = newRows[i];
747
+ r = rows[i];
748
+ if ((groupingInfos.length && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
749
+ item.__group !== r.__group ||
750
+ item.__group && !item.equals(r))
751
+ || (eitherIsNonData &&
752
+ // no good way to compare totals since they are arbitrary DTOs
753
+ // deep object comparison is pretty expensive
754
+ // always considering them 'dirty' seems easier for the time being
755
+ (item.__groupTotals || r.__groupTotals))
756
+ || item[idProperty] != r[idProperty]
757
+ || (updated && updated[item[idProperty]])) {
758
+ diff[diff.length] = i;
759
+ }
760
+ }
761
+ }
762
+ return diff;
763
+ }
764
+ function recalc(_items, second) {
765
+ rowsById = null;
766
+ if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
767
+ refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
768
+ filterCache = [];
769
+ }
770
+ let filteredItems = getFilteredAndPagedItems(_items);
771
+ totalRows = filteredItems.totalRows;
772
+ let newRows = filteredItems.rows;
773
+ groups = [];
774
+ if (groupingInfos.length) {
775
+ groups = extractGroups(newRows);
776
+ if (groups.length) {
777
+ addTotals(groups);
778
+ newRows = flattenGroupedRows(groups);
779
+ }
780
+ }
781
+ let diff = getRowDiffs(rows, newRows);
782
+ rows = newRows;
783
+ return diff;
784
+ }
785
+ function refresh() {
786
+ if (suspend) {
787
+ return;
788
+ }
789
+ let countBefore = rows.length;
790
+ let totalRowsBefore = totalRows;
791
+ let diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
792
+ // if the current page is no longer valid, go to last page and recalc
793
+ // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
794
+ if (pagesize && totalRows < pagenum * pagesize) {
795
+ pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
796
+ diff = recalc(items, filter);
797
+ }
798
+ updated = null;
799
+ prevRefreshHints = refreshHints;
800
+ refreshHints = {};
801
+ if (totalRowsBefore !== totalRows) {
802
+ onPagingInfoChanged.notify(getPagingInfo(), null, self);
803
+ }
804
+ if (countBefore !== rows.length) {
805
+ onRowCountChanged.notify({ previous: countBefore, current: rows.length, dataView: self, callingOnRowsChanged: (diff.length > 0) }, null, self);
806
+ }
807
+ if (diff.length > 0) {
808
+ onRowsChanged.notify({ rows: diff, dataView: self, calledOnRowCountChanged: (countBefore !== rows.length) }, null, self);
809
+ }
810
+ if (countBefore !== rows.length || diff.length > 0) {
811
+ onRowsOrCountChanged.notify({
812
+ rowsDiff: diff, previousRowCount: countBefore, currentRowCount: rows.length,
813
+ rowCountChanged: countBefore !== rows.length, rowsChanged: diff.length > 0, dataView: self
814
+ }, null, self);
815
+ }
816
+ }
817
+ /***
818
+ * Wires the grid and the DataView together to keep row selection tied to item ids.
819
+ * This is useful since, without it, the grid only knows about rows, so if the items
820
+ * move around, the same rows stay selected instead of the selection moving along
821
+ * with the items.
822
+ *
823
+ * NOTE: This doesn't work with cell selection model.
824
+ *
825
+ * @param grid {Slick.Grid} The grid to sync selection with.
826
+ * @param preserveHidden {Boolean} Whether to keep selected items that go out of the
827
+ * view due to them getting filtered out.
828
+ * @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items
829
+ * that are currently out of the view (see preserveHidden) as selected when selection
830
+ * changes.
831
+ * @return {Slick.Event} An event that notifies when an internal list of selected row ids
832
+ * changes. This is useful since, in combination with the above two options, it allows
833
+ * access to the full list selected row ids, and not just the ones visible to the grid.
834
+ * @method syncGridSelection
835
+ */
836
+ function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
837
+ let self = this;
838
+ let inHandler;
839
+ let selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
840
+ let onSelectedRowIdsChanged = new Slick.Event();
841
+ function setSelectedRowIds(rowIds) {
842
+ if (selectedRowIds.join(",") == rowIds.join(",")) {
843
+ return;
844
+ }
845
+ selectedRowIds = rowIds;
846
+ onSelectedRowIdsChanged.notify({
847
+ grid: grid,
848
+ ids: selectedRowIds,
849
+ dataView: self
850
+ }, new Slick.EventData(), self);
851
+ }
852
+ function update() {
853
+ if (selectedRowIds.length > 0) {
854
+ inHandler = true;
855
+ let selectedRows = self.mapIdsToRows(selectedRowIds);
856
+ if (!preserveHidden) {
857
+ setSelectedRowIds(self.mapRowsToIds(selectedRows));
858
+ }
859
+ grid.setSelectedRows(selectedRows);
860
+ inHandler = false;
861
+ }
862
+ }
863
+ grid.onSelectedRowsChanged.subscribe(function (e, args) {
864
+ if (inHandler) {
865
+ return;
866
+ }
867
+ let newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
868
+ if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
869
+ setSelectedRowIds(newSelectedRowIds);
870
+ }
871
+ else {
872
+ // keep the ones that are hidden
873
+ let existing = [];
874
+ for (let i = 0; i < selectedRowIds.length; i++) {
875
+ if (self.getRowById(selectedRowIds[i]) === undefined) {
876
+ existing.push(selectedRowIds[i]);
877
+ }
878
+ }
879
+ // $.grep(selectedRowIds, function(id) { return self.getRowById(id) === undefined; });
880
+ // add the newly selected ones
881
+ setSelectedRowIds(existing.concat(newSelectedRowIds));
882
+ }
883
+ });
884
+ this.onRowsOrCountChanged.subscribe(update);
885
+ return onSelectedRowIdsChanged;
886
+ }
887
+ function syncGridCellCssStyles(grid, key) {
888
+ let hashById;
889
+ let inHandler;
890
+ // since this method can be called after the cell styles have been set,
891
+ // get the existing ones right away
892
+ storeCellCssStyles(grid.getCellCssStyles(key));
893
+ function storeCellCssStyles(hash) {
894
+ hashById = {};
895
+ for (let row in hash) {
896
+ let id = rows[row][idProperty];
897
+ hashById[id] = hash[row];
898
+ }
899
+ }
900
+ function update() {
901
+ if (hashById) {
902
+ inHandler = true;
903
+ ensureRowsByIdCache();
904
+ let newHash = {};
905
+ for (let id in hashById) {
906
+ let row = rowsById[id];
907
+ if (row != undefined) {
908
+ newHash[row] = hashById[id];
909
+ }
910
+ }
911
+ grid.setCellCssStyles(key, newHash);
912
+ inHandler = false;
913
+ }
914
+ }
915
+ grid.onCellCssStylesChanged.subscribe(function (e, args) {
916
+ if (inHandler) {
917
+ return;
918
+ }
919
+ if (key != args.key) {
920
+ return;
921
+ }
922
+ if (args.hash) {
923
+ storeCellCssStyles(args.hash);
924
+ }
925
+ else {
926
+ // grid.onCellCssStylesChanged.unsubscribe(styleChanged); //styleChanged not declared
927
+ self.onRowsOrCountChanged.unsubscribe(update);
928
+ }
929
+ });
930
+ this.onRowsOrCountChanged.subscribe(update);
931
+ }
932
+ $.shallowExtend(this, {
933
+ // methods
934
+ beginUpdate: beginUpdate,
935
+ endUpdate: endUpdate,
936
+ setPagingOptions: setPagingOptions,
937
+ getPagingInfo: getPagingInfo,
938
+ getItems: getItems,
939
+ setItems: setItems,
940
+ setFilter: setFilter,
941
+ getFilter: getFilter,
942
+ getFilteredItems: getFilteredItems,
943
+ sort: sort,
944
+ // "fastSort": fastSort,
945
+ reSort: reSort,
946
+ setGrouping: setGrouping,
947
+ getGrouping: getGrouping,
948
+ groupBy: groupBy,
949
+ setAggregators: setAggregators,
950
+ collapseAllGroups: collapseAllGroups,
951
+ expandAllGroups: expandAllGroups,
952
+ collapseGroup: collapseGroup,
953
+ expandGroup: expandGroup,
954
+ getGroups: getGroups,
955
+ getIdxById: getIdxById,
956
+ getIdxByItem: getIdxByItem,
957
+ getRowByItem: getRowByItem,
958
+ getRowById: getRowById,
959
+ getItemById: getItemById,
960
+ getItemByIdx: getItemByIdx,
961
+ mapItemsToRows: mapItemsToRows,
962
+ mapRowsToIds: mapRowsToIds,
963
+ mapIdsToRows: mapIdsToRows,
964
+ setRefreshHints: setRefreshHints,
965
+ setFilterArgs: setFilterArgs,
966
+ refresh: refresh,
967
+ updateItem: updateItem,
968
+ insertItem: insertItem,
969
+ addItem: addItem,
970
+ deleteItem: deleteItem,
971
+ sortedAddItem: sortedAddItem,
972
+ sortedUpdateItem: sortedUpdateItem,
973
+ syncGridSelection: syncGridSelection,
974
+ syncGridCellCssStyles: syncGridCellCssStyles,
975
+ // data provider methods
976
+ getLength: getLength,
977
+ getItem: getItem,
978
+ getItemMetadata: getItemMetadata,
979
+ // events
980
+ onRowCountChanged: onRowCountChanged,
981
+ onRowsChanged: onRowsChanged,
982
+ onRowsOrCountChanged: onRowsOrCountChanged,
983
+ onPagingInfoChanged: onPagingInfoChanged
984
+ });
985
+ }
986
+ export function AvgAggregator(field) {
987
+ this.field_ = field;
988
+ this.init = function () {
989
+ this.count_ = 0;
990
+ this.nonNullCount_ = 0;
991
+ this.sum_ = 0;
992
+ };
993
+ this.accumulate = function (item) {
994
+ let val = item[this.field_];
995
+ this.count_++;
996
+ if (val != null && val !== "" && !isNaN(val)) {
997
+ this.nonNullCount_++;
998
+ this.sum_ += parseFloat(val);
999
+ }
1000
+ };
1001
+ this.storeResult = function (groupTotals) {
1002
+ if (!groupTotals.avg) {
1003
+ groupTotals.avg = {};
1004
+ }
1005
+ if (this.nonNullCount_ != 0) {
1006
+ groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
1007
+ }
1008
+ };
1009
+ }
1010
+ export function MinAggregator(field) {
1011
+ this.field_ = field;
1012
+ this.init = function () {
1013
+ this.min_ = null;
1014
+ };
1015
+ this.accumulate = function (item) {
1016
+ let val = item[this.field_];
1017
+ if (val != null && val !== "" && !isNaN(val)) {
1018
+ if (this.min_ == null || val < this.min_) {
1019
+ this.min_ = val;
1020
+ }
1021
+ }
1022
+ };
1023
+ this.storeResult = function (groupTotals) {
1024
+ if (!groupTotals.min) {
1025
+ groupTotals.min = {};
1026
+ }
1027
+ groupTotals.min[this.field_] = this.min_;
1028
+ };
1029
+ }
1030
+ export function MaxAggregator(field) {
1031
+ this.field_ = field;
1032
+ this.init = function () {
1033
+ this.max_ = null;
1034
+ };
1035
+ this.accumulate = function (item) {
1036
+ let val = item[this.field_];
1037
+ if (val != null && val !== "" && !isNaN(val)) {
1038
+ if (this.max_ == null || val > this.max_) {
1039
+ this.max_ = val;
1040
+ }
1041
+ }
1042
+ };
1043
+ this.storeResult = function (groupTotals) {
1044
+ if (!groupTotals.max) {
1045
+ groupTotals.max = {};
1046
+ }
1047
+ groupTotals.max[this.field_] = this.max_;
1048
+ };
1049
+ }
1050
+ export function SumAggregator(field) {
1051
+ this.field_ = field;
1052
+ this.init = function () {
1053
+ this.sum_ = null;
1054
+ };
1055
+ this.accumulate = function (item) {
1056
+ let val = item[this.field_];
1057
+ if (val != null && val !== "" && !isNaN(val)) {
1058
+ this.sum_ += parseFloat(val);
1059
+ }
1060
+ };
1061
+ this.storeResult = function (groupTotals) {
1062
+ if (!groupTotals.sum) {
1063
+ groupTotals.sum = {};
1064
+ }
1065
+ groupTotals.sum[this.field_] = this.sum_;
1066
+ };
1067
+ }
1068
+ // tODO: add more built-in aggregators
1069
+ // tODO: merge common aggregators in one to prevent needles iterating