datatables.net-searchbuilder 1.3.4 → 1.4.2

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