@refinitiv-ui/efx-grid 6.0.83 → 6.0.84

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,15 +1,14 @@
1
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
2
-
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
3
2
  import { Ext } from "../../tr-grid-util/es6/Ext.js";
4
3
  import { GridPlugin } from "../../tr-grid-util/es6/GridPlugin.js";
5
4
  import { FilterBuilder, stringToDateObject } from "../../tr-grid-util/es6/FilterBuilder.js";
6
5
  import { FilterOperators } from "../../tr-grid-util/es6/FilterOperators.js";
7
6
  import { ElfUtil } from "../../tr-grid-util/es6/ElfUtil.js";
8
- import { injectCss, prettifyCss } from "../../tr-grid-util/es6/Util.js";
7
+ import { injectCss, prettifyCss, cloneObject } from "../../tr-grid-util/es6/Util.js";
8
+
9
9
  /** @event RowFilteringPlugin#click
10
10
  * @description click event is dispatched when a user clicks the column filter icon.
11
11
  */
12
-
13
12
  /** @event RowFilteringPlugin#beforeDialogOpened
14
13
  * @description Fired before the opening of filter dialog. This can be used to cancel the operation or set a dialog configuration at runtime.
15
14
  * @property {number} colIndex Column index
@@ -23,7 +22,6 @@ import { injectCss, prettifyCss } from "../../tr-grid-util/es6/Util.js";
23
22
  * e.dialogOptions = { sortLogic: func }; // To set a dialog configuration
24
23
  * },
25
24
  */
26
-
27
25
  /** @event RowFilteringPlugin#dialogCommitted
28
26
  * @description Fired after a user clicks done button from the filter dialog or changes sort order.
29
27
  * @property {number} colIndex
@@ -31,14 +29,12 @@ import { injectCss, prettifyCss } from "../../tr-grid-util/es6/Util.js";
31
29
  * @property {number=} sortOrder When sort order is changed, the change will be passed through this property
32
30
  * @property {string=} fieldDataType
33
31
  */
34
-
35
32
  /** @event RowFilteringPlugin#iconCreated
36
33
  * @description iconCreated event is dispatched when a new column filter icon is created.
37
34
  * @property {Element} icon Filter icon element
38
35
  * @property {number} colIndex Column index
39
36
  * @property {Object} grid Core grid instance
40
37
  */
41
-
42
38
  /** @event RowFilteringPlugin#filterChanged
43
39
  * @description Fired whenever global or column filter is changed by either adding or removing. The change will not immediately applied to grid's data view
44
40
  * @property {string} filterType This can be either "global" or "column"
@@ -46,7 +42,6 @@ import { injectCss, prettifyCss } from "../../tr-grid-util/es6/Util.js";
46
42
  * @property {number} colIndex Column index
47
43
  * @property {string} field specified by the current column
48
44
  */
49
-
50
45
  /** @event RowFilteringPlugin#refreshed
51
46
  * @description Fired after new filter is applied to grid's data view
52
47
  */
@@ -93,6 +88,7 @@ The expression can take various forms:<br>
93
88
  * @property {Function=} sortLogic This function for sorting filter item list in the dialog. The comparison will perform on raw values, and not formatted values
94
89
  * @property {Array=} itemList Item list to be shown in the dialog. If this is not specified, the list will be collected from existing data on the grid
95
90
  * @property {Array=} additionalItems Additional items to be put on the itemList
91
+ * @property {(boolean|string)=} blankValues Display a "(Blanks)" item in the filter dialog to represent an empty value. If a string is passed, it will be used as the label for the blank item
96
92
  */
97
93
 
98
94
  /** @typedef {Object} RowFilteringPlugin~Options
@@ -113,21 +109,25 @@ The expression can take various forms:<br>
113
109
  * @param {Object} cfo
114
110
  * @return {!RowFilteringPlugin~FilterExpression}
115
111
  */
116
-
117
112
  var toFilterExpression = function toFilterExpression(cfo) {
118
- var ctx = cfo._context[0]; // TODO: Handle rawDataAccessor and formattedDataAccessor (saving and loading of functions)
119
-
113
+ var ctx = cfo._context[0];
114
+ // TODO: Handle rawDataAccessor and formattedDataAccessor (saving and loading of functions)
120
115
  return {
121
116
  field: cfo._field || "",
122
117
  expression: cfo._expressions[0],
123
118
  context: ctx != null && !ctx._autoGenerated ? ctx : null
124
119
  };
125
120
  };
121
+
122
+ /** @type {string}
123
+ * @private
124
+ * @const
125
+ */
126
+ var BLANKS = "(Blanks)";
127
+
126
128
  /** @constructor
127
129
  * @extends {GridPlugin}
128
130
  */
