datatables.net-searchbuilder 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3829 @@
1
+ /*! SearchBuilder 1.4.0
2
+ * ©SpryMedia Ltd - datatables.net/license/mit
3
+ */
4
+
5
+ import $ from 'jquery';
6
+ import DataTable from 'datatables.net';
7
+
8
+
9
+ (function () {
10
+ 'use strict';
11
+
12
+ var $$3;
13
+ var dataTable$3;
14
+ function moment() {
15
+ return window.moment;
16
+ }
17
+ function luxon() {
18
+ return window.luxon;
19
+ }
20
+ /**
21
+ * Sets the value of jQuery for use in the file
22
+ *
23
+ * @param jq the instance of jQuery to be set
24
+ */
25
+ function setJQuery$2(jq) {
26
+ $$3 = jq;
27
+ dataTable$3 = jq.fn.dataTable;
28
+ }
29
+ /**
30
+ * The Criteria class is used within SearchBuilder to represent a search criteria
31
+ */
32
+ var Criteria = /** @class */ (function () {
33
+ function Criteria(table, opts, topGroup, index, depth, serverData) {
34
+ var _this = this;
35
+ if (index === void 0) { index = 0; }
36
+ if (depth === void 0) { depth = 1; }
37
+ if (serverData === void 0) { serverData = undefined; }
38
+ // Check that the required version of DataTables is included
39
+ if (!dataTable$3 || !dataTable$3.versionCheck || !dataTable$3.versionCheck('1.10.0')) {
40
+ throw new Error('SearchPane requires DataTables 1.10 or newer');
41
+ }
42
+ this.classes = $$3.extend(true, {}, Criteria.classes);
43
+ // Get options from user and any extra conditions/column types defined by plug-ins
44
+ this.c = $$3.extend(true, {}, Criteria.defaults, $$3.fn.dataTable.ext.searchBuilder, opts);
45
+ var i18n = this.c.i18n;
46
+ this.s = {
47
+ condition: undefined,
48
+ conditions: {},
49
+ data: undefined,
50
+ dataIdx: -1,
51
+ dataPoints: [],
52
+ dateFormat: false,
53
+ depth: depth,
54
+ dt: table,
55
+ filled: false,
56
+ index: index,
57
+ origData: undefined,
58
+ preventRedraw: false,
59
+ serverData: serverData,
60
+ topGroup: topGroup,
61
+ type: '',
62
+ value: []
63
+ };
64
+ this.dom = {
65
+ buttons: $$3('<div/>')
66
+ .addClass(this.classes.buttonContainer),
67
+ condition: $$3('<select disabled/>')
68
+ .addClass(this.classes.condition)
69
+ .addClass(this.classes.dropDown)
70
+ .addClass(this.classes.italic)
71
+ .attr('autocomplete', 'hacking'),
72
+ conditionTitle: $$3('<option value="" disabled selected hidden/>')
73
+ .html(this.s.dt.i18n('searchBuilder.condition', i18n.condition)),
74
+ container: $$3('<div/>')
75
+ .addClass(this.classes.container),
76
+ data: $$3('<select/>')
77
+ .addClass(this.classes.data)
78
+ .addClass(this.classes.dropDown)
79
+ .addClass(this.classes.italic),
80
+ dataTitle: $$3('<option value="" disabled selected hidden/>')
81
+ .html(this.s.dt.i18n('searchBuilder.data', i18n.data)),
82
+ defaultValue: $$3('<select disabled/>')
83
+ .addClass(this.classes.value)
84
+ .addClass(this.classes.dropDown)
85
+ .addClass(this.classes.select)
86
+ .addClass(this.classes.italic),
87
+ "delete": $$3('<button/>')
88
+ .html(this.s.dt.i18n('searchBuilder.delete', i18n["delete"]))
89
+ .addClass(this.classes["delete"])
90
+ .addClass(this.classes.button)
91
+ .attr('title', this.s.dt.i18n('searchBuilder.deleteTitle', i18n.deleteTitle))
92
+ .attr('type', 'button'),
93
+ inputCont: $$3('<div/>')
94
+ .addClass(this.classes.inputCont),
95
+ // eslint-disable-next-line no-useless-escape
96
+ left: $$3('<button/>')
97
+ .html(this.s.dt.i18n('searchBuilder.left', i18n.left))
98
+ .addClass(this.classes.left)
99
+ .addClass(this.classes.button)
100
+ .attr('title', this.s.dt.i18n('searchBuilder.leftTitle', i18n.leftTitle))
101
+ .attr('type', 'button'),
102
+ // eslint-disable-next-line no-useless-escape
103
+ right: $$3('<button/>')
104
+ .html(this.s.dt.i18n('searchBuilder.right', i18n.right))
105
+ .addClass(this.classes.right)
106
+ .addClass(this.classes.button)
107
+ .attr('title', this.s.dt.i18n('searchBuilder.rightTitle', i18n.rightTitle))
108
+ .attr('type', 'button'),
109
+ value: [
110
+ $$3('<select disabled/>')
111
+ .addClass(this.classes.value)
112
+ .addClass(this.classes.dropDown)
113
+ .addClass(this.classes.italic)
114
+ .addClass(this.classes.select)
115
+ ],
116
+ valueTitle: $$3('<option value="--valueTitle--" disabled selected hidden/>')
117
+ .html(this.s.dt.i18n('searchBuilder.value', i18n.value))
118
+ };
119
+ // If the greyscale option is selected then add the class to add the grey colour to SearchBuilder
120
+ if (this.c.greyscale) {
121
+ this.dom.data.addClass(this.classes.greyscale);
122
+ this.dom.condition.addClass(this.classes.greyscale);
123
+ this.dom.defaultValue.addClass(this.classes.greyscale);
124
+ for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) {
125
+ var val = _a[_i];
126
+ val.addClass(this.classes.greyscale);
127
+ }
128
+ }
129
+ $$3(window).on('resize.dtsb', dataTable$3.util.throttle(function () {
130
+ _this.s.topGroup.trigger('dtsb-redrawLogic');
131
+ }));
132
+ this._buildCriteria();
133
+ return this;
134
+ }
135
+ /**
136
+ * Escape html characters within a string
137
+ *
138
+ * @param txt the string to be escaped
139
+ * @returns the escaped string
140
+ */
141
+ Criteria._escapeHTML = function (txt) {
142
+ return txt
143
+ .toString()
144
+ .replace(/&amp;/g, '&')
145
+ .replace(/&lt;/g, '<')
146
+ .replace(/&gt;/g, '>')
147
+ .replace(/&quot;/g, '"');
148
+ };
149
+ /**
150
+ * Parses formatted numbers down to a form where they can be compared
151
+ *
152
+ * @param val the value to convert
153
+ * @returns the converted value
154
+ */
155
+ Criteria.parseNumFmt = function (val) {
156
+ return +val.replace(/(?!^-)[^0-9.]/g, '');
157
+ };
158
+ /**
159
+ * Adds the left button to the criteria
160
+ */
161
+ Criteria.prototype.updateArrows = function (hasSiblings) {
162
+ if (hasSiblings === void 0) { hasSiblings = false; }
163
+ // Empty the container and append all of the elements in the correct order
164
+ this.dom.container.children().detach();
165
+ this.dom.container
166
+ .append(this.dom.data)
167
+ .append(this.dom.condition)
168
+ .append(this.dom.inputCont);
169
+ this.setListeners();
170
+ // Trigger the inserted events for the value elements as they are inserted
171
+ if (this.dom.value[0] !== undefined) {
172
+ this.dom.value[0].trigger('dtsb-inserted');
173
+ }
174
+ for (var i = 1; i < this.dom.value.length; i++) {
175
+ this.dom.inputCont.append(this.dom.value[i]);
176
+ this.dom.value[i].trigger('dtsb-inserted');
177
+ }
178
+ // If this is a top level criteria then don't let it move left
179
+ if (this.s.depth > 1) {
180
+ this.dom.buttons.append(this.dom.left);
181
+ }
182
+ // If the depthLimit of the query has been hit then don't add the right button
183
+ if ((this.c.depthLimit === false || this.s.depth < this.c.depthLimit) && hasSiblings) {
184
+ this.dom.buttons.append(this.dom.right);
185
+ }
186
+ else {
187
+ this.dom.right.remove();
188
+ }
189
+ this.dom.buttons.append(this.dom["delete"]);
190
+ this.dom.container.append(this.dom.buttons);
191
+ };
192
+ /**
193
+ * Destroys the criteria, removing listeners and container from the dom
194
+ */
195
+ Criteria.prototype.destroy = function () {
196
+ // Turn off listeners
197
+ this.dom.data.off('.dtsb');
198
+ this.dom.condition.off('.dtsb');
199
+ this.dom["delete"].off('.dtsb');
200
+ for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) {
201
+ var val = _a[_i];
202
+ val.off('.dtsb');
203
+ }
204
+ // Remove container from the dom
205
+ this.dom.container.remove();
206
+ };
207
+ /**
208
+ * Passes in the data for the row and compares it against this single criteria
209
+ *
210
+ * @param rowData The data for the row to be compared
211
+ * @returns boolean Whether the criteria has passed
212
+ */
213
+ Criteria.prototype.search = function (rowData, rowIdx) {
214
+ var condition = this.s.conditions[this.s.condition];
215
+ if (this.s.condition !== undefined && condition !== undefined) {
216
+ var filter = rowData[this.s.dataIdx];
217
+ // This check is in place for if a custom decimal character is in place
218
+ if (this.s.type.includes('num') &&
219
+ (this.s.dt.settings()[0].oLanguage.sDecimal !== '' ||
220
+ this.s.dt.settings()[0].oLanguage.sThousands !== '')) {
221
+ var splitRD = [rowData[this.s.dataIdx]];
222
+ if (this.s.dt.settings()[0].oLanguage.sDecimal !== '') {
223
+ splitRD = rowData[this.s.dataIdx].split(this.s.dt.settings()[0].oLanguage.sDecimal);
224
+ }
225
+ if (this.s.dt.settings()[0].oLanguage.sThousands !== '') {
226
+ for (var i = 0; i < splitRD.length; i++) {
227
+ splitRD[i] = splitRD[i].replace(this.s.dt.settings()[0].oLanguage.sThousands, ',');
228
+ }
229
+ }
230
+ filter = splitRD.join('.');
231
+ }
232
+ // If orthogonal data is in place we need to get it's values for searching
233
+ if (this.c.orthogonal.search !== 'filter') {
234
+ var settings = this.s.dt.settings()[0];
235
+ filter = settings.oApi._fnGetCellData(settings, rowIdx, this.s.dataIdx, typeof this.c.orthogonal === 'string' ?
236
+ this.c.orthogonal :
237
+ this.c.orthogonal.search);
238
+ }
239
+ if (this.s.type === 'array') {
240
+ // Make sure we are working with an array
241
+ if (!Array.isArray(filter)) {
242
+ filter = [filter];
243
+ }
244
+ filter.sort();
245
+ for (var _i = 0, filter_1 = filter; _i < filter_1.length; _i++) {
246
+ var filt = filter_1[_i];
247
+ if (filt && typeof filt === 'string') {
248
+ filt = filt.replace(/[\r\n\u2028]/g, ' ');
249
+ }
250
+ }
251
+ }
252
+ else if (filter !== null && typeof filter === 'string') {
253
+ filter = filter.replace(/[\r\n\u2028]/g, ' ');
254
+ }
255
+ if (this.s.type.includes('html') && typeof filter === 'string') {
256
+ filter = filter.replace(/(<([^>]+)>)/ig, '');
257
+ }
258
+ // Not ideal, but jqueries .val() returns an empty string even
259
+ // when the value set is null, so we shall assume the two are equal
260
+ if (filter === null) {
261
+ filter = '';
262
+ }
263
+ return condition.search(filter, this.s.value, this);
264
+ }
265
+ };
266
+ /**
267
+ * Gets the details required to rebuild the criteria
268
+ */
269
+ Criteria.prototype.getDetails = function (deFormatDates) {
270
+ if (deFormatDates === void 0) { deFormatDates = false; }
271
+ // This check is in place for if a custom decimal character is in place
272
+ if (this.s.type !== null &&
273
+ this.s.type.includes('num') &&
274
+ (this.s.dt.settings()[0].oLanguage.sDecimal !== '' || this.s.dt.settings()[0].oLanguage.sThousands !== '')) {
275
+ for (var i = 0; i < this.s.value.length; i++) {
276
+ var splitRD = [this.s.value[i].toString()];
277
+ if (this.s.dt.settings()[0].oLanguage.sDecimal !== '') {
278
+ splitRD = this.s.value[i].split(this.s.dt.settings()[0].oLanguage.sDecimal);
279
+ }
280
+ if (this.s.dt.settings()[0].oLanguage.sThousands !== '') {
281
+ for (var j = 0; j < splitRD.length; j++) {
282
+ splitRD[j] = splitRD[j].replace(this.s.dt.settings()[0].oLanguage.sThousands, ',');
283
+ }
284
+ }
285
+ this.s.value[i] = splitRD.join('.');
286
+ }
287
+ }
288
+ else if (this.s.type !== null && deFormatDates) {
289
+ if (this.s.type.includes('date') ||
290
+ this.s.type.includes('time')) {
291
+ for (var i = 0; i < this.s.value.length; i++) {
292
+ if (this.s.value[i].match(/^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])$/g) === null) {
293
+ this.s.value[i] = '';
294
+ }
295
+ }
296
+ }
297
+ else if (this.s.type.includes('moment')) {
298
+ for (var i = 0; i < this.s.value.length; i++) {
299
+ if (this.s.value[i] &&
300
+ this.s.value[i].length > 0 &&
301
+ moment()(this.s.value[i], this.s.dateFormat, true).isValid()) {
302
+ this.s.value[i] = moment()(this.s.value[i], this.s.dateFormat).format('YYYY-MM-DD HH:mm:ss');
303
+ }
304
+ }
305
+ }
306
+ else if (this.s.type.includes('luxon')) {
307
+ for (var i = 0; i < this.s.value.length; i++) {
308
+ if (this.s.value[i] &&
309
+ this.s.value[i].length > 0 &&
310
+ luxon().DateTime.fromFormat(this.s.value[i], this.s.dateFormat).invalid === null) {
311
+ this.s.value[i] = luxon().DateTime.fromFormat(this.s.value[i], this.s.dateFormat).toFormat('yyyy-MM-dd HH:mm:ss');
312
+ }
313
+ }
314
+ }
315
+ }
316
+ if (this.s.type.includes('num') && this.s.dt.page.info().serverSide) {
317
+ for (var i = 0; i < this.s.value.length; i++) {
318
+ this.s.value[i] = this.s.value[i].replace(/[^0-9.]/g, '');
319
+ }
320
+ }
321
+ return {
322
+ condition: this.s.condition,
323
+ data: this.s.data,
324
+ origData: this.s.origData,
325
+ type: this.s.type,
326
+ value: this.s.value.map(function (a) { return a !== null && a !== undefined ? a.toString() : a; })
327
+ };
328
+ };
329
+ /**
330
+ * Getter for the node for the container of the criteria
331
+ *
332
+ * @returns JQuery<HTMLElement> the node for the container
333
+ */
334
+ Criteria.prototype.getNode = function () {
335
+ return this.dom.container;
336
+ };
337
+ /**
338
+ * Populates the criteria data, condition and value(s) as far as has been selected
339
+ */
340
+ Criteria.prototype.populate = function () {
341
+ this._populateData();
342
+ // If the column index has been found attempt to select a condition
343
+ if (this.s.dataIdx !== -1) {
344
+ this._populateCondition();
345
+ // If the condittion has been found attempt to select the values
346
+ if (this.s.condition !== undefined) {
347
+ this._populateValue();
348
+ }
349
+ }
350
+ };
351
+ /**
352
+ * Rebuilds the criteria based upon the details passed in
353
+ *
354
+ * @param loadedCriteria the details required to rebuild the criteria
355
+ */
356
+ Criteria.prototype.rebuild = function (loadedCriteria) {
357
+ // Check to see if the previously selected data exists, if so select it
358
+ var foundData = false;
359
+ var dataIdx;
360
+ this._populateData();
361
+ // If a data selection has previously been made attempt to find and select it
362
+ if (loadedCriteria.data !== undefined) {
363
+ var italic_1 = this.classes.italic;
364
+ var data_1 = this.dom.data;
365
+ this.dom.data.children('option').each(function () {
366
+ if (!foundData &&
367
+ ($$3(this).text() === loadedCriteria.data ||
368
+ loadedCriteria.origData && $$3(this).prop('origData') === loadedCriteria.origData)) {
369
+ $$3(this).prop('selected', true);
370
+ data_1.removeClass(italic_1);
371
+ foundData = true;
372
+ dataIdx = $$3(this).val();
373
+ }
374
+ else {
375
+ $$3(this).removeProp('selected');
376
+ }
377
+ });
378
+ }
379
+ // If the data has been found and selected then the condition can be populated and searched
380
+ if (foundData) {
381
+ this.s.data = loadedCriteria.data;
382
+ this.s.origData = loadedCriteria.origData;
383
+ this.s.dataIdx = dataIdx;
384
+ this.c.orthogonal = this._getOptions().orthogonal;
385
+ this.dom.dataTitle.remove();
386
+ this._populateCondition();
387
+ this.dom.conditionTitle.remove();
388
+ var condition = void 0;
389
+ // Check to see if the previously selected condition exists, if so select it
390
+ var options = this.dom.condition.children('option');
391
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
392
+ for (var i = 0; i < options.length; i++) {
393
+ var option = $$3(options[i]);
394
+ if (loadedCriteria.condition !== undefined &&
395
+ option.val() === loadedCriteria.condition &&
396
+ typeof loadedCriteria.condition === 'string') {
397
+ option.prop('selected', true);
398
+ condition = option.val();
399
+ }
400
+ else {
401
+ option.removeProp('selected');
402
+ }
403
+ }
404
+ this.s.condition = condition;
405
+ // If the condition has been found and selected then the value can be populated and searched
406
+ if (this.s.condition !== undefined) {
407
+ this.dom.conditionTitle.removeProp('selected');
408
+ this.dom.conditionTitle.remove();
409
+ this.dom.condition.removeClass(this.classes.italic);
410
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
411
+ for (var i = 0; i < options.length; i++) {
412
+ var option = $$3(options[i]);
413
+ if (option.val() !== this.s.condition) {
414
+ option.removeProp('selected');
415
+ }
416
+ }
417
+ this._populateValue(loadedCriteria);
418
+ }
419
+ else {
420
+ this.dom.conditionTitle.prependTo(this.dom.condition).prop('selected', true);
421
+ }
422
+ }
423
+ };
424
+ /**
425
+ * Sets the listeners for the criteria
426
+ */
427
+ Criteria.prototype.setListeners = function () {
428
+ var _this = this;
429
+ this.dom.data
430
+ .unbind('change')
431
+ .on('change.dtsb', function () {
432
+ _this.dom.dataTitle.removeProp('selected');
433
+ // Need to go over every option to identify the correct selection
434
+ var options = _this.dom.data.children('option.' + _this.classes.option);
435
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
436
+ for (var i = 0; i < options.length; i++) {
437
+ var option = $$3(options[i]);
438
+ if (option.val() === _this.dom.data.val()) {
439
+ _this.dom.data.removeClass(_this.classes.italic);
440
+ option.prop('selected', true);
441
+ _this.s.dataIdx = +option.val();
442
+ _this.s.data = option.text();
443
+ _this.s.origData = option.prop('origData');
444
+ _this.c.orthogonal = _this._getOptions().orthogonal;
445
+ // When the data is changed, the values in condition and
446
+ // value may also change so need to renew them
447
+ _this._clearCondition();
448
+ _this._clearValue();
449
+ _this._populateCondition();
450
+ // If this criteria was previously active in the search then
451
+ // remove it from the search and trigger a new search
452
+ if (_this.s.filled) {
453
+ _this.s.filled = false;
454
+ _this.s.dt.draw();
455
+ _this.setListeners();
456
+ }
457
+ _this.s.dt.state.save();
458
+ }
459
+ else {
460
+ option.removeProp('selected');
461
+ }
462
+ }
463
+ });
464
+ this.dom.condition
465
+ .unbind('change')
466
+ .on('change.dtsb', function () {
467
+ _this.dom.conditionTitle.removeProp('selected');
468
+ // Need to go over every option to identify the correct selection
469
+ var options = _this.dom.condition.children('option.' + _this.classes.option);
470
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
471
+ for (var i = 0; i < options.length; i++) {
472
+ var option = $$3(options[i]);
473
+ if (option.val() === _this.dom.condition.val()) {
474
+ _this.dom.condition.removeClass(_this.classes.italic);
475
+ option.prop('selected', true);
476
+ var condDisp = option.val();
477
+ // Find the condition that has been selected and store it internally
478
+ for (var _i = 0, _a = Object.keys(_this.s.conditions); _i < _a.length; _i++) {
479
+ var cond = _a[_i];
480
+ if (cond === condDisp) {
481
+ _this.s.condition = condDisp;
482
+ break;
483
+ }
484
+ }
485
+ // When the condition is changed, the value selector may switch between
486
+ // a select element and an input element
487
+ _this._clearValue();
488
+ _this._populateValue();
489
+ for (var _b = 0, _c = _this.dom.value; _b < _c.length; _b++) {
490
+ var val = _c[_b];
491
+ // If this criteria was previously active in the search then remove
492
+ // it from the search and trigger a new search
493
+ if (_this.s.filled && val !== undefined && _this.dom.inputCont.has(val[0]).length !== 0) {
494
+ _this.s.filled = false;
495
+ _this.s.dt.draw();
496
+ _this.setListeners();
497
+ }
498
+ }
499
+ if (_this.dom.value.length === 0 ||
500
+ _this.dom.value.length === 1 && _this.dom.value[0] === undefined) {
501
+ _this.s.dt.draw();
502
+ }
503
+ }
504
+ else {
505
+ option.removeProp('selected');
506
+ }
507
+ }
508
+ });
509
+ };
510
+ Criteria.prototype.setupButtons = function () {
511
+ if (window.innerWidth > 550) {
512
+ this.dom.container.removeClass(this.classes.vertical);
513
+ this.dom.buttons.css('left', null);
514
+ this.dom.buttons.css('top', null);
515
+ return;
516
+ }
517
+ this.dom.container.addClass(this.classes.vertical);
518
+ this.dom.buttons.css('left', this.dom.data.innerWidth());
519
+ this.dom.buttons.css('top', this.dom.data.position().top);
520
+ };
521
+ /**
522
+ * Builds the elements of the dom together
523
+ */
524
+ Criteria.prototype._buildCriteria = function () {
525
+ // Append Titles for select elements
526
+ this.dom.data.append(this.dom.dataTitle);
527
+ this.dom.condition.append(this.dom.conditionTitle);
528
+ // Add elements to container
529
+ this.dom.container
530
+ .append(this.dom.data)
531
+ .append(this.dom.condition);
532
+ this.dom.inputCont.empty();
533
+ for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) {
534
+ var val = _a[_i];
535
+ val.append(this.dom.valueTitle);
536
+ this.dom.inputCont.append(val);
537
+ }
538
+ // Add buttons to container
539
+ this.dom.buttons
540
+ .append(this.dom["delete"])
541
+ .append(this.dom.right);
542
+ this.dom.container.append(this.dom.inputCont).append(this.dom.buttons);
543
+ this.setListeners();
544
+ };
545
+ /**
546
+ * Clears the condition select element
547
+ */
548
+ Criteria.prototype._clearCondition = function () {
549
+ this.dom.condition.empty();
550
+ this.dom.conditionTitle.prop('selected', true).attr('disabled', 'true');
551
+ this.dom.condition.prepend(this.dom.conditionTitle).prop('selectedIndex', 0);
552
+ this.s.conditions = {};
553
+ this.s.condition = undefined;
554
+ };
555
+ /**
556
+ * Clears the value elements
557
+ */
558
+ Criteria.prototype._clearValue = function () {
559
+ if (this.s.condition !== undefined) {
560
+ if (this.dom.value.length > 0 && this.dom.value[0] !== undefined) {
561
+ var _loop_1 = function (val) {
562
+ if (val !== undefined) {
563
+ // Timeout is annoying but because of IOS
564
+ setTimeout(function () {
565
+ val.remove();
566
+ }, 50);
567
+ }
568
+ };
569
+ // Remove all of the value elements
570
+ for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) {
571
+ var val = _a[_i];
572
+ _loop_1(val);
573
+ }
574
+ }
575
+ // Call the init function to get the value elements for this condition
576
+ this.dom.value = [].concat(this.s.conditions[this.s.condition].init(this, Criteria.updateListener));
577
+ if (this.dom.value.length > 0 && this.dom.value[0] !== undefined) {
578
+ this.dom.inputCont
579
+ .empty()
580
+ .append(this.dom.value[0])
581
+ .insertAfter(this.dom.condition);
582
+ this.dom.value[0].trigger('dtsb-inserted');
583
+ // Insert all of the value elements
584
+ for (var i = 1; i < this.dom.value.length; i++) {
585
+ this.dom.inputCont.append(this.dom.value[i]);
586
+ this.dom.value[i].trigger('dtsb-inserted');
587
+ }
588
+ }
589
+ }
590
+ else {
591
+ var _loop_2 = function (val) {
592
+ if (val !== undefined) {
593
+ // Timeout is annoying but because of IOS
594
+ setTimeout(function () {
595
+ val.remove();
596
+ }, 50);
597
+ }
598
+ };
599
+ // Remove all of the value elements
600
+ for (var _b = 0, _c = this.dom.value; _b < _c.length; _b++) {
601
+ var val = _c[_b];
602
+ _loop_2(val);
603
+ }
604
+ // Append the default valueTitle to the default select element
605
+ this.dom.valueTitle
606
+ .prop('selected', true);
607
+ this.dom.defaultValue
608
+ .append(this.dom.valueTitle)
609
+ .insertAfter(this.dom.condition);
610
+ }
611
+ this.s.value = [];
612
+ this.dom.value = [
613
+ $$3('<select disabled/>')
614
+ .addClass(this.classes.value)
615
+ .addClass(this.classes.dropDown)
616
+ .addClass(this.classes.italic)
617
+ .addClass(this.classes.select)
618
+ .append(this.dom.valueTitle.clone())
619
+ ];
620
+ };
621
+ /**
622
+ * Gets the options for the column
623
+ *
624
+ * @returns {object} The options for the column
625
+ */
626
+ Criteria.prototype._getOptions = function () {
627
+ var table = this.s.dt;
628
+ return $$3.extend(true, {}, Criteria.defaults, table.settings()[0].aoColumns[this.s.dataIdx].searchBuilder);
629
+ };
630
+ /**
631
+ * Populates the condition dropdown
632
+ */
633
+ Criteria.prototype._populateCondition = function () {
634
+ var conditionOpts = [];
635
+ var conditionsLength = Object.keys(this.s.conditions).length;
636
+ var colInits = this.s.dt.settings()[0].aoColumns;
637
+ var column = +this.dom.data.children('option:selected').val();
638
+ // If there are no conditions stored then we need to get them from the appropriate type
639
+ if (conditionsLength === 0) {
640
+ this.s.type = this.s.dt.columns().type().toArray()[column];
641
+ if (colInits !== undefined) {
642
+ var colInit = colInits[column];
643
+ if (colInit.searchBuilderType !== undefined && colInit.searchBuilderType !== null) {
644
+ this.s.type = colInit.searchBuilderType;
645
+ }
646
+ else if (this.s.type === undefined || this.s.type === null) {
647
+ this.s.type = colInit.sType;
648
+ }
649
+ }
650
+ // If the column type is still unknown, call a draw to try reading it again
651
+ if (this.s.type === null || this.s.type === undefined) {
652
+ $$3.fn.dataTable.ext.oApi._fnColumnTypes(this.s.dt.settings()[0]);
653
+ this.s.type = this.s.dt.columns().type().toArray()[column];
654
+ }
655
+ // Enable the condition element
656
+ this.dom.condition
657
+ .removeAttr('disabled')
658
+ .empty()
659
+ .append(this.dom.conditionTitle)
660
+ .addClass(this.classes.italic);
661
+ this.dom.conditionTitle
662
+ .prop('selected', true);
663
+ var decimal = this.s.dt.settings()[0].oLanguage.sDecimal;
664
+ // This check is in place for if a custom decimal character is in place
665
+ if (decimal !== '' && this.s.type.indexOf(decimal) === this.s.type.length - decimal.length) {
666
+ if (this.s.type.includes('num-fmt')) {
667
+ this.s.type = this.s.type.replace(decimal, '');
668
+ }
669
+ else if (this.s.type.includes('num')) {
670
+ this.s.type = this.s.type.replace(decimal, '');
671
+ }
672
+ }
673
+ // Select which conditions are going to be used based on the column type
674
+ var conditionObj = this.c.conditions[this.s.type] !== undefined ?
675
+ this.c.conditions[this.s.type] :
676
+ this.s.type.includes('moment') ?
677
+ this.c.conditions.moment :
678
+ this.s.type.includes('luxon') ?
679
+ this.c.conditions.luxon :
680
+ this.c.conditions.string;
681
+ // If it is a moment format then extract the date format
682
+ if (this.s.type.includes('moment')) {
683
+ this.s.dateFormat = this.s.type.replace(/moment-/g, '');
684
+ }
685
+ else if (this.s.type.includes('luxon')) {
686
+ this.s.dateFormat = this.s.type.replace(/luxon-/g, '');
687
+ }
688
+ // Add all of the conditions to the select element
689
+ for (var _i = 0, _a = Object.keys(conditionObj); _i < _a.length; _i++) {
690
+ var condition = _a[_i];
691
+ if (conditionObj[condition] !== null) {
692
+ // Serverside processing does not supply the options for the select elements
693
+ // Instead input elements need to be used for these instead
694
+ if (this.s.dt.page.info().serverSide && conditionObj[condition].init === Criteria.initSelect) {
695
+ var col = colInits[column];
696
+ if (this.s.serverData && this.s.serverData[col.data]) {
697
+ conditionObj[condition].init = Criteria.initSelectSSP;
698
+ conditionObj[condition].inputValue = Criteria.inputValueSelect;
699
+ conditionObj[condition].isInputValid = Criteria.isInputValidSelect;
700
+ }
701
+ else {
702
+ conditionObj[condition].init = Criteria.initInput;
703
+ conditionObj[condition].inputValue = Criteria.inputValueInput;
704
+ conditionObj[condition].isInputValid = Criteria.isInputValidInput;
705
+ }
706
+ }
707
+ this.s.conditions[condition] = conditionObj[condition];
708
+ var condName = conditionObj[condition].conditionName;
709
+ if (typeof condName === 'function') {
710
+ condName = condName(this.s.dt, this.c.i18n);
711
+ }
712
+ conditionOpts.push($$3('<option>', {
713
+ text: condName,
714
+ value: condition
715
+ })
716
+ .addClass(this.classes.option)
717
+ .addClass(this.classes.notItalic));
718
+ }
719
+ }
720
+ }
721
+ // Otherwise we can just load them in
722
+ else if (conditionsLength > 0) {
723
+ this.dom.condition.empty().removeAttr('disabled').addClass(this.classes.italic);
724
+ for (var _b = 0, _c = Object.keys(this.s.conditions); _b < _c.length; _b++) {
725
+ var condition = _c[_b];
726
+ var condName = this.s.conditions[condition].conditionName;
727
+ if (typeof condName === 'function') {
728
+ condName = condName(this.s.dt, this.c.i18n);
729
+ }
730
+ var newOpt = $$3('<option>', {
731
+ text: condName,
732
+ value: condition
733
+ })
734
+ .addClass(this.classes.option)
735
+ .addClass(this.classes.notItalic);
736
+ if (this.s.condition !== undefined && this.s.condition === condName) {
737
+ newOpt.prop('selected', true);
738
+ this.dom.condition.removeClass(this.classes.italic);
739
+ }
740
+ conditionOpts.push(newOpt);
741
+ }
742
+ }
743
+ else {
744
+ this.dom.condition
745
+ .attr('disabled', 'true')
746
+ .addClass(this.classes.italic);
747
+ return;
748
+ }
749
+ for (var _d = 0, conditionOpts_1 = conditionOpts; _d < conditionOpts_1.length; _d++) {
750
+ var opt = conditionOpts_1[_d];
751
+ this.dom.condition.append(opt);
752
+ }
753
+ // Selecting a default condition if one is set
754
+ if (colInits[column].searchBuilder && colInits[column].searchBuilder.defaultCondition) {
755
+ var defaultCondition = colInits[column].searchBuilder.defaultCondition;
756
+ // If it is a number just use it as an index
757
+ if (typeof defaultCondition === 'number') {
758
+ this.dom.condition.prop('selectedIndex', defaultCondition);
759
+ this.dom.condition.trigger('change');
760
+ }
761
+ // If it is a string then things get slightly more tricly
762
+ else if (typeof defaultCondition === 'string') {
763
+ // We need to check each condition option to see if any will match
764
+ for (var i = 0; i < conditionOpts.length; i++) {
765
+ // Need to check against the stored conditions so we can match the token "cond" to the option
766
+ for (var _e = 0, _f = Object.keys(this.s.conditions); _e < _f.length; _e++) {
767
+ var cond = _f[_e];
768
+ var condName = this.s.conditions[cond].conditionName;
769
+ if (
770
+ // If the conditionName matches the text of the option
771
+ (typeof condName === 'string' ? condName : condName(this.s.dt, this.c.i18n)) ===
772
+ conditionOpts[i].text() &&
773
+ // and the tokens match
774
+ cond === defaultCondition) {
775
+ // Select that option
776
+ this.dom.condition
777
+ .prop('selectedIndex', this.dom.condition.children().toArray().indexOf(conditionOpts[i][0]))
778
+ .removeClass(this.classes.italic);
779
+ this.dom.condition.trigger('change');
780
+ i = conditionOpts.length;
781
+ break;
782
+ }
783
+ }
784
+ }
785
+ }
786
+ }
787
+ // If not default set then default to 0, the title
788
+ else {
789
+ this.dom.condition.prop('selectedIndex', 0);
790
+ }
791
+ };
792
+ /**
793
+ * Populates the data select element
794
+ */
795
+ Criteria.prototype._populateData = function () {
796
+ var _this = this;
797
+ this.dom.data.empty().append(this.dom.dataTitle);
798
+ // If there are no datas stored then we need to get them from the table
799
+ if (this.s.dataPoints.length === 0) {
800
+ this.s.dt.columns().every(function (index) {
801
+ // Need to check that the column can be filtered on before adding it
802
+ if (_this.c.columns === true ||
803
+ _this.s.dt.columns(_this.c.columns).indexes().toArray().includes(index)) {
804
+ var found = false;
805
+ for (var _i = 0, _a = _this.s.dataPoints; _i < _a.length; _i++) {
806
+ var val = _a[_i];
807
+ if (val.index === index) {
808
+ found = true;
809
+ break;
810
+ }
811
+ }
812
+ if (!found) {
813
+ var col = _this.s.dt.settings()[0].aoColumns[index];
814
+ var opt = {
815
+ index: index,
816
+ origData: col.data,
817
+ text: (col.searchBuilderTitle === undefined ?
818
+ col.sTitle :
819
+ col.searchBuilderTitle).replace(/(<([^>]+)>)/ig, '')
820
+ };
821
+ _this.s.dataPoints.push(opt);
822
+ _this.dom.data.append($$3('<option>', {
823
+ text: opt.text,
824
+ value: opt.index
825
+ })
826
+ .addClass(_this.classes.option)
827
+ .addClass(_this.classes.notItalic)
828
+ .prop('origData', col.data)
829
+ .prop('selected', _this.s.dataIdx === opt.index ? true : false));
830
+ if (_this.s.dataIdx === opt.index) {
831
+ _this.dom.dataTitle.removeProp('selected');
832
+ }
833
+ }
834
+ }
835
+ });
836
+ }
837
+ // Otherwise we can just load them in
838
+ else {
839
+ var _loop_3 = function (data) {
840
+ this_1.s.dt.columns().every(function (index) {
841
+ var col = _this.s.dt.settings()[0].aoColumns[index];
842
+ if ((col.searchBuilderTitle === undefined ?
843
+ col.sTitle :
844
+ col.searchBuilderTitle).replace(/(<([^>]+)>)/ig, '') === data.text) {
845
+ data.index = index;
846
+ data.origData = col.data;
847
+ }
848
+ });
849
+ var newOpt = $$3('<option>', {
850
+ text: data.text.replace(/(<([^>]+)>)/ig, ''),
851
+ value: data.index
852
+ })
853
+ .addClass(this_1.classes.option)
854
+ .addClass(this_1.classes.notItalic)
855
+ .prop('origData', data.origData);
856
+ if (this_1.s.data === data.text) {
857
+ this_1.s.dataIdx = data.index;
858
+ this_1.dom.dataTitle.removeProp('selected');
859
+ newOpt.prop('selected', true);
860
+ this_1.dom.data.removeClass(this_1.classes.italic);
861
+ }
862
+ this_1.dom.data.append(newOpt);
863
+ };
864
+ var this_1 = this;
865
+ for (var _i = 0, _a = this.s.dataPoints; _i < _a.length; _i++) {
866
+ var data = _a[_i];
867
+ _loop_3(data);
868
+ }
869
+ }
870
+ };
871
+ /**
872
+ * Populates the Value select element
873
+ *
874
+ * @param loadedCriteria optional, used to reload criteria from predefined filters
875
+ */
876
+ Criteria.prototype._populateValue = function (loadedCriteria) {
877
+ var _this = this;
878
+ var prevFilled = this.s.filled;
879
+ this.s.filled = false;
880
+ // Remove any previous value elements
881
+ // Timeout is annoying but because of IOS
882
+ setTimeout(function () {
883
+ _this.dom.defaultValue.remove();
884
+ }, 50);
885
+ var _loop_4 = function (val) {
886
+ // Timeout is annoying but because of IOS
887
+ setTimeout(function () {
888
+ if (val !== undefined) {
889
+ val.remove();
890
+ }
891
+ }, 50);
892
+ };
893
+ for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) {
894
+ var val = _a[_i];
895
+ _loop_4(val);
896
+ }
897
+ var children = this.dom.inputCont.children();
898
+ if (children.length > 1) {
899
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
900
+ for (var i = 0; i < children.length; i++) {
901
+ $$3(children[i]).remove();
902
+ }
903
+ }
904
+ // Find the column with the title matching the data for the criteria and take note of the index
905
+ if (loadedCriteria !== undefined) {
906
+ this.s.dt.columns().every(function (index) {
907
+ if (_this.s.dt.settings()[0].aoColumns[index].sTitle === loadedCriteria.data) {
908
+ _this.s.dataIdx = index;
909
+ }
910
+ });
911
+ }
912
+ // Initialise the value elements based on the condition
913
+ this.dom.value = [].concat(this.s.conditions[this.s.condition].init(this, Criteria.updateListener, loadedCriteria !== undefined ? loadedCriteria.value : undefined));
914
+ if (loadedCriteria !== undefined && loadedCriteria.value !== undefined) {
915
+ this.s.value = loadedCriteria.value;
916
+ }
917
+ this.dom.inputCont.empty();
918
+ // Insert value elements and trigger the inserted event
919
+ if (this.dom.value[0] !== undefined) {
920
+ this.dom.value[0]
921
+ .appendTo(this.dom.inputCont)
922
+ .trigger('dtsb-inserted');
923
+ }
924
+ for (var i = 1; i < this.dom.value.length; i++) {
925
+ this.dom.value[i]
926
+ .insertAfter(this.dom.value[i - 1])
927
+ .trigger('dtsb-inserted');
928
+ }
929
+ // Check if the criteria can be used in a search
930
+ this.s.filled = this.s.conditions[this.s.condition].isInputValid(this.dom.value, this);
931
+ this.setListeners();
932
+ // If it can and this is different to before then trigger a draw
933
+ if (!this.s.preventRedraw && prevFilled !== this.s.filled) {
934
+ // If using SSP we want to restrict the amount of server calls that take place
935
+ // and this will already have taken place
936
+ if (!this.s.dt.page.info().serverSide) {
937
+ this.s.dt.draw();
938
+ }
939
+ this.setListeners();
940
+ }
941
+ };
942
+ /**
943
+ * Provides throttling capabilities to SearchBuilder without having to use dt's _fnThrottle function
944
+ * This is because that function is not quite suitable for our needs as it runs initially rather than waiting
945
+ *
946
+ * @param args arguments supplied to the throttle function
947
+ * @returns Function that is to be run that implements the throttling
948
+ */
949
+ Criteria.prototype._throttle = function (fn, frequency) {
950
+ if (frequency === void 0) { frequency = 200; }
951
+ var last = null;
952
+ var timer = null;
953
+ var that = this;
954
+ if (frequency === null) {
955
+ frequency = 200;
956
+ }
957
+ return function () {
958
+ var args = [];
959
+ for (var _i = 0; _i < arguments.length; _i++) {
960
+ args[_i] = arguments[_i];
961
+ }
962
+ var now = +new Date();
963
+ if (last !== null && now < last + frequency) {
964
+ clearTimeout(timer);
965
+ }
966
+ else {
967
+ last = now;
968
+ }
969
+ timer = setTimeout(function () {
970
+ last = null;
971
+ fn.apply(that, args);
972
+ }, frequency);
973
+ };
974
+ };
975
+ Criteria.version = '1.1.0';
976
+ Criteria.classes = {
977
+ button: 'dtsb-button',
978
+ buttonContainer: 'dtsb-buttonContainer',
979
+ condition: 'dtsb-condition',
980
+ container: 'dtsb-criteria',
981
+ data: 'dtsb-data',
982
+ "delete": 'dtsb-delete',
983
+ dropDown: 'dtsb-dropDown',
984
+ greyscale: 'dtsb-greyscale',
985
+ input: 'dtsb-input',
986
+ inputCont: 'dtsb-inputCont',
987
+ italic: 'dtsb-italic',
988
+ joiner: 'dtsp-joiner',
989
+ left: 'dtsb-left',
990
+ notItalic: 'dtsb-notItalic',
991
+ option: 'dtsb-option',
992
+ right: 'dtsb-right',
993
+ select: 'dtsb-select',
994
+ value: 'dtsb-value',
995
+ vertical: 'dtsb-vertical'
996
+ };
997
+ /**
998
+ * Default initialisation function for select conditions
999
+ */
1000
+ Criteria.initSelect = function (that, fn, preDefined, array) {
1001
+ if (preDefined === void 0) { preDefined = null; }
1002
+ if (array === void 0) { array = false; }
1003
+ var column = that.dom.data.children('option:selected').val();
1004
+ var indexArray = that.s.dt.rows().indexes().toArray();
1005
+ var settings = that.s.dt.settings()[0];
1006
+ that.dom.valueTitle.prop('selected', true);
1007
+ // Declare select element to be used with all of the default classes and listeners.
1008
+ var el = $$3('<select/>')
1009
+ .addClass(Criteria.classes.value)
1010
+ .addClass(Criteria.classes.dropDown)
1011
+ .addClass(Criteria.classes.italic)
1012
+ .addClass(Criteria.classes.select)
1013
+ .append(that.dom.valueTitle)
1014
+ .on('change.dtsb', function () {
1015
+ $$3(this).removeClass(Criteria.classes.italic);
1016
+ fn(that, this);
1017
+ });
1018
+ if (that.c.greyscale) {
1019
+ el.addClass(Criteria.classes.greyscale);
1020
+ }
1021
+ var added = [];
1022
+ var options = [];
1023
+ // Add all of the options from the table to the select element.
1024
+ // Only add one option for each possible value
1025
+ for (var _i = 0, indexArray_1 = indexArray; _i < indexArray_1.length; _i++) {
1026
+ var index = indexArray_1[_i];
1027
+ var filter = settings.oApi._fnGetCellData(settings, index, column, typeof that.c.orthogonal === 'string' ?
1028
+ that.c.orthogonal :
1029
+ that.c.orthogonal.search);
1030
+ var value = {
1031
+ filter: typeof filter === 'string' ?
1032
+ filter.replace(/[\r\n\u2028]/g, ' ') : // Need to replace certain characters to match search values
1033
+ filter,
1034
+ index: index,
1035
+ text: settings.oApi._fnGetCellData(settings, index, column, typeof that.c.orthogonal === 'string' ?
1036
+ that.c.orthogonal :
1037
+ that.c.orthogonal.display)
1038
+ };
1039
+ // If we are dealing with an array type, either make sure we are working with arrays, or sort them
1040
+ if (that.s.type === 'array') {
1041
+ value.filter = !Array.isArray(value.filter) ? [value.filter] : value.filter;
1042
+ value.text = !Array.isArray(value.text) ? [value.text] : value.text;
1043
+ }
1044
+ // Function to add an option to the select element
1045
+ var addOption = function (filt, text) {
1046
+ if (that.s.type.includes('html') && filt !== null && typeof filt === 'string') {
1047
+ filt.replace(/(<([^>]+)>)/ig, '');
1048
+ }
1049
+ // Add text and value, stripping out any html if that is the column type
1050
+ var opt = $$3('<option>', {
1051
+ type: Array.isArray(filt) ? 'Array' : 'String',
1052
+ value: filt
1053
+ })
1054
+ .data('sbv', filt)
1055
+ .addClass(that.classes.option)
1056
+ .addClass(that.classes.notItalic)
1057
+ // Have to add the text this way so that special html characters are not escaped - &amp; etc.
1058
+ .html(typeof text === 'string' ?
1059
+ text.replace(/(<([^>]+)>)/ig, '') :
1060
+ text);
1061
+ var val = opt.val();
1062
+ // Check that this value has not already been added
1063
+ if (added.indexOf(val) === -1) {
1064
+ added.push(val);
1065
+ options.push(opt);
1066
+ if (preDefined !== null && Array.isArray(preDefined[0])) {
1067
+ preDefined[0] = preDefined[0].sort().join(',');
1068
+ }
1069
+ // If this value was previously selected as indicated by preDefined, then select it again
1070
+ if (preDefined !== null && opt.val() === preDefined[0]) {
1071
+ opt.prop('selected', true);
1072
+ el.removeClass(Criteria.classes.italic);
1073
+ that.dom.valueTitle.removeProp('selected');
1074
+ }
1075
+ }
1076
+ };
1077
+ // If this is to add the individual values within the array we need to loop over the array
1078
+ if (array) {
1079
+ for (var i = 0; i < value.filter.length; i++) {
1080
+ addOption(value.filter[i], value.text[i]);
1081
+ }
1082
+ }
1083
+ // Otherwise the value that is in the cell is to be added
1084
+ else {
1085
+ addOption(value.filter, Array.isArray(value.text) ? value.text.join(', ') : value.text);
1086
+ }
1087
+ }
1088
+ options.sort(function (a, b) {
1089
+ if (that.s.type === 'array' ||
1090
+ that.s.type === 'string' ||
1091
+ that.s.type === 'html') {
1092
+ if (a.val() < b.val()) {
1093
+ return -1;
1094
+ }
1095
+ else if (a.val() > b.val()) {
1096
+ return 1;
1097
+ }
1098
+ else {
1099
+ return 0;
1100
+ }
1101
+ }
1102
+ else if (that.s.type === 'num' ||
1103
+ that.s.type === 'html-num') {
1104
+ if (+a.val().replace(/(<([^>]+)>)/ig, '') < +b.val().replace(/(<([^>]+)>)/ig, '')) {
1105
+ return -1;
1106
+ }
1107
+ else if (+a.val().replace(/(<([^>]+)>)/ig, '') > +b.val().replace(/(<([^>]+)>)/ig, '')) {
1108
+ return 1;
1109
+ }
1110
+ else {
1111
+ return 0;
1112
+ }
1113
+ }
1114
+ else if (that.s.type === 'num-fmt' || that.s.type === 'html-num-fmt') {
1115
+ if (+a.val().replace(/[^0-9.]/g, '') < +b.val().replace(/[^0-9.]/g, '')) {
1116
+ return -1;
1117
+ }
1118
+ else if (+a.val().replace(/[^0-9.]/g, '') > +b.val().replace(/[^0-9.]/g, '')) {
1119
+ return 1;
1120
+ }
1121
+ else {
1122
+ return 0;
1123
+ }
1124
+ }
1125
+ });
1126
+ for (var _a = 0, options_1 = options; _a < options_1.length; _a++) {
1127
+ var opt = options_1[_a];
1128
+ el.append(opt);
1129
+ }
1130
+ return el;
1131
+ };
1132
+ /**
1133
+ * Default initialisation function for select conditions
1134
+ */
1135
+ Criteria.initSelectSSP = function (that, fn, preDefined) {
1136
+ if (preDefined === void 0) { preDefined = null; }
1137
+ that.dom.valueTitle.prop('selected', true);
1138
+ // Declare select element to be used with all of the default classes and listeners.
1139
+ var el = $$3('<select/>')
1140
+ .addClass(Criteria.classes.value)
1141
+ .addClass(Criteria.classes.dropDown)
1142
+ .addClass(Criteria.classes.italic)
1143
+ .addClass(Criteria.classes.select)
1144
+ .append(that.dom.valueTitle)
1145
+ .on('change.dtsb', function () {
1146
+ $$3(this).removeClass(Criteria.classes.italic);
1147
+ fn(that, this);
1148
+ });
1149
+ if (that.c.greyscale) {
1150
+ el.addClass(Criteria.classes.greyscale);
1151
+ }
1152
+ var options = [];
1153
+ for (var _i = 0, _a = that.s.serverData[that.s.origData]; _i < _a.length; _i++) {
1154
+ var option = _a[_i];
1155
+ var value = option.value;
1156
+ var label = option.label;
1157
+ // Function to add an option to the select element
1158
+ var addOption = function (filt, text) {
1159
+ if (that.s.type.includes('html') && filt !== null && typeof filt === 'string') {
1160
+ filt.replace(/(<([^>]+)>)/ig, '');
1161
+ }
1162
+ // Add text and value, stripping out any html if that is the column type
1163
+ var opt = $$3('<option>', {
1164
+ type: Array.isArray(filt) ? 'Array' : 'String',
1165
+ value: filt
1166
+ })
1167
+ .data('sbv', filt)
1168
+ .addClass(that.classes.option)
1169
+ .addClass(that.classes.notItalic)
1170
+ // Have to add the text this way so that special html characters are not escaped - &amp; etc.
1171
+ .html(typeof text === 'string' ?
1172
+ text.replace(/(<([^>]+)>)/ig, '') :
1173
+ text);
1174
+ options.push(opt);
1175
+ // If this value was previously selected as indicated by preDefined, then select it again
1176
+ if (preDefined !== null && opt.val() === preDefined[0]) {
1177
+ opt.prop('selected', true);
1178
+ el.removeClass(Criteria.classes.italic);
1179
+ that.dom.valueTitle.removeProp('selected');
1180
+ }
1181
+ };
1182
+ addOption(value, label);
1183
+ }
1184
+ for (var _b = 0, options_2 = options; _b < options_2.length; _b++) {
1185
+ var opt = options_2[_b];
1186
+ el.append(opt);
1187
+ }
1188
+ return el;
1189
+ };
1190
+ /**
1191
+ * Default initialisation function for select array conditions
1192
+ *
1193
+ * This exists because there needs to be different select functionality for contains/without and equals/not
1194
+ */
1195
+ Criteria.initSelectArray = function (that, fn, preDefined) {
1196
+ if (preDefined === void 0) { preDefined = null; }
1197
+ return Criteria.initSelect(that, fn, preDefined, true);
1198
+ };
1199
+ /**
1200
+ * Default initialisation function for input conditions
1201
+ */
1202
+ Criteria.initInput = function (that, fn, preDefined) {
1203
+ if (preDefined === void 0) { preDefined = null; }
1204
+ // Declare the input element
1205
+ var searchDelay = that.s.dt.settings()[0].searchDelay;
1206
+ var el = $$3('<input/>')
1207
+ .addClass(Criteria.classes.value)
1208
+ .addClass(Criteria.classes.input)
1209
+ .on('input.dtsb keypress.dtsb', that._throttle(function (e) {
1210
+ var code = e.keyCode || e.which;
1211
+ return fn(that, this, code);
1212
+ }, searchDelay === null ? 100 : searchDelay));
1213
+ if (that.c.greyscale) {
1214
+ el.addClass(Criteria.classes.greyscale);
1215
+ }
1216
+ // If there is a preDefined value then add it
1217
+ if (preDefined !== null) {
1218
+ el.val(preDefined[0]);
1219
+ }
1220
+ // This is add responsive functionality to the logic button without redrawing everything else
1221
+ that.s.dt.one('draw.dtsb', function () {
1222
+ that.s.topGroup.trigger('dtsb-redrawLogic');
1223
+ });
1224
+ return el;
1225
+ };
1226
+ /**
1227
+ * Default initialisation function for conditions requiring 2 inputs
1228
+ */
1229
+ Criteria.init2Input = function (that, fn, preDefined) {
1230
+ if (preDefined === void 0) { preDefined = null; }
1231
+ // Declare all of the necessary jQuery elements
1232
+ var searchDelay = that.s.dt.settings()[0].searchDelay;
1233
+ var els = [
1234
+ $$3('<input/>')
1235
+ .addClass(Criteria.classes.value)
1236
+ .addClass(Criteria.classes.input)
1237
+ .on('input.dtsb keypress.dtsb', that._throttle(function (e) {
1238
+ var code = e.keyCode || e.which;
1239
+ return fn(that, this, code);
1240
+ }, searchDelay === null ? 100 : searchDelay)),
1241
+ $$3('<span>')
1242
+ .addClass(that.classes.joiner)
1243
+ .html(that.s.dt.i18n('searchBuilder.valueJoiner', that.c.i18n.valueJoiner)),
1244
+ $$3('<input/>')
1245
+ .addClass(Criteria.classes.value)
1246
+ .addClass(Criteria.classes.input)
1247
+ .on('input.dtsb keypress.dtsb', that._throttle(function (e) {
1248
+ var code = e.keyCode || e.which;
1249
+ return fn(that, this, code);
1250
+ }, searchDelay === null ? 100 : searchDelay))
1251
+ ];
1252
+ if (that.c.greyscale) {
1253
+ els[0].addClass(Criteria.classes.greyscale);
1254
+ els[2].addClass(Criteria.classes.greyscale);
1255
+ }
1256
+ // If there is a preDefined value then add it
1257
+ if (preDefined !== null) {
1258
+ els[0].val(preDefined[0]);
1259
+ els[2].val(preDefined[1]);
1260
+ }
1261
+ // This is add responsive functionality to the logic button without redrawing everything else
1262
+ that.s.dt.one('draw.dtsb', function () {
1263
+ that.s.topGroup.trigger('dtsb-redrawLogic');
1264
+ });
1265
+ return els;
1266
+ };
1267
+ /**
1268
+ * Default initialisation function for date conditions
1269
+ */
1270
+ Criteria.initDate = function (that, fn, preDefined) {
1271
+ if (preDefined === void 0) { preDefined = null; }
1272
+ var searchDelay = that.s.dt.settings()[0].searchDelay;
1273
+ // Declare date element using DataTables dateTime plugin
1274
+ var el = $$3('<input/>')
1275
+ .addClass(Criteria.classes.value)
1276
+ .addClass(Criteria.classes.input)
1277
+ .dtDateTime({
1278
+ attachTo: 'input',
1279
+ format: that.s.dateFormat ? that.s.dateFormat : undefined
1280
+ })
1281
+ .on('change.dtsb', that._throttle(function () {
1282
+ return fn(that, this);
1283
+ }, searchDelay === null ? 100 : searchDelay))
1284
+ .on('input.dtsb keypress.dtsb', function (e) {
1285
+ that._throttle(function () {
1286
+ var code = e.keyCode || e.which;
1287
+ return fn(that, this, code);
1288
+ }, searchDelay === null ? 100 : searchDelay);
1289
+ });
1290
+ if (that.c.greyscale) {
1291
+ el.addClass(Criteria.classes.greyscale);
1292
+ }
1293
+ // If there is a preDefined value then add it
1294
+ if (preDefined !== null) {
1295
+ el.val(preDefined[0]);
1296
+ }
1297
+ // This is add responsive functionality to the logic button without redrawing everything else
1298
+ that.s.dt.one('draw.dtsb', function () {
1299
+ that.s.topGroup.trigger('dtsb-redrawLogic');
1300
+ });
1301
+ return el;
1302
+ };
1303
+ Criteria.initNoValue = function (that) {
1304
+ // This is add responsive functionality to the logic button without redrawing everything else
1305
+ that.s.dt.one('draw.dtsb', function () {
1306
+ that.s.topGroup.trigger('dtsb-redrawLogic');
1307
+ });
1308
+ };
1309
+ Criteria.init2Date = function (that, fn, preDefined) {
1310
+ var _this = this;
1311
+ if (preDefined === void 0) { preDefined = null; }
1312
+ var searchDelay = that.s.dt.settings()[0].searchDelay;
1313
+ // Declare all of the date elements that are required using DataTables dateTime plugin
1314
+ var els = [
1315
+ $$3('<input/>')
1316
+ .addClass(Criteria.classes.value)
1317
+ .addClass(Criteria.classes.input)
1318
+ .dtDateTime({
1319
+ attachTo: 'input',
1320
+ format: that.s.dateFormat ? that.s.dateFormat : undefined
1321
+ })
1322
+ .on('change.dtsb', searchDelay !== null ?
1323
+ that.s.dt.settings()[0].oApi._fnThrottle(function () {
1324
+ return fn(that, this);
1325
+ }, searchDelay) :
1326
+ function () {
1327
+ fn(that, _this);
1328
+ })
1329
+ .on('input.dtsb keypress.dtsb', function (e) {
1330
+ that.s.dt.settings()[0].oApi._fnThrottle(function () {
1331
+ var code = e.keyCode || e.which;
1332
+ return fn(that, this, code);
1333
+ }, searchDelay === null ? 0 : searchDelay);
1334
+ }),
1335
+ $$3('<span>')
1336
+ .addClass(that.classes.joiner)
1337
+ .html(that.s.dt.i18n('searchBuilder.valueJoiner', that.c.i18n.valueJoiner)),
1338
+ $$3('<input/>')
1339
+ .addClass(Criteria.classes.value)
1340
+ .addClass(Criteria.classes.input)
1341
+ .dtDateTime({
1342
+ attachTo: 'input',
1343
+ format: that.s.dateFormat ? that.s.dateFormat : undefined
1344
+ })
1345
+ .on('change.dtsb', searchDelay !== null ?
1346
+ that.s.dt.settings()[0].oApi._fnThrottle(function () {
1347
+ return fn(that, this);
1348
+ }, searchDelay) :
1349
+ function () {
1350
+ fn(that, _this);
1351
+ })
1352
+ .on('input.dtsb keypress.dtsb', !that.c.enterSearch &&
1353
+ !(that.s.dt.settings()[0].oInit.search !== undefined &&
1354
+ that.s.dt.settings()[0].oInit.search["return"]) &&
1355
+ searchDelay !== null ?
1356
+ that.s.dt.settings()[0].oApi._fnThrottle(function () {
1357
+ return fn(that, this);
1358
+ }, searchDelay) :
1359
+ function (e) {
1360
+ var code = e.keyCode || e.which;
1361
+ fn(that, _this, code);
1362
+ })
1363
+ ];
1364
+ if (that.c.greyscale) {
1365
+ els[0].addClass(Criteria.classes.greyscale);
1366
+ els[2].addClass(Criteria.classes.greyscale);
1367
+ }
1368
+ // If there are and preDefined values then add them
1369
+ if (preDefined !== null && preDefined.length > 0) {
1370
+ els[0].val(preDefined[0]);
1371
+ els[2].val(preDefined[1]);
1372
+ }
1373
+ // This is add responsive functionality to the logic button without redrawing everything else
1374
+ that.s.dt.one('draw.dtsb', function () {
1375
+ that.s.topGroup.trigger('dtsb-redrawLogic');
1376
+ });
1377
+ return els;
1378
+ };
1379
+ /**
1380
+ * Default function for select elements to validate condition
1381
+ */
1382
+ Criteria.isInputValidSelect = function (el) {
1383
+ var allFilled = true;
1384
+ // Check each element to make sure that the selections are valid
1385
+ for (var _i = 0, el_1 = el; _i < el_1.length; _i++) {
1386
+ var element = el_1[_i];
1387
+ if (element.children('option:selected').length ===
1388
+ element.children('option').length -
1389
+ element.children('option.' + Criteria.classes.notItalic).length &&
1390
+ element.children('option:selected').length === 1 &&
1391
+ element.children('option:selected')[0] === element.children('option')[0]) {
1392
+ allFilled = false;
1393
+ }
1394
+ }
1395
+ return allFilled;
1396
+ };
1397
+ /**
1398
+ * Default function for input and date elements to validate condition
1399
+ */
1400
+ Criteria.isInputValidInput = function (el) {
1401
+ var allFilled = true;
1402
+ // Check each element to make sure that the inputs are valid
1403
+ for (var _i = 0, el_2 = el; _i < el_2.length; _i++) {
1404
+ var element = el_2[_i];
1405
+ if (element.is('input') && element.val().length === 0) {
1406
+ allFilled = false;
1407
+ }
1408
+ }
1409
+ return allFilled;
1410
+ };
1411
+ /**
1412
+ * Default function for getting select conditions
1413
+ */
1414
+ Criteria.inputValueSelect = function (el) {
1415
+ var values = [];
1416
+ // Go through the select elements and push each selected option to the return array
1417
+ for (var _i = 0, el_3 = el; _i < el_3.length; _i++) {
1418
+ var element = el_3[_i];
1419
+ if (element.is('select')) {
1420
+ values.push(Criteria._escapeHTML(element.children('option:selected').data('sbv')));
1421
+ }
1422
+ }
1423
+ return values;
1424
+ };
1425
+ /**
1426
+ * Default function for getting input conditions
1427
+ */
1428
+ Criteria.inputValueInput = function (el) {
1429
+ var values = [];
1430
+ // Go through the input elements and push each value to the return array
1431
+ for (var _i = 0, el_4 = el; _i < el_4.length; _i++) {
1432
+ var element = el_4[_i];
1433
+ if (element.is('input')) {
1434
+ values.push(Criteria._escapeHTML(element.val()));
1435
+ }
1436
+ }
1437
+ return values;
1438
+ };
1439
+ /**
1440
+ * Function that is run on each element as a call back when a search should be triggered
1441
+ */
1442
+ Criteria.updateListener = function (that, el, code) {
1443
+ // When the value is changed the criteria is now complete so can be included in searches
1444
+ // Get the condition from the map based on the key that has been selected for the condition
1445
+ var condition = that.s.conditions[that.s.condition];
1446
+ that.s.filled = condition.isInputValid(that.dom.value, that);
1447
+ that.s.value = condition.inputValue(that.dom.value, that);
1448
+ if (!that.s.filled) {
1449
+ if (!that.c.enterSearch &&
1450
+ !(that.s.dt.settings()[0].oInit.search !== undefined &&
1451
+ that.s.dt.settings()[0].oInit.search["return"]) ||
1452
+ code === 13) {
1453
+ that.s.dt.draw();
1454
+ }
1455
+ return;
1456
+ }
1457
+ if (!Array.isArray(that.s.value)) {
1458
+ that.s.value = [that.s.value];
1459
+ }
1460
+ for (var i = 0; i < that.s.value.length; i++) {
1461
+ // If the value is an array we need to sort it
1462
+ if (Array.isArray(that.s.value[i])) {
1463
+ that.s.value[i].sort();
1464
+ }
1465
+ // Otherwise replace the decimal place character for i18n
1466
+ else if (that.s.type.includes('num') &&
1467
+ (that.s.dt.settings()[0].oLanguage.sDecimal !== '' ||
1468
+ that.s.dt.settings()[0].oLanguage.sThousands !== '')) {
1469
+ var splitRD = [that.s.value[i].toString()];
1470
+ if (that.s.dt.settings()[0].oLanguage.sDecimal !== '') {
1471
+ splitRD = that.s.value[i].split(that.s.dt.settings()[0].oLanguage.sDecimal);
1472
+ }
1473
+ if (that.s.dt.settings()[0].oLanguage.sThousands !== '') {
1474
+ for (var j = 0; j < splitRD.length; j++) {
1475
+ splitRD[j] = splitRD[j].replace(that.s.dt.settings()[0].oLanguage.sThousands, ',');
1476
+ }
1477
+ }
1478
+ that.s.value[i] = splitRD.join('.');
1479
+ }
1480
+ }
1481
+ // Take note of the cursor position so that we can refocus there later
1482
+ var idx = null;
1483
+ var cursorPos = null;
1484
+ for (var i = 0; i < that.dom.value.length; i++) {
1485
+ if (el === that.dom.value[i][0]) {
1486
+ idx = i;
1487
+ if (el.selectionStart !== undefined) {
1488
+ cursorPos = el.selectionStart;
1489
+ }
1490
+ }
1491
+ }
1492
+ if (!that.c.enterSearch &&
1493
+ !(that.s.dt.settings()[0].oInit.search !== undefined &&
1494
+ that.s.dt.settings()[0].oInit.search["return"]) ||
1495
+ code === 13) {
1496
+ // Trigger a search
1497
+ that.s.dt.draw();
1498
+ }
1499
+ // Refocus the element and set the correct cursor position
1500
+ if (idx !== null) {
1501
+ that.dom.value[idx].removeClass(that.classes.italic);
1502
+ that.dom.value[idx].focus();
1503
+ if (cursorPos !== null) {
1504
+ that.dom.value[idx][0].setSelectionRange(cursorPos, cursorPos);
1505
+ }
1506
+ }
1507
+ };
1508
+ // The order of the conditions will make eslint sad :(
1509
+ // Has to be in this order so that they are displayed correctly in select elements
1510
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
1511
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1512
+ Criteria.dateConditions = {
1513
+ '=': {
1514
+ conditionName: function (dt, i18n) {
1515
+ return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals);
1516
+ },
1517
+ init: Criteria.initDate,
1518
+ inputValue: Criteria.inputValueInput,
1519
+ isInputValid: Criteria.isInputValidInput,
1520
+ search: function (value, comparison) {
1521
+ value = value.replace(/(\/|-|,)/g, '-');
1522
+ return value === comparison[0];
1523
+ }
1524
+ },
1525
+ // eslint-disable-next-line sort-keys
1526
+ '!=': {
1527
+ conditionName: function (dt, i18n) {
1528
+ return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not);
1529
+ },
1530
+ init: Criteria.initDate,
1531
+ inputValue: Criteria.inputValueInput,
1532
+ isInputValid: Criteria.isInputValidInput,
1533
+ search: function (value, comparison) {
1534
+ value = value.replace(/(\/|-|,)/g, '-');
1535
+ return value !== comparison[0];
1536
+ }
1537
+ },
1538
+ '<': {
1539
+ conditionName: function (dt, i18n) {
1540
+ return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before);
1541
+ },
1542
+ init: Criteria.initDate,
1543
+ inputValue: Criteria.inputValueInput,
1544
+ isInputValid: Criteria.isInputValidInput,
1545
+ search: function (value, comparison) {
1546
+ value = value.replace(/(\/|-|,)/g, '-');
1547
+ return value < comparison[0];
1548
+ }
1549
+ },
1550
+ '>': {
1551
+ conditionName: function (dt, i18n) {
1552
+ return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after);
1553
+ },
1554
+ init: Criteria.initDate,
1555
+ inputValue: Criteria.inputValueInput,
1556
+ isInputValid: Criteria.isInputValidInput,
1557
+ search: function (value, comparison) {
1558
+ value = value.replace(/(\/|-|,)/g, '-');
1559
+ return value > comparison[0];
1560
+ }
1561
+ },
1562
+ 'between': {
1563
+ conditionName: function (dt, i18n) {
1564
+ return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between);
1565
+ },
1566
+ init: Criteria.init2Date,
1567
+ inputValue: Criteria.inputValueInput,
1568
+ isInputValid: Criteria.isInputValidInput,
1569
+ search: function (value, comparison) {
1570
+ value = value.replace(/(\/|-|,)/g, '-');
1571
+ if (comparison[0] < comparison[1]) {
1572
+ return comparison[0] <= value && value <= comparison[1];
1573
+ }
1574
+ else {
1575
+ return comparison[1] <= value && value <= comparison[0];
1576
+ }
1577
+ }
1578
+ },
1579
+ // eslint-disable-next-line sort-keys
1580
+ '!between': {
1581
+ conditionName: function (dt, i18n) {
1582
+ return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween);
1583
+ },
1584
+ init: Criteria.init2Date,
1585
+ inputValue: Criteria.inputValueInput,
1586
+ isInputValid: Criteria.isInputValidInput,
1587
+ search: function (value, comparison) {
1588
+ value = value.replace(/(\/|-|,)/g, '-');
1589
+ if (comparison[0] < comparison[1]) {
1590
+ return !(comparison[0] <= value && value <= comparison[1]);
1591
+ }
1592
+ else {
1593
+ return !(comparison[1] <= value && value <= comparison[0]);
1594
+ }
1595
+ }
1596
+ },
1597
+ 'null': {
1598
+ conditionName: function (dt, i18n) {
1599
+ return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty);
1600
+ },
1601
+ init: Criteria.initNoValue,
1602
+ inputValue: function () {
1603
+ return;
1604
+ },
1605
+ isInputValid: function () {
1606
+ return true;
1607
+ },
1608
+ search: function (value) {
1609
+ return value === null || value === undefined || value.length === 0;
1610
+ }
1611
+ },
1612
+ // eslint-disable-next-line sort-keys
1613
+ '!null': {
1614
+ conditionName: function (dt, i18n) {
1615
+ return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty);
1616
+ },
1617
+ init: Criteria.initNoValue,
1618
+ inputValue: function () {
1619
+ return;
1620
+ },
1621
+ isInputValid: function () {
1622
+ return true;
1623
+ },
1624
+ search: function (value) {
1625
+ return !(value === null || value === undefined || value.length === 0);
1626
+ }
1627
+ }
1628
+ };
1629
+ // The order of the conditions will make eslint sad :(
1630
+ // Has to be in this order so that they are displayed correctly in select elements
1631
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
1632
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1633
+ Criteria.momentDateConditions = {
1634
+ '=': {
1635
+ conditionName: function (dt, i18n) {
1636
+ return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals);
1637
+ },
1638
+ init: Criteria.initDate,
1639
+ inputValue: Criteria.inputValueInput,
1640
+ isInputValid: Criteria.isInputValidInput,
1641
+ search: function (value, comparison, that) {
1642
+ return moment()(value, that.s.dateFormat).valueOf() ===
1643
+ moment()(comparison[0], that.s.dateFormat).valueOf();
1644
+ }
1645
+ },
1646
+ // eslint-disable-next-line sort-keys
1647
+ '!=': {
1648
+ conditionName: function (dt, i18n) {
1649
+ return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not);
1650
+ },
1651
+ init: Criteria.initDate,
1652
+ inputValue: Criteria.inputValueInput,
1653
+ isInputValid: Criteria.isInputValidInput,
1654
+ search: function (value, comparison, that) {
1655
+ return moment()(value, that.s.dateFormat).valueOf() !==
1656
+ moment()(comparison[0], that.s.dateFormat).valueOf();
1657
+ }
1658
+ },
1659
+ '<': {
1660
+ conditionName: function (dt, i18n) {
1661
+ return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before);
1662
+ },
1663
+ init: Criteria.initDate,
1664
+ inputValue: Criteria.inputValueInput,
1665
+ isInputValid: Criteria.isInputValidInput,
1666
+ search: function (value, comparison, that) {
1667
+ return moment()(value, that.s.dateFormat).valueOf() < moment()(comparison[0], that.s.dateFormat).valueOf();
1668
+ }
1669
+ },
1670
+ '>': {
1671
+ conditionName: function (dt, i18n) {
1672
+ return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after);
1673
+ },
1674
+ init: Criteria.initDate,
1675
+ inputValue: Criteria.inputValueInput,
1676
+ isInputValid: Criteria.isInputValidInput,
1677
+ search: function (value, comparison, that) {
1678
+ return moment()(value, that.s.dateFormat).valueOf() > moment()(comparison[0], that.s.dateFormat).valueOf();
1679
+ }
1680
+ },
1681
+ 'between': {
1682
+ conditionName: function (dt, i18n) {
1683
+ return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between);
1684
+ },
1685
+ init: Criteria.init2Date,
1686
+ inputValue: Criteria.inputValueInput,
1687
+ isInputValid: Criteria.isInputValidInput,
1688
+ search: function (value, comparison, that) {
1689
+ var val = moment()(value, that.s.dateFormat).valueOf();
1690
+ var comp0 = moment()(comparison[0], that.s.dateFormat).valueOf();
1691
+ var comp1 = moment()(comparison[1], that.s.dateFormat).valueOf();
1692
+ if (comp0 < comp1) {
1693
+ return comp0 <= val && val <= comp1;
1694
+ }
1695
+ else {
1696
+ return comp1 <= val && val <= comp0;
1697
+ }
1698
+ }
1699
+ },
1700
+ // eslint-disable-next-line sort-keys
1701
+ '!between': {
1702
+ conditionName: function (dt, i18n) {
1703
+ return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween);
1704
+ },
1705
+ init: Criteria.init2Date,
1706
+ inputValue: Criteria.inputValueInput,
1707
+ isInputValid: Criteria.isInputValidInput,
1708
+ search: function (value, comparison, that) {
1709
+ var val = moment()(value, that.s.dateFormat).valueOf();
1710
+ var comp0 = moment()(comparison[0], that.s.dateFormat).valueOf();
1711
+ var comp1 = moment()(comparison[1], that.s.dateFormat).valueOf();
1712
+ if (comp0 < comp1) {
1713
+ return !(+comp0 <= +val && +val <= +comp1);
1714
+ }
1715
+ else {
1716
+ return !(+comp1 <= +val && +val <= +comp0);
1717
+ }
1718
+ }
1719
+ },
1720
+ 'null': {
1721
+ conditionName: function (dt, i18n) {
1722
+ return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty);
1723
+ },
1724
+ init: Criteria.initNoValue,
1725
+ inputValue: function () {
1726
+ return;
1727
+ },
1728
+ isInputValid: function () {
1729
+ return true;
1730
+ },
1731
+ search: function (value) {
1732
+ return value === null || value === undefined || value.length === 0;
1733
+ }
1734
+ },
1735
+ // eslint-disable-next-line sort-keys
1736
+ '!null': {
1737
+ conditionName: function (dt, i18n) {
1738
+ return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty);
1739
+ },
1740
+ init: Criteria.initNoValue,
1741
+ inputValue: function () {
1742
+ return;
1743
+ },
1744
+ isInputValid: function () {
1745
+ return true;
1746
+ },
1747
+ search: function (value) {
1748
+ return !(value === null || value === undefined || value.length === 0);
1749
+ }
1750
+ }
1751
+ };
1752
+ // The order of the conditions will make eslint sad :(
1753
+ // Has to be in this order so that they are displayed correctly in select elements
1754
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
1755
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1756
+ Criteria.luxonDateConditions = {
1757
+ '=': {
1758
+ conditionName: function (dt, i18n) {
1759
+ return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals);
1760
+ },
1761
+ init: Criteria.initDate,
1762
+ inputValue: Criteria.inputValueInput,
1763
+ isInputValid: Criteria.isInputValidInput,
1764
+ search: function (value, comparison, that) {
1765
+ return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts
1766
+ === luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1767
+ }
1768
+ },
1769
+ // eslint-disable-next-line sort-keys
1770
+ '!=': {
1771
+ conditionName: function (dt, i18n) {
1772
+ return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not);
1773
+ },
1774
+ init: Criteria.initDate,
1775
+ inputValue: Criteria.inputValueInput,
1776
+ isInputValid: Criteria.isInputValidInput,
1777
+ search: function (value, comparison, that) {
1778
+ return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts
1779
+ !== luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1780
+ }
1781
+ },
1782
+ '<': {
1783
+ conditionName: function (dt, i18n) {
1784
+ return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before);
1785
+ },
1786
+ init: Criteria.initDate,
1787
+ inputValue: Criteria.inputValueInput,
1788
+ isInputValid: Criteria.isInputValidInput,
1789
+ search: function (value, comparison, that) {
1790
+ return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts
1791
+ < luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1792
+ }
1793
+ },
1794
+ '>': {
1795
+ conditionName: function (dt, i18n) {
1796
+ return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after);
1797
+ },
1798
+ init: Criteria.initDate,
1799
+ inputValue: Criteria.inputValueInput,
1800
+ isInputValid: Criteria.isInputValidInput,
1801
+ search: function (value, comparison, that) {
1802
+ return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts
1803
+ > luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1804
+ }
1805
+ },
1806
+ 'between': {
1807
+ conditionName: function (dt, i18n) {
1808
+ return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between);
1809
+ },
1810
+ init: Criteria.init2Date,
1811
+ inputValue: Criteria.inputValueInput,
1812
+ isInputValid: Criteria.isInputValidInput,
1813
+ search: function (value, comparison, that) {
1814
+ var val = luxon().DateTime.fromFormat(value, that.s.dateFormat).ts;
1815
+ var comp0 = luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1816
+ var comp1 = luxon().DateTime.fromFormat(comparison[1], that.s.dateFormat).ts;
1817
+ if (comp0 < comp1) {
1818
+ return comp0 <= val && val <= comp1;
1819
+ }
1820
+ else {
1821
+ return comp1 <= val && val <= comp0;
1822
+ }
1823
+ }
1824
+ },
1825
+ // eslint-disable-next-line sort-keys
1826
+ '!between': {
1827
+ conditionName: function (dt, i18n) {
1828
+ return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween);
1829
+ },
1830
+ init: Criteria.init2Date,
1831
+ inputValue: Criteria.inputValueInput,
1832
+ isInputValid: Criteria.isInputValidInput,
1833
+ search: function (value, comparison, that) {
1834
+ var val = luxon().DateTime.fromFormat(value, that.s.dateFormat).ts;
1835
+ var comp0 = luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts;
1836
+ var comp1 = luxon().DateTime.fromFormat(comparison[1], that.s.dateFormat).ts;
1837
+ if (comp0 < comp1) {
1838
+ return !(+comp0 <= +val && +val <= +comp1);
1839
+ }
1840
+ else {
1841
+ return !(+comp1 <= +val && +val <= +comp0);
1842
+ }
1843
+ }
1844
+ },
1845
+ 'null': {
1846
+ conditionName: function (dt, i18n) {
1847
+ return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty);
1848
+ },
1849
+ init: Criteria.initNoValue,
1850
+ inputValue: function () {
1851
+ return;
1852
+ },
1853
+ isInputValid: function () {
1854
+ return true;
1855
+ },
1856
+ search: function (value) {
1857
+ return value === null || value === undefined || value.length === 0;
1858
+ }
1859
+ },
1860
+ // eslint-disable-next-line sort-keys
1861
+ '!null': {
1862
+ conditionName: function (dt, i18n) {
1863
+ return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty);
1864
+ },
1865
+ init: Criteria.initNoValue,
1866
+ inputValue: function () {
1867
+ return;
1868
+ },
1869
+ isInputValid: function () {
1870
+ return true;
1871
+ },
1872
+ search: function (value) {
1873
+ return !(value === null || value === undefined || value.length === 0);
1874
+ }
1875
+ }
1876
+ };
1877
+ // The order of the conditions will make eslint sad :(
1878
+ // Has to be in this order so that they are displayed correctly in select elements
1879
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
1880
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1881
+ Criteria.numConditions = {
1882
+ '=': {
1883
+ conditionName: function (dt, i18n) {
1884
+ return dt.i18n('searchBuilder.conditions.number.equals', i18n.conditions.number.equals);
1885
+ },
1886
+ init: Criteria.initSelect,
1887
+ inputValue: Criteria.inputValueSelect,
1888
+ isInputValid: Criteria.isInputValidSelect,
1889
+ search: function (value, comparison) {
1890
+ return +value === +comparison[0];
1891
+ }
1892
+ },
1893
+ // eslint-disable-next-line sort-keys
1894
+ '!=': {
1895
+ conditionName: function (dt, i18n) {
1896
+ return dt.i18n('searchBuilder.conditions.number.not', i18n.conditions.number.not);
1897
+ },
1898
+ init: Criteria.initSelect,
1899
+ inputValue: Criteria.inputValueSelect,
1900
+ isInputValid: Criteria.isInputValidSelect,
1901
+ search: function (value, comparison) {
1902
+ return +value !== +comparison[0];
1903
+ }
1904
+ },
1905
+ '<': {
1906
+ conditionName: function (dt, i18n) {
1907
+ return dt.i18n('searchBuilder.conditions.number.lt', i18n.conditions.number.lt);
1908
+ },
1909
+ init: Criteria.initInput,
1910
+ inputValue: Criteria.inputValueInput,
1911
+ isInputValid: Criteria.isInputValidInput,
1912
+ search: function (value, comparison) {
1913
+ return +value < +comparison[0];
1914
+ }
1915
+ },
1916
+ '<=': {
1917
+ conditionName: function (dt, i18n) {
1918
+ return dt.i18n('searchBuilder.conditions.number.lte', i18n.conditions.number.lte);
1919
+ },
1920
+ init: Criteria.initInput,
1921
+ inputValue: Criteria.inputValueInput,
1922
+ isInputValid: Criteria.isInputValidInput,
1923
+ search: function (value, comparison) {
1924
+ return +value <= +comparison[0];
1925
+ }
1926
+ },
1927
+ '>=': {
1928
+ conditionName: function (dt, i18n) {
1929
+ return dt.i18n('searchBuilder.conditions.number.gte', i18n.conditions.number.gte);
1930
+ },
1931
+ init: Criteria.initInput,
1932
+ inputValue: Criteria.inputValueInput,
1933
+ isInputValid: Criteria.isInputValidInput,
1934
+ search: function (value, comparison) {
1935
+ return +value >= +comparison[0];
1936
+ }
1937
+ },
1938
+ // eslint-disable-next-line sort-keys
1939
+ '>': {
1940
+ conditionName: function (dt, i18n) {
1941
+ return dt.i18n('searchBuilder.conditions.number.gt', i18n.conditions.number.gt);
1942
+ },
1943
+ init: Criteria.initInput,
1944
+ inputValue: Criteria.inputValueInput,
1945
+ isInputValid: Criteria.isInputValidInput,
1946
+ search: function (value, comparison) {
1947
+ return +value > +comparison[0];
1948
+ }
1949
+ },
1950
+ 'between': {
1951
+ conditionName: function (dt, i18n) {
1952
+ return dt.i18n('searchBuilder.conditions.number.between', i18n.conditions.number.between);
1953
+ },
1954
+ init: Criteria.init2Input,
1955
+ inputValue: Criteria.inputValueInput,
1956
+ isInputValid: Criteria.isInputValidInput,
1957
+ search: function (value, comparison) {
1958
+ if (+comparison[0] < +comparison[1]) {
1959
+ return +comparison[0] <= +value && +value <= +comparison[1];
1960
+ }
1961
+ else {
1962
+ return +comparison[1] <= +value && +value <= +comparison[0];
1963
+ }
1964
+ }
1965
+ },
1966
+ // eslint-disable-next-line sort-keys
1967
+ '!between': {
1968
+ conditionName: function (dt, i18n) {
1969
+ return dt.i18n('searchBuilder.conditions.number.notBetween', i18n.conditions.number.notBetween);
1970
+ },
1971
+ init: Criteria.init2Input,
1972
+ inputValue: Criteria.inputValueInput,
1973
+ isInputValid: Criteria.isInputValidInput,
1974
+ search: function (value, comparison) {
1975
+ if (+comparison[0] < +comparison[1]) {
1976
+ return !(+comparison[0] <= +value && +value <= +comparison[1]);
1977
+ }
1978
+ else {
1979
+ return !(+comparison[1] <= +value && +value <= +comparison[0]);
1980
+ }
1981
+ }
1982
+ },
1983
+ 'null': {
1984
+ conditionName: function (dt, i18n) {
1985
+ return dt.i18n('searchBuilder.conditions.number.empty', i18n.conditions.number.empty);
1986
+ },
1987
+ init: Criteria.initNoValue,
1988
+ inputValue: function () {
1989
+ return;
1990
+ },
1991
+ isInputValid: function () {
1992
+ return true;
1993
+ },
1994
+ search: function (value) {
1995
+ return value === null || value === undefined || value.length === 0;
1996
+ }
1997
+ },
1998
+ // eslint-disable-next-line sort-keys
1999
+ '!null': {
2000
+ conditionName: function (dt, i18n) {
2001
+ return dt.i18n('searchBuilder.conditions.number.notEmpty', i18n.conditions.number.notEmpty);
2002
+ },
2003
+ init: Criteria.initNoValue,
2004
+ inputValue: function () {
2005
+ return;
2006
+ },
2007
+ isInputValid: function () {
2008
+ return true;
2009
+ },
2010
+ search: function (value) {
2011
+ return !(value === null || value === undefined || value.length === 0);
2012
+ }
2013
+ }
2014
+ };
2015
+ // The order of the conditions will make eslint sad :(
2016
+ // Has to be in this order so that they are displayed correctly in select elements
2017
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
2018
+ // eslint-disable-next-line @typescript-eslint/member-ordering
2019
+ Criteria.numFmtConditions = {
2020
+ '=': {
2021
+ conditionName: function (dt, i18n) {
2022
+ return dt.i18n('searchBuilder.conditions.number.equals', i18n.conditions.number.equals);
2023
+ },
2024
+ init: Criteria.initSelect,
2025
+ inputValue: Criteria.inputValueSelect,
2026
+ isInputValid: Criteria.isInputValidSelect,
2027
+ search: function (value, comparison) {
2028
+ return Criteria.parseNumFmt(value) === Criteria.parseNumFmt(comparison[0]);
2029
+ }
2030
+ },
2031
+ // eslint-disable-next-line sort-keys
2032
+ '!=': {
2033
+ conditionName: function (dt, i18n) {
2034
+ return dt.i18n('searchBuilder.conditions.number.not', i18n.conditions.number.not);
2035
+ },
2036
+ init: Criteria.initSelect,
2037
+ inputValue: Criteria.inputValueSelect,
2038
+ isInputValid: Criteria.isInputValidSelect,
2039
+ search: function (value, comparison) {
2040
+ return Criteria.parseNumFmt(value) !== Criteria.parseNumFmt(comparison[0]);
2041
+ }
2042
+ },
2043
+ '<': {
2044
+ conditionName: function (dt, i18n) {
2045
+ return dt.i18n('searchBuilder.conditions.number.lt', i18n.conditions.number.lt);
2046
+ },
2047
+ init: Criteria.initInput,
2048
+ inputValue: Criteria.inputValueInput,
2049
+ isInputValid: Criteria.isInputValidInput,
2050
+ search: function (value, comparison) {
2051
+ return Criteria.parseNumFmt(value) < Criteria.parseNumFmt(comparison[0]);
2052
+ }
2053
+ },
2054
+ '<=': {
2055
+ conditionName: function (dt, i18n) {
2056
+ return dt.i18n('searchBuilder.conditions.number.lte', i18n.conditions.number.lte);
2057
+ },
2058
+ init: Criteria.initInput,
2059
+ inputValue: Criteria.inputValueInput,
2060
+ isInputValid: Criteria.isInputValidInput,
2061
+ search: function (value, comparison) {
2062
+ return Criteria.parseNumFmt(value) <= Criteria.parseNumFmt(comparison[0]);
2063
+ }
2064
+ },
2065
+ '>=': {
2066
+ conditionName: function (dt, i18n) {
2067
+ return dt.i18n('searchBuilder.conditions.number.gte', i18n.conditions.number.gte);
2068
+ },
2069
+ init: Criteria.initInput,
2070
+ inputValue: Criteria.inputValueInput,
2071
+ isInputValid: Criteria.isInputValidInput,
2072
+ search: function (value, comparison) {
2073
+ return Criteria.parseNumFmt(value) >= Criteria.parseNumFmt(comparison[0]);
2074
+ }
2075
+ },
2076
+ // eslint-disable-next-line sort-keys
2077
+ '>': {
2078
+ conditionName: function (dt, i18n) {
2079
+ return dt.i18n('searchBuilder.conditions.number.gt', i18n.conditions.number.gt);
2080
+ },
2081
+ init: Criteria.initInput,
2082
+ inputValue: Criteria.inputValueInput,
2083
+ isInputValid: Criteria.isInputValidInput,
2084
+ search: function (value, comparison) {
2085
+ return Criteria.parseNumFmt(value) > Criteria.parseNumFmt(comparison[0]);
2086
+ }
2087
+ },
2088
+ 'between': {
2089
+ conditionName: function (dt, i18n) {
2090
+ return dt.i18n('searchBuilder.conditions.number.between', i18n.conditions.number.between);
2091
+ },
2092
+ init: Criteria.init2Input,
2093
+ inputValue: Criteria.inputValueInput,
2094
+ isInputValid: Criteria.isInputValidInput,
2095
+ search: function (value, comparison) {
2096
+ var val = Criteria.parseNumFmt(value);
2097
+ var comp0 = Criteria.parseNumFmt(comparison[0]);
2098
+ var comp1 = Criteria.parseNumFmt(comparison[1]);
2099
+ if (+comp0 < +comp1) {
2100
+ return +comp0 <= +val && +val <= +comp1;
2101
+ }
2102
+ else {
2103
+ return +comp1 <= +val && +val <= +comp0;
2104
+ }
2105
+ }
2106
+ },
2107
+ // eslint-disable-next-line sort-keys
2108
+ '!between': {
2109
+ conditionName: function (dt, i18n) {
2110
+ return dt.i18n('searchBuilder.conditions.number.notBetween', i18n.conditions.number.notBetween);
2111
+ },
2112
+ init: Criteria.init2Input,
2113
+ inputValue: Criteria.inputValueInput,
2114
+ isInputValid: Criteria.isInputValidInput,
2115
+ search: function (value, comparison) {
2116
+ var val = Criteria.parseNumFmt(value);
2117
+ var comp0 = Criteria.parseNumFmt(comparison[0]);
2118
+ var comp1 = Criteria.parseNumFmt(comparison[1]);
2119
+ if (+comp0 < +comp1) {
2120
+ return !(+comp0 <= +val && +val <= +comp1);
2121
+ }
2122
+ else {
2123
+ return !(+comp1 <= +val && +val <= +comp0);
2124
+ }
2125
+ }
2126
+ },
2127
+ 'null': {
2128
+ conditionName: function (dt, i18n) {
2129
+ return dt.i18n('searchBuilder.conditions.number.empty', i18n.conditions.number.empty);
2130
+ },
2131
+ init: Criteria.initNoValue,
2132
+ inputValue: function () {
2133
+ return;
2134
+ },
2135
+ isInputValid: function () {
2136
+ return true;
2137
+ },
2138
+ search: function (value) {
2139
+ return value === null || value === undefined || value.length === 0;
2140
+ }
2141
+ },
2142
+ // eslint-disable-next-line sort-keys
2143
+ '!null': {
2144
+ conditionName: function (dt, i18n) {
2145
+ return dt.i18n('searchBuilder.conditions.number.notEmpty', i18n.conditions.number.notEmpty);
2146
+ },
2147
+ init: Criteria.initNoValue,
2148
+ inputValue: function () {
2149
+ return;
2150
+ },
2151
+ isInputValid: function () {
2152
+ return true;
2153
+ },
2154
+ search: function (value) {
2155
+ return !(value === null || value === undefined || value.length === 0);
2156
+ }
2157
+ }
2158
+ };
2159
+ // The order of the conditions will make eslint sad :(
2160
+ // Has to be in this order so that they are displayed correctly in select elements
2161
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
2162
+ // eslint-disable-next-line @typescript-eslint/member-ordering
2163
+ Criteria.stringConditions = {
2164
+ '=': {
2165
+ conditionName: function (dt, i18n) {
2166
+ return dt.i18n('searchBuilder.conditions.string.equals', i18n.conditions.string.equals);
2167
+ },
2168
+ init: Criteria.initSelect,
2169
+ inputValue: Criteria.inputValueSelect,
2170
+ isInputValid: Criteria.isInputValidSelect,
2171
+ search: function (value, comparison) {
2172
+ return value === comparison[0];
2173
+ }
2174
+ },
2175
+ // eslint-disable-next-line sort-keys
2176
+ '!=': {
2177
+ conditionName: function (dt, i18n) {
2178
+ return dt.i18n('searchBuilder.conditions.string.not', i18n.conditions.string.not);
2179
+ },
2180
+ init: Criteria.initSelect,
2181
+ inputValue: Criteria.inputValueSelect,
2182
+ isInputValid: Criteria.isInputValidInput,
2183
+ search: function (value, comparison) {
2184
+ return value !== comparison[0];
2185
+ }
2186
+ },
2187
+ 'starts': {
2188
+ conditionName: function (dt, i18n) {
2189
+ return dt.i18n('searchBuilder.conditions.string.startsWith', i18n.conditions.string.startsWith);
2190
+ },
2191
+ init: Criteria.initInput,
2192
+ inputValue: Criteria.inputValueInput,
2193
+ isInputValid: Criteria.isInputValidInput,
2194
+ search: function (value, comparison) {
2195
+ return value.toLowerCase().indexOf(comparison[0].toLowerCase()) === 0;
2196
+ }
2197
+ },
2198
+ // eslint-disable-next-line sort-keys
2199
+ '!starts': {
2200
+ conditionName: function (dt, i18n) {
2201
+ return dt.i18n('searchBuilder.conditions.string.notStartsWith', i18n.conditions.string.notStartsWith);
2202
+ },
2203
+ init: Criteria.initInput,
2204
+ inputValue: Criteria.inputValueInput,
2205
+ isInputValid: Criteria.isInputValidInput,
2206
+ search: function (value, comparison) {
2207
+ return value.toLowerCase().indexOf(comparison[0].toLowerCase()) !== 0;
2208
+ }
2209
+ },
2210
+ // eslint-disable-next-line sort-keys
2211
+ 'contains': {
2212
+ conditionName: function (dt, i18n) {
2213
+ return dt.i18n('searchBuilder.conditions.string.contains', i18n.conditions.string.contains);
2214
+ },
2215
+ init: Criteria.initInput,
2216
+ inputValue: Criteria.inputValueInput,
2217
+ isInputValid: Criteria.isInputValidInput,
2218
+ search: function (value, comparison) {
2219
+ return value.toLowerCase().includes(comparison[0].toLowerCase());
2220
+ }
2221
+ },
2222
+ // eslint-disable-next-line sort-keys
2223
+ '!contains': {
2224
+ conditionName: function (dt, i18n) {
2225
+ return dt.i18n('searchBuilder.conditions.string.notContains', i18n.conditions.string.notContains);
2226
+ },
2227
+ init: Criteria.initInput,
2228
+ inputValue: Criteria.inputValueInput,
2229
+ isInputValid: Criteria.isInputValidInput,
2230
+ search: function (value, comparison) {
2231
+ return !value.toLowerCase().includes(comparison[0].toLowerCase());
2232
+ }
2233
+ },
2234
+ 'ends': {
2235
+ conditionName: function (dt, i18n) {
2236
+ return dt.i18n('searchBuilder.conditions.string.endsWith', i18n.conditions.string.endsWith);
2237
+ },
2238
+ init: Criteria.initInput,
2239
+ inputValue: Criteria.inputValueInput,
2240
+ isInputValid: Criteria.isInputValidInput,
2241
+ search: function (value, comparison) {
2242
+ return value.toLowerCase().endsWith(comparison[0].toLowerCase());
2243
+ }
2244
+ },
2245
+ // eslint-disable-next-line sort-keys
2246
+ '!ends': {
2247
+ conditionName: function (dt, i18n) {
2248
+ return dt.i18n('searchBuilder.conditions.string.notEndsWith', i18n.conditions.string.notEndsWith);
2249
+ },
2250
+ init: Criteria.initInput,
2251
+ inputValue: Criteria.inputValueInput,
2252
+ isInputValid: Criteria.isInputValidInput,
2253
+ search: function (value, comparison) {
2254
+ return !value.toLowerCase().endsWith(comparison[0].toLowerCase());
2255
+ }
2256
+ },
2257
+ 'null': {
2258
+ conditionName: function (dt, i18n) {
2259
+ return dt.i18n('searchBuilder.conditions.string.empty', i18n.conditions.string.empty);
2260
+ },
2261
+ init: Criteria.initNoValue,
2262
+ inputValue: function () {
2263
+ return;
2264
+ },
2265
+ isInputValid: function () {
2266
+ return true;
2267
+ },
2268
+ search: function (value) {
2269
+ return value === null || value === undefined || value.length === 0;
2270
+ }
2271
+ },
2272
+ // eslint-disable-next-line sort-keys
2273
+ '!null': {
2274
+ conditionName: function (dt, i18n) {
2275
+ return dt.i18n('searchBuilder.conditions.string.notEmpty', i18n.conditions.string.notEmpty);
2276
+ },
2277
+ init: Criteria.initNoValue,
2278
+ inputValue: function () {
2279
+ return;
2280
+ },
2281
+ isInputValid: function () {
2282
+ return true;
2283
+ },
2284
+ search: function (value) {
2285
+ return !(value === null || value === undefined || value.length === 0);
2286
+ }
2287
+ }
2288
+ };
2289
+ // The order of the conditions will make eslint sad :(
2290
+ // Also have to disable member ordering for this as the private methods used are not yet declared otherwise
2291
+ // eslint-disable-next-line @typescript-eslint/member-ordering
2292
+ Criteria.arrayConditions = {
2293
+ 'contains': {
2294
+ conditionName: function (dt, i18n) {
2295
+ return dt.i18n('searchBuilder.conditions.array.contains', i18n.conditions.array.contains);
2296
+ },
2297
+ init: Criteria.initSelectArray,
2298
+ inputValue: Criteria.inputValueSelect,
2299
+ isInputValid: Criteria.isInputValidSelect,
2300
+ search: function (value, comparison) {
2301
+ return value.includes(comparison[0]);
2302
+ }
2303
+ },
2304
+ 'without': {
2305
+ conditionName: function (dt, i18n) {
2306
+ return dt.i18n('searchBuilder.conditions.array.without', i18n.conditions.array.without);
2307
+ },
2308
+ init: Criteria.initSelectArray,
2309
+ inputValue: Criteria.inputValueSelect,
2310
+ isInputValid: Criteria.isInputValidSelect,
2311
+ search: function (value, comparison) {
2312
+ return value.indexOf(comparison[0]) === -1;
2313
+ }
2314
+ },
2315
+ // eslint-disable-next-line sort-keys
2316
+ '=': {
2317
+ conditionName: function (dt, i18n) {
2318
+ return dt.i18n('searchBuilder.conditions.array.equals', i18n.conditions.array.equals);
2319
+ },
2320
+ init: Criteria.initSelect,
2321
+ inputValue: Criteria.inputValueSelect,
2322
+ isInputValid: Criteria.isInputValidSelect,
2323
+ search: function (value, comparison) {
2324
+ if (value.length === comparison[0].length) {
2325
+ for (var i = 0; i < value.length; i++) {
2326
+ if (value[i] !== comparison[0][i]) {
2327
+ return false;
2328
+ }
2329
+ }
2330
+ return true;
2331
+ }
2332
+ return false;
2333
+ }
2334
+ },
2335
+ // eslint-disable-next-line sort-keys
2336
+ '!=': {
2337
+ conditionName: function (dt, i18n) {
2338
+ return dt.i18n('searchBuilder.conditions.array.not', i18n.conditions.array.not);
2339
+ },
2340
+ init: Criteria.initSelect,
2341
+ inputValue: Criteria.inputValueSelect,
2342
+ isInputValid: Criteria.isInputValidSelect,
2343
+ search: function (value, comparison) {
2344
+ if (value.length === comparison[0].length) {
2345
+ for (var i = 0; i < value.length; i++) {
2346
+ if (value[i] !== comparison[0][i]) {
2347
+ return true;
2348
+ }
2349
+ }
2350
+ return false;
2351
+ }
2352
+ return true;
2353
+ }
2354
+ },
2355
+ 'null': {
2356
+ conditionName: function (dt, i18n) {
2357
+ return dt.i18n('searchBuilder.conditions.array.empty', i18n.conditions.array.empty);
2358
+ },
2359
+ init: Criteria.initNoValue,
2360
+ inputValue: function () {
2361
+ return;
2362
+ },
2363
+ isInputValid: function () {
2364
+ return true;
2365
+ },
2366
+ search: function (value) {
2367
+ return value === null || value === undefined || value.length === 0;
2368
+ }
2369
+ },
2370
+ // eslint-disable-next-line sort-keys
2371
+ '!null': {
2372
+ conditionName: function (dt, i18n) {
2373
+ return dt.i18n('searchBuilder.conditions.array.notEmpty', i18n.conditions.array.notEmpty);
2374
+ },
2375
+ init: Criteria.initNoValue,
2376
+ inputValue: function () {
2377
+ return;
2378
+ },
2379
+ isInputValid: function () {
2380
+ return true;
2381
+ },
2382
+ search: function (value) {
2383
+ return value !== null && value !== undefined && value.length !== 0;
2384
+ }
2385
+ }
2386
+ };
2387
+ // eslint will be sad because we have to disable member ordering for this as the
2388
+ // private static properties used are not yet declared otherwise
2389
+ // eslint-disable-next-line @typescript-eslint/member-ordering
2390
+ Criteria.defaults = {
2391
+ columns: true,
2392
+ conditions: {
2393
+ 'array': Criteria.arrayConditions,
2394
+ 'date': Criteria.dateConditions,
2395
+ 'html': Criteria.stringConditions,
2396
+ 'html-num': Criteria.numConditions,
2397
+ 'html-num-fmt': Criteria.numFmtConditions,
2398
+ 'luxon': Criteria.luxonDateConditions,
2399
+ 'moment': Criteria.momentDateConditions,
2400
+ 'num': Criteria.numConditions,
2401
+ 'num-fmt': Criteria.numFmtConditions,
2402
+ 'string': Criteria.stringConditions
2403
+ },
2404
+ depthLimit: false,
2405
+ enterSearch: false,
2406
+ filterChanged: undefined,
2407
+ greyscale: false,
2408
+ i18n: {
2409
+ add: 'Add Condition',
2410
+ button: {
2411
+ 0: 'Search Builder',
2412
+ _: 'Search Builder (%d)'
2413
+ },
2414
+ clearAll: 'Clear All',
2415
+ condition: 'Condition',
2416
+ data: 'Data',
2417
+ "delete": '&times',
2418
+ deleteTitle: 'Delete filtering rule',
2419
+ left: '<',
2420
+ leftTitle: 'Outdent criteria',
2421
+ logicAnd: 'And',
2422
+ logicOr: 'Or',
2423
+ right: '>',
2424
+ rightTitle: 'Indent criteria',
2425
+ title: {
2426
+ 0: 'Custom Search Builder',
2427
+ _: 'Custom Search Builder (%d)'
2428
+ },
2429
+ value: 'Value',
2430
+ valueJoiner: 'and'
2431
+ },
2432
+ logic: 'AND',
2433
+ orthogonal: {
2434
+ display: 'display',
2435
+ search: 'filter'
2436
+ },
2437
+ preDefined: false
2438
+ };
2439
+ return Criteria;
2440
+ }());
2441
+
2442
+ var $$2;
2443
+ var dataTable$2;
2444
+ /**
2445
+ * Sets the value of jQuery for use in the file
2446
+ *
2447
+ * @param jq the instance of jQuery to be set
2448
+ */
2449
+ function setJQuery$1(jq) {
2450
+ $$2 = jq;
2451
+ dataTable$2 = jq.fn.dataTable;
2452
+ }
2453
+ /**
2454
+ * The Group class is used within SearchBuilder to represent a group of criteria
2455
+ */
2456
+ var Group = /** @class */ (function () {
2457
+ function Group(table, opts, topGroup, index, isChild, depth, serverData) {
2458
+ if (index === void 0) { index = 0; }
2459
+ if (isChild === void 0) { isChild = false; }
2460
+ if (depth === void 0) { depth = 1; }
2461
+ if (serverData === void 0) { serverData = undefined; }
2462
+ // Check that the required version of DataTables is included
2463
+ if (!dataTable$2 || !dataTable$2.versionCheck || !dataTable$2.versionCheck('1.10.0')) {
2464
+ throw new Error('SearchBuilder requires DataTables 1.10 or newer');
2465
+ }
2466
+ this.classes = $$2.extend(true, {}, Group.classes);
2467
+ // Get options from user
2468
+ this.c = $$2.extend(true, {}, Group.defaults, opts);
2469
+ this.s = {
2470
+ criteria: [],
2471
+ depth: depth,
2472
+ dt: table,
2473
+ index: index,
2474
+ isChild: isChild,
2475
+ logic: undefined,
2476
+ opts: opts,
2477
+ preventRedraw: false,
2478
+ serverData: serverData,
2479
+ toDrop: undefined,
2480
+ topGroup: topGroup
2481
+ };
2482
+ this.dom = {
2483
+ add: $$2('<button/>')
2484
+ .addClass(this.classes.add)
2485
+ .addClass(this.classes.button)
2486
+ .attr('type', 'button'),
2487
+ clear: $$2('<button>&times</button>')
2488
+ .addClass(this.classes.button)
2489
+ .addClass(this.classes.clearGroup)
2490
+ .attr('type', 'button'),
2491
+ container: $$2('<div/>')
2492
+ .addClass(this.classes.group),
2493
+ logic: $$2('<button><div/></button>')
2494
+ .addClass(this.classes.logic)
2495
+ .addClass(this.classes.button)
2496
+ .attr('type', 'button'),
2497
+ logicContainer: $$2('<div/>')
2498
+ .addClass(this.classes.logicContainer)
2499
+ };
2500
+ // A reference to the top level group is maintained throughout any subgroups and criteria that may be created
2501
+ if (this.s.topGroup === undefined) {
2502
+ this.s.topGroup = this.dom.container;
2503
+ }
2504
+ this._setup();
2505
+ return this;
2506
+ }
2507
+ /**
2508
+ * Destroys the groups buttons, clears the internal criteria and removes it from the dom
2509
+ */
2510
+ Group.prototype.destroy = function () {
2511
+ // Turn off listeners
2512
+ this.dom.add.off('.dtsb');
2513
+ this.dom.logic.off('.dtsb');
2514
+ // Trigger event for groups at a higher level to pick up on
2515
+ this.dom.container
2516
+ .trigger('dtsb-destroy')
2517
+ .remove();
2518
+ this.s.criteria = [];
2519
+ };
2520
+ /**
2521
+ * Gets the details required to rebuild the group
2522
+ */
2523
+ // Eslint upset at empty object but needs to be done
2524
+ // eslint-disable-next-line @typescript-eslint/ban-types
2525
+ Group.prototype.getDetails = function (deFormatDates) {
2526
+ if (deFormatDates === void 0) { deFormatDates = false; }
2527
+ if (this.s.criteria.length === 0) {
2528
+ return {};
2529
+ }
2530
+ var details = {
2531
+ criteria: [],
2532
+ logic: this.s.logic
2533
+ };
2534
+ // NOTE here crit could be either a subgroup or a criteria
2535
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2536
+ var crit = _a[_i];
2537
+ details.criteria.push(crit.criteria.getDetails(deFormatDates));
2538
+ }
2539
+ return details;
2540
+ };
2541
+ /**
2542
+ * Getter for the node for the container of the group
2543
+ *
2544
+ * @returns Node for the container of the group
2545
+ */
2546
+ Group.prototype.getNode = function () {
2547
+ return this.dom.container;
2548
+ };
2549
+ /**
2550
+ * Rebuilds the group based upon the details passed in
2551
+ *
2552
+ * @param loadedDetails the details required to rebuild the group
2553
+ */
2554
+ Group.prototype.rebuild = function (loadedDetails) {
2555
+ // If no criteria are stored then just return
2556
+ if (loadedDetails.criteria === undefined ||
2557
+ loadedDetails.criteria === null ||
2558
+ Array.isArray(loadedDetails.criteria) && loadedDetails.criteria.length === 0) {
2559
+ return;
2560
+ }
2561
+ this.s.logic = loadedDetails.logic;
2562
+ this.dom.logic.children().first().html(this.s.logic === 'OR'
2563
+ ? this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr)
2564
+ : this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd));
2565
+ // Add all of the criteria, be it a sub group or a criteria
2566
+ if (Array.isArray(loadedDetails.criteria)) {
2567
+ for (var _i = 0, _a = loadedDetails.criteria; _i < _a.length; _i++) {
2568
+ var crit = _a[_i];
2569
+ if (crit.logic !== undefined) {
2570
+ this._addPrevGroup(crit);
2571
+ }
2572
+ else if (crit.logic === undefined) {
2573
+ this._addPrevCriteria(crit);
2574
+ }
2575
+ }
2576
+ }
2577
+ // For all of the criteria children, update the arrows incase they require changing and set the listeners
2578
+ for (var _b = 0, _c = this.s.criteria; _b < _c.length; _b++) {
2579
+ var crit = _c[_b];
2580
+ if (crit.criteria instanceof Criteria) {
2581
+ crit.criteria.updateArrows(this.s.criteria.length > 1);
2582
+ this._setCriteriaListeners(crit.criteria);
2583
+ }
2584
+ }
2585
+ };
2586
+ /**
2587
+ * Redraws the Contents of the searchBuilder Groups and Criteria
2588
+ */
2589
+ Group.prototype.redrawContents = function () {
2590
+ if (this.s.preventRedraw) {
2591
+ return;
2592
+ }
2593
+ // Clear the container out and add the basic elements
2594
+ this.dom.container.children().detach();
2595
+ this.dom.container
2596
+ .append(this.dom.logicContainer)
2597
+ .append(this.dom.add);
2598
+ // Sort the criteria by index so that they appear in the correct order
2599
+ this.s.criteria.sort(function (a, b) {
2600
+ if (a.criteria.s.index < b.criteria.s.index) {
2601
+ return -1;
2602
+ }
2603
+ else if (a.criteria.s.index > b.criteria.s.index) {
2604
+ return 1;
2605
+ }
2606
+ return 0;
2607
+ });
2608
+ this.setListeners();
2609
+ for (var i = 0; i < this.s.criteria.length; i++) {
2610
+ var crit = this.s.criteria[i].criteria;
2611
+ if (crit instanceof Criteria) {
2612
+ // Reset the index to the new value
2613
+ this.s.criteria[i].index = i;
2614
+ this.s.criteria[i].criteria.s.index = i;
2615
+ // Add to the group
2616
+ this.s.criteria[i].criteria.dom.container.insertBefore(this.dom.add);
2617
+ // Set listeners for various points
2618
+ this._setCriteriaListeners(crit);
2619
+ this.s.criteria[i].criteria.s.preventRedraw = this.s.preventRedraw;
2620
+ this.s.criteria[i].criteria.rebuild(this.s.criteria[i].criteria.getDetails());
2621
+ this.s.criteria[i].criteria.s.preventRedraw = false;
2622
+ }
2623
+ else if (crit instanceof Group && crit.s.criteria.length > 0) {
2624
+ // Reset the index to the new value
2625
+ this.s.criteria[i].index = i;
2626
+ this.s.criteria[i].criteria.s.index = i;
2627
+ // Add the sub group to the group
2628
+ this.s.criteria[i].criteria.dom.container.insertBefore(this.dom.add);
2629
+ // Redraw the contents of the group
2630
+ crit.s.preventRedraw = this.s.preventRedraw;
2631
+ crit.redrawContents();
2632
+ crit.s.preventRedraw = false;
2633
+ this._setGroupListeners(crit);
2634
+ }
2635
+ else {
2636
+ // The group is empty so remove it
2637
+ this.s.criteria.splice(i, 1);
2638
+ i--;
2639
+ }
2640
+ }
2641
+ this.setupLogic();
2642
+ };
2643
+ /**
2644
+ * Resizes the logic button only rather than the entire dom.
2645
+ */
2646
+ Group.prototype.redrawLogic = function () {
2647
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2648
+ var crit = _a[_i];
2649
+ if (crit.criteria instanceof Group) {
2650
+ crit.criteria.redrawLogic();
2651
+ }
2652
+ }
2653
+ this.setupLogic();
2654
+ };
2655
+ /**
2656
+ * Search method, checking the row data against the criteria in the group
2657
+ *
2658
+ * @param rowData The row data to be compared
2659
+ * @returns boolean The result of the search
2660
+ */
2661
+ Group.prototype.search = function (rowData, rowIdx) {
2662
+ if (this.s.logic === 'AND') {
2663
+ return this._andSearch(rowData, rowIdx);
2664
+ }
2665
+ else if (this.s.logic === 'OR') {
2666
+ return this._orSearch(rowData, rowIdx);
2667
+ }
2668
+ return true;
2669
+ };
2670
+ /**
2671
+ * Locates the groups logic button to the correct location on the page
2672
+ */
2673
+ Group.prototype.setupLogic = function () {
2674
+ // Remove logic button
2675
+ this.dom.logicContainer.remove();
2676
+ this.dom.clear.remove();
2677
+ // If there are no criteria in the group then keep the logic removed and return
2678
+ if (this.s.criteria.length < 1) {
2679
+ if (!this.s.isChild) {
2680
+ this.dom.container.trigger('dtsb-destroy');
2681
+ // Set criteria left margin
2682
+ this.dom.container.css('margin-left', 0);
2683
+ }
2684
+ return;
2685
+ }
2686
+ this.dom.clear.height('0px');
2687
+ this.dom.logicContainer.append(this.dom.clear);
2688
+ // Prepend logic button
2689
+ this.dom.container.prepend(this.dom.logicContainer);
2690
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2691
+ var crit = _a[_i];
2692
+ if (crit.criteria instanceof Criteria) {
2693
+ crit.criteria.setupButtons();
2694
+ }
2695
+ }
2696
+ // Set width, take 2 for the border
2697
+ var height = this.dom.container.outerHeight() - 1;
2698
+ this.dom.logicContainer.width(height);
2699
+ this._setLogicListener();
2700
+ // Set criteria left margin
2701
+ this.dom.container.css('margin-left', this.dom.logicContainer.outerHeight(true));
2702
+ var logicOffset = this.dom.logicContainer.offset();
2703
+ // Set horizontal alignment
2704
+ var currentLeft = logicOffset.left;
2705
+ var groupLeft = this.dom.container.offset().left;
2706
+ var shuffleLeft = currentLeft - groupLeft;
2707
+ var newPos = currentLeft - shuffleLeft - this.dom.logicContainer.outerHeight(true);
2708
+ this.dom.logicContainer.offset({ left: newPos });
2709
+ // Set vertical alignment
2710
+ var firstCrit = this.dom.logicContainer.next();
2711
+ var currentTop = logicOffset.top;
2712
+ var firstTop = $$2(firstCrit).offset().top;
2713
+ var shuffleTop = currentTop - firstTop;
2714
+ var newTop = currentTop - shuffleTop;
2715
+ this.dom.logicContainer.offset({ top: newTop });
2716
+ this.dom.clear.outerHeight(this.dom.logicContainer.height());
2717
+ this._setClearListener();
2718
+ };
2719
+ /**
2720
+ * Sets listeners on the groups elements
2721
+ */
2722
+ Group.prototype.setListeners = function () {
2723
+ var _this = this;
2724
+ this.dom.add.unbind('click');
2725
+ this.dom.add.on('click.dtsb', function () {
2726
+ // If this is the parent group then the logic button has not been added yet
2727
+ if (!_this.s.isChild) {
2728
+ _this.dom.container.prepend(_this.dom.logicContainer);
2729
+ }
2730
+ _this.addCriteria();
2731
+ _this.dom.container.trigger('dtsb-add');
2732
+ _this.s.dt.state.save();
2733
+ return false;
2734
+ });
2735
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2736
+ var crit = _a[_i];
2737
+ crit.criteria.setListeners();
2738
+ }
2739
+ this._setClearListener();
2740
+ this._setLogicListener();
2741
+ };
2742
+ /**
2743
+ * Adds a criteria to the group
2744
+ *
2745
+ * @param crit Instance of Criteria to be added to the group
2746
+ */
2747
+ Group.prototype.addCriteria = function (crit) {
2748
+ if (crit === void 0) { crit = null; }
2749
+ var index = crit === null ? this.s.criteria.length : crit.s.index;
2750
+ var criteria = new Criteria(this.s.dt, this.s.opts, this.s.topGroup, index, this.s.depth, this.s.serverData);
2751
+ // If a Criteria has been passed in then set the values to continue that
2752
+ if (crit !== null) {
2753
+ criteria.c = crit.c;
2754
+ criteria.s = crit.s;
2755
+ criteria.s.depth = this.s.depth;
2756
+ criteria.classes = crit.classes;
2757
+ }
2758
+ criteria.populate();
2759
+ var inserted = false;
2760
+ for (var i = 0; i < this.s.criteria.length; i++) {
2761
+ if (i === 0 && this.s.criteria[i].criteria.s.index > criteria.s.index) {
2762
+ // Add the node for the criteria at the start of the group
2763
+ criteria.getNode().insertBefore(this.s.criteria[i].criteria.dom.container);
2764
+ inserted = true;
2765
+ }
2766
+ else if (i < this.s.criteria.length - 1 &&
2767
+ this.s.criteria[i].criteria.s.index < criteria.s.index &&
2768
+ this.s.criteria[i + 1].criteria.s.index > criteria.s.index) {
2769
+ // Add the node for the criteria in the correct location
2770
+ criteria.getNode().insertAfter(this.s.criteria[i].criteria.dom.container);
2771
+ inserted = true;
2772
+ }
2773
+ }
2774
+ if (!inserted) {
2775
+ criteria.getNode().insertBefore(this.dom.add);
2776
+ }
2777
+ // Add the details for this criteria to the array
2778
+ this.s.criteria.push({
2779
+ criteria: criteria,
2780
+ index: index
2781
+ });
2782
+ this.s.criteria = this.s.criteria.sort(function (a, b) { return a.criteria.s.index - b.criteria.s.index; });
2783
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2784
+ var opt = _a[_i];
2785
+ if (opt.criteria instanceof Criteria) {
2786
+ opt.criteria.updateArrows(this.s.criteria.length > 1);
2787
+ }
2788
+ }
2789
+ this._setCriteriaListeners(criteria);
2790
+ criteria.setListeners();
2791
+ this.setupLogic();
2792
+ };
2793
+ /**
2794
+ * Checks the group to see if it has any filled criteria
2795
+ */
2796
+ Group.prototype.checkFilled = function () {
2797
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2798
+ var crit = _a[_i];
2799
+ if (crit.criteria instanceof Criteria && crit.criteria.s.filled ||
2800
+ crit.criteria instanceof Group && crit.criteria.checkFilled()) {
2801
+ return true;
2802
+ }
2803
+ }
2804
+ return false;
2805
+ };
2806
+ /**
2807
+ * Gets the count for the number of criteria in this group and any sub groups
2808
+ */
2809
+ Group.prototype.count = function () {
2810
+ var count = 0;
2811
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2812
+ var crit = _a[_i];
2813
+ if (crit.criteria instanceof Group) {
2814
+ count += crit.criteria.count();
2815
+ }
2816
+ else {
2817
+ count++;
2818
+ }
2819
+ }
2820
+ return count;
2821
+ };
2822
+ /**
2823
+ * Rebuilds a sub group that previously existed
2824
+ *
2825
+ * @param loadedGroup The details of a group within this group
2826
+ */
2827
+ Group.prototype._addPrevGroup = function (loadedGroup) {
2828
+ var idx = this.s.criteria.length;
2829
+ var group = new Group(this.s.dt, this.c, this.s.topGroup, idx, true, this.s.depth + 1, this.s.serverData);
2830
+ // Add the new group to the criteria array
2831
+ this.s.criteria.push({
2832
+ criteria: group,
2833
+ index: idx,
2834
+ logic: group.s.logic
2835
+ });
2836
+ // Rebuild it with the previous conditions for that group
2837
+ group.rebuild(loadedGroup);
2838
+ this.s.criteria[idx].criteria = group;
2839
+ this.s.topGroup.trigger('dtsb-redrawContents');
2840
+ this._setGroupListeners(group);
2841
+ };
2842
+ /**
2843
+ * Rebuilds a criteria of this group that previously existed
2844
+ *
2845
+ * @param loadedCriteria The details of a criteria within the group
2846
+ */
2847
+ Group.prototype._addPrevCriteria = function (loadedCriteria) {
2848
+ var idx = this.s.criteria.length;
2849
+ var criteria = new Criteria(this.s.dt, this.s.opts, this.s.topGroup, idx, this.s.depth, this.s.serverData);
2850
+ criteria.populate();
2851
+ // Add the new criteria to the criteria array
2852
+ this.s.criteria.push({
2853
+ criteria: criteria,
2854
+ index: idx
2855
+ });
2856
+ // Rebuild it with the previous conditions for that criteria
2857
+ criteria.s.preventRedraw = this.s.preventRedraw;
2858
+ criteria.rebuild(loadedCriteria);
2859
+ criteria.s.preventRedraw = false;
2860
+ this.s.criteria[idx].criteria = criteria;
2861
+ if (!this.s.preventRedraw) {
2862
+ this.s.topGroup.trigger('dtsb-redrawContents');
2863
+ }
2864
+ };
2865
+ /**
2866
+ * Checks And the criteria using AND logic
2867
+ *
2868
+ * @param rowData The row data to be checked against the search criteria
2869
+ * @returns boolean The result of the AND search
2870
+ */
2871
+ Group.prototype._andSearch = function (rowData, rowIdx) {
2872
+ // If there are no criteria then return true for this group
2873
+ if (this.s.criteria.length === 0) {
2874
+ return true;
2875
+ }
2876
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2877
+ var crit = _a[_i];
2878
+ // If the criteria is not complete then skip it
2879
+ if (crit.criteria instanceof Criteria && !crit.criteria.s.filled) {
2880
+ continue;
2881
+ }
2882
+ // Otherwise if a single one fails return false
2883
+ else if (!crit.criteria.search(rowData, rowIdx)) {
2884
+ return false;
2885
+ }
2886
+ }
2887
+ // If we get to here then everything has passed, so return true for the group
2888
+ return true;
2889
+ };
2890
+ /**
2891
+ * Checks And the criteria using OR logic
2892
+ *
2893
+ * @param rowData The row data to be checked against the search criteria
2894
+ * @returns boolean The result of the OR search
2895
+ */
2896
+ Group.prototype._orSearch = function (rowData, rowIdx) {
2897
+ // If there are no criteria in the group then return true
2898
+ if (this.s.criteria.length === 0) {
2899
+ return true;
2900
+ }
2901
+ // This will check to make sure that at least one criteria in the group is complete
2902
+ var filledfound = false;
2903
+ for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) {
2904
+ var crit = _a[_i];
2905
+ if (crit.criteria instanceof Criteria && crit.criteria.s.filled) {
2906
+ // A completed criteria has been found so set the flag
2907
+ filledfound = true;
2908
+ // If the search passes then return true
2909
+ if (crit.criteria.search(rowData, rowIdx)) {
2910
+ return true;
2911
+ }
2912
+ }
2913
+ else if (crit.criteria instanceof Group && crit.criteria.checkFilled()) {
2914
+ filledfound = true;
2915
+ if (crit.criteria.search(rowData, rowIdx)) {
2916
+ return true;
2917
+ }
2918
+ }
2919
+ }
2920
+ // If we get here we need to return the inverse of filledfound,
2921
+ // as if any have been found and we are here then none have passed
2922
+ return !filledfound;
2923
+ };
2924
+ /**
2925
+ * Removes a criteria from the group
2926
+ *
2927
+ * @param criteria The criteria instance to be removed
2928
+ */
2929
+ Group.prototype._removeCriteria = function (criteria, group) {
2930
+ if (group === void 0) { group = false; }
2931
+ // If removing a criteria and there is only then then just destroy the group
2932
+ if (this.s.criteria.length <= 1 && this.s.isChild) {
2933
+ this.destroy();
2934
+ }
2935
+ else {
2936
+ // Otherwise splice the given criteria out and redo the indexes
2937
+ var last = void 0;
2938
+ for (var i = 0; i < this.s.criteria.length; i++) {
2939
+ if (this.s.criteria[i].index === criteria.s.index &&
2940
+ (!group || this.s.criteria[i].criteria instanceof Group)) {
2941
+ last = i;
2942
+ }
2943
+ }
2944
+ // We want to remove the last element with the desired index, as its replacement will be inserted before it
2945
+ if (last !== undefined) {
2946
+ this.s.criteria.splice(last, 1);
2947
+ }
2948
+ for (var i = 0; i < this.s.criteria.length; i++) {
2949
+ this.s.criteria[i].index = i;
2950
+ this.s.criteria[i].criteria.s.index = i;
2951
+ }
2952
+ }
2953
+ };
2954
+ /**
2955
+ * Sets the listeners in group for a criteria
2956
+ *
2957
+ * @param criteria The criteria for the listeners to be set on
2958
+ */
2959
+ Group.prototype._setCriteriaListeners = function (criteria) {
2960
+ var _this = this;
2961
+ criteria.dom["delete"]
2962
+ .unbind('click')
2963
+ .on('click.dtsb', function () {
2964
+ _this._removeCriteria(criteria);
2965
+ criteria.dom.container.remove();
2966
+ for (var _i = 0, _a = _this.s.criteria; _i < _a.length; _i++) {
2967
+ var crit = _a[_i];
2968
+ if (crit.criteria instanceof Criteria) {
2969
+ crit.criteria.updateArrows(_this.s.criteria.length > 1);
2970
+ }
2971
+ }
2972
+ criteria.destroy();
2973
+ _this.s.dt.draw();
2974
+ _this.s.topGroup.trigger('dtsb-redrawContents');
2975
+ return false;
2976
+ });
2977
+ criteria.dom.right
2978
+ .unbind('click')
2979
+ .on('click.dtsb', function () {
2980
+ var idx = criteria.s.index;
2981
+ var group = new Group(_this.s.dt, _this.s.opts, _this.s.topGroup, criteria.s.index, true, _this.s.depth + 1, _this.s.serverData);
2982
+ // Add the criteria that is to be moved to the new group
2983
+ group.addCriteria(criteria);
2984
+ // Update the details in the current groups criteria array
2985
+ _this.s.criteria[idx].criteria = group;
2986
+ _this.s.criteria[idx].logic = 'AND';
2987
+ _this.s.topGroup.trigger('dtsb-redrawContents');
2988
+ _this._setGroupListeners(group);
2989
+ return false;
2990
+ });
2991
+ criteria.dom.left
2992
+ .unbind('click')
2993
+ .on('click.dtsb', function () {
2994
+ _this.s.toDrop = new Criteria(_this.s.dt, _this.s.opts, _this.s.topGroup, criteria.s.index, undefined, _this.s.serverData);
2995
+ _this.s.toDrop.s = criteria.s;
2996
+ _this.s.toDrop.c = criteria.c;
2997
+ _this.s.toDrop.classes = criteria.classes;
2998
+ _this.s.toDrop.populate();
2999
+ // The dropCriteria event mutates the reference to the index so need to store it
3000
+ var index = _this.s.toDrop.s.index;
3001
+ _this.dom.container.trigger('dtsb-dropCriteria');
3002
+ criteria.s.index = index;
3003
+ _this._removeCriteria(criteria);
3004
+ // By tracking the top level group we can directly trigger a redraw on it,
3005
+ // bubbling is also possible, but that is slow with deep levelled groups
3006
+ _this.s.topGroup.trigger('dtsb-redrawContents');
3007
+ _this.s.dt.draw();
3008
+ return false;
3009
+ });
3010
+ };
3011
+ /**
3012
+ * Set's the listeners for the group clear button
3013
+ */
3014
+ Group.prototype._setClearListener = function () {
3015
+ var _this = this;
3016
+ this.dom.clear
3017
+ .unbind('click')
3018
+ .on('click.dtsb', function () {
3019
+ if (!_this.s.isChild) {
3020
+ _this.dom.container.trigger('dtsb-clearContents');
3021
+ return false;
3022
+ }
3023
+ _this.destroy();
3024
+ _this.s.topGroup.trigger('dtsb-redrawContents');
3025
+ return false;
3026
+ });
3027
+ };
3028
+ /**
3029
+ * Sets listeners for sub groups of this group
3030
+ *
3031
+ * @param group The sub group that the listeners are to be set on
3032
+ */
3033
+ Group.prototype._setGroupListeners = function (group) {
3034
+ var _this = this;
3035
+ // Set listeners for the new group
3036
+ group.dom.add
3037
+ .unbind('click')
3038
+ .on('click.dtsb', function () {
3039
+ _this.setupLogic();
3040
+ _this.dom.container.trigger('dtsb-add');
3041
+ return false;
3042
+ });
3043
+ group.dom.container
3044
+ .unbind('dtsb-add')
3045
+ .on('dtsb-add.dtsb', function () {
3046
+ _this.setupLogic();
3047
+ _this.dom.container.trigger('dtsb-add');
3048
+ return false;
3049
+ });
3050
+ group.dom.container
3051
+ .unbind('dtsb-destroy')
3052
+ .on('dtsb-destroy.dtsb', function () {
3053
+ _this._removeCriteria(group, true);
3054
+ group.dom.container.remove();
3055
+ _this.setupLogic();
3056
+ return false;
3057
+ });
3058
+ group.dom.container
3059
+ .unbind('dtsb-dropCriteria')
3060
+ .on('dtsb-dropCriteria.dtsb', function () {
3061
+ var toDrop = group.s.toDrop;
3062
+ toDrop.s.index = group.s.index;
3063
+ toDrop.updateArrows(_this.s.criteria.length > 1);
3064
+ _this.addCriteria(toDrop);
3065
+ return false;
3066
+ });
3067
+ group.setListeners();
3068
+ };
3069
+ /**
3070
+ * Sets up the Group instance, setting listeners and appending elements
3071
+ */
3072
+ Group.prototype._setup = function () {
3073
+ this.setListeners();
3074
+ this.dom.add.html(this.s.dt.i18n('searchBuilder.add', this.c.i18n.add));
3075
+ this.dom.logic.children().first().html(this.c.logic === 'OR'
3076
+ ? this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr)
3077
+ : this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd));
3078
+ this.s.logic = this.c.logic === 'OR' ? 'OR' : 'AND';
3079
+ if (this.c.greyscale) {
3080
+ this.dom.logic.addClass(this.classes.greyscale);
3081
+ }
3082
+ this.dom.logicContainer.append(this.dom.logic).append(this.dom.clear);
3083
+ // Only append the logic button immediately if this is a sub group,
3084
+ // otherwise it will be prepended later when adding a criteria
3085
+ if (this.s.isChild) {
3086
+ this.dom.container.append(this.dom.logicContainer);
3087
+ }
3088
+ this.dom.container.append(this.dom.add);
3089
+ };
3090
+ /**
3091
+ * Sets the listener for the logic button
3092
+ */
3093
+ Group.prototype._setLogicListener = function () {
3094
+ var _this = this;
3095
+ this.dom.logic
3096
+ .unbind('click')
3097
+ .on('click.dtsb', function () {
3098
+ _this._toggleLogic();
3099
+ _this.s.dt.draw();
3100
+ for (var _i = 0, _a = _this.s.criteria; _i < _a.length; _i++) {
3101
+ var crit = _a[_i];
3102
+ crit.criteria.setListeners();
3103
+ }
3104
+ });
3105
+ };
3106
+ /**
3107
+ * Toggles the logic for the group
3108
+ */
3109
+ Group.prototype._toggleLogic = function () {
3110
+ if (this.s.logic === 'OR') {
3111
+ this.s.logic = 'AND';
3112
+ this.dom.logic.children().first().html(this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd));
3113
+ }
3114
+ else if (this.s.logic === 'AND') {
3115
+ this.s.logic = 'OR';
3116
+ this.dom.logic.children().first().html(this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr));
3117
+ }
3118
+ };
3119
+ Group.version = '1.1.0';
3120
+ Group.classes = {
3121
+ add: 'dtsb-add',
3122
+ button: 'dtsb-button',
3123
+ clearGroup: 'dtsb-clearGroup',
3124
+ greyscale: 'dtsb-greyscale',
3125
+ group: 'dtsb-group',
3126
+ inputButton: 'dtsb-iptbtn',
3127
+ logic: 'dtsb-logic',
3128
+ logicContainer: 'dtsb-logicContainer'
3129
+ };
3130
+ Group.defaults = {
3131
+ columns: true,
3132
+ conditions: {
3133
+ 'date': Criteria.dateConditions,
3134
+ 'html': Criteria.stringConditions,
3135
+ 'html-num': Criteria.numConditions,
3136
+ 'html-num-fmt': Criteria.numFmtConditions,
3137
+ 'luxon': Criteria.luxonDateConditions,
3138
+ 'moment': Criteria.momentDateConditions,
3139
+ 'num': Criteria.numConditions,
3140
+ 'num-fmt': Criteria.numFmtConditions,
3141
+ 'string': Criteria.stringConditions
3142
+ },
3143
+ depthLimit: false,
3144
+ enterSearch: false,
3145
+ filterChanged: undefined,
3146
+ greyscale: false,
3147
+ i18n: {
3148
+ add: 'Add Condition',
3149
+ button: {
3150
+ 0: 'Search Builder',
3151
+ _: 'Search Builder (%d)'
3152
+ },
3153
+ clearAll: 'Clear All',
3154
+ condition: 'Condition',
3155
+ data: 'Data',
3156
+ "delete": '&times',
3157
+ deleteTitle: 'Delete filtering rule',
3158
+ left: '<',
3159
+ leftTitle: 'Outdent criteria',
3160
+ logicAnd: 'And',
3161
+ logicOr: 'Or',
3162
+ right: '>',
3163
+ rightTitle: 'Indent criteria',
3164
+ title: {
3165
+ 0: 'Custom Search Builder',
3166
+ _: 'Custom Search Builder (%d)'
3167
+ },
3168
+ value: 'Value',
3169
+ valueJoiner: 'and'
3170
+ },
3171
+ logic: 'AND',
3172
+ orthogonal: {
3173
+ display: 'display',
3174
+ search: 'filter'
3175
+ },
3176
+ preDefined: false
3177
+ };
3178
+ return Group;
3179
+ }());
3180
+
3181
+ var $$1;
3182
+ var dataTable$1;
3183
+ /**
3184
+ * Sets the value of jQuery for use in the file
3185
+ *
3186
+ * @param jq the instance of jQuery to be set
3187
+ */
3188
+ function setJQuery(jq) {
3189
+ $$1 = jq;
3190
+ dataTable$1 = jq.fn.DataTable;
3191
+ }
3192
+ /**
3193
+ * SearchBuilder class for DataTables.
3194
+ * Allows for complex search queries to be constructed and implemented on a DataTable
3195
+ */
3196
+ var SearchBuilder = /** @class */ (function () {
3197
+ function SearchBuilder(builderSettings, opts) {
3198
+ var _this = this;
3199
+ // Check that the required version of DataTables is included
3200
+ if (!dataTable$1 || !dataTable$1.versionCheck || !dataTable$1.versionCheck('1.10.0')) {
3201
+ throw new Error('SearchBuilder requires DataTables 1.10 or newer');
3202
+ }
3203
+ var table = new dataTable$1.Api(builderSettings);
3204
+ this.classes = $$1.extend(true, {}, SearchBuilder.classes);
3205
+ // Get options from user
3206
+ this.c = $$1.extend(true, {}, SearchBuilder.defaults, opts);
3207
+ this.dom = {
3208
+ clearAll: $$1('<button type="button">' + table.i18n('searchBuilder.clearAll', this.c.i18n.clearAll) + '</button>')
3209
+ .addClass(this.classes.clearAll)
3210
+ .addClass(this.classes.button)
3211
+ .attr('type', 'button'),
3212
+ container: $$1('<div/>')
3213
+ .addClass(this.classes.container),
3214
+ title: $$1('<div/>')
3215
+ .addClass(this.classes.title),
3216
+ titleRow: $$1('<div/>')
3217
+ .addClass(this.classes.titleRow),
3218
+ topGroup: undefined
3219
+ };
3220
+ this.s = {
3221
+ dt: table,
3222
+ opts: opts,
3223
+ search: undefined,
3224
+ serverData: undefined,
3225
+ topGroup: undefined
3226
+ };
3227
+ // If searchbuilder is already defined for this table then return
3228
+ if (table.settings()[0]._searchBuilder !== undefined) {
3229
+ return;
3230
+ }
3231
+ table.settings()[0]._searchBuilder = this;
3232
+ // If using SSP we want to include the previous state in the very first server call
3233
+ if (this.s.dt.page.info().serverSide) {
3234
+ this.s.dt.on('preXhr.dtsb', function (e, settings, data) {
3235
+ var loadedState = _this.s.dt.state.loaded();
3236
+ if (loadedState && loadedState.searchBuilder) {
3237
+ data.searchBuilder = _this._collapseArray(loadedState.searchBuilder);
3238
+ }
3239
+ });
3240
+ this.s.dt.on('xhr.dtsb', function (e, settings, json) {
3241
+ if (json && json.searchBuilder && json.searchBuilder.options) {
3242
+ _this.s.serverData = json.searchBuilder.options;
3243
+ }
3244
+ });
3245
+ }
3246
+ // Run the remaining setup when the table is initialised
3247
+ if (this.s.dt.settings()[0]._bInitComplete) {
3248
+ this._setUp();
3249
+ }
3250
+ else {
3251
+ table.one('init.dt', function () {
3252
+ _this._setUp();
3253
+ });
3254
+ }
3255
+ return this;
3256
+ }
3257
+ /**
3258
+ * Gets the details required to rebuild the SearchBuilder as it currently is
3259
+ */
3260
+ // eslint upset at empty object but that is what it is
3261
+ // eslint-disable-next-line @typescript-eslint/ban-types
3262
+ SearchBuilder.prototype.getDetails = function (deFormatDates) {
3263
+ if (deFormatDates === void 0) { deFormatDates = false; }
3264
+ return this.s.topGroup.getDetails(deFormatDates);
3265
+ };
3266
+ /**
3267
+ * Getter for the node of the container for the searchBuilder
3268
+ *
3269
+ * @returns JQuery<HTMLElement> the node of the container
3270
+ */
3271
+ SearchBuilder.prototype.getNode = function () {
3272
+ return this.dom.container;
3273
+ };
3274
+ /**
3275
+ * Rebuilds the SearchBuilder to a state that is provided
3276
+ *
3277
+ * @param details The details required to perform a rebuild
3278
+ */
3279
+ SearchBuilder.prototype.rebuild = function (details) {
3280
+ this.dom.clearAll.click();
3281
+ // If there are no details to rebuild then return
3282
+ if (details === undefined || details === null) {
3283
+ return this;
3284
+ }
3285
+ this.s.topGroup.s.preventRedraw = true;
3286
+ this.s.topGroup.rebuild(details);
3287
+ this.s.topGroup.s.preventRedraw = false;
3288
+ this._checkClear();
3289
+ this._updateTitle(this.s.topGroup.count());
3290
+ this.s.topGroup.redrawContents();
3291
+ this.s.dt.draw(false);
3292
+ this.s.topGroup.setListeners();
3293
+ return this;
3294
+ };
3295
+ /**
3296
+ * Applies the defaults to preDefined criteria
3297
+ *
3298
+ * @param preDef the array of criteria to be processed.
3299
+ */
3300
+ SearchBuilder.prototype._applyPreDefDefaults = function (preDef) {
3301
+ var _this = this;
3302
+ if (preDef.criteria !== undefined && preDef.logic === undefined) {
3303
+ preDef.logic = 'AND';
3304
+ }
3305
+ var _loop_1 = function (crit) {
3306
+ // Apply the defaults to any further criteria
3307
+ if (crit.criteria !== undefined) {
3308
+ crit = this_1._applyPreDefDefaults(crit);
3309
+ }
3310
+ else {
3311
+ this_1.s.dt.columns().every(function (index) {
3312
+ if (_this.s.dt.settings()[0].aoColumns[index].sTitle === crit.data) {
3313
+ crit.dataIdx = index;
3314
+ }
3315
+ });
3316
+ }
3317
+ };
3318
+ var this_1 = this;
3319
+ for (var _i = 0, _a = preDef.criteria; _i < _a.length; _i++) {
3320
+ var crit = _a[_i];
3321
+ _loop_1(crit);
3322
+ }
3323
+ return preDef;
3324
+ };
3325
+ /**
3326
+ * Set's up the SearchBuilder
3327
+ */
3328
+ SearchBuilder.prototype._setUp = function (loadState) {
3329
+ var _this = this;
3330
+ if (loadState === void 0) { loadState = true; }
3331
+ // Register an Api method for getting the column type
3332
+ $$1.fn.DataTable.Api.registerPlural('columns().type()', 'column().type()', function () {
3333
+ return this.iterator('column', function (settings, column) {
3334
+ return settings.aoColumns[column].sType;
3335
+ }, 1);
3336
+ });
3337
+ // Check that DateTime is included, If not need to check if it could be used
3338
+ // eslint-disable-next-line no-extra-parens
3339
+ if (!dataTable$1.DateTime) {
3340
+ var types = this.s.dt.columns().type().toArray();
3341
+ if (types === undefined || types.includes(undefined) || types.includes(null)) {
3342
+ types = [];
3343
+ for (var _i = 0, _a = this.s.dt.settings()[0].aoColumns; _i < _a.length; _i++) {
3344
+ var colInit = _a[_i];
3345
+ types.push(colInit.searchBuilderType !== undefined ? colInit.searchBuilderType : colInit.sType);
3346
+ }
3347
+ }
3348
+ var columnIdxs = this.s.dt.columns().toArray();
3349
+ // If the types are not yet set then draw to see if they can be retrieved then
3350
+ if (types === undefined || types.includes(undefined) || types.includes(null)) {
3351
+ $$1.fn.dataTable.ext.oApi._fnColumnTypes(this.s.dt.settings()[0]);
3352
+ types = this.s.dt.columns().type().toArray();
3353
+ }
3354
+ for (var i = 0; i < columnIdxs[0].length; i++) {
3355
+ var column = columnIdxs[0][i];
3356
+ var type = types[column];
3357
+ if (
3358
+ // Check if this column can be filtered
3359
+ (this.c.columns === true ||
3360
+ Array.isArray(this.c.columns) &&
3361
+ this.c.columns.includes(i)) &&
3362
+ // Check if the type is one of the restricted types
3363
+ (type.includes('date') ||
3364
+ type.includes('moment') ||
3365
+ type.includes('luxon'))) {
3366
+ alert('SearchBuilder Requires DateTime when used with dates.');
3367
+ throw new Error('SearchBuilder requires DateTime');
3368
+ }
3369
+ }
3370
+ }
3371
+ this.s.topGroup = new Group(this.s.dt, this.c, undefined, undefined, undefined, undefined, this.s.serverData);
3372
+ this._setClearListener();
3373
+ this.s.dt.on('stateSaveParams.dtsb', function (e, settings, data) {
3374
+ data.searchBuilder = _this.getDetails();
3375
+ if (!data.scroller) {
3376
+ data.page = _this.s.dt.page();
3377
+ }
3378
+ else {
3379
+ data.start = _this.s.dt.state().start;
3380
+ }
3381
+ });
3382
+ this.s.dt.on('stateLoadParams.dtsb', function (e, settings, data) {
3383
+ _this.rebuild(data.searchBuilder);
3384
+ });
3385
+ this._build();
3386
+ this.s.dt.on('preXhr.dtsb', function (e, settings, data) {
3387
+ if (_this.s.dt.page.info().serverSide) {
3388
+ data.searchBuilder = _this._collapseArray(_this.getDetails(true));
3389
+ }
3390
+ });
3391
+ this.s.dt.on('column-reorder', function () {
3392
+ _this.rebuild(_this.getDetails());
3393
+ });
3394
+ if (loadState) {
3395
+ var loadedState = this.s.dt.state.loaded();
3396
+ // If the loaded State is not null rebuild based on it for statesave
3397
+ if (loadedState !== null && loadedState.searchBuilder !== undefined) {
3398
+ this.s.topGroup.rebuild(loadedState.searchBuilder);
3399
+ this.s.topGroup.dom.container.trigger('dtsb-redrawContents');
3400
+ // If using SSP we want to restrict the amount of server calls that take place
3401
+ // and this information will already have been processed
3402
+ if (!this.s.dt.page.info().serverSide) {
3403
+ if (loadedState.page) {
3404
+ this.s.dt.page(loadedState.page).draw('page');
3405
+ }
3406
+ else if (this.s.dt.scroller && loadedState.scroller) {
3407
+ this.s.dt.scroller().scrollToRow(loadedState.scroller.topRow);
3408
+ }
3409
+ }
3410
+ this.s.topGroup.setListeners();
3411
+ }
3412
+ // Otherwise load any predefined options
3413
+ else if (this.c.preDefined !== false) {
3414
+ this.c.preDefined = this._applyPreDefDefaults(this.c.preDefined);
3415
+ this.rebuild(this.c.preDefined);
3416
+ }
3417
+ }
3418
+ this._setEmptyListener();
3419
+ this.s.dt.state.save();
3420
+ };
3421
+ SearchBuilder.prototype._collapseArray = function (criteria) {
3422
+ if (criteria.logic === undefined) {
3423
+ if (criteria.value !== undefined) {
3424
+ criteria.value.sort(function (a, b) {
3425
+ if (!isNaN(+a)) {
3426
+ a = +a;
3427
+ b = +b;
3428
+ }
3429
+ if (a < b) {
3430
+ return -1;
3431
+ }
3432
+ else if (b < a) {
3433
+ return 1;
3434
+ }
3435
+ else {
3436
+ return 0;
3437
+ }
3438
+ });
3439
+ criteria.value1 = criteria.value[0];
3440
+ criteria.value2 = criteria.value[1];
3441
+ }
3442
+ }
3443
+ else {
3444
+ for (var i = 0; i < criteria.criteria.length; i++) {
3445
+ criteria.criteria[i] = this._collapseArray(criteria.criteria[i]);
3446
+ }
3447
+ }
3448
+ return criteria;
3449
+ };
3450
+ /**
3451
+ * Updates the title of the SearchBuilder
3452
+ *
3453
+ * @param count the number of filters in the SearchBuilder
3454
+ */
3455
+ SearchBuilder.prototype._updateTitle = function (count) {
3456
+ this.dom.title.html(this.s.dt.i18n('searchBuilder.title', this.c.i18n.title, count));
3457
+ };
3458
+ /**
3459
+ * Builds all of the dom elements together
3460
+ */
3461
+ SearchBuilder.prototype._build = function () {
3462
+ var _this = this;
3463
+ // Empty and setup the container
3464
+ this.dom.clearAll.remove();
3465
+ this.dom.container.empty();
3466
+ var count = this.s.topGroup.count();
3467
+ this._updateTitle(count);
3468
+ this.dom.titleRow.append(this.dom.title);
3469
+ this.dom.container.append(this.dom.titleRow);
3470
+ this.dom.topGroup = this.s.topGroup.getNode();
3471
+ this.dom.container.append(this.dom.topGroup);
3472
+ this._setRedrawListener();
3473
+ var tableNode = this.s.dt.table(0).node();
3474
+ if (!$$1.fn.dataTable.ext.search.includes(this.s.search)) {
3475
+ // Custom search function for SearchBuilder
3476
+ this.s.search = function (settings, searchData, dataIndex) {
3477
+ if (settings.nTable !== tableNode) {
3478
+ return true;
3479
+ }
3480
+ return _this.s.topGroup.search(searchData, dataIndex);
3481
+ };
3482
+ // Add SearchBuilder search function to the dataTables search array
3483
+ $$1.fn.dataTable.ext.search.push(this.s.search);
3484
+ }
3485
+ this.s.dt.on('destroy.dtsb', function () {
3486
+ _this.dom.container.remove();
3487
+ _this.dom.clearAll.remove();
3488
+ var searchIdx = $$1.fn.dataTable.ext.search.indexOf(_this.s.search);
3489
+ while (searchIdx !== -1) {
3490
+ $$1.fn.dataTable.ext.search.splice(searchIdx, 1);
3491
+ searchIdx = $$1.fn.dataTable.ext.search.indexOf(_this.s.search);
3492
+ }
3493
+ _this.s.dt.off('.dtsb');
3494
+ $$1(_this.s.dt.table().node()).off('.dtsb');
3495
+ });
3496
+ };
3497
+ /**
3498
+ * Checks if the clearAll button should be added or not
3499
+ */
3500
+ SearchBuilder.prototype._checkClear = function () {
3501
+ if (this.s.topGroup.s.criteria.length > 0) {
3502
+ this.dom.clearAll.insertAfter(this.dom.title);
3503
+ this._setClearListener();
3504
+ }
3505
+ else {
3506
+ this.dom.clearAll.remove();
3507
+ }
3508
+ };
3509
+ /**
3510
+ * Update the count in the title/button
3511
+ *
3512
+ * @param count Number of filters applied
3513
+ */
3514
+ SearchBuilder.prototype._filterChanged = function (count) {
3515
+ var fn = this.c.filterChanged;
3516
+ if (typeof fn === 'function') {
3517
+ fn(count, this.s.dt.i18n('searchBuilder.button', this.c.i18n.button, count));
3518
+ }
3519
+ };
3520
+ /**
3521
+ * Set the listener for the clear button
3522
+ */
3523
+ SearchBuilder.prototype._setClearListener = function () {
3524
+ var _this = this;
3525
+ this.dom.clearAll.unbind('click');
3526
+ this.dom.clearAll.on('click.dtsb', function () {
3527
+ _this.s.topGroup = new Group(_this.s.dt, _this.c, undefined, undefined, undefined, undefined, _this.s.serverData);
3528
+ _this._build();
3529
+ _this.s.dt.draw();
3530
+ _this.s.topGroup.setListeners();
3531
+ _this.dom.clearAll.remove();
3532
+ _this._setEmptyListener();
3533
+ _this._filterChanged(0);
3534
+ return false;
3535
+ });
3536
+ };
3537
+ /**
3538
+ * Set the listener for the Redraw event
3539
+ */
3540
+ SearchBuilder.prototype._setRedrawListener = function () {
3541
+ var _this = this;
3542
+ this.s.topGroup.dom.container.unbind('dtsb-redrawContents');
3543
+ this.s.topGroup.dom.container.on('dtsb-redrawContents.dtsb', function () {
3544
+ _this._checkClear();
3545
+ _this.s.topGroup.redrawContents();
3546
+ _this.s.topGroup.setupLogic();
3547
+ _this._setEmptyListener();
3548
+ var count = _this.s.topGroup.count();
3549
+ _this._updateTitle(count);
3550
+ _this._filterChanged(count);
3551
+ // If using SSP we want to restrict the amount of server calls that take place
3552
+ // and this information will already have been processed
3553
+ if (!_this.s.dt.page.info().serverSide) {
3554
+ _this.s.dt.draw();
3555
+ }
3556
+ _this.s.dt.state.save();
3557
+ });
3558
+ this.s.topGroup.dom.container.unbind('dtsb-redrawContents-noDraw');
3559
+ this.s.topGroup.dom.container.on('dtsb-redrawContents-noDraw.dtsb', function () {
3560
+ _this._checkClear();
3561
+ _this.s.topGroup.s.preventRedraw = true;
3562
+ _this.s.topGroup.redrawContents();
3563
+ _this.s.topGroup.s.preventRedraw = false;
3564
+ _this.s.topGroup.setupLogic();
3565
+ _this._setEmptyListener();
3566
+ var count = _this.s.topGroup.count();
3567
+ _this._updateTitle(count);
3568
+ _this._filterChanged(count);
3569
+ });
3570
+ this.s.topGroup.dom.container.unbind('dtsb-redrawLogic');
3571
+ this.s.topGroup.dom.container.on('dtsb-redrawLogic.dtsb', function () {
3572
+ _this.s.topGroup.redrawLogic();
3573
+ var count = _this.s.topGroup.count();
3574
+ _this._updateTitle(count);
3575
+ _this._filterChanged(count);
3576
+ });
3577
+ this.s.topGroup.dom.container.unbind('dtsb-add');
3578
+ this.s.topGroup.dom.container.on('dtsb-add.dtsb', function () {
3579
+ var count = _this.s.topGroup.count();
3580
+ _this._updateTitle(count);
3581
+ _this._filterChanged(count);
3582
+ });
3583
+ this.s.dt.on('postEdit.dtsb postCreate.dtsb postRemove.dtsb', function () {
3584
+ _this.s.topGroup.redrawContents();
3585
+ });
3586
+ this.s.topGroup.dom.container.unbind('dtsb-clearContents');
3587
+ this.s.topGroup.dom.container.on('dtsb-clearContents.dtsb', function () {
3588
+ _this._setUp(false);
3589
+ _this._filterChanged(0);
3590
+ _this.s.dt.draw();
3591
+ });
3592
+ };
3593
+ /**
3594
+ * Sets listeners to check whether clearAll should be added or removed
3595
+ */
3596
+ SearchBuilder.prototype._setEmptyListener = function () {
3597
+ var _this = this;
3598
+ this.s.topGroup.dom.add.on('click.dtsb', function () {
3599
+ _this._checkClear();
3600
+ });
3601
+ this.s.topGroup.dom.container.on('dtsb-destroy.dtsb', function () {
3602
+ _this.dom.clearAll.remove();
3603
+ });
3604
+ };
3605
+ SearchBuilder.version = '1.4.0';
3606
+ SearchBuilder.classes = {
3607
+ button: 'dtsb-button',
3608
+ clearAll: 'dtsb-clearAll',
3609
+ container: 'dtsb-searchBuilder',
3610
+ inputButton: 'dtsb-iptbtn',
3611
+ title: 'dtsb-title',
3612
+ titleRow: 'dtsb-titleRow'
3613
+ };
3614
+ SearchBuilder.defaults = {
3615
+ columns: true,
3616
+ conditions: {
3617
+ 'date': Criteria.dateConditions,
3618
+ 'html': Criteria.stringConditions,
3619
+ 'html-num': Criteria.numConditions,
3620
+ 'html-num-fmt': Criteria.numFmtConditions,
3621
+ 'luxon': Criteria.luxonDateConditions,
3622
+ 'moment': Criteria.momentDateConditions,
3623
+ 'num': Criteria.numConditions,
3624
+ 'num-fmt': Criteria.numFmtConditions,
3625
+ 'string': Criteria.stringConditions
3626
+ },
3627
+ depthLimit: false,
3628
+ enterSearch: false,
3629
+ filterChanged: undefined,
3630
+ greyscale: false,
3631
+ i18n: {
3632
+ add: 'Add Condition',
3633
+ button: {
3634
+ 0: 'Search Builder',
3635
+ _: 'Search Builder (%d)'
3636
+ },
3637
+ clearAll: 'Clear All',
3638
+ condition: 'Condition',
3639
+ conditions: {
3640
+ array: {
3641
+ contains: 'Contains',
3642
+ empty: 'Empty',
3643
+ equals: 'Equals',
3644
+ not: 'Not',
3645
+ notEmpty: 'Not Empty',
3646
+ without: 'Without'
3647
+ },
3648
+ date: {
3649
+ after: 'After',
3650
+ before: 'Before',
3651
+ between: 'Between',
3652
+ empty: 'Empty',
3653
+ equals: 'Equals',
3654
+ not: 'Not',
3655
+ notBetween: 'Not Between',
3656
+ notEmpty: 'Not Empty'
3657
+ },
3658
+ // eslint-disable-next-line id-blacklist
3659
+ number: {
3660
+ between: 'Between',
3661
+ empty: 'Empty',
3662
+ equals: 'Equals',
3663
+ gt: 'Greater Than',
3664
+ gte: 'Greater Than Equal To',
3665
+ lt: 'Less Than',
3666
+ lte: 'Less Than Equal To',
3667
+ not: 'Not',
3668
+ notBetween: 'Not Between',
3669
+ notEmpty: 'Not Empty'
3670
+ },
3671
+ // eslint-disable-next-line id-blacklist
3672
+ string: {
3673
+ contains: 'Contains',
3674
+ empty: 'Empty',
3675
+ endsWith: 'Ends With',
3676
+ equals: 'Equals',
3677
+ not: 'Not',
3678
+ notContains: 'Does Not Contain',
3679
+ notEmpty: 'Not Empty',
3680
+ notEndsWith: 'Does Not End With',
3681
+ notStartsWith: 'Does Not Start With',
3682
+ startsWith: 'Starts With'
3683
+ }
3684
+ },
3685
+ data: 'Data',
3686
+ "delete": '&times',
3687
+ deleteTitle: 'Delete filtering rule',
3688
+ left: '<',
3689
+ leftTitle: 'Outdent criteria',
3690
+ logicAnd: 'And',
3691
+ logicOr: 'Or',
3692
+ right: '>',
3693
+ rightTitle: 'Indent criteria',
3694
+ title: {
3695
+ 0: 'Custom Search Builder',
3696
+ _: 'Custom Search Builder (%d)'
3697
+ },
3698
+ value: 'Value',
3699
+ valueJoiner: 'and'
3700
+ },
3701
+ logic: 'AND',
3702
+ orthogonal: {
3703
+ display: 'display',
3704
+ search: 'filter'
3705
+ },
3706
+ preDefined: false
3707
+ };
3708
+ return SearchBuilder;
3709
+ }());
3710
+
3711
+ /*! SearchBuilder 1.4.0
3712
+ * ©SpryMedia Ltd - datatables.net/license/mit
3713
+ */
3714
+ setJQuery($);
3715
+ setJQuery$1($);
3716
+ setJQuery$2($);
3717
+ var dataTable = $.fn.dataTable;
3718
+ // eslint-disable-next-line no-extra-parens
3719
+ DataTable.SearchBuilder = SearchBuilder;
3720
+ // eslint-disable-next-line no-extra-parens
3721
+ dataTable.SearchBuilder = SearchBuilder;
3722
+ // eslint-disable-next-line no-extra-parens
3723
+ DataTable.Group = Group;
3724
+ // eslint-disable-next-line no-extra-parens
3725
+ dataTable.Group = Group;
3726
+ // eslint-disable-next-line no-extra-parens
3727
+ DataTable.Criteria = Criteria;
3728
+ // eslint-disable-next-line no-extra-parens
3729
+ dataTable.Criteria = Criteria;
3730
+ // eslint-disable-next-line no-extra-parens
3731
+ var apiRegister = DataTable.Api.register;
3732
+ // Set up object for plugins
3733
+ DataTable.ext.searchBuilder = {
3734
+ conditions: {}
3735
+ };
3736
+ DataTable.ext.buttons.searchBuilder = {
3737
+ action: function (e, dt, node, config) {
3738
+ this.popover(config._searchBuilder.getNode(), {
3739
+ align: 'container',
3740
+ span: 'container'
3741
+ });
3742
+ var topGroup = config._searchBuilder.s.topGroup;
3743
+ // Need to redraw the contents to calculate the correct positions for the elements
3744
+ if (topGroup !== undefined) {
3745
+ topGroup.dom.container.trigger('dtsb-redrawContents-noDraw');
3746
+ }
3747
+ if (topGroup.s.criteria.length === 0) {
3748
+ $('.' + $.fn.dataTable.Group.classes.add.replace(/ /g, '.')).click();
3749
+ }
3750
+ },
3751
+ config: {},
3752
+ init: function (dt, node, config) {
3753
+ var sb = new DataTable.SearchBuilder(dt, $.extend({
3754
+ filterChanged: function (count, text) {
3755
+ dt.button(node).text(text);
3756
+ }
3757
+ }, config.config));
3758
+ dt.button(node).text(config.text || dt.i18n('searchBuilder.button', sb.c.i18n.button, 0));
3759
+ config._searchBuilder = sb;
3760
+ },
3761
+ text: null
3762
+ };
3763
+ apiRegister('searchBuilder.getDetails()', function (deFormatDates) {
3764
+ if (deFormatDates === void 0) { deFormatDates = false; }
3765
+ var ctx = this.context[0];
3766
+ // If SearchBuilder has not been initialised on this instance then return
3767
+ return ctx._searchBuilder ?
3768
+ ctx._searchBuilder.getDetails(deFormatDates) :
3769
+ null;
3770
+ });
3771
+ apiRegister('searchBuilder.rebuild()', function (details) {
3772
+ var ctx = this.context[0];
3773
+ // If SearchBuilder has not been initialised on this instance then return
3774
+ if (ctx._searchBuilder === undefined) {
3775
+ return null;
3776
+ }
3777
+ ctx._searchBuilder.rebuild(details);
3778
+ return this;
3779
+ });
3780
+ apiRegister('searchBuilder.container()', function () {
3781
+ var ctx = this.context[0];
3782
+ // If SearchBuilder has not been initialised on this instance then return
3783
+ return ctx._searchBuilder ?
3784
+ ctx._searchBuilder.getNode() :
3785
+ null;
3786
+ });
3787
+ /**
3788
+ * Init function for SearchBuilder
3789
+ *
3790
+ * @param settings the settings to be applied
3791
+ * @param options the options for SearchBuilder
3792
+ * @returns JQUERY<HTMLElement> Returns the node of the SearchBuilder
3793
+ */
3794
+ function _init(settings, options) {
3795
+ var api = new DataTable.Api(settings);
3796
+ var opts = options
3797
+ ? options
3798
+ : api.init().searchBuilder || DataTable.defaults.searchBuilder;
3799
+ var searchBuilder = new SearchBuilder(api, opts);
3800
+ var node = searchBuilder.getNode();
3801
+ return node;
3802
+ }
3803
+ // Attach a listener to the document which listens for DataTables initialisation
3804
+ // events so we can automatically initialise
3805
+ $(document).on('preInit.dt.dtsp', function (e, settings) {
3806
+ if (e.namespace !== 'dt') {
3807
+ return;
3808
+ }
3809
+ if (settings.oInit.searchBuilder ||
3810
+ DataTable.defaults.searchBuilder) {
3811
+ if (!settings._searchBuilder) {
3812
+ _init(settings);
3813
+ }
3814
+ }
3815
+ });
3816
+ // DataTables `dom` feature option
3817
+ DataTable.ext.feature.push({
3818
+ cFeature: 'Q',
3819
+ fnInit: _init
3820
+ });
3821
+ // DataTables 2 layout feature
3822
+ if (DataTable.ext.features) {
3823
+ DataTable.ext.features.register('searchBuilder', _init);
3824
+ }
3825
+
3826
+ }());
3827
+
3828
+
3829
+ export default DataTable;