129
-
130
-
131
131
  var RowFilteringPlugin = function RowFilteringPlugin() {
132
132
  var t = this;
133
133
  t._onPreSectionRender = t._onPreSectionRender.bind(t);
@@ -147,122 +147,100 @@ var RowFilteringPlugin = function RowFilteringPlugin() {
147
147
  t._funcMap = {};
148
148
  t._nameMap = {};
149
149
  };
150
-
151
150
  Ext.inherits(RowFilteringPlugin, GridPlugin);
151
+
152
152
  /** @type {!Object.<string, Function>}
153
153
  * @private
154
154
  */
155
-
156
155
  RowFilteringPlugin.prototype._funcMap = null; // For preventing repetition of resolving the same expression
157
-
158
156
  /** @type {!Object.<string, Function>}
159
157
  * @private
160
158
  */
161
-
162
159
  RowFilteringPlugin.prototype._nameMap; // Mapping name to filter function for referencing
163
160
 
164
161
  /** @type {boolean}
165
162
  * @private
166
163
  */
167
-
168
164
  RowFilteringPlugin.prototype._disabled = false;
169
165
  /** @type {Object.<string, boolean>}
170
166
  * @private
171
167
  */
172
-
173
168
  RowFilteringPlugin.prototype._disablingIds = null; // For nested disabling
174
169
 
175
170
  /** @type {!Array.<Function>}
176
171
  * @private
177
172
  */
178
-
179
173
  RowFilteringPlugin.prototype._globalFilters;
180
174
  /** @type {!Array.<Object>}
181
175
  * @private
182
176
  */
183
-
184
177
  RowFilteringPlugin.prototype._globalContexts;
185
178
  /** @type {!Array.<Object>}
186
179
  * @private
187
180
  */
188
-
189
181
  RowFilteringPlugin.prototype._columnFilters;
190
182
  /** @type {Array.<Object>}
191
183
  * @private
192
184
  */
193
-
194
185
  RowFilteringPlugin.prototype._activeColFilters = null;
195
186
  /** @type {string}
196
187
  * @private
197
188
  */
198
-
199
189
  RowFilteringPlugin.prototype._iconActivation = "onActiveFilter";
200
190
  /** @type {number}
201
191
  * @private
202
192
  */
203
-
204
193
  RowFilteringPlugin.prototype._filterId = 0;
205
194
  /** @type {number}
206
195
  * @private
207
196
  */
208
-
209
197
  RowFilteringPlugin.prototype._uiTimerId = 0;
210
198
  /** @type {number}
211
199
  * @private
212
200
  */
213
-
214
201
  RowFilteringPlugin.prototype._filterTimerId = 0;
215
202
  /** @type {Function}
216
203
  * @private
217
204
  */
218
-
219
205
  RowFilteringPlugin.prototype._overridingFilter = null;
220
206
  /** @type {Function}
221
207
  * @private
222
208
  */
223
-
224
209
  RowFilteringPlugin.prototype._preTransform = null;
225
210
  /** @type {Function}
226
211
  * @private
227
212
  */
228
-
229
213
  RowFilteringPlugin.prototype._rowTransform = null;
230
214
  /** @type {Element}
231
215
  * @private
232
216
  */
233
-
234
217
  RowFilteringPlugin.prototype._filterDialog = null;
235
218
  /** @type {boolean}
236
219
  * @private
237
220
  */
238
-
239
221
  RowFilteringPlugin.prototype._dialogInitialized = false;
240
222
  /** @type {RowFilteringPlugin~FilterDialogOptions}
241
223
  * @private
242
224
  */
243
-
244
225
  RowFilteringPlugin.prototype._dialogOptions = null;
245
226
  /** @type {FilterBuilder}
246
227
  * @private
247
228
  */
248
-
249
229
  RowFilteringPlugin._filterBuilder = null;
250
230
  /** @type {string}
251
231
  * @private
252
232
  */
253
-
254
233
  RowFilteringPlugin._dialogTagName; // intentionally left undefined
255
234
 
256
235
  /** Array of DataView objects
257
236
  * @type {!Array.<Object>}
258
237
  * @private
259
238
  */
260
-
261
239
  RowFilteringPlugin.prototype._dvs;
240
+
262
241
  /** @public
263
242
  * @return {string}
264
243
  */
265
-
266
244
  RowFilteringPlugin.prototype.getName = function () {
267
245
  return "RowFilteringPlugin"; // Read Only
268
246
  };
@@ -270,115 +248,88 @@ RowFilteringPlugin.prototype.getName = function () {
270
248
  * @param {Object} host core grid instance
271
249
  * @param {Object=} options
272
250
  */
273
-
274
-
275
251
  RowFilteringPlugin.prototype.initialize = function (host, options) {
276
252
  if (this._hosts.indexOf(host) >= 0) {
277
253
  return;
278
254
  }
279
-
280
255
  this._hosts.push(host);
281
-
282
256
  if (!RowFilteringPlugin._styles) {
283
257
  RowFilteringPlugin._styles = prettifyCss([".hovering-filter-icon .cell:not(.active-filter):hover .floating-panel .title-filter-icon", ["display: flex;"], ".hovering-filter-icon .cell:not(.active-filter) .floating-panel .title-filter-icon", ["display: none;"], ".floating-panel", ["position:relative;"], ".floating-panel .title-filter-icon", ["color: var(--grid-title-filter-icon-color,inherit);"], ".title .floating-panel .title-filter-icon:hover", ["color: var(--grid-title-filter-icon-hover-color,inherit);"], ".always-on-filter .floating-panel .title-filter-icon", ["color: var(--grid-header-txtcolor,inherit);"], ".always-on-filter .active-filter .floating-panel .title-filter-icon", ["color: var(--grid-title-filter-icon-hover-color,inherit);"], ".hovering-filter-icon .tiny-col .cell:hover, .tr-grid .tiny-col .cell.active-filter", ["padding-left:0px;"], ".tiny-col.movable .cell .floating-panel .title-filter-icon:before", ["content: '.';", "position: absolute;", "margin-left: auto;", "margin-right: auto;", "left: 0;", "right: 0;", "top: -10px;", "font-size: 10px;", "font-family: monospace;", "color: var(--grid-title-dot-icon,inherit);", "text-align:center;"]]);
284
258
  }
285
-
286
259
  if (!host._rowFilteringStyles) {
287
260
  host._rowFilteringStyles = true;
288
261
  injectCss(RowFilteringPlugin._styles, host.getElement());
289
262
  }
290
-
291
263
  host.unloadPlugin("ColumnFilterPlugin");
292
264
  host.listen("preSectionRender", this._onPreSectionRender);
293
265
  host.listen("postDataSourceChanged", this._requestFilterRefresh); // TODO: Check if this is necessary
294
-
295
266
  host.listen("columnAdded", this._onColumnAdded);
296
267
  host.listen("columnRemoved", this._onColumnRemoved);
297
- this.config(options); // In case of lazy loading
268
+ this.config(options);
269
+ // In case of lazy loading
298
270
  // TODO
299
271
  };
300
272
  /** @public
301
273
  * @param {Object} host core grid instance
302
274
  */
303
-
304
-
305
275
  RowFilteringPlugin.prototype.unload = function (host) {
306
276
  var at = this._hosts.indexOf(host);
307
-
308
277
  if (at < 0) {
309
278
  return;
310
279
  }
311
-
312
280
  this._hosts.splice(at, 1);
313
-
314
281
  host.unlisten("preSectionRender", this._onPreSectionRender);
315
282
  host.unlisten("postDataSourceChanged", this._requestFilterRefresh);
316
283
  host.unlisten("columnAdded", this._onColumnAdded);
317
284
  host.unlisten("columnRemoved", this._onColumnRemoved);
318
-
319
285
  if (!this._hosts.length) {
320
286
  if (this._uiTimerId) {
321
287
  clearTimeout(this._uiTimerId);
322
288
  this._uiTimerId = 0;
323
289
  }
324
-
325
290
  if (this._filterTimerId) {
326
291
  clearTimeout(this._filterTimerId);
327
292
  this._filterTimerId = 0;
328
293
  }
329
-
330
294
  this._hasPendingFilter = false;
331
-
332
295
  if (this._filterDialog) {
333
296
  this._filterDialog.hide(); // Remove the dialog from document
334
-
335
-
336
297
  this._filterDialog = null;
337
298
  this._dialogInitialized = false;
338
299
  }
339
300
  }
340
-
341
301
  this._dispose();
342
302
  };
343
303
  /**
344
304
  * @protected
345
305
  * @ignore
346
306
  */
347
-
348
-
349
307
  RowFilteringPlugin.prototype._afterInit = function () {
350
308
  if (!this._filterDialog) {
351
309
  this._filterDialog = RowFilteringPlugin._createDialog();
352
310
  this._dialogInitialized = false;
353
-
354
311
  if (this._filterDialog) {
355
312
  this._filterDialog.style.display = "none";
356
313
  document.body.appendChild(this._filterDialog);
357
314
  setTimeout(this._onPreLoadedDialog, 10);
358
315
  }
359
316
  }
360
-
361
317
  this._applyPendingFilter();
362
318
  };
319
+
363
320
  /** @private
364
321
  */
365
-
366
-
367
322
  RowFilteringPlugin.prototype._applyPendingFilter = function () {
368
323
  if (!this._initializedGrid) {
369
324
  return;
370
325
  }
371
-
372
326
  if (!this._hasPendingFilter) {
373
327
  return;
374
328
  }
375
-
376
329
  this._hasPendingFilter = false;
377
330
  var colCount = this.getColumnCount();
378
-
379
331
  for (var c = 0; c < colCount; ++c) {
380
332
  var colSettings = this._getUserColumnSettings(c);
381
-
382
333
  if (colSettings.expression) {
383
334
  this.addColumnFilter(c, colSettings.expression, colSettings.filterState);
384
335
  } else {
@@ -388,55 +339,44 @@ RowFilteringPlugin.prototype._applyPendingFilter = function () {
388
339
  };
389
340
  /** @private
390
341
  */
391
-
392
-
393
342
  RowFilteringPlugin.prototype._onPreLoadedDialog = function () {
394
343
  if (this._filterDialog) {
395
344
  this._filterDialog.style.display = "";
396
345
  var pn = this._filterDialog.parentNode;
397
-
398
346
  if (pn) {
399
347
  pn.removeChild(this._filterDialog);
400
348
  }
401
349
  }
402
350
  };
351
+
403
352
  /** @public
404
353
  * @param {Object=} options
405
354
  */
406
-
407
-
408
355
  RowFilteringPlugin.prototype.config = function (options) {
409
356
  if (!options) {
410
357
  return;
411
358
  }
412
-
413
359
  var rowFiltering = options["rowFiltering"];
414
-
415
360
  if (rowFiltering) {
416
361
  if (rowFiltering["disabledUI"] || rowFiltering["uiDisabled"]) {
417
362
  this._iconActivation = "none";
418
363
  }
419
-
420
364
  if (rowFiltering["emptySegmentFiltering"] != null) {
421
365
  // TODO: there is a chance that there is no DataView during the configuration
422
366
  this.enableEmptySegmentFiltering(rowFiltering["emptySegmentFiltering"] ? true : false);
423
367
  }
424
-
425
368
  if (rowFiltering["separatorFiltering"] != null) {
426
369
  // TODO: there is a chance that there is no DataView during the configuration
427
370
  this.enableSeparatorFiltering(rowFiltering["separatorFiltering"] ? true : false);
428
371
  }
429
-
430
372
  if (rowFiltering["iconActivation"]) {
431
373
  this._iconActivation = rowFiltering["iconActivation"];
432
-
433
374
  for (var index = 0; index < this._hosts.length; index++) {
434
375
  if (this._iconActivation === "onHover") {
435
376
  this._hosts[index].enableClass("hovering-filter-icon", true);
436
377
  } else {
437
378
  this._hosts[index].enableClass("hovering-filter-icon", false);
438
379
  }
439
-
440
380
  if (this._iconActivation === "always") {
441
381
  this._hosts[index].enableClass("always-on-filter", true);
442
382
  } else {
@@ -444,15 +384,12 @@ RowFilteringPlugin.prototype.config = function (options) {
444
384
  }
445
385
  }
446
386
  }
447
-
448
387
  if (rowFiltering["dialogOptions"]) {
449
388
  this._dialogOptions = rowFiltering["dialogOptions"];
450
389
  }
451
-
452
390
  if (rowFiltering["clicked"]) {
453
391
  rowFiltering["click"] = rowFiltering["clicked"];
454
392
  }
455
-
456
393
  this.addListener(rowFiltering, "click");
457
394
  this.addListener(rowFiltering, "beforeDialogOpened");
458
395
  this.addListener(rowFiltering, "dialogCommitted");
@@ -460,112 +397,99 @@ RowFilteringPlugin.prototype.config = function (options) {
460
397
  this.addListener(rowFiltering, "filterChanged");
461
398
  this.addListener(rowFiltering, "refreshed");
462
399
  }
463
-
464
400
  var columns = options["columns"];
465
-
466
401
  if (!columns) {
467
402
  return;
468
- } // var host = this._hosts[0];
469
-
403
+ }
470
404
 
405
+ // var host = this._hosts[0];
471
406
  var len = columns.length;
472
-
473
407
  for (var i = 0; i < len; ++i) {
474
408
  var column = columns[i];
475
-
476
409
  this._setColumnOptions(i, column);
477
410
  }
478
-
479
411
  this._applyPendingFilter();
480
412
  };
481
413
  /** @public
482
414
  * @param {Object=} gridOptions
483
415
  * @return {!Object}
484
416
  */
485
-
486
-
487
417
  RowFilteringPlugin.prototype.getConfigObject = function (gridOptions) {
488
418
  var obj = gridOptions || {};
489
419
  var columns = obj.columns;
490
-
491
420
  if (!columns) {
492
421
  columns = obj.columns = [];
493
422
  }
494
-
495
423
  var len = this.getColumnCount();
496
-
497
424
  for (var i = 0; i < len; ++i) {
498
425
  var column = columns[i];
499
-
500
426
  if (!column) {
501
427
  column = columns[i] = {};
502
428
  }
503
-
504
429
  var colSettings = this._getUserColumnSettings(i);
505
-
506
430
  var exp = colSettings.expression;
507
-
508
431
  if (exp && typeof exp !== "function") {
509
432
  // TODO: Accept function type
510
- column.filter = exp; // This could be string, array, or object
433
+ if (_typeof(exp) === "object" && !Array.isArray(exp)) {
434
+ var expClone = cloneObject(exp);
435
+ if (expClone[""] || expClone["null"] || expClone["undefined"] || expClone["NaN"]) {
436
+ delete expClone[""];
437
+ delete expClone["null"];
438
+ delete expClone["undefined"];
439
+ delete expClone["NaN"];
440
+ expClone[BLANKS] = true;
441
+ column.filter = expClone; // This could be only object
442
+ } else {
443
+ column.filter = exp;
444
+ }
445
+ } else {
446
+ column.filter = exp; // This could be string or array
447
+ }
511
448
  }
512
449
 
513
450
  var ctx = colSettings.filterState;
514
-
515
451
  if (ctx != null) {
516
452
  if (_typeof(ctx) !== "object" || !ctx._autoGenerated) {
517
453
  column.filterState = ctx;
518
454
  }
519
455
  }
520
456
  }
521
-
522
457
  var extOptions = obj.rowFiltering;
523
458
  var dirty = false;
524
-
525
459
  if (!extOptions) {
526
460
  extOptions = {};
527
461
  }
528
-
529
462
  if (this._iconActivation !== "onActiveFilter") {
530
463
  extOptions.iconActivation = this._iconActivation;
531
464
  dirty = true;
532
465
  }
533
-
534
466
  if (this._dialogOptions) {
535
467
  extOptions.dialogOptions = this._dialogOptions; // TODO: dialogOptions should not contain any function
536
-
537
468
  dirty = true;
538
- } // TODO: get emptySegmentFiltering setting from DataView
469
+ }
470
+ // TODO: get emptySegmentFiltering setting from DataView
539
471
  // TODO: get separatorFiltering setting from DataView
540
-
541
-
542
472
  if (dirty) {
543
473
  obj.rowFiltering = extOptions;
544
474
  }
545
-
546
475
  return obj;
547
476
  };
477
+
548
478
  /** All filter logics in DataView will be temporarily removed until re-enabling. This is useful when trying to insert an item at the specified index. After re-enabling, both logics and icons will be restored.
549
479
  * @public
550
480
  * @param {boolean=} opt_disabled
551
481
  * @param {string=} opt_id For handling nested called
552
482
  */
553
-
554
-
555
483
  RowFilteringPlugin.prototype.disable = function (opt_disabled, opt_id) {
556
484
  var disabled = opt_disabled !== false;
557
-
558
485
  if (!this._disablingIds) {
559
486
  this._disablingIds = {};
560
487
  }
561
-
562
488
  if (!opt_id) {
563
489
  opt_id = "_";
564
490
  }
565
-
566
491
  this._disablingIds[opt_id] = disabled;
567
492
  disabled = false;
568
-
569
493
  for (var key in this._disablingIds) {
570
494
  // Find cumulative state
571
495
  if (this._disablingIds[key]) {
@@ -573,22 +497,18 @@ RowFilteringPlugin.prototype.disable = function (opt_disabled, opt_id) {
573
497
  break;
574
498
  }
575
499
  }
576
-
577
500
  if (this._disabled !== disabled) {
578
501
  this._disabled = disabled;
579
-
580
502
  if (disabled) {
581
503
  this.refresh(); // Take an effect immediately
582
-
583
504
  this._updateAllColumnIcons();
584
505
  } else {
585
506
  this._requestFilterRefresh(); // Take an effect later
586
-
587
-
588
507
  this._setTimerForUpdatingIcons();
589
508
  }
590
509
  }
591
510
  };
511
+
592
512
  /** Add a global filter that is not related to any column. No filter icon is created in this way
593
513
  * @public
594
514
  * @param {RowFilteringPlugin~Expression} exp Expression or Function
@@ -597,39 +517,29 @@ RowFilteringPlugin.prototype.disable = function (opt_disabled, opt_id) {
597
517
  * @return {string} If success, function name is returned, otherwise empty string
598
518
  * @fires RowFilteringPlugin#filterChanged
599
519
  */
600
-
601
-
602
520
  RowFilteringPlugin.prototype.addFilter = function (exp, funcName, ctx) {
603
521
  var func = this._parseFilter(exp, -1);
604
-
605
522
  if (!func) {
606
523
  return "";
607
524
  }
608
-
609
525
  if (!funcName) {
610
526
  funcName = "_" + this._filterId++;
611
527
  }
612
-
613
528
  if (this._nameMap[funcName] || this._globalFilters.indexOf(func) >= 0) {
614
529
  return ""; // Function is already exists
615
530
  }
616
531
 
617
532
  ctx = ctx != null ? ctx : null;
618
533
  this._nameMap[funcName] = func;
619
-
620
534
  this._globalFilters.push(func);
621
-
622
535
  this._globalContexts.push(ctx);
623
-
624
536
  this._dispatch("filterChanged", {
625
537
  "filterType": "global",
626
538
  "changeType": "add",
627
539
  "colIndex": -1,
628
540
  "field": null
629
541
  });
630
-
631
542
  this._requestFilterRefresh();
632
-
633
543
  return funcName;
634
544
  };
635
545
  /** Add a global filter that is not related to any column. No filter icon is created in this way
@@ -639,8 +549,6 @@ RowFilteringPlugin.prototype.addFilter = function (exp, funcName, ctx) {
639
549
  * @return {string} If success, function name is returned, otherwise empty string
640
550
  * @fires RowFilteringPlugin#filterChanged
641
551
  */
642
-
643
-
644
552
  RowFilteringPlugin.prototype.addGridFilter = function (exp, ctx) {
645
553
  return this.addFilter(exp, null, ctx);
646
554
  };
@@ -650,43 +558,39 @@ RowFilteringPlugin.prototype.addGridFilter = function (exp, ctx) {
650
558
  * @param {*=} ctx
651
559
  * @return {Function}
652
560
  */
653
-
654
-
655
561
  RowFilteringPlugin.prototype._parseFilter = function (exp, colIndex, ctx) {
656
562
  if (!exp) {
657
563
  return null;
658
564
  }
659
-
660
565
  if (typeof exp === "function") {
661
566
  return exp;
662
567
  }
663
-
664
568
  var filterBuilder = RowFilteringPlugin._getFilterBuilder();
665
-
666
569
  var validIdx = colIndex || colIndex === 0;
667
570
  var field = validIdx ? this._getField(colIndex) : "";
668
571
  var formatter = validIdx ? this._getFormatter(colIndex) : null;
669
572
  var func = null;
670
-
671
573
  if (typeof exp === "string") {
672
574
  // Free text does not need data accessors
673
575
  func = this._funcMap[exp];
674
-
675
576
  if (func == null) {
676
577
  func = this._funcMap[exp] = filterBuilder.parse(exp, field, formatter, field);
677
578
  }
678
579
  } else {
679
580
  var rawDataAccessor = null;
680
581
  var formattedDataAccessor = null;
681
-
682
582
  if (ctx) {
683
583
  rawDataAccessor = ctx.rawDataAccessor || null;
684
584
  formattedDataAccessor = ctx.formattedDataAccessor || null;
685
585
  }
686
-
586
+ if (!Array.isArray(exp)) {
587
+ if (exp[BLANKS] || ctx && ctx.blankValues) {
588
+ exp[""] = exp["null"] = exp["undefined"] = exp["NaN"] = true;
589
+ delete exp[BLANKS];
590
+ }
591
+ }
687
592
  func = filterBuilder.parse(exp, field, formatter, field, rawDataAccessor, formattedDataAccessor);
688
593
  }
689
-
690
594
  return func;
691
595
  };
692
596
  /** If you want the column to always have one single filter, please use {@link RowFilteringPlugin#setColumnFilter} instead. This method allow a single column to have multiple filters.
@@ -697,15 +601,11 @@ RowFilteringPlugin.prototype._parseFilter = function (exp, colIndex, ctx) {
697
601
  * @return {boolean} True if success
698
602
  * @fires RowFilteringPlugin#filterChanged
699
603
  */
700
-
701
-
702
604
  RowFilteringPlugin.prototype.addColumnFilter = function (colIndex, exp, ctx) {
703
605
  if (colIndex < 0 || colIndex >= this.getColumnCount()) {
704
606
  return false;
705
607
  }
706
-
707
608
  var cfo = this._getColumnFilterOption(colIndex);
708
-
709
609
  if (cfo) {
710
610
  if (cfo._expressions[0] === exp) {
711
611
  return false; // The same expression is getting added on the same column twice
@@ -713,67 +613,47 @@ RowFilteringPlugin.prototype.addColumnFilter = function (colIndex, exp, ctx) {
713
613
  }
714
614
 
715
615
  var func = null;
716
-
717
616
  if (typeof exp === "function") {
718
- func =
719
- /** @type{Function} */
720
- exp;
721
-
617
+ func = /** @type{Function} */exp;
722
618
  if (ctx && typeof ctx === "string") {
723
619
  exp = ctx;
724
620
  }
725
621
  } else {
726
622
  func = this._parseFilter(exp, colIndex, ctx);
727
623
  }
728
-
729
624
  if (!func) {
730
625
  return false;
731
626
  }
732
-
733
627
  var colSettings = this._getUserColumnSettings(colIndex);
734
-
735
628
  colSettings.expression = exp; // WARNING: Only the last expression are saved (previous one is overwritten)
736
-
737
629
  colSettings.filterState = ctx;
738
-
739
630
  if (ctx == null) {
740
631
  ctx = {
741
632
  "_autoGenerated": true
742
633
  };
743
634
  }
744
-
745
635
  var field = this._getField(colIndex);
746
-
747
636
  if (ctx && _typeof(ctx) === "object") {
748
637
  ctx["field"] = field;
749
638
  }
750
-
751
639
  cfo = this._initColumnFilterOption(colIndex);
752
640
  cfo._field = field; // TODO: Handle fieldDataType
753
-
754
641
  cfo._filters.push(func);
755
-
756
642
  cfo._expressions.push(exp);
757
-
758
643
  cfo._context.push(ctx);
759
-
760
644
  cfo._rawDataAccessor = ctx.rawDataAccessor || null;
761
645
  cfo._formattedDataAccessor = ctx.formattedDataAccessor || null;
762
-
763
646
  this._columnFilters.push(cfo);
764
-
765
647
  this._dispatch("filterChanged", {
766
648
  "filterType": "column",
767
649
  "changeType": "add",
768
650
  "colIndex": colIndex,
769
651
  "field": field
770
- }); // UI
771
-
652
+ });
772
653
 
654
+ // UI
773
655
  this._requestFilterRefresh();
774
-
775
656
  this._updateColumnIcon(colIndex);
776
-
777
657
  return true;
778
658
  };
779
659
  /** This method guarantees that the column can have at most one filter at the time. It performs {@link RowFilteringPlugin#removeColumnFilters} before {@link RowFilteringPlugin#addColumnFilter}
@@ -796,34 +676,24 @@ RowFilteringPlugin.prototype.addColumnFilter = function (colIndex, exp, ctx) {
796
676
  * }
797
677
  * );
798
678
  */
799
-
800
-
801
679
  RowFilteringPlugin.prototype.setColumnFilter = function (colIndex, exp, ctx) {
802
680
  var curExp = this._getColumnExpression(colIndex);
803
-
804
681
  if (curExp === exp) {
805
682
  return false;
806
683
  }
807
-
808
684
  var removed = this._removeColumnFilters(colIndex);
809
-
810
685
  var added = this.addColumnFilter(colIndex, exp, ctx);
811
-
812
686
  if (!added && removed) {
813
687
  this._updateColumnIcon(colIndex);
814
688
  }
815
-
816
689
  return removed || added;
817
690
  };
818
691
  /** @private
819
692
  * @param {number} colIndex
820
693
  * @return {RowFilteringPlugin~Expression}
821
694
  */
822
-
823
-
824
695
  RowFilteringPlugin.prototype._getColumnExpression = function (colIndex) {
825
696
  var colSettings = this._getUserColumnSettings(colIndex);
826
-
827
697
  return colSettings.expression || null;
828
698
  };
829
699
  /** Set data to colData["rowFiltering"]
@@ -845,15 +715,12 @@ RowFilteringPlugin.prototype._getColumnExpression = function (colIndex) {
845
715
  * }
846
716
  * };
847
717
  */
848
-
849
-
850
718
  RowFilteringPlugin.prototype._setColumnOptions = function (colIndex, userObj) {
851
719
  var colSettings = this._getUserColumnSettings(colIndex);
720
+ var filterIcon = userObj["filterIcon"];
852
721
 
853
- var filterIcon = userObj["filterIcon"]; // TODO: This should not be set here, should retreive data type from Composite/Realtime Grid
854
-
722
+ // TODO: This should not be set here, should retreive data type from Composite/Realtime Grid
855
723
  var fieldDataType = userObj["fieldDataType"] || userObj["dataType"];
856
-
857
724
  if (fieldDataType) {
858
725
  colSettings.fieldDataType = fieldDataType; // TODO: This should not be set here, should retreive data type from Composite/Realtime Grid
859
726
  }
@@ -861,55 +728,40 @@ RowFilteringPlugin.prototype._setColumnOptions = function (colIndex, userObj) {
861
728
  if (filterIcon != null) {
862
729
  colSettings.filterIcon = filterIcon;
863
730
  }
864
-
865
731
  var exp = userObj["filter"];
866
-
867
732
  if (exp != null) {
868
733
  colSettings.expression = exp;
869
734
  colSettings.filterState = null;
870
735
  this._hasPendingFilter = true;
871
736
  }
872
-
873
737
  var filterState = userObj["filterState"];
874
-
875
738
  if (filterState != null) {
876
739
  colSettings.filterState = filterState;
877
740
  }
878
-
879
741
  var iconActivation = filterIcon == false ? "none" : this._iconActivation;
880
-
881
742
  if (iconActivation == "always" || iconActivation == "onHover") {
882
743
  this._updateColumnIcon(colIndex);
883
744
  }
884
-
885
745
  return exp != null;
886
746
  };
887
747
  /** @private
888
748
  * @param {number} colIndex
889
749
  * @return {!Object} colData["rowFiltering"]
890
750
  */
891
-
892
-
893
751
  RowFilteringPlugin.prototype._getUserColumnSettings = function (colIndex) {
894
752
  var colData = this._newColumnData(colIndex);
895
-
896
753
  var colSettings = colData["rowFiltering"];
897
-
898
754
  if (!colSettings) {
899
755
  colSettings = colData["rowFiltering"] = {};
900
756
  }
901
-
902
757
  return colSettings;
903
758
  };
904
759
  /** @private
905
760
  * @param {number} colIndex
906
761
  * @return {Object} colData["rowFiltering"]["filterOption"]
907
762
  */
908
-
909
-
910
763
  RowFilteringPlugin.prototype._getColumnFilterOption = function (colIndex) {
911
764
  var colSettings = this._getUserColumnSettings(colIndex);
912
-
913
765
  if (colSettings) {
914
766
  return colSettings["filterOption"] || null;
915
767
  } else {
@@ -920,18 +772,13 @@ RowFilteringPlugin.prototype._getColumnFilterOption = function (colIndex) {
920
772
  * @private
921
773
  * @param {number} colIndex
922
774
  */
923
-
924
-
925
775
  RowFilteringPlugin.prototype._removeActiveFilterStates = function (colIndex) {
926
776
  var colSettings = this._getUserColumnSettings(colIndex);
927
-
928
777
  colSettings.expression = null;
929
778
  colSettings.filterState = null;
930
779
  var cfo = colSettings["filterOption"];
931
-
932
780
  if (cfo) {
933
781
  colSettings["filterOption"] = null;
934
-
935
782
  if (cfo._filters.length) {
936
783
  this._dispatch("filterChanged", {
937
784
  "filterType": "column",
@@ -946,48 +793,35 @@ RowFilteringPlugin.prototype._removeActiveFilterStates = function (colIndex) {
946
793
  * @param {number} colIndex
947
794
  * @return {!Object}
948
795
  */
949
-
950
-
951
796
  RowFilteringPlugin.prototype._initColumnFilterOption = function (colIndex) {
952
797
  var cfo = this._getColumnFilterOption(colIndex);
953
-
954
798
  if (!cfo) {
955
799
  cfo = {};
956
800
  cfo._filters = [];
957
801
  cfo._expressions = [];
958
802
  cfo._context = [];
959
-
960
803
  var colSettings = this._getUserColumnSettings(colIndex);
961
-
962
804
  colSettings["filterOption"] = cfo;
963
805
  }
964
-
965
806
  return cfo;
966
807
  };
808
+
967
809
  /** Remove the registered global filter. The column filter cannot be removed
968
810
  * @public
969
811
  * @param {Function|string} funcRef Function object or the function name can be used to remove
970
812
  * @return {boolean} True if success
971
813
  */
972
-
973
-
974
814
  RowFilteringPlugin.prototype.removeFilter = function (funcRef) {
975
815
  var func = null;
976
816
  var funcName = "";
977
817
  var funcIndex = -1;
978
-
979
818
  if (typeof funcRef === "string") {
980
- funcName =
981
- /** @type{string} */
982
- funcRef;
819
+ funcName = /** @type{string} */funcRef;
983
820
  func = this._nameMap[funcRef];
984
821
  funcIndex = this._globalFilters.indexOf(func);
985
822
  } else {
986
- func =
987
- /** @type{Function} */
988
- funcRef;
823
+ func = /** @type{Function} */funcRef;
989
824
  funcIndex = this._globalFilters.indexOf(func);
990
-
991
825
  if (funcIndex >= 0) {
992
826
  for (var key in this._nameMap) {
993
827
  if (this._nameMap[key] === func) {
@@ -996,19 +830,13 @@ RowFilteringPlugin.prototype.removeFilter = function (funcRef) {
996
830
  }
997
831
  }
998
832
  }
999
-
1000
833
  if (funcIndex < 0) {
1001
834
  return false;
1002
835
  }
1003
-
1004
836
  delete this._nameMap[funcName];
1005
-
1006
837
  this._globalFilters.splice(funcIndex, 1);
1007
-
1008
838
  this._globalContexts.splice(funcIndex, 1);
1009
-
1010
839
  this._requestFilterRefresh();
1011
-
1012
840
  return true;
1013
841
  };
1014
842
  /** Remove all filters in from the specified column
@@ -1017,20 +845,15 @@ RowFilteringPlugin.prototype.removeFilter = function (funcRef) {
1017
845
  * @return {boolean} True if there is any change
1018
846
  * @fires RowFilteringPlugin#filterChanged
1019
847
  */
1020
-
1021
-
1022
848
  RowFilteringPlugin.prototype.removeColumnFilters = function (colIndex) {
1023
849
  if (colIndex == null) {
1024
850
  // Prevent user mistake
1025
851
  return this.removeAllColumnFilters();
1026
852
  }
1027
-
1028
853
  var dirty = this._removeColumnFilters(colIndex);
1029
-
1030
854
  if (dirty) {
1031
855
  this._updateColumnIcon(colIndex);
1032
856
  }
1033
-
1034
857
  return dirty;
1035
858
  };
1036
859
  /** @private
@@ -1038,29 +861,18 @@ RowFilteringPlugin.prototype.removeColumnFilters = function (colIndex) {
1038
861
  * @return {boolean} True if there is any change
1039
862
  * @fires RowFilteringPlugin#filterChanged
1040
863
  */
1041
-
1042
-
1043
864
  RowFilteringPlugin.prototype._removeColumnFilters = function (colIndex) {
1044
865
  var cfo = this._getColumnFilterOption(colIndex);
1045
-
1046
866
  if (cfo) {
1047
867
  var funcIndex = this._columnFilters.indexOf(cfo);
1048
-
1049
868
  if (funcIndex >= 0) {
1050
869
  this._columnFilters.splice(funcIndex, 1);
1051
870
  }
1052
-
1053
871
  this._removeActiveFilterStates(colIndex); // filterChanged fired
1054
-
1055
-
1056
872
  var inputExt = this._getPlugin("FilterInputPlugin"); // TODO: Use the event instead
1057
-
1058
-
1059
873
  inputExt && inputExt.updateUI(colIndex, "");
1060
-
1061
874
  this._requestFilterRefresh();
1062
875
  }
1063
-
1064
876
  return cfo ? true : false;
1065
877
  };
1066
878
  /** Alias to {@link RowFilteringPlugin#removeColumnFilters} Remove all filters from the specified column
@@ -1070,55 +882,40 @@ RowFilteringPlugin.prototype._removeColumnFilters = function (colIndex) {
1070
882
  * @return {boolean} True if there is any change
1071
883
  * @fires RowFilteringPlugin#filterChanged
1072
884
  */
1073
-
1074
-
1075
885
  RowFilteringPlugin.prototype.removeColumnFilter = RowFilteringPlugin.prototype.removeColumnFilters;
886
+
1076
887
  /** Remove all column filters from all columns, excluding global filters
1077
888
  * @public
1078
889
  * @return {boolean} Return true if there is any change
1079
890
  * @fires RowFilteringPlugin#filterChanged
1080
891
  */
1081
-
1082
892
  RowFilteringPlugin.prototype.removeAllColumnFilters = function () {
1083
893
  if (this._columnFilters.length) {
1084
894
  this._columnFilters.length = 0;
1085
-
1086
895
  var inputExt = this._getPlugin("FilterInputPlugin");
1087
-
1088
896
  var colCount = this._getColumnCount();
1089
-
1090
897
  for (var i = 0; i < colCount; ++i) {
1091
898
  this._removeActiveFilterStates(i); // filterChanged fired
1092
-
1093
-
1094
899
  inputExt && inputExt.updateUI(i, ""); // TODO: Use the event instead
1095
900
  }
1096
901
 
1097
902
  this._updateAllColumnIcons();
1098
-
1099
903
  this._requestFilterRefresh();
1100
-
1101
904
  return true;
1102
905
  }
1103
-
1104
906
  return false;
1105
907
  };
1106
908
  /** Remove all column and global filters. OverridingFilters are not removed by this method
1107
909
  * @public
1108
910
  */
1109
-
1110
-
1111
911
  RowFilteringPlugin.prototype.removeAllFilters = function () {
1112
912
  var totalFilter = this._globalFilters.length + this._columnFilters.length;
1113
-
1114
913
  if (totalFilter <= 0) {
1115
914
  return;
1116
915
  }
1117
-
1118
916
  if (this._globalFilters.length) {
1119
917
  this._globalFilters.length = 0;
1120
918
  this._nameMap = {};
1121
-
1122
919
  this._dispatch("filterChanged", {
1123
920
  "filterType": "global",
1124
921
  "changeType": "remove",
@@ -1126,17 +923,14 @@ RowFilteringPlugin.prototype.removeAllFilters = function () {
1126
923
  "field": ""
1127
924
  });
1128
925
  }
1129
-
1130
926
  this.removeAllColumnFilters();
1131
-
1132
927
  this._requestFilterRefresh();
1133
928
  };
929
+
1134
930
  /** Column overriding function is processed before column filters and after global filters. If it returns non-zero, the result will override all other column filter results. If it returns 1, the row will be always included. If it returns -1, the row will be always excluded. If it returns 0, the column filters will be used as normal.
1135
931
  * @public
1136
932
  * @param {Function} func
1137
933
  */
1138
-
1139
-
1140
934
  RowFilteringPlugin.prototype.setOverridingFilter = function (func) {
1141
935
  this._overridingFilter = func;
1142
936
  };
@@ -1144,8 +938,6 @@ RowFilteringPlugin.prototype.setOverridingFilter = function (func) {
1144
938
  * @public
1145
939
  * @param {Function} func This function must return object with key and value pairs
1146
940
  */
1147
-
1148
-
1149
941
  RowFilteringPlugin.prototype.setPreTransform = function (func) {
1150
942
  this._preTransform = func;
1151
943
  };
@@ -1153,16 +945,13 @@ RowFilteringPlugin.prototype.setPreTransform = function (func) {
1153
945
  * @public
1154
946
  * @param {Function} func This function must return object with key and value pairs
1155
947
  */
1156
-
1157
-
1158
948
  RowFilteringPlugin.prototype.setRowTransform = function (func) {
1159
949
  this._rowTransform = func;
1160
950
  };
951
+
1161
952
  /** @public
1162
953
  * @return {!Array.<Function>} All global filters
1163
954
  */
1164
-
1165
-
1166
955
  RowFilteringPlugin.prototype.getFilters = function () {
1167
956
  return this._globalFilters;
1168
957
  };
@@ -1171,21 +960,16 @@ RowFilteringPlugin.prototype.getFilters = function () {
1171
960
  * @return {!Array.<Function>} All column filters
1172
961
  * @see {@link RowFilteringPlugin.getConfigObject}
1173
962
  */
1174
-
1175
-
1176
963
  RowFilteringPlugin.prototype.getAllColumnFilters = function () {
1177
964
  var filters = [];
1178
965
  var len = this._columnFilters.length;
1179
-
1180
966
  for (var i = 0; i < len; ++i) {
1181
967
  var cfo = this._columnFilters[i];
1182
968
  var jLen = cfo._filters.length;
1183
-
1184
969
  for (var j = 0; j < jLen; ++j) {
1185
970
  filters.push(cfo._filters[j]);
1186
971
  }
1187
972
  }
1188
-
1189
973
  return filters;
1190
974
  };
1191
975
  /** Deprecated in favor of getConfigObject(). Get existing filter expressions for saving and restoring.
@@ -1193,46 +977,37 @@ RowFilteringPlugin.prototype.getAllColumnFilters = function () {
1193
977
  * @return {Array.<RowFilteringPlugin~FilterExpression>} Return null if there is no column filter
1194
978
  * @see {@link RowFilteringPlugin.getConfigObject}
1195
979
  */
1196
-
1197
-
1198
980
  RowFilteringPlugin.prototype.getFilterExpressions = function () {
1199
981
  if (this._columnFilters.length) {
1200
982
  // TODO: Provide a way to save rawDataAccessor and formattedDataAccessor
1201
983
  return this._columnFilters.map(toFilterExpression);
1202
984
  }
1203
-
1204
985
  return null;
1205
986
  };
1206
987
  /** Deprecated. Clear all existing column filters and restore column filters from the given valid filter expressions. If the parameter is null, the result is equivalent to calling removeAllColumnFilters();
1207
988
  * @public
1208
989
  * @param {Array.<RowFilteringPlugin~FilterExpression>} filterExps
1209
990
  */
1210
-
1211
-
1212
991
  RowFilteringPlugin.prototype.setFilterExpressions = function (filterExps) {
1213
992
  this.removeAllColumnFilters();
1214
-
1215
993
  if (Array.isArray(filterExps)) {
1216
994
  var api = this.getGridApi();
1217
995
  var fields = api.getColumnFields();
1218
996
  var len = filterExps.length;
1219
-
1220
997
  for (var i = 0; i < len; ++i) {
1221
998
  var filterExp = filterExps[i];
1222
999
  var field = filterExp.field;
1223
1000
  var colIndex = fields.indexOf(field);
1224
-
1225
1001
  if (colIndex >= 0) {
1226
1002
  this.setColumnFilter(colIndex, filterExp.expression, filterExp.context);
1227
1003
  }
1228
1004
  }
1229
1005
  }
1230
1006
  };
1007
+
1231
1008
  /** @public
1232
1009
  * @return {boolean}
1233
1010
  */
1234
-
1235
-
1236
1011
  RowFilteringPlugin.prototype.hasColumnFilter = function () {
1237
1012
  return this._columnFilters.length > 0;
1238
1013
  };
@@ -1240,100 +1015,75 @@ RowFilteringPlugin.prototype.hasColumnFilter = function () {
1240
1015
  * @param {number} colIndex
1241
1016
  * @return {Array.<Element>} icons
1242
1017
  */
1243
-
1244
-
1245
1018
  RowFilteringPlugin.prototype.getColumnFilterIcons = function (colIndex) {
1246
1019
  var icons = [];
1247
-
1248
1020
  for (var i = this._hosts.length; --i >= 0;) {
1249
1021
  var host = this._hosts[i];
1250
1022
  var tsect = host.getSection("title");
1251
-
1252
1023
  if (!tsect) {
1253
1024
  continue;
1254
1025
  }
1255
-
1256
1026
  var rCount = tsect.getRowCount();
1257
1027
  var cell = tsect.getCell(colIndex, rCount - 1, true); // Get bottom cell
1258
-
1259
1028
  if (cell && cell._filterIcon) {
1260
1029
  icons.push(cell._filterIcon);
1261
1030
  }
1262
1031
  }
1263
-
1264
1032
  return icons;
1265
1033
  };
1266
1034
  /** @public */
1267
-
1268
-
1269
1035
  RowFilteringPlugin.prototype.updateAllColumnIcons = function () {
1270
1036
  if (this._uiTimerId) {
1271
1037
  clearTimeout(this._uiTimerId);
1272
1038
  this._uiTimerId = 0;
1273
1039
  }
1274
-
1275
1040
  this._updateAllColumnIcons();
1276
1041
  };
1042
+
1277
1043
  /** Specify a list of data views to be filtered, excluding default data views used by UI. <br>
1278
1044
  * This is useful when multiple shared or nested data views are employed.
1279
1045
  * @public
1280
1046
  * @param {Object} dv DataView
1281
1047
  */
1282
-
1283
-
1284
1048
  RowFilteringPlugin.prototype.addDataView = function (dv) {
1285
1049
  var at = this._dvs.indexOf(dv);
1286
-
1287
1050
  if (at < 0) {
1288
1051
  this._dvs.push(dv);
1289
-
1290
1052
  this._requestFilterRefresh();
1291
1053
  }
1292
1054
  };
1293
1055
  /** @public
1294
1056
  * @param {Object} dv DataView
1295
1057
  */
1296
-
1297
-
1298
1058
  RowFilteringPlugin.prototype.removeDataView = function (dv) {
1299
1059
  var at = this._dvs.indexOf(dv);
1300
-
1301
1060
  if (at >= 0) {
1302
1061
  this._dvs.splice(at, 1);
1303
-
1304
1062
  this._requestFilterRefresh(); // This could be unnecessary
1305
-
1306
1063
  }
1307
1064
  };
1065
+
1308
1066
  /** @private
1309
1067
  * @param {Object} e
1310
1068
  */
1311
-
1312
-
1313
1069
  RowFilteringPlugin.prototype._onPreSectionRender = function (e) {
1314
1070
  if (e["sectionType"] !== "title") {
1315
1071
  return;
1316
1072
  }
1317
-
1318
1073
  this._setTimerForUpdatingIcons();
1319
1074
  };
1320
1075
  /** @private
1321
1076
  * @param {Event} e
1322
1077
  */
1323
-
1324
-
1325
1078
  RowFilteringPlugin.prototype._onIconClicked = function (e) {
1326
1079
  var host = this._hosts[0];
1327
-
1328
1080
  if (!host) {
1329
1081
  return;
1330
1082
  }
1331
-
1332
1083
  var pos = host.getRelativePosition(e);
1333
1084
  this.openDialog(pos.colIndex);
1334
1085
  e.stopPropagation();
1335
1086
  e.preventDefault();
1336
-
1337
1087
  this._dispatch("click", e);
1338
1088
  };
1339
1089
  /** @private
@@ -1341,46 +1091,35 @@ RowFilteringPlugin.prototype._onIconClicked = function (e) {
1341
1091
  * @param {Object} rowData
1342
1092
  * @return {boolean}
1343
1093
  */
1344
-
1345
-
1346
1094
  RowFilteringPlugin.prototype._filterLogic = function (rid, rowData) {
1347
1095
  if (rowData) {
1348
1096
  if (this._rowGetter) {
1349
1097
  rowData = this._rowGetter(rowData);
1350
1098
  }
1351
-
1352
1099
  if (this._preTransform) {
1353
1100
  rowData = this._preTransform(rowData);
1354
1101
  }
1355
-
1356
1102
  var i;
1357
1103
  var len = this._globalFilters.length;
1358
-
1359
1104
  for (i = 0; i < len; ++i) {
1360
1105
  if (!this._globalFilters[i](rowData, rid, this._globalContexts[i])) {
1361
1106
  return false;
1362
1107
  }
1363
1108
  }
1364
-
1365
1109
  len = this._activeColFilters.length;
1366
-
1367
1110
  if (len) {
1368
1111
  if (this._overridingFilter) {
1369
1112
  var ret = this._overridingFilter(rowData, rid);
1370
-
1371
1113
  if (ret) {
1372
1114
  return ret > 0;
1373
1115
  }
1374
1116
  }
1375
-
1376
1117
  if (this._rowTransform) {
1377
1118
  rowData = this._rowTransform(rowData);
1378
1119
  }
1379
-
1380
1120
  for (i = 0; i < len; ++i) {
1381
1121
  var cfo = this._activeColFilters[i];
1382
1122
  var jLen = cfo._filters.length;
1383
-
1384
1123
  for (var j = 0; j < jLen; ++j) {
1385
1124
  if (!cfo._filters[j](rowData, rid, cfo._context[j])) {
1386
1125
  return false;
@@ -1389,69 +1128,53 @@ RowFilteringPlugin.prototype._filterLogic = function (rid, rowData) {
1389
1128
  }
1390
1129
  }
1391
1130
  }
1392
-
1393
1131
  return true;
1394
1132
  };
1395
1133
  /** @private */
1396
-
1397
-
1398
1134
  RowFilteringPlugin.prototype._requestFilterRefresh = function () {
1399
1135
  if (!this._filterTimerId) {
1400
1136
  this._filterTimerId = setTimeout(this.refresh, 10);
1401
1137
  }
1402
1138
  };
1403
1139
  /** @private */
1404
-
1405
-
1406
1140
  RowFilteringPlugin.prototype._setTimerForUpdatingIcons = function () {
1407
1141
  if (this._iconActivation === "none") {
1408
1142
  return;
1409
1143
  }
1410
-
1411
1144
  if (!this._uiTimerId) {
1412
1145
  this._uiTimerId = setTimeout(this._updateAllColumnIcons, 10);
1413
1146
  }
1414
1147
  };
1148
+
1415
1149
  /** Perform filtering with the same parameters. Do not call this method repeatedly as the operation is quite expensive.
1416
1150
  * @public
1417
1151
  * @suppress {checkTypes}
1418
1152
  * @fires RowFilteringPlugin#refreshed
1419
1153
  */
1420
-
1421
-
1422
1154
  RowFilteringPlugin.prototype.refresh = function () {
1423
1155
  this._filterTimerId = 0;
1424
- this._activeColFilters = this._columnFilters; //check cstp
1425
-
1156
+ this._activeColFilters = this._columnFilters;
1157
+ //check cstp
1426
1158
  var cstkp = this._getPlugin("ColumnStackPlugin");
1427
-
1428
1159
  if (cstkp) {
1429
1160
  var colIndex, cfo;
1430
1161
  var host = this._hosts[0];
1431
-
1432
1162
  var colCount = this._getColumnCount();
1433
-
1434
1163
  this._activeColFilters = [];
1435
-
1436
1164
  for (colIndex = 0; colIndex < colCount; ++colIndex) {
1437
1165
  cfo = this._getColumnFilterOption(colIndex);
1438
-
1439
1166
  if (cfo && host.getColumnVisibility(colIndex, 2)) {
1440
1167
  this._activeColFilters.push(cfo);
1441
1168
  }
1442
1169
  }
1443
1170
  }
1444
-
1445
1171
  var totalFilter = this._globalFilters.length + this._activeColFilters.length;
1446
1172
  var logic = !this._disabled && totalFilter ? this._filterLogic : null;
1447
1173
  var dirty = 0;
1448
-
1449
1174
  var dvs = this._getAvailableDataViews();
1450
-
1451
1175
  for (var i = dvs.length; --i >= 0;) {
1452
1176
  dirty |= dvs[i].filterIn(logic);
1453
1177
  }
1454
-
1455
1178
  if (dirty) {
1456
1179
  this._dispatch("refreshed", {});
1457
1180
  }
@@ -1459,55 +1182,38 @@ RowFilteringPlugin.prototype.refresh = function () {
1459
1182
  /** @private
1460
1183
  * @param {number} colIndex
1461
1184
  */
1462
-
1463
-
1464
1185
  RowFilteringPlugin.prototype._updateColumnIcon = function (colIndex) {
1465
1186
  var cfo = this._getColumnFilterOption(colIndex); // colData["rowFiltering"]["filterOption"]
1466
-
1467
-
1468
1187
  var colSettings = this._getUserColumnSettings(colIndex); // colData["rowFiltering"]
1469
-
1470
-
1471
1188
  var iconActivation = colSettings.filterIcon == false ? "none" : this._iconActivation;
1472
1189
  var hasFilter = cfo ? cfo._filters.length : 0;
1473
-
1474
1190
  for (var i = this._hosts.length; --i >= 0;) {
1475
1191
  var host = this._hosts[i];
1476
1192
  var tsect = host.getSection("title");
1477
-
1478
1193
  if (!tsect) {
1479
1194
  continue;
1480
1195
  }
1481
-
1482
1196
  var rCount = tsect.getRowCount();
1483
1197
  var cell = tsect.getCell(colIndex, rCount - 1, true); // Get bottom cell
1484
-
1485
1198
  var column = tsect.getColumn(colIndex);
1486
-
1487
1199
  if (!cell) {
1488
1200
  continue;
1489
- } // HACK: Update cell padding for all type of icons (sorting and column grouping icons)
1490
-
1491
-
1201
+ }
1202
+ // HACK: Update cell padding for all type of icons (sorting and column grouping icons)
1492
1203
  if (cell["updatePadding"]) {
1493
1204
  cell["updatePadding"]();
1494
1205
  }
1495
-
1496
1206
  var isColumnMovable = host.isColumnMovable(colIndex);
1497
-
1498
1207
  if (isColumnMovable) {
1499
1208
  column.enableClass("movable", true);
1500
1209
  } else {
1501
1210
  column.enableClass("movable", false);
1502
1211
  }
1503
-
1504
1212
  var onActiveFilter = iconActivation !== "always" && iconActivation !== "onHover";
1505
1213
  var noFilterIcon = this._disabled || iconActivation === "none" || onActiveFilter && !hasFilter;
1506
-
1507
1214
  if (!noFilterIcon) {
1508
1215
  if (!cell._filterIcon) {
1509
1216
  var filterIcon;
1510
-
1511
1217
  if (ElfUtil.hasComponent("ef-icon") >= 3) {
1512
1218
  filterIcon = document.createElement("ef-icon");
1513
1219
  filterIcon.setAttribute("icon", "filter");
@@ -1515,21 +1221,16 @@ RowFilteringPlugin.prototype._updateColumnIcon = function (colIndex) {
1515
1221
  filterIcon = document.createElement("div");
1516
1222
  filterIcon.className = "filter-symbol icon-filter ef-icon";
1517
1223
  }
1518
-
1519
1224
  filterIcon.classList.add("title-filter-icon"); // Icon reference
1520
-
1521
1225
  filterIcon.addEventListener("click", this._onIconClicked, false);
1522
-
1523
1226
  this._dispatch("iconCreated", {
1524
1227
  "icon": filterIcon,
1525
1228
  "colIndex": colIndex,
1526
1229
  "grid": host
1527
1230
  });
1528
-
1529
1231
  cell.insertFloatingIcon(filterIcon, 10);
1530
1232
  cell._filterIcon = filterIcon;
1531
1233
  }
1532
-
1533
1234
  if (hasFilter) {
1534
1235
  cell.enableClass("active-filter", true);
1535
1236
  } else {
@@ -1545,50 +1246,38 @@ RowFilteringPlugin.prototype._updateColumnIcon = function (colIndex) {
1545
1246
  }
1546
1247
  };
1547
1248
  /** @private */
1548
-
1549
-
1550
1249
  RowFilteringPlugin.prototype._updateAllColumnIcons = function () {
1551
1250
  this._uiTimerId = 0;
1552
-
1553
1251
  var colCount = this._getColumnCount();
1554
-
1555
1252
  for (var i = 0; i < colCount; ++i) {
1556
1253
  this._updateColumnIcon(i);
1557
1254
  }
1558
1255
  };
1256
+
1559
1257
  /** @private
1560
1258
  * @return {number}
1561
1259
  */
1562
-
1563
-
1564
1260
  RowFilteringPlugin.prototype._getColumnCount = function () {
1565
1261
  var grid = this._hosts[0];
1566
-
1567
1262
  if (grid) {
1568
1263
  return grid.getColumnCount();
1569
1264
  }
1570
-
1571
1265
  return 0;
1572
1266
  };
1267
+
1573
1268
  /** Update existing filter state by replacing the old one. Note that filtering will be performed asynchronously after executing this method.
1574
1269
  * @public
1575
1270
  * @param {number} colIndex
1576
1271
  * @param {*} ctx Context object that will be passed as the third parameter for the filter logic
1577
1272
  * @return {boolean} Returns true if there is any change
1578
1273
  */
1579
-
1580
-
1581
1274
  RowFilteringPlugin.prototype.setColumnFilterState = function (colIndex, ctx) {
1582
1275
  var cfo = this._getColumnFilterOption(colIndex);
1583
-
1584
1276
  if (cfo) {
1585
1277
  cfo._context[0] = ctx;
1586
-
1587
1278
  this._requestFilterRefresh();
1588
-
1589
1279
  return true;
1590
1280
  }
1591
-
1592
1281
  return false;
1593
1282
  };
1594
1283
  /** Get the stored user context from the specified column
@@ -1596,15 +1285,11 @@ RowFilteringPlugin.prototype.setColumnFilterState = function (colIndex, ctx) {
1596
1285
  * @param {number} colIndex
1597
1286
  * @return {*} Context object that is passed as the third parameter for the filter logic
1598
1287
  */
1599
-
1600
-
1601
1288
  RowFilteringPlugin.prototype.getColumnFilterState = function (colIndex) {
1602
1289
  var cfo = this._getColumnFilterOption(colIndex);
1603
-
1604
1290
  if (cfo) {
1605
1291
  return cfo._context[0];
1606
1292
  }
1607
-
1608
1293
  return null;
1609
1294
  };
1610
1295
  /** Deprecated in favor of getConfigObject(). Get the stored user context from all columns. The column with no filter will return null value
@@ -1612,39 +1297,31 @@ RowFilteringPlugin.prototype.getColumnFilterState = function (colIndex) {
1612
1297
  * @return {!Array} Array of context objects
1613
1298
  * @see {@link RowFilteringPlugin.getConfigObject}
1614
1299
  */
1615
-
1616
-
1617
1300
  RowFilteringPlugin.prototype.getColumnFilterStates = function () {
1618
1301
  var colCount = this._hosts[0] ? this._hosts[0].getColumnCount() : 0;
1619
1302
  var states = new Array(colCount);
1620
-
1621
1303
  for (var c = 0; c < colCount; ++c) {
1622
1304
  states[c] = this.getColumnFilterState(c);
1623
1305
  }
1624
-
1625
1306
  return states;
1626
1307
  };
1308
+
1627
1309
  /** @private
1628
1310
  * @return {!Array.<Object>} array of DataView
1629
1311
  */
1630
-
1631
-
1632
1312
  RowFilteringPlugin.prototype._getAvailableDataViews = function () {
1633
1313
  if (this._dvs.length) {
1634
1314
  return this._dvs;
1635
1315
  } else {
1636
1316
  var len = this._hosts.length;
1637
1317
  var ary = [];
1638
-
1639
1318
  for (var i = 0; i < len; ++i) {
1640
1319
  var host = this._hosts[i];
1641
1320
  var dv = host.getDataSource();
1642
-
1643
1321
  if (dv) {
1644
1322
  ary.push(dv);
1645
1323
  }
1646
1324
  }
1647
-
1648
1325
  return ary;
1649
1326
  }
1650
1327
  };
@@ -1652,17 +1329,14 @@ RowFilteringPlugin.prototype._getAvailableDataViews = function () {
1652
1329
  * @param {Object} dv DataView
1653
1330
  * @return {Object} DataTable
1654
1331
  */
1655
-
1656
-
1657
1332
  RowFilteringPlugin.prototype._getDataTable = function (dv) {
1658
1333
  var dt = dv ? dv.getDataSource() : null;
1659
-
1660
1334
  while (dt && dt.getDataSource()) {
1661
1335
  dt = dt.getDataSource();
1662
1336
  }
1663
-
1664
1337
  return dt;
1665
1338
  };
1339
+
1666
1340
  /** @public
1667
1341
  * @deprecated
1668
1342
  * @ignore
@@ -1675,8 +1349,6 @@ RowFilteringPlugin.prototype._getDataTable = function (dv) {
1675
1349
  * @param {Object=} selectedItems
1676
1350
  * @return {Object} Object that maps formatted value to array of raw values
1677
1351
  */
1678
-
1679
-
1680
1352
  RowFilteringPlugin.prototype.getUniqueValues = function (field, formatter, fmtField, rawDataAccessor, formattedDataAccessor, filterFuncs, selectedItems) {
1681
1353
  var dialogConfig = {
1682
1354
  rawDataAccessor: rawDataAccessor,
@@ -1684,18 +1356,16 @@ RowFilteringPlugin.prototype.getUniqueValues = function (field, formatter, fmtFi
1684
1356
  };
1685
1357
  return this._getUniqueValues(field, dialogConfig, formatter, filterFuncs, selectedItems);
1686
1358
  };
1359
+
1687
1360
  /** @private
1688
1361
  * @param {*} formattedVal
1689
1362
  * @param {*} rawVal
1690
1363
  * @returns {string}
1691
1364
  */
1692
-
1693
-
1694
1365
  var _valueToString = function _valueToString(formattedVal, rawVal) {
1695
1366
  if (typeof formattedVal === "string") {
1696
1367
  return formattedVal;
1697
1368
  }
1698
-
1699
1369
  if (formattedVal) {
1700
1370
  if (_typeof(formattedVal) != "object") {
1701
1371
  return rawVal + "";
@@ -1710,7 +1380,6 @@ var _valueToString = function _valueToString(formattedVal, rawVal) {
1710
1380
  } else if (formattedVal === false) {
1711
1381
  return "false";
1712
1382
  }
1713
-
1714
1383
  return "";
1715
1384
  };
1716
1385
  /** @private
@@ -1718,32 +1387,29 @@ var _valueToString = function _valueToString(formattedVal, rawVal) {
1718
1387
  * @param {string} formattedVal
1719
1388
  * @param {Object} row
1720
1389
  * @param {!Array.<Function>} filterFuncs A selector function that execute on each item to determine the selection
1390
+ * @return {boolean}
1721
1391
  */
1722
-
1723
-
1724
1392
  var _collectSelectedItem = function _collectSelectedItem(selectedItems, formattedVal, row, filterFuncs) {
1725
1393
  if (filterFuncs) {
1726
1394
  if (!selectedItems[formattedVal]) {
1727
1395
  for (var i = filterFuncs.length; --i >= 0;) {
1728
1396
  if (!filterFuncs[i](row)) {
1729
- return;
1397
+ return false;
1730
1398
  }
1731
1399
  }
1732
-
1733
1400
  selectedItems[formattedVal] = true;
1401
+ return true;
1734
1402
  }
1735
1403
  }
1404
+ return false;
1736
1405
  };
1737
1406
  /** @private
1738
1407
  * @param {Object} uniqueValues
1739
1408
  * @param {string} formattedVal
1740
1409
  * @param {*} rawVal
1741
1410
  */
1742
-
1743
-
1744
1411
  var _collectUniqueValue = function _collectUniqueValue(uniqueValues, formattedVal, rawVal) {
1745
1412
  var rawValues = uniqueValues[formattedVal];
1746
-
1747
1413
  if (rawValues) {
1748
1414
  if (rawValues.indexOf(rawVal) < 0) {
1749
1415
  // Check for unique raw values
@@ -1762,59 +1428,44 @@ var _collectUniqueValue = function _collectUniqueValue(uniqueValues, formattedVa
1762
1428
  * @param {Object} selectedItems
1763
1429
  * @return {Object} Object that maps formatted value to array of raw values
1764
1430
  */
1765
-
1766
-
1767
1431
  RowFilteringPlugin.prototype._getUniqueValues = function (field, dialogConfig, formatter, filterFuncs, selectedItems) {
1768
1432
  if (!field) {
1769
1433
  return null;
1770
1434
  }
1771
-
1772
1435
  var rawDataAccessor = dialogConfig.rawDataAccessor || null;
1773
1436
  var formattedDataAccessor = dialogConfig.formattedDataAccessor || null;
1774
1437
  var userItemList = dialogConfig.itemList;
1775
1438
  var uniqueValues = {};
1776
1439
  var formattedVal = null;
1777
1440
  var rawVal = null;
1778
-
1779
1441
  if (!Array.isArray(userItemList)) {
1780
1442
  userItemList = null;
1781
-
1782
1443
  var dvs = this._getAvailableDataViews();
1783
-
1784
1444
  var dts = dvs.map(this._getDataTable);
1785
1445
  var tblCount = dts.length;
1786
-
1787
1446
  for (var t = 0; t < tblCount; ++t) {
1788
1447
  var rows = dts[t].getAllRowData();
1789
1448
  var rowCount = rows.length;
1790
-
1791
1449
  for (var r = 0; r < rowCount; ++r) {
1792
1450
  var row = rows[r];
1793
-
1794
1451
  if (this._rowGetter) {
1795
1452
  row = this._rowGetter(row);
1796
1453
  }
1797
-
1798
1454
  if (this._rowTransform) {
1799
1455
  row = this._rowTransform(row);
1800
1456
  }
1801
-
1802
1457
  var fieldVal = row[field];
1803
1458
  rawVal = fieldVal;
1804
-
1805
1459
  if (rawDataAccessor) {
1806
1460
  rawVal = rawDataAccessor(rawVal);
1807
1461
  }
1808
-
1809
1462
  if (!rawVal) {
1810
1463
  // Only valid values are accepted
1811
1464
  if (rawVal !== 0 && rawVal !== false) {
1812
1465
  continue;
1813
1466
  }
1814
1467
  }
1815
-
1816
1468
  formattedVal = rawVal;
1817
-
1818
1469
  if (formattedDataAccessor) {
1819
1470
  formattedVal = formattedDataAccessor(fieldVal); // The function takes data value
1820
1471
  } else if (formatter) {
@@ -1822,18 +1473,14 @@ RowFilteringPlugin.prototype._getUniqueValues = function (field, dialogConfig, f
1822
1473
  }
1823
1474
 
1824
1475
  formattedVal = _valueToString(formattedVal, rawVal);
1825
-
1826
1476
  if (formattedVal) {
1827
1477
  _collectSelectedItem(selectedItems, formattedVal, row, filterFuncs);
1828
-
1829
1478
  _collectUniqueValue(uniqueValues, formattedVal, rawVal);
1830
1479
  }
1831
1480
  }
1832
1481
  }
1833
1482
  }
1834
-
1835
1483
  var additionalItems = dialogConfig.additionalItems;
1836
-
1837
1484
  if (Array.isArray(additionalItems)) {
1838
1485
  if (userItemList) {
1839
1486
  userItemList = userItemList.concat(additionalItems);
@@ -1841,52 +1488,40 @@ RowFilteringPlugin.prototype._getUniqueValues = function (field, dialogConfig, f
1841
1488
  userItemList = additionalItems;
1842
1489
  }
1843
1490
  }
1844
-
1845
1491
  var dummyRow = {};
1846
1492
  var userItemCount = userItemList ? userItemList.length : 0;
1847
-
1848
1493
  for (var i = 0; i < userItemCount; ++i) {
1849
1494
  rawVal = dummyRow[field] = userItemList[i];
1850
1495
  formattedVal = rawVal;
1851
-
1852
1496
  if (formattedDataAccessor) {
1853
1497
  formattedVal = formattedDataAccessor(rawVal);
1854
1498
  } else if (formatter) {
1855
1499
  formattedVal = formatter(dummyRow);
1856
1500
  }
1857
-
1858
1501
  formattedVal = _valueToString(formattedVal, rawVal);
1859
-
1860
1502
  if (formattedVal) {
1861
1503
  _collectSelectedItem(selectedItems, formattedVal, dummyRow, filterFuncs);
1862
-
1863
1504
  _collectUniqueValue(uniqueValues, formattedVal, rawVal);
1864
1505
  }
1865
1506
  }
1866
-
1867
1507
  return uniqueValues;
1868
1508
  };
1509
+
1869
1510
  /** @private
1870
1511
  * @function
1871
1512
  * @returns {Element}
1872
1513
  */
1873
-
1874
-
1875
1514
  RowFilteringPlugin._createDialog = function () {
1876
1515
  var tag = RowFilteringPlugin._dialogTagName;
1877
-
1878
1516
  if (tag == null) {
1879
1517
  var dialogVersion = ElfUtil.hasComponent("filter-dialog"); // WARNING: this cannot detect version 2 or less
1880
-
1881
1518
  if (dialogVersion) {
1882
1519
  RowFilteringPlugin._dialogTagName = dialogVersion >= 3 ? "filter-dialog" : "tr-grid-filter-dialog";
1883
1520
  } else {
1884
1521
  RowFilteringPlugin._dialogTagName = "";
1885
1522
  }
1886
-
1887
1523
  tag = RowFilteringPlugin._dialogTagName;
1888
1524
  }
1889
-
1890
1525
  return tag ? document.createElement(tag) : null;
1891
1526
  };
1892
1527
  /** @private
@@ -1896,26 +1531,20 @@ RowFilteringPlugin._createDialog = function () {
1896
1531
  * @param {Function} formatter
1897
1532
  * @returns {Array}
1898
1533
  */
1899
-
1900
-
1901
1534
  RowFilteringPlugin._formatArrayExpression = function (exp, field, formatter) {
1902
1535
  if (Array.isArray(exp)) {
1903
1536
  var ary = exp.slice(); // Clone to avoid modifying original data
1904
-
1905
1537
  var formattedVal = ary[1];
1906
1538
  var val = stringToDateObject(formattedVal);
1907
-
1908
1539
  if (val !== formattedVal) {
1909
1540
  ary.rawValue = val;
1910
1541
  ary.formattedValue = formattedVal;
1911
1542
  }
1912
-
1913
1543
  if (field && formatter && typeof val !== "string") {
1914
1544
  if (val != null) {
1915
1545
  var dummyRow = {};
1916
1546
  dummyRow[field] = val;
1917
1547
  formattedVal = formatter(dummyRow);
1918
-
1919
1548
  if (formattedVal) {
1920
1549
  ary.rawValue = val;
1921
1550
  ary.formattedValue = formattedVal;
@@ -1923,49 +1552,37 @@ RowFilteringPlugin._formatArrayExpression = function (exp, field, formatter) {
1923
1552
  }
1924
1553
  }
1925
1554
  }
1926
-
1927
1555
  ary[1] = val;
1928
1556
  return ary;
1929
1557
  }
1930
-
1931
1558
  return null;
1932
1559
  };
1933
1560
  /** @public
1934
1561
  * @param {number} colIndex
1935
1562
  * @param {RowFilteringPlugin~FilterDialogOptions=} runtimeDialogOptions
1936
1563
  */
1937
-
1938
-
1939
1564
  RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptions) {
1940
1565
  var stp = this._getPlugin("SortableTitlePlugin");
1941
-
1942
1566
  if (!this._filterDialog || !this._dialogInitialized) {
1943
1567
  if (!this._filterDialog) {
1944
1568
  this._filterDialog = RowFilteringPlugin._createDialog();
1945
1569
  }
1946
-
1947
1570
  if (this._filterDialog) {
1948
1571
  this._dialogInitialized = true;
1949
-
1950
1572
  if (!stp) {
1951
1573
  this._filterDialog.hideSortUI();
1952
1574
  } else {
1953
1575
  this._filterDialog.addEventListener("sortChanged", this._onDialogSortChanged.bind(this));
1954
1576
  }
1955
-
1956
1577
  this._filterDialog.addEventListener("filterChanged", this._onDialogFilterChanged.bind(this));
1957
1578
  }
1958
1579
  }
1959
-
1960
1580
  if (!this._filterDialog) {
1961
1581
  console.log("Filter dialog does not exist");
1962
1582
  return;
1963
1583
  }
1964
-
1965
1584
  if (this._filterDialog.isShown) {
1966
1585
  this._filterDialog.hide(); // Hide previously opened dialog
1967
-
1968
-
1969
1586
  if (this._filterDialog._colIndex === colIndex) {
1970
1587
  // The dialog is already openned
1971
1588
  return; // Toggle open state
@@ -1973,28 +1590,23 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
1973
1590
  }
1974
1591
 
1975
1592
  var host = this._hosts[0];
1976
-
1977
1593
  if (!host) {
1978
1594
  return;
1979
- } // Find target cell for positioning filter dialog
1980
-
1595
+ }
1981
1596
 
1597
+ // Find target cell for positioning filter dialog
1982
1598
  var tsect = host.getSection("title");
1983
-
1984
1599
  if (!tsect) {
1985
1600
  return;
1986
1601
  }
1987
-
1988
1602
  var rCount = tsect.getRowCount();
1989
1603
  var cell = tsect.getCell(colIndex, rCount - 1, true); // Get bottom cell
1990
-
1991
1604
  if (!cell || !cell.getElement()) {
1992
1605
  return;
1993
- } // TODO: Handle newly inserted/added columns
1994
-
1606
+ }
1995
1607
 
1608
+ // TODO: Handle newly inserted/added columns
1996
1609
  var field = this._getField(colIndex);
1997
-
1998
1610
  if (!field) {
1999
1611
  return; // The specified column has no field
2000
1612
  }
@@ -2005,46 +1617,36 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
2005
1617
  field: field,
2006
1618
  grid: host
2007
1619
  };
2008
-
2009
1620
  if (runtimeDialogOptions) {
2010
1621
  arg["dialogOptions"] = runtimeDialogOptions;
2011
1622
  }
2012
-
2013
1623
  this._dispatch("beforeDialogOpened", arg);
2014
-
2015
1624
  if (arg["cancel"]) {
2016
1625
  return;
2017
1626
  }
2018
-
2019
1627
  if (arg["dialogOptions"]) {
2020
1628
  runtimeDialogOptions = arg["dialogOptions"];
2021
1629
  }
2022
1630
  }
2023
-
2024
1631
  if (_typeof(runtimeDialogOptions) !== "object") {
2025
1632
  runtimeDialogOptions = null;
2026
1633
  }
2027
-
2028
1634
  if (stp) {
2029
1635
  this._filterDialog.setSortState(stp.getSortOrder(colIndex)); // This is for ELF v3
1636
+ }
2030
1637
 
2031
- } // Setting up dialog configuration
2032
-
2033
-
1638
+ // Setting up dialog configuration
2034
1639
  var colData = host.getColumnData(colIndex);
2035
1640
  var formatOptions = colData.formatOptions;
2036
1641
  var useUTCTime = false;
2037
-
2038
1642
  if (formatOptions) {
2039
1643
  if (formatOptions.formatType) {
2040
1644
  useUTCTime = true;
2041
-
2042
1645
  if (formatOptions.useUTCTime != null) {
2043
1646
  useUTCTime = formatOptions.useUTCTime;
2044
1647
  }
2045
1648
  }
2046
1649
  }
2047
-
2048
1650
  var dialogConfig = {
2049
1651
  // default config
2050
1652
  sortUI: true,
@@ -2053,48 +1655,39 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
2053
1655
  lang: "",
2054
1656
  rawDataAccessor: null,
2055
1657
  formattedDataAccessor: null,
2056
- sortLogic: null
1658
+ sortLogic: null,
1659
+ blankValues: false,
1660
+ blankValuesChecked: false
2057
1661
  };
2058
1662
  var columnDialogOptions = null;
2059
-
2060
1663
  var colSettings = this._getUserColumnSettings(colIndex); // colData["rowFiltering"]
2061
-
2062
-
2063
1664
  if (colSettings.fieldDataType) {
2064
1665
  // TODO: Use data type from Composite Grid (getColumnDataType) or Realtime Grid (getDataType) instead
2065
1666
  columnDialogOptions = {
2066
1667
  fieldDataType: colSettings.fieldDataType
2067
1668
  };
2068
1669
  }
2069
-
2070
1670
  RowFilteringPlugin._overrideConfig(dialogConfig, this._dialogOptions);
2071
-
2072
1671
  RowFilteringPlugin._overrideConfig(dialogConfig, columnDialogOptions);
1672
+ RowFilteringPlugin._overrideConfig(dialogConfig, runtimeDialogOptions);
2073
1673
 
2074
- RowFilteringPlugin._overrideConfig(dialogConfig, runtimeDialogOptions); // cfo is required for storing unique entries in the dialog, even though no filter is active
1674
+ // cfo is required for storing unique entries in the dialog, even though no filter is active
2075
1675
  // TODO: move rawDataAccessor and other settings to colSettings
2076
-
2077
-
2078
1676
  var cfo = this._initColumnFilterOption(colIndex); // colData["rowFiltering"]["filterOption"]
2079
-
2080
-
2081
1677
  cfo._rawDataAccessor = dialogConfig.rawDataAccessor || null;
2082
1678
  cfo._formattedDataAccessor = dialogConfig.formattedDataAccessor || null;
2083
- var sortLogic = dialogConfig.sortLogic || null; // Populate data for filter dialog based on existing states
1679
+ var sortLogic = dialogConfig.sortLogic || null;
2084
1680
 
1681
+ // Populate data for filter dialog based on existing states
2085
1682
  var formatter = this._getFormatter(colIndex);
2086
-
2087
1683
  var condition2D = null;
2088
1684
  var filterMode = ""; // default
2089
-
2090
1685
  var filterFuncs = null;
2091
1686
  var exp = colSettings.expression;
2092
-
2093
1687
  if (exp) {
2094
1688
  if (Array.isArray(exp)) {
2095
1689
  if (exp.length) {
2096
1690
  condition2D = Array.isArray(exp[0]) ? exp.slice() : [exp]; // Guaranteed condition2D to be a 2D array
2097
-
2098
1691
  condition2D[0] = RowFilteringPlugin._formatArrayExpression(condition2D[0], field, formatter);
2099
1692
  condition2D[1] = RowFilteringPlugin._formatArrayExpression(condition2D[1], field, formatter);
2100
1693
  filterMode = "advanced";
@@ -2105,13 +1698,23 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
2105
1698
  }
2106
1699
  }
2107
1700
  }
2108
-
2109
1701
  var selectedItems = {};
2110
-
2111
1702
  var uniqueValues = cfo.uniqueValues = this._getUniqueValues(field, dialogConfig, formatter, filterFuncs, selectedItems);
2112
-
1703
+ if (dialogConfig.blankValues) {
1704
+ delete uniqueValues[BLANKS];
1705
+ var dunmmySelectItem = {};
1706
+ var blkVals = ["", null, undefined, NaN]; // eslint-disable-line
1707
+ var dummyRow = {};
1708
+ for (var i = 0; i < blkVals.length; i++) {
1709
+ var blkVal = blkVals[i];
1710
+ dummyRow[field] = blkVal;
1711
+ if (_collectSelectedItem(dunmmySelectItem, BLANKS, dummyRow, filterFuncs)) {
1712
+ dialogConfig.blankValuesChecked = true;
1713
+ break;
1714
+ }
1715
+ }
1716
+ }
2113
1717
  var keys = Object.keys(uniqueValues);
2114
-
2115
1718
  if (sortLogic) {
2116
1719
  keys.sort(function (a, b) {
2117
1720
  var rawValueA = uniqueValues[a][0];
@@ -2127,41 +1730,37 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
2127
1730
  nodes: [],
2128
1731
  checked: selectedItems[formattedVal] ? true : false
2129
1732
  };
2130
- }); // Adding inputs from conditions to uniqueValues for mapping back from the dialog
1733
+ });
2131
1734
 
1735
+ // Adding inputs from conditions to uniqueValues for mapping back from the dialog
2132
1736
  if (condition2D) {
2133
1737
  var cond = condition2D[0];
2134
-
2135
1738
  if (cond && cond.formattedValue) {
2136
1739
  if (!uniqueValues[cond.formattedValue]) {
2137
1740
  uniqueValues[cond.formattedValue] = [cond.rawValue];
2138
1741
  }
2139
1742
  }
2140
-
2141
1743
  cond = condition2D[1];
2142
-
2143
1744
  if (cond && cond.formattedValue) {
2144
1745
  if (!uniqueValues[cond.formattedValue]) {
2145
1746
  uniqueValues[cond.formattedValue] = [cond.rawValue];
2146
1747
  }
2147
1748
  }
2148
- } // Initialize dialog
2149
-
1749
+ }
2150
1750
 
1751
+ // Initialize dialog
2151
1752
  if (this._filterDialog.init) {
2152
1753
  // TODO: support initiailization in v1
2153
1754
  this._filterDialog.init(dialogConfig);
2154
- } // TODO: Move all settings to configuration object
2155
-
1755
+ }
2156
1756
 
1757
+ // TODO: Move all settings to configuration object
2157
1758
  this._filterDialog.useUTCTime = useUTCTime;
2158
1759
  this._filterDialog.target = cell.getElement();
2159
1760
  this._filterDialog._colIndex = colIndex;
2160
1761
  this._filterDialog.data = items; // TODO: Move all settings to configuration object
2161
-
2162
1762
  this._filterDialog.filterMode = filterMode;
2163
1763
  this._filterDialog.conditions = condition2D;
2164
-
2165
1764
  this._filterDialog.show();
2166
1765
  };
2167
1766
  /** @private
@@ -2169,160 +1768,128 @@ RowFilteringPlugin.prototype.openDialog = function (colIndex, runtimeDialogOptio
2169
1768
  * @param {Object} config
2170
1769
  * @param {RowFilteringPlugin~FilterDialogOptions=} userConfig
2171
1770
  */
2172
-
2173
-
2174
1771
  RowFilteringPlugin._overrideConfig = function (config, userConfig) {
2175
1772
  if (!userConfig) {
2176
1773
  return;
2177
1774
  }
2178
-
2179
1775
  var sortUI = userConfig["sortUI"];
2180
-
2181
1776
  if (sortUI != null) {
2182
1777
  config.sortUI = sortUI;
2183
1778
  }
2184
-
2185
1779
  var filterUI = userConfig["filterUI"];
2186
-
2187
1780
  if (filterUI != null) {
2188
1781
  config.filterUI = filterUI;
2189
1782
  }
2190
-
2191
1783
  var fieldDataType = userConfig["fieldDataType"];
2192
-
2193
1784
  if (fieldDataType != null) {
2194
1785
  config.fieldDataType = fieldDataType;
2195
1786
  }
2196
-
2197
1787
  var lang = userConfig["lang"];
2198
-
2199
1788
  if (lang != null) {
2200
1789
  config.lang = lang;
2201
1790
  }
2202
-
2203
1791
  var rawDataAccessor = userConfig["rawDataAccessor"];
2204
-
2205
1792
  if (typeof rawDataAccessor === "function" || rawDataAccessor === null) {
2206
1793
  // Allow null value
2207
1794
  config.rawDataAccessor = rawDataAccessor;
2208
1795
  }
2209
-
2210
1796
  var formattedDataAccessor = userConfig["formattedDataAccessor"];
2211
-
2212
1797
  if (typeof formattedDataAccessor === "function" || formattedDataAccessor === null) {
2213
1798
  // Allow null value
2214
1799
  config.formattedDataAccessor = formattedDataAccessor;
2215
1800
  }
2216
-
2217
1801
  var sortLogic = userConfig["sortLogic"];
2218
-
2219
1802
  if (typeof sortLogic === "function" || sortLogic === null) {
2220
1803
  // Allow null value
2221
1804
  config.sortLogic = sortLogic;
2222
1805
  }
2223
-
2224
1806
  var itemList = userConfig["itemList"];
2225
-
2226
1807
  if (itemList != null) {
2227
1808
  config.itemList = itemList;
2228
1809
  }
2229
-
2230
1810
  var additionalItems = userConfig["additionalItems"];
2231
-
2232
1811
  if (additionalItems != null) {
2233
1812
  config.additionalItems = additionalItems;
2234
1813
  }
1814
+ var blankValues = userConfig["blankValues"];
1815
+ if (blankValues) {
1816
+ if (typeof blankValues === "string") {
1817
+ config.blankValues = blankValues;
1818
+ } else {
1819
+ config.blankValues = BLANKS;
1820
+ }
1821
+ }
2235
1822
  };
2236
1823
  /** @private
2237
1824
  * @param {number} colIndex
2238
1825
  * @return {Function}
2239
1826
  */
2240
-
2241
-
2242
1827
  RowFilteringPlugin.prototype._getFormatter = function (colIndex) {
2243
1828
  var tfp = this._getPlugin("TextFormattingPlugin");
2244
-
2245
1829
  if (tfp) {
2246
1830
  var formatter = tfp.getFormatter(colIndex);
2247
-
2248
1831
  if (formatter) {
2249
1832
  return formatter.format || null;
2250
1833
  }
2251
1834
  }
2252
-
2253
1835
  return null;
2254
1836
  };
2255
1837
  /** @private
2256
1838
  * @return {!FilterBuilder}
2257
1839
  */
2258
-
2259
-
2260
1840
  RowFilteringPlugin._getFilterBuilder = function () {
2261
1841
  if (!RowFilteringPlugin._filterBuilder) {
2262
1842
  RowFilteringPlugin._filterBuilder = new FilterBuilder();
2263
1843
  }
2264
-
2265
1844
  return RowFilteringPlugin._filterBuilder;
2266
1845
  };
1846
+
2267
1847
  /** @private
2268
1848
  * @param {Object} e
2269
1849
  */
2270
-
2271
-
2272
1850
  RowFilteringPlugin.prototype._onDialogFilterChanged = function (e) {
2273
1851
  var colIndex = this._filterDialog._colIndex;
2274
-
2275
1852
  var cfo = this._getColumnFilterOption(colIndex);
2276
-
2277
1853
  var uniqueValues = cfo.uniqueValues; // Unique values have to be stored before the removal of the filter
2278
-
2279
1854
  var rawDataAccessor = cfo._rawDataAccessor;
2280
1855
  var formattedDataAccessor = cfo._formattedDataAccessor;
2281
1856
  var ctx = null;
2282
-
2283
1857
  if (rawDataAccessor || formattedDataAccessor) {
2284
1858
  ctx = {
2285
1859
  "rawDataAccessor": rawDataAccessor || null,
2286
1860
  "formattedDataAccessor": formattedDataAccessor || null
2287
1861
  };
2288
1862
  }
1863
+ this.removeColumnFilters(colIndex);
2289
1864
 
2290
- this.removeColumnFilters(colIndex); // Check inputs from advanced filter UIs
2291
-
1865
+ // Check inputs from advanced filter UIs
2292
1866
  var conditions = e.detail.conditions;
2293
-
2294
1867
  if (Array.isArray(conditions)) {
2295
1868
  // Advanced condition filtering. Expecting 2D-Array
2296
1869
  // Ensure rawValue input for number field data type
2297
1870
  var condCount = conditions.length;
2298
-
2299
1871
  for (var m = 0; m < condCount; ++m) {
2300
1872
  var cond = conditions[m];
2301
- var opDef = FilterOperators[cond[0]]; // string type has no need for formatted data or raw data. What is in display is the most important
2302
-
1873
+ var opDef = FilterOperators[cond[0]];
1874
+ // string type has no need for formatted data or raw data. What is in display is the most important
2303
1875
  if (opDef && opDef.type !== "string") {
2304
1876
  var inputVal = cond[1]; // inputVal is hardcoded at index 1
2305
-
2306
1877
  var rawValues = uniqueValues[inputVal];
2307
-
2308
1878
  if (rawValues != null) {
2309
1879
  cond[1] = rawValues[0];
2310
1880
  }
2311
1881
  }
2312
1882
  }
2313
-
2314
1883
  if (ctx) {
2315
1884
  ctx["_autoGenerated"] = true;
2316
1885
  }
2317
-
2318
1886
  this.addColumnFilter(colIndex, conditions, ctx);
2319
1887
  return;
2320
- } // Check input from free text input
2321
-
1888
+ }
2322
1889
 
1890
+ // Check input from free text input
2323
1891
  var selVal = e.detail.value;
2324
1892
  var selAry = null;
2325
-
2326
1893
  if (selVal) {
2327
1894
  if (typeof selVal === "string") {
2328
1895
  // Custom filter mode (free style text).
@@ -2330,47 +1897,45 @@ RowFilteringPlugin.prototype._onDialogFilterChanged = function (e) {
2330
1897
  this.addColumnFilter(colIndex, selVal);
2331
1898
  return;
2332
1899
  } else {
2333
- selAry =
2334
- /** @type{Array} */
2335
- selVal; // Expecting Array of object
1900
+ selAry = /** @type{Array} */selVal; // Expecting Array of object
2336
1901
  }
2337
1902
  }
2338
1903
 
2339
1904
  var selCount = selAry ? selAry.length : 0;
2340
-
2341
1905
  if (!selCount) {
2342
1906
  return;
2343
- } // The given input is from simple text filter selector
2344
- // Validate if the input is correct and prepare selected items for building filter
2345
-
1907
+ }
2346
1908
 
1909
+ // The given input is from simple text filter selector
1910
+ // Validate if the input is correct and prepare selected items for building filter
2347
1911
  var itemMap = {};
2348
1912
  var selectedItems = {};
2349
1913
  var atLeastOne = false;
2350
-
2351
1914
  for (var i = 0; i < selCount; ++i) {
2352
1915
  var formattedVal = selAry[i].title; // title is defined by the multi-select element
2353
1916
  // var selIdx = selAry[i].index; // index cannot be used due to filtering
2354
-
1917
+ if (selAry[i].value === BLANKS) {
1918
+ if (!ctx) {
1919
+ ctx = {};
1920
+ }
1921
+ ctx.blankValues = true;
1922
+ atLeastOne = true;
1923
+ continue;
1924
+ }
2355
1925
  var rawVals = uniqueValues[formattedVal];
2356
-
2357
1926
  if (!rawVals) {
2358
1927
  continue;
2359
1928
  }
2360
-
2361
1929
  atLeastOne = true;
2362
1930
  selectedItems[formattedVal] = true;
2363
1931
  var jLen = rawVals.length;
2364
-
2365
1932
  for (var j = 0; j < jLen; ++j) {
2366
1933
  itemMap[rawVals[j]] = true;
2367
1934
  }
2368
1935
  }
2369
-
2370
1936
  if (atLeastOne) {
2371
1937
  this.addColumnFilter(colIndex, itemMap, ctx);
2372
1938
  }
2373
-
2374
1939
  this._dispatch("dialogCommitted", {
2375
1940
  "value": e.detail.value,
2376
1941
  "fieldDataType": e.detail.fieldDataType,
@@ -2380,21 +1945,16 @@ RowFilteringPlugin.prototype._onDialogFilterChanged = function (e) {
2380
1945
  /** @private
2381
1946
  * @param {Object} e
2382
1947
  */
2383
-
2384
-
2385
1948
  RowFilteringPlugin.prototype._onDialogSortChanged = function (e) {
2386
1949
  var stp = this._getPlugin("SortableTitlePlugin");
2387
-
2388
1950
  if (stp) {
2389
1951
  var colIndex = this._filterDialog._colIndex;
2390
1952
  var eDetail = e.detail.value ? e.detail.value : e.detail;
2391
-
2392
1953
  if (stp.getSortOrder(colIndex) === eDetail) {
2393
1954
  stp.sortColumn(colIndex, "n");
2394
1955
  } else {
2395
1956
  stp.sortColumn(colIndex, eDetail);
2396
1957
  }
2397
-
2398
1958
  this._dispatch("dialogCommitted", {
2399
1959
  "sortOrder": e.detail.value,
2400
1960
  "colIndex": colIndex
@@ -2404,12 +1964,9 @@ RowFilteringPlugin.prototype._onDialogSortChanged = function (e) {
2404
1964
  /** @private
2405
1965
  * @param {Object} e
2406
1966
  */
2407
-
2408
-
2409
1967
  RowFilteringPlugin.prototype._onColumnAdded = function (e) {
2410
1968
  if (e["context"]) {
2411
1969
  var hasFilter = this._setColumnOptions(e["colIndex"], e["context"]);
2412
-
2413
1970
  if (hasFilter) {
2414
1971
  this._applyPendingFilter();
2415
1972
  }
@@ -2418,47 +1975,35 @@ RowFilteringPlugin.prototype._onColumnAdded = function (e) {
2418
1975
  /** @private
2419
1976
  * @param {Object} e
2420
1977
  */
2421
-
2422
-
2423
1978
  RowFilteringPlugin.prototype._onColumnRemoved = function (e) {
2424
- var colData =
2425
- /** @type{Object} */
2426
- e.columnData;
2427
-
1979
+ var colData = /** @type{Object} */e.columnData;
2428
1980
  if (!colData) {
2429
1981
  return;
2430
1982
  }
2431
-
2432
1983
  var crf = colData["rowFiltering"];
2433
1984
  var cfo = crf["filterOption"];
2434
-
2435
1985
  if (cfo) {
2436
1986
  var funcIndex = this._columnFilters.indexOf(cfo);
2437
-
2438
1987
  if (funcIndex >= 0) {
2439
1988
  this._columnFilters.splice(funcIndex, 1);
2440
1989
  }
2441
-
2442
1990
  this._dispatch("filterChanged", {
2443
1991
  "filterType": "column",
2444
1992
  "changeType": "remove",
2445
1993
  "colIndex": e.colIndex,
2446
1994
  "field": cfo._field || ""
2447
1995
  });
2448
-
2449
1996
  this._requestFilterRefresh();
2450
1997
  }
2451
1998
  };
1999
+
2452
2000
  /** the filter will automatically hide empty segment when all of its member are filtered out. If there is no active filter, any empty segment will not be hidden. Collapsed segment does not count as having a filter. A segment with no child is treated the same way as an empty segment.
2453
2001
  * @public
2454
2002
  * @param {boolean=} enabled=true
2455
2003
  */
2456
-
2457
-
2458
2004
  RowFilteringPlugin.prototype.enableEmptySegmentFiltering = function (enabled) {
2459
2005
  var host = this._hosts[0];
2460
2006
  var dv = host ? host.getDataSource() : null;
2461
-
2462
2007
  if (dv && dv.enableEmptySegmentFiltering) {
2463
2008
  dv.enableEmptySegmentFiltering(enabled);
2464
2009
  }
@@ -2467,16 +2012,12 @@ RowFilteringPlugin.prototype.enableEmptySegmentFiltering = function (enabled) {
2467
2012
  * @public
2468
2013
  * @param {boolean=} enabled=true
2469
2014
  */
2470
-
2471
-
2472
2015
  RowFilteringPlugin.prototype.enableSeparatorFiltering = function (enabled) {
2473
2016
  var host = this._hosts[0];
2474
2017
  var dv = host ? host.getDataSource() : null;
2475
-
2476
2018
  if (dv && dv.enableSeparatorFiltering) {
2477
2019
  dv.enableSeparatorFiltering(enabled);
2478
2020
  }
2479
2021
  };
2480
-
2481
2022
  export default RowFilteringPlugin;
2482
2023
  export { RowFilteringPlugin, RowFilteringPlugin as RowFiltering, RowFilteringPlugin as RowFilteringExtension };