PHP Classes

File: vendor/datatables/SearchBuilder-1.3.4/js/dataTables.searchBuilder.js

Recommend this page to a friend!
  Classes of Braun Okoi Boniface   eprotech   vendor/datatables/SearchBuilder-1.3.4/js/dataTables.searchBuilder.js   Download  
File: vendor/datatables/SearchBuilder-1.3.4/js/dataTables.searchBuilder.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: eprotech
Application to access medical product suppliers
Author: By
Last change:
Date: 2 years ago
Size: 176,650 bytes
 

Contents

Class file image Download
/*! SearchBuilder 1.3.4 * ©SpryMedia Ltd - datatables.net/license/mit */ (function () { 'use strict'; var $$2; var dataTable$2; function moment() { return window.moment; } function luxon() { return window.luxon; } /** * Sets the value of jQuery for use in the file * * @param jq the instance of jQuery to be set */ function setJQuery$2(jq) { $$2 = jq; dataTable$2 = jq.fn.dataTable; } /** * The Criteria class is used within SearchBuilder to represent a search criteria */ var Criteria = /** @class */ (function () { function Criteria(table, opts, topGroup, index, depth, serverData) { var _this = this; if (index === void 0) { index = 0; } if (depth === void 0) { depth = 1; } if (serverData === void 0) { serverData = undefined; } // Check that the required version of DataTables is included if (!dataTable$2 || !dataTable$2.versionCheck || !dataTable$2.versionCheck('1.10.0')) { throw new Error('SearchPane requires DataTables 1.10 or newer'); } this.classes = $$2.extend(true, {}, Criteria.classes); // Get options from user and any extra conditions/column types defined by plug-ins this.c = $$2.extend(true, {}, Criteria.defaults, $$2.fn.dataTable.ext.searchBuilder, opts); var i18n = this.c.i18n; this.s = { condition: undefined, conditions: {}, data: undefined, dataIdx: -1, dataPoints: [], dateFormat: false, depth: depth, dt: table, filled: false, index: index, origData: undefined, preventRedraw: false, serverData: serverData, topGroup: topGroup, type: '', value: [] }; this.dom = { buttons: $$2('<div/>') .addClass(this.classes.buttonContainer), condition: $$2('<select disabled/>') .addClass(this.classes.condition) .addClass(this.classes.dropDown) .addClass(this.classes.italic) .attr('autocomplete', 'hacking'), conditionTitle: $$2('<option value="" disabled selected hidden/>') .html(this.s.dt.i18n('searchBuilder.condition', i18n.condition)), container: $$2('<div/>') .addClass(this.classes.container), data: $$2('<select/>') .addClass(this.classes.data) .addClass(this.classes.dropDown) .addClass(this.classes.italic), dataTitle: $$2('<option value="" disabled selected hidden/>') .html(this.s.dt.i18n('searchBuilder.data', i18n.data)), defaultValue: $$2('<select disabled/>') .addClass(this.classes.value) .addClass(this.classes.dropDown) .addClass(this.classes.select) .addClass(this.classes.italic), "delete": $$2('<button/>') .html(this.s.dt.i18n('searchBuilder.delete', i18n["delete"])) .addClass(this.classes["delete"]) .addClass(this.classes.button) .attr('title', this.s.dt.i18n('searchBuilder.deleteTitle', i18n.deleteTitle)) .attr('type', 'button'), inputCont: $$2('<div/>') .addClass(this.classes.inputCont), // eslint-disable-next-line no-useless-escape left: $$2('<button/>') .html(this.s.dt.i18n('searchBuilder.left', i18n.left)) .addClass(this.classes.left) .addClass(this.classes.button) .attr('title', this.s.dt.i18n('searchBuilder.leftTitle', i18n.leftTitle)) .attr('type', 'button'), // eslint-disable-next-line no-useless-escape right: $$2('<button/>') .html(this.s.dt.i18n('searchBuilder.right', i18n.right)) .addClass(this.classes.right) .addClass(this.classes.button) .attr('title', this.s.dt.i18n('searchBuilder.rightTitle', i18n.rightTitle)) .attr('type', 'button'), value: [ $$2('<select disabled/>') .addClass(this.classes.value) .addClass(this.classes.dropDown) .addClass(this.classes.italic) .addClass(this.classes.select) ], valueTitle: $$2('<option value="--valueTitle--" disabled selected hidden/>') .html(this.s.dt.i18n('searchBuilder.value', i18n.value)) }; // If the greyscale option is selected then add the class to add the grey colour to SearchBuilder if (this.c.greyscale) { this.dom.data.addClass(this.classes.greyscale); this.dom.condition.addClass(this.classes.greyscale); this.dom.defaultValue.addClass(this.classes.greyscale); for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) { var val = _a[_i]; val.addClass(this.classes.greyscale); } } $$2(window).on('resize.dtsb', dataTable$2.util.throttle(function () { _this.s.topGroup.trigger('dtsb-redrawLogic'); })); this._buildCriteria(); return this; } /** * Escape html characters within a string * * @param txt the string to be escaped * @returns the escaped string */ Criteria._escapeHTML = function (txt) { return txt .toString() .replace(/&amp;/g, '&') .replace(/&lt;/g, '<') .replace(/&gt;/g, '>') .replace(/&quot;/g, '"'); }; /** * Parses formatted numbers down to a form where they can be compared * * @param val the value to convert * @returns the converted value */ Criteria.parseNumFmt = function (val) { return +val.replace(/(?!^-)[^0-9.]/g, ''); }; /** * Adds the left button to the criteria */ Criteria.prototype.updateArrows = function (hasSiblings) { if (hasSiblings === void 0) { hasSiblings = false; } // Empty the container and append all of the elements in the correct order this.dom.container.children().detach(); this.dom.container .append(this.dom.data) .append(this.dom.condition) .append(this.dom.inputCont); this.setListeners(); // Trigger the inserted events for the value elements as they are inserted if (this.dom.value[0] !== undefined) { this.dom.value[0].trigger('dtsb-inserted'); } for (var i = 1; i < this.dom.value.length; i++) { this.dom.inputCont.append(this.dom.value[i]); this.dom.value[i].trigger('dtsb-inserted'); } // If this is a top level criteria then don't let it move left if (this.s.depth > 1) { this.dom.buttons.append(this.dom.left); } // If the depthLimit of the query has been hit then don't add the right button if ((this.c.depthLimit === false || this.s.depth < this.c.depthLimit) && hasSiblings) { this.dom.buttons.append(this.dom.right); } else { this.dom.right.remove(); } this.dom.buttons.append(this.dom["delete"]); this.dom.container.append(this.dom.buttons); }; /** * Destroys the criteria, removing listeners and container from the dom */ Criteria.prototype.destroy = function () { // Turn off listeners this.dom.data.off('.dtsb'); this.dom.condition.off('.dtsb'); this.dom["delete"].off('.dtsb'); for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) { var val = _a[_i]; val.off('.dtsb'); } // Remove container from the dom this.dom.container.remove(); }; /** * Passes in the data for the row and compares it against this single criteria * * @param rowData The data for the row to be compared * @returns boolean Whether the criteria has passed */ Criteria.prototype.search = function (rowData, rowIdx) { var condition = this.s.conditions[this.s.condition]; if (this.s.condition !== undefined && condition !== undefined) { var filter = rowData[this.s.dataIdx]; // This check is in place for if a custom decimal character is in place if (this.s.type.includes('num') && (this.s.dt.settings()[0].oLanguage.sDecimal !== '' || this.s.dt.settings()[0].oLanguage.sThousands !== '')) { var splitRD = [rowData[this.s.dataIdx]]; if (this.s.dt.settings()[0].oLanguage.sDecimal !== '') { splitRD = rowData[this.s.dataIdx].split(this.s.dt.settings()[0].oLanguage.sDecimal); } if (this.s.dt.settings()[0].oLanguage.sThousands !== '') { for (var i = 0; i < splitRD.length; i++) { splitRD[i] = splitRD[i].replace(this.s.dt.settings()[0].oLanguage.sThousands, ','); } } filter = splitRD.join('.'); } // If orthogonal data is in place we need to get it's values for searching if (this.c.orthogonal.search !== 'filter') { var settings = this.s.dt.settings()[0]; filter = settings.oApi._fnGetCellData(settings, rowIdx, this.s.dataIdx, typeof this.c.orthogonal === 'string' ? this.c.orthogonal : this.c.orthogonal.search); } if (this.s.type === 'array') { // Make sure we are working with an array if (!Array.isArray(filter)) { filter = [filter]; } filter.sort(); for (var _i = 0, filter_1 = filter; _i < filter_1.length; _i++) { var filt = filter_1[_i]; if (filt && typeof filt === 'string') { filt = filt.replace(/[\r\n\u2028]/g, ' '); } } } else if (filter !== null && typeof filter === 'string') { filter = filter.replace(/[\r\n\u2028]/g, ' '); } if (this.s.type.includes('html') && typeof filter === 'string') { filter = filter.replace(/(<([^>]+)>)/ig, ''); } // Not ideal, but jqueries .val() returns an empty string even // when the value set is null, so we shall assume the two are equal if (filter === null) { filter = ''; } return condition.search(filter, this.s.value, this); } }; /** * Gets the details required to rebuild the criteria */ Criteria.prototype.getDetails = function (deFormatDates) { if (deFormatDates === void 0) { deFormatDates = false; } // This check is in place for if a custom decimal character is in place if (this.s.type !== null && this.s.type.includes('num') && (this.s.dt.settings()[0].oLanguage.sDecimal !== '' || this.s.dt.settings()[0].oLanguage.sThousands !== '')) { for (var i = 0; i < this.s.value.length; i++) { var splitRD = [this.s.value[i].toString()]; if (this.s.dt.settings()[0].oLanguage.sDecimal !== '') { splitRD = this.s.value[i].split(this.s.dt.settings()[0].oLanguage.sDecimal); } if (this.s.dt.settings()[0].oLanguage.sThousands !== '') { for (var j = 0; j < splitRD.length; j++) { splitRD[j] = splitRD[j].replace(this.s.dt.settings()[0].oLanguage.sThousands, ','); } } this.s.value[i] = splitRD.join('.'); } } else if (this.s.type !== null && deFormatDates) { if (this.s.type.includes('date') || this.s.type.includes('time')) { for (var i = 0; i < this.s.value.length; i++) { if (this.s.value[i].match(/^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])$/g) === null) { this.s.value[i] = ''; } } } else if (this.s.type.includes('moment')) { for (var i = 0; i < this.s.value.length; i++) { if (this.s.value[i] && this.s.value[i].length > 0 && moment()(this.s.value[i], this.s.dateFormat, true).isValid()) { this.s.value[i] = moment()(this.s.value[i], this.s.dateFormat).format('YYYY-MM-DD HH:mm:ss'); } } } else if (this.s.type.includes('luxon')) { for (var i = 0; i < this.s.value.length; i++) { if (this.s.value[i] && this.s.value[i].length > 0 && luxon().DateTime.fromFormat(this.s.value[i], this.s.dateFormat).invalid === null) { this.s.value[i] = luxon().DateTime.fromFormat(this.s.value[i], this.s.dateFormat).toFormat('yyyy-MM-dd HH:mm:ss'); } } } } if (this.s.type.includes('num') && this.s.dt.page.info().serverSide) { for (var i = 0; i < this.s.value.length; i++) { this.s.value[i] = this.s.value[i].replace(/[^0-9.]/g, ''); } } return { condition: this.s.condition, data: this.s.data, origData: this.s.origData, type: this.s.type, value: this.s.value.map(function (a) { return a !== null && a !== undefined ? a.toString() : a; }) }; }; /** * Getter for the node for the container of the criteria * * @returns JQuery<HTMLElement> the node for the container */ Criteria.prototype.getNode = function () { return this.dom.container; }; /** * Populates the criteria data, condition and value(s) as far as has been selected */ Criteria.prototype.populate = function () { this._populateData(); // If the column index has been found attempt to select a condition if (this.s.dataIdx !== -1) { this._populateCondition(); // If the condittion has been found attempt to select the values if (this.s.condition !== undefined) { this._populateValue(); } } }; /** * Rebuilds the criteria based upon the details passed in * * @param loadedCriteria the details required to rebuild the criteria */ Criteria.prototype.rebuild = function (loadedCriteria) { // Check to see if the previously selected data exists, if so select it var foundData = false; var dataIdx; this._populateData(); // If a data selection has previously been made attempt to find and select it if (loadedCriteria.data !== undefined) { var italic_1 = this.classes.italic; var data_1 = this.dom.data; this.dom.data.children('option').each(function () { if (!foundData && ($$2(this).text() === loadedCriteria.data || loadedCriteria.origData && $$2(this).prop('origData') === loadedCriteria.origData)) { $$2(this).prop('selected', true); data_1.removeClass(italic_1); foundData = true; dataIdx = $$2(this).val(); } else { $$2(this).removeProp('selected'); } }); } // If the data has been found and selected then the condition can be populated and searched if (foundData) { this.s.data = loadedCriteria.data; this.s.origData = loadedCriteria.origData; this.s.dataIdx = dataIdx; this.c.orthogonal = this._getOptions().orthogonal; this.dom.dataTitle.remove(); this._populateCondition(); this.dom.conditionTitle.remove(); var condition = void 0; // Check to see if the previously selected condition exists, if so select it var options = this.dom.condition.children('option'); // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < options.length; i++) { var option = $$2(options[i]); if (loadedCriteria.condition !== undefined && option.val() === loadedCriteria.condition && typeof loadedCriteria.condition === 'string') { option.prop('selected', true); condition = option.val(); } else { option.removeProp('selected'); } } this.s.condition = condition; // If the condition has been found and selected then the value can be populated and searched if (this.s.condition !== undefined) { this.dom.conditionTitle.removeProp('selected'); this.dom.conditionTitle.remove(); this.dom.condition.removeClass(this.classes.italic); // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < options.length; i++) { var option = $$2(options[i]); if (option.val() !== this.s.condition) { option.removeProp('selected'); } } this._populateValue(loadedCriteria); } else { this.dom.conditionTitle.prependTo(this.dom.condition).prop('selected', true); } } }; /** * Sets the listeners for the criteria */ Criteria.prototype.setListeners = function () { var _this = this; this.dom.data .unbind('change') .on('change.dtsb', function () { _this.dom.dataTitle.removeProp('selected'); // Need to go over every option to identify the correct selection var options = _this.dom.data.children('option.' + _this.classes.option); // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < options.length; i++) { var option = $$2(options[i]); if (option.val() === _this.dom.data.val()) { _this.dom.data.removeClass(_this.classes.italic); option.prop('selected', true); _this.s.dataIdx = +option.val(); _this.s.data = option.text(); _this.s.origData = option.prop('origData'); _this.c.orthogonal = _this._getOptions().orthogonal; // When the data is changed, the values in condition and // value may also change so need to renew them _this._clearCondition(); _this._clearValue(); _this._populateCondition(); // If this criteria was previously active in the search then // remove it from the search and trigger a new search if (_this.s.filled) { _this.s.filled = false; _this.s.dt.draw(); _this.setListeners(); } _this.s.dt.state.save(); } else { option.removeProp('selected'); } } }); this.dom.condition .unbind('change') .on('change.dtsb', function () { _this.dom.conditionTitle.removeProp('selected'); // Need to go over every option to identify the correct selection var options = _this.dom.condition.children('option.' + _this.classes.option); // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < options.length; i++) { var option = $$2(options[i]); if (option.val() === _this.dom.condition.val()) { _this.dom.condition.removeClass(_this.classes.italic); option.prop('selected', true); var condDisp = option.val(); // Find the condition that has been selected and store it internally for (var _i = 0, _a = Object.keys(_this.s.conditions); _i < _a.length; _i++) { var cond = _a[_i]; if (cond === condDisp) { _this.s.condition = condDisp; break; } } // When the condition is changed, the value selector may switch between // a select element and an input element _this._clearValue(); _this._populateValue(); for (var _b = 0, _c = _this.dom.value; _b < _c.length; _b++) { var val = _c[_b]; // If this criteria was previously active in the search then remove // it from the search and trigger a new search if (_this.s.filled && val !== undefined && _this.dom.inputCont.has(val[0]).length !== 0) { _this.s.filled = false; _this.s.dt.draw(); _this.setListeners(); } } if (_this.dom.value.length === 0 || _this.dom.value.length === 1 && _this.dom.value[0] === undefined) { _this.s.dt.draw(); } } else { option.removeProp('selected'); } } }); }; Criteria.prototype.setupButtons = function () { if (window.innerWidth > 550) { this.dom.container.removeClass(this.classes.vertical); this.dom.buttons.css('left', null); this.dom.buttons.css('top', null); return; } this.dom.container.addClass(this.classes.vertical); this.dom.buttons.css('left', this.dom.data.innerWidth()); this.dom.buttons.css('top', this.dom.data.position().top); }; /** * Builds the elements of the dom together */ Criteria.prototype._buildCriteria = function () { // Append Titles for select elements this.dom.data.append(this.dom.dataTitle); this.dom.condition.append(this.dom.conditionTitle); // Add elements to container this.dom.container .append(this.dom.data) .append(this.dom.condition); this.dom.inputCont.empty(); for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) { var val = _a[_i]; val.append(this.dom.valueTitle); this.dom.inputCont.append(val); } // Add buttons to container this.dom.buttons .append(this.dom["delete"]) .append(this.dom.right); this.dom.container.append(this.dom.inputCont).append(this.dom.buttons); this.setListeners(); }; /** * Clears the condition select element */ Criteria.prototype._clearCondition = function () { this.dom.condition.empty(); this.dom.conditionTitle.prop('selected', true).attr('disabled', 'true'); this.dom.condition.prepend(this.dom.conditionTitle).prop('selectedIndex', 0); this.s.conditions = {}; this.s.condition = undefined; }; /** * Clears the value elements */ Criteria.prototype._clearValue = function () { if (this.s.condition !== undefined) { if (this.dom.value.length > 0 && this.dom.value[0] !== undefined) { var _loop_1 = function (val) { if (val !== undefined) { // Timeout is annoying but because of IOS setTimeout(function () { val.remove(); }, 50); } }; // Remove all of the value elements for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) { var val = _a[_i]; _loop_1(val); } } // Call the init function to get the value elements for this condition this.dom.value = [].concat(this.s.conditions[this.s.condition].init(this, Criteria.updateListener)); if (this.dom.value.length > 0 && this.dom.value[0] !== undefined) { this.dom.inputCont .empty() .append(this.dom.value[0]) .insertAfter(this.dom.condition); this.dom.value[0].trigger('dtsb-inserted'); // Insert all of the value elements for (var i = 1; i < this.dom.value.length; i++) { this.dom.inputCont.append(this.dom.value[i]); this.dom.value[i].trigger('dtsb-inserted'); } } } else { var _loop_2 = function (val) { if (val !== undefined) { // Timeout is annoying but because of IOS setTimeout(function () { val.remove(); }, 50); } }; // Remove all of the value elements for (var _b = 0, _c = this.dom.value; _b < _c.length; _b++) { var val = _c[_b]; _loop_2(val); } // Append the default valueTitle to the default select element this.dom.valueTitle .prop('selected', true); this.dom.defaultValue .append(this.dom.valueTitle) .insertAfter(this.dom.condition); } this.s.value = []; this.dom.value = [ $$2('<select disabled/>') .addClass(this.classes.value) .addClass(this.classes.dropDown) .addClass(this.classes.italic) .addClass(this.classes.select) .append(this.dom.valueTitle.clone()) ]; }; /** * Gets the options for the column * * @returns {object} The options for the column */ Criteria.prototype._getOptions = function () { var table = this.s.dt; return $$2.extend(true, {}, Criteria.defaults, table.settings()[0].aoColumns[this.s.dataIdx].searchBuilder); }; /** * Populates the condition dropdown */ Criteria.prototype._populateCondition = function () { var conditionOpts = []; var conditionsLength = Object.keys(this.s.conditions).length; var colInits = this.s.dt.settings()[0].aoColumns; var column = +this.dom.data.children('option:selected').val(); // If there are no conditions stored then we need to get them from the appropriate type if (conditionsLength === 0) { this.s.type = this.s.dt.columns().type().toArray()[column]; if (colInits !== undefined) { var colInit = colInits[column]; if (colInit.searchBuilderType !== undefined && colInit.searchBuilderType !== null) { this.s.type = colInit.searchBuilderType; } else if (this.s.type === undefined || this.s.type === null) { this.s.type = colInit.sType; } } // If the column type is still unknown, call a draw to try reading it again if (this.s.type === null || this.s.type === undefined) { $$2.fn.dataTable.ext.oApi._fnColumnTypes(this.s.dt.settings()[0]); this.s.type = this.s.dt.columns().type().toArray()[column]; } // Enable the condition element this.dom.condition .removeAttr('disabled') .empty() .append(this.dom.conditionTitle) .addClass(this.classes.italic); this.dom.conditionTitle .prop('selected', true); var decimal = this.s.dt.settings()[0].oLanguage.sDecimal; // This check is in place for if a custom decimal character is in place if (decimal !== '' && this.s.type.indexOf(decimal) === this.s.type.length - decimal.length) { if (this.s.type.includes('num-fmt')) { this.s.type = this.s.type.replace(decimal, ''); } else if (this.s.type.includes('num')) { this.s.type = this.s.type.replace(decimal, ''); } } // Select which conditions are going to be used based on the column type var conditionObj = this.c.conditions[this.s.type] !== undefined ? this.c.conditions[this.s.type] : this.s.type.includes('moment') ? this.c.conditions.moment : this.s.type.includes('luxon') ? this.c.conditions.luxon : this.c.conditions.string; // If it is a moment format then extract the date format if (this.s.type.includes('moment')) { this.s.dateFormat = this.s.type.replace(/moment-/g, ''); } else if (this.s.type.includes('luxon')) { this.s.dateFormat = this.s.type.replace(/luxon-/g, ''); } // Add all of the conditions to the select element for (var _i = 0, _a = Object.keys(conditionObj); _i < _a.length; _i++) { var condition = _a[_i]; if (conditionObj[condition] !== null) { // Serverside processing does not supply the options for the select elements // Instead input elements need to be used for these instead if (this.s.dt.page.info().serverSide && conditionObj[condition].init === Criteria.initSelect) { var col = colInits[column]; if (this.s.serverData && this.s.serverData[col.data]) { conditionObj[condition].init = Criteria.initSelectSSP; conditionObj[condition].inputValue = Criteria.inputValueSelect; conditionObj[condition].isInputValid = Criteria.isInputValidSelect; } else { conditionObj[condition].init = Criteria.initInput; conditionObj[condition].inputValue = Criteria.inputValueInput; conditionObj[condition].isInputValid = Criteria.isInputValidInput; } } this.s.conditions[condition] = conditionObj[condition]; var condName = conditionObj[condition].conditionName; if (typeof condName === 'function') { condName = condName(this.s.dt, this.c.i18n); } conditionOpts.push($$2('<option>', { text: condName, value: condition }) .addClass(this.classes.option) .addClass(this.classes.notItalic)); } } } // Otherwise we can just load them in else if (conditionsLength > 0) { this.dom.condition.empty().removeAttr('disabled').addClass(this.classes.italic); for (var _b = 0, _c = Object.keys(this.s.conditions); _b < _c.length; _b++) { var condition = _c[_b]; var condName = this.s.conditions[condition].conditionName; if (typeof condName === 'function') { condName = condName(this.s.dt, this.c.i18n); } var newOpt = $$2('<option>', { text: condName, value: condition }) .addClass(this.classes.option) .addClass(this.classes.notItalic); if (this.s.condition !== undefined && this.s.condition === condName) { newOpt.prop('selected', true); this.dom.condition.removeClass(this.classes.italic); } conditionOpts.push(newOpt); } } else { this.dom.condition .attr('disabled', 'true') .addClass(this.classes.italic); return; } for (var _d = 0, conditionOpts_1 = conditionOpts; _d < conditionOpts_1.length; _d++) { var opt = conditionOpts_1[_d]; this.dom.condition.append(opt); } // Selecting a default condition if one is set if (colInits[column].searchBuilder && colInits[column].searchBuilder.defaultCondition) { var defaultCondition = colInits[column].searchBuilder.defaultCondition; // If it is a number just use it as an index if (typeof defaultCondition === 'number') { this.dom.condition.prop('selectedIndex', defaultCondition); this.dom.condition.trigger('change'); } // If it is a string then things get slightly more tricly else if (typeof defaultCondition === 'string') { // We need to check each condition option to see if any will match for (var i = 0; i < conditionOpts.length; i++) { // Need to check against the stored conditions so we can match the token "cond" to the option for (var _e = 0, _f = Object.keys(this.s.conditions); _e < _f.length; _e++) { var cond = _f[_e]; var condName = this.s.conditions[cond].conditionName; if ( // If the conditionName matches the text of the option (typeof condName === 'string' ? condName : condName(this.s.dt, this.c.i18n)) === conditionOpts[i].text() && // and the tokens match cond === defaultCondition) { // Select that option this.dom.condition .prop('selectedIndex', this.dom.condition.children().toArray().indexOf(conditionOpts[i][0])) .removeClass(this.classes.italic); this.dom.condition.trigger('change'); i = conditionOpts.length; break; } } } } } // If not default set then default to 0, the title else { this.dom.condition.prop('selectedIndex', 0); } }; /** * Populates the data select element */ Criteria.prototype._populateData = function () { var _this = this; this.dom.data.empty().append(this.dom.dataTitle); // If there are no datas stored then we need to get them from the table if (this.s.dataPoints.length === 0) { this.s.dt.columns().every(function (index) { // Need to check that the column can be filtered on before adding it if (_this.c.columns === true || _this.s.dt.columns(_this.c.columns).indexes().toArray().includes(index)) { var found = false; for (var _i = 0, _a = _this.s.dataPoints; _i < _a.length; _i++) { var val = _a[_i]; if (val.index === index) { found = true; break; } } if (!found) { var col = _this.s.dt.settings()[0].aoColumns[index]; var opt = { index: index, origData: col.data, text: (col.searchBuilderTitle === undefined ? col.sTitle : col.searchBuilderTitle).replace(/(<([^>]+)>)/ig, '') }; _this.s.dataPoints.push(opt); _this.dom.data.append($$2('<option>', { text: opt.text, value: opt.index }) .addClass(_this.classes.option) .addClass(_this.classes.notItalic) .prop('origData', col.data) .prop('selected', _this.s.dataIdx === opt.index ? true : false)); if (_this.s.dataIdx === opt.index) { _this.dom.dataTitle.removeProp('selected'); } } } }); } // Otherwise we can just load them in else { var _loop_3 = function (data) { this_1.s.dt.columns().every(function (index) { var col = _this.s.dt.settings()[0].aoColumns[index]; if ((col.searchBuilderTitle === undefined ? col.sTitle : col.searchBuilderTitle).replace(/(<([^>]+)>)/ig, '') === data.text) { data.index = index; data.origData = col.data; } }); var newOpt = $$2('<option>', { text: data.text.replace(/(<([^>]+)>)/ig, ''), value: data.index }) .addClass(this_1.classes.option) .addClass(this_1.classes.notItalic) .prop('origData', data.origData); if (this_1.s.data === data.text) { this_1.s.dataIdx = data.index; this_1.dom.dataTitle.removeProp('selected'); newOpt.prop('selected', true); this_1.dom.data.removeClass(this_1.classes.italic); } this_1.dom.data.append(newOpt); }; var this_1 = this; for (var _i = 0, _a = this.s.dataPoints; _i < _a.length; _i++) { var data = _a[_i]; _loop_3(data); } } }; /** * Populates the Value select element * * @param loadedCriteria optional, used to reload criteria from predefined filters */ Criteria.prototype._populateValue = function (loadedCriteria) { var _this = this; var prevFilled = this.s.filled; this.s.filled = false; // Remove any previous value elements // Timeout is annoying but because of IOS setTimeout(function () { _this.dom.defaultValue.remove(); }, 50); var _loop_4 = function (val) { // Timeout is annoying but because of IOS setTimeout(function () { if (val !== undefined) { val.remove(); } }, 50); }; for (var _i = 0, _a = this.dom.value; _i < _a.length; _i++) { var val = _a[_i]; _loop_4(val); } var children = this.dom.inputCont.children(); if (children.length > 1) { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (var i = 0; i < children.length; i++) { $$2(children[i]).remove(); } } // Find the column with the title matching the data for the criteria and take note of the index if (loadedCriteria !== undefined) { this.s.dt.columns().every(function (index) { if (_this.s.dt.settings()[0].aoColumns[index].sTitle === loadedCriteria.data) { _this.s.dataIdx = index; } }); } // Initialise the value elements based on the condition this.dom.value = [].concat(this.s.conditions[this.s.condition].init(this, Criteria.updateListener, loadedCriteria !== undefined ? loadedCriteria.value : undefined)); if (loadedCriteria !== undefined && loadedCriteria.value !== undefined) { this.s.value = loadedCriteria.value; } this.dom.inputCont.empty(); // Insert value elements and trigger the inserted event if (this.dom.value[0] !== undefined) { this.dom.value[0] .appendTo(this.dom.inputCont) .trigger('dtsb-inserted'); } for (var i = 1; i < this.dom.value.length; i++) { this.dom.value[i] .insertAfter(this.dom.value[i - 1]) .trigger('dtsb-inserted'); } // Check if the criteria can be used in a search this.s.filled = this.s.conditions[this.s.condition].isInputValid(this.dom.value, this); this.setListeners(); // If it can and this is different to before then trigger a draw if (!this.s.preventRedraw && prevFilled !== this.s.filled) { // If using SSP we want to restrict the amount of server calls that take place // and this will already have taken place if (!this.s.dt.page.info().serverSide) { this.s.dt.draw(); } this.setListeners(); } }; /** * Provides throttling capabilities to SearchBuilder without having to use dt's _fnThrottle function * This is because that function is not quite suitable for our needs as it runs initially rather than waiting * * @param args arguments supplied to the throttle function * @returns Function that is to be run that implements the throttling */ Criteria.prototype._throttle = function (fn, frequency) { if (frequency === void 0) { frequency = 200; } var last = null; var timer = null; var that = this; if (frequency === null) { frequency = 200; } return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var now = +new Date(); if (last !== null && now < last + frequency) { clearTimeout(timer); } else { last = now; } timer = setTimeout(function () { last = null; fn.apply(that, args); }, frequency); }; }; Criteria.version = '1.1.0'; Criteria.classes = { button: 'dtsb-button', buttonContainer: 'dtsb-buttonContainer', condition: 'dtsb-condition', container: 'dtsb-criteria', data: 'dtsb-data', "delete": 'dtsb-delete', dropDown: 'dtsb-dropDown', greyscale: 'dtsb-greyscale', input: 'dtsb-input', inputCont: 'dtsb-inputCont', italic: 'dtsb-italic', joiner: 'dtsp-joiner', left: 'dtsb-left', notItalic: 'dtsb-notItalic', option: 'dtsb-option', right: 'dtsb-right', select: 'dtsb-select', value: 'dtsb-value', vertical: 'dtsb-vertical' }; /** * Default initialisation function for select conditions */ Criteria.initSelect = function (that, fn, preDefined, array) { if (preDefined === void 0) { preDefined = null; } if (array === void 0) { array = false; } var column = that.dom.data.children('option:selected').val(); var indexArray = that.s.dt.rows().indexes().toArray(); var settings = that.s.dt.settings()[0]; that.dom.valueTitle.prop('selected', true); // Declare select element to be used with all of the default classes and listeners. var el = $$2('<select/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.dropDown) .addClass(Criteria.classes.italic) .addClass(Criteria.classes.select) .append(that.dom.valueTitle) .on('change.dtsb', function () { $$2(this).removeClass(Criteria.classes.italic); fn(that, this); }); if (that.c.greyscale) { el.addClass(Criteria.classes.greyscale); } var added = []; var options = []; // Add all of the options from the table to the select element. // Only add one option for each possible value for (var _i = 0, indexArray_1 = indexArray; _i < indexArray_1.length; _i++) { var index = indexArray_1[_i]; var filter = settings.oApi._fnGetCellData(settings, index, column, typeof that.c.orthogonal === 'string' ? that.c.orthogonal : that.c.orthogonal.search); var value = { filter: typeof filter === 'string' ? filter.replace(/[\r\n\u2028]/g, ' ') : // Need to replace certain characters to match search values filter, index: index, text: settings.oApi._fnGetCellData(settings, index, column, typeof that.c.orthogonal === 'string' ? that.c.orthogonal : that.c.orthogonal.display) }; // If we are dealing with an array type, either make sure we are working with arrays, or sort them if (that.s.type === 'array') { value.filter = !Array.isArray(value.filter) ? [value.filter] : value.filter; value.text = !Array.isArray(value.text) ? [value.text] : value.text; } // Function to add an option to the select element var addOption = function (filt, text) { if (that.s.type.includes('html') && filt !== null && typeof filt === 'string') { filt.replace(/(<([^>]+)>)/ig, ''); } // Add text and value, stripping out any html if that is the column type var opt = $$2('<option>', { type: Array.isArray(filt) ? 'Array' : 'String', value: filt }) .data('sbv', filt) .addClass(that.classes.option) .addClass(that.classes.notItalic) // Have to add the text this way so that special html characters are not escaped - &amp; etc. .html(typeof text === 'string' ? text.replace(/(<([^>]+)>)/ig, '') : text); var val = opt.val(); // Check that this value has not already been added if (added.indexOf(val) === -1) { added.push(val); options.push(opt); if (preDefined !== null && Array.isArray(preDefined[0])) { preDefined[0] = preDefined[0].sort().join(','); } // If this value was previously selected as indicated by preDefined, then select it again if (preDefined !== null && opt.val() === preDefined[0]) { opt.prop('selected', true); el.removeClass(Criteria.classes.italic); that.dom.valueTitle.removeProp('selected'); } } }; // If this is to add the individual values within the array we need to loop over the array if (array) { for (var i = 0; i < value.filter.length; i++) { addOption(value.filter[i], value.text[i]); } } // Otherwise the value that is in the cell is to be added else { addOption(value.filter, Array.isArray(value.text) ? value.text.join(', ') : value.text); } } options.sort(function (a, b) { if (that.s.type === 'array' || that.s.type === 'string' || that.s.type === 'html') { if (a.val() < b.val()) { return -1; } else if (a.val() > b.val()) { return 1; } else { return 0; } } else if (that.s.type === 'num' || that.s.type === 'html-num') { if (+a.val().replace(/(<([^>]+)>)/ig, '') < +b.val().replace(/(<([^>]+)>)/ig, '')) { return -1; } else if (+a.val().replace(/(<([^>]+)>)/ig, '') > +b.val().replace(/(<([^>]+)>)/ig, '')) { return 1; } else { return 0; } } else if (that.s.type === 'num-fmt' || that.s.type === 'html-num-fmt') { if (+a.val().replace(/[^0-9.]/g, '') < +b.val().replace(/[^0-9.]/g, '')) { return -1; } else if (+a.val().replace(/[^0-9.]/g, '') > +b.val().replace(/[^0-9.]/g, '')) { return 1; } else { return 0; } } }); for (var _a = 0, options_1 = options; _a < options_1.length; _a++) { var opt = options_1[_a]; el.append(opt); } return el; }; /** * Default initialisation function for select conditions */ Criteria.initSelectSSP = function (that, fn, preDefined) { if (preDefined === void 0) { preDefined = null; } that.dom.valueTitle.prop('selected', true); // Declare select element to be used with all of the default classes and listeners. var el = $$2('<select/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.dropDown) .addClass(Criteria.classes.italic) .addClass(Criteria.classes.select) .append(that.dom.valueTitle) .on('change.dtsb', function () { $$2(this).removeClass(Criteria.classes.italic); fn(that, this); }); if (that.c.greyscale) { el.addClass(Criteria.classes.greyscale); } var options = []; for (var _i = 0, _a = that.s.serverData[that.s.origData]; _i < _a.length; _i++) { var option = _a[_i]; var value = option.value; var label = option.label; // Function to add an option to the select element var addOption = function (filt, text) { if (that.s.type.includes('html') && filt !== null && typeof filt === 'string') { filt.replace(/(<([^>]+)>)/ig, ''); } // Add text and value, stripping out any html if that is the column type var opt = $$2('<option>', { type: Array.isArray(filt) ? 'Array' : 'String', value: filt }) .data('sbv', filt) .addClass(that.classes.option) .addClass(that.classes.notItalic) // Have to add the text this way so that special html characters are not escaped - &amp; etc. .html(typeof text === 'string' ? text.replace(/(<([^>]+)>)/ig, '') : text); options.push(opt); // If this value was previously selected as indicated by preDefined, then select it again if (preDefined !== null && opt.val() === preDefined[0]) { opt.prop('selected', true); el.removeClass(Criteria.classes.italic); that.dom.valueTitle.removeProp('selected'); } }; addOption(value, label); } for (var _b = 0, options_2 = options; _b < options_2.length; _b++) { var opt = options_2[_b]; el.append(opt); } return el; }; /** * Default initialisation function for select array conditions * * This exists because there needs to be different select functionality for contains/without and equals/not */ Criteria.initSelectArray = function (that, fn, preDefined) { if (preDefined === void 0) { preDefined = null; } return Criteria.initSelect(that, fn, preDefined, true); }; /** * Default initialisation function for input conditions */ Criteria.initInput = function (that, fn, preDefined) { if (preDefined === void 0) { preDefined = null; } // Declare the input element var searchDelay = that.s.dt.settings()[0].searchDelay; var el = $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .on('input.dtsb keypress.dtsb', that._throttle(function (e) { var code = e.keyCode || e.which; return fn(that, this, code); }, searchDelay === null ? 100 : searchDelay)); if (that.c.greyscale) { el.addClass(Criteria.classes.greyscale); } // If there is a preDefined value then add it if (preDefined !== null) { el.val(preDefined[0]); } // This is add responsive functionality to the logic button without redrawing everything else that.s.dt.one('draw.dtsb', function () { that.s.topGroup.trigger('dtsb-redrawLogic'); }); return el; }; /** * Default initialisation function for conditions requiring 2 inputs */ Criteria.init2Input = function (that, fn, preDefined) { if (preDefined === void 0) { preDefined = null; } // Declare all of the necessary jQuery elements var searchDelay = that.s.dt.settings()[0].searchDelay; var els = [ $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .on('input.dtsb keypress.dtsb', that._throttle(function (e) { var code = e.keyCode || e.which; return fn(that, this, code); }, searchDelay === null ? 100 : searchDelay)), $$2('<span>') .addClass(that.classes.joiner) .html(that.s.dt.i18n('searchBuilder.valueJoiner', that.c.i18n.valueJoiner)), $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .on('input.dtsb keypress.dtsb', that._throttle(function (e) { var code = e.keyCode || e.which; return fn(that, this, code); }, searchDelay === null ? 100 : searchDelay)) ]; if (that.c.greyscale) { els[0].addClass(Criteria.classes.greyscale); els[2].addClass(Criteria.classes.greyscale); } // If there is a preDefined value then add it if (preDefined !== null) { els[0].val(preDefined[0]); els[2].val(preDefined[1]); } // This is add responsive functionality to the logic button without redrawing everything else that.s.dt.one('draw.dtsb', function () { that.s.topGroup.trigger('dtsb-redrawLogic'); }); return els; }; /** * Default initialisation function for date conditions */ Criteria.initDate = function (that, fn, preDefined) { if (preDefined === void 0) { preDefined = null; } var searchDelay = that.s.dt.settings()[0].searchDelay; // Declare date element using DataTables dateTime plugin var el = $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .dtDateTime({ attachTo: 'input', format: that.s.dateFormat ? that.s.dateFormat : undefined }) .on('change.dtsb', that._throttle(function () { return fn(that, this); }, searchDelay === null ? 100 : searchDelay)) .on('input.dtsb keypress.dtsb', function (e) { that._throttle(function () { var code = e.keyCode || e.which; return fn(that, this, code); }, searchDelay === null ? 100 : searchDelay); }); if (that.c.greyscale) { el.addClass(Criteria.classes.greyscale); } // If there is a preDefined value then add it if (preDefined !== null) { el.val(preDefined[0]); } // This is add responsive functionality to the logic button without redrawing everything else that.s.dt.one('draw.dtsb', function () { that.s.topGroup.trigger('dtsb-redrawLogic'); }); return el; }; Criteria.initNoValue = function (that) { // This is add responsive functionality to the logic button without redrawing everything else that.s.dt.one('draw.dtsb', function () { that.s.topGroup.trigger('dtsb-redrawLogic'); }); }; Criteria.init2Date = function (that, fn, preDefined) { var _this = this; if (preDefined === void 0) { preDefined = null; } var searchDelay = that.s.dt.settings()[0].searchDelay; // Declare all of the date elements that are required using DataTables dateTime plugin var els = [ $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .dtDateTime({ attachTo: 'input', format: that.s.dateFormat ? that.s.dateFormat : undefined }) .on('change.dtsb', searchDelay !== null ? that.s.dt.settings()[0].oApi._fnThrottle(function () { return fn(that, this); }, searchDelay) : function () { fn(that, _this); }) .on('input.dtsb keypress.dtsb', function (e) { that.s.dt.settings()[0].oApi._fnThrottle(function () { var code = e.keyCode || e.which; return fn(that, this, code); }, searchDelay === null ? 0 : searchDelay); }), $$2('<span>') .addClass(that.classes.joiner) .html(that.s.dt.i18n('searchBuilder.valueJoiner', that.c.i18n.valueJoiner)), $$2('<input/>') .addClass(Criteria.classes.value) .addClass(Criteria.classes.input) .dtDateTime({ attachTo: 'input', format: that.s.dateFormat ? that.s.dateFormat : undefined }) .on('change.dtsb', searchDelay !== null ? that.s.dt.settings()[0].oApi._fnThrottle(function () { return fn(that, this); }, searchDelay) : function () { fn(that, _this); }) .on('input.dtsb keypress.dtsb', !that.c.enterSearch && !(that.s.dt.settings()[0].oInit.search !== undefined && that.s.dt.settings()[0].oInit.search["return"]) && searchDelay !== null ? that.s.dt.settings()[0].oApi._fnThrottle(function () { return fn(that, this); }, searchDelay) : function (e) { var code = e.keyCode || e.which; fn(that, _this, code); }) ]; if (that.c.greyscale) { els[0].addClass(Criteria.classes.greyscale); els[2].addClass(Criteria.classes.greyscale); } // If there are and preDefined values then add them if (preDefined !== null && preDefined.length > 0) { els[0].val(preDefined[0]); els[2].val(preDefined[1]); } // This is add responsive functionality to the logic button without redrawing everything else that.s.dt.one('draw.dtsb', function () { that.s.topGroup.trigger('dtsb-redrawLogic'); }); return els; }; /** * Default function for select elements to validate condition */ Criteria.isInputValidSelect = function (el) { var allFilled = true; // Check each element to make sure that the selections are valid for (var _i = 0, el_1 = el; _i < el_1.length; _i++) { var element = el_1[_i]; if (element.children('option:selected').length === element.children('option').length - element.children('option.' + Criteria.classes.notItalic).length && element.children('option:selected').length === 1 && element.children('option:selected')[0] === element.children('option')[0]) { allFilled = false; } } return allFilled; }; /** * Default function for input and date elements to validate condition */ Criteria.isInputValidInput = function (el) { var allFilled = true; // Check each element to make sure that the inputs are valid for (var _i = 0, el_2 = el; _i < el_2.length; _i++) { var element = el_2[_i]; if (element.is('input') && element.val().length === 0) { allFilled = false; } } return allFilled; }; /** * Default function for getting select conditions */ Criteria.inputValueSelect = function (el) { var values = []; // Go through the select elements and push each selected option to the return array for (var _i = 0, el_3 = el; _i < el_3.length; _i++) { var element = el_3[_i]; if (element.is('select')) { values.push(Criteria._escapeHTML(element.children('option:selected').data('sbv'))); } } return values; }; /** * Default function for getting input conditions */ Criteria.inputValueInput = function (el) { var values = []; // Go through the input elements and push each value to the return array for (var _i = 0, el_4 = el; _i < el_4.length; _i++) { var element = el_4[_i]; if (element.is('input')) { values.push(Criteria._escapeHTML(element.val())); } } return values; }; /** * Function that is run on each element as a call back when a search should be triggered */ Criteria.updateListener = function (that, el, code) { // When the value is changed the criteria is now complete so can be included in searches // Get the condition from the map based on the key that has been selected for the condition var condition = that.s.conditions[that.s.condition]; that.s.filled = condition.isInputValid(that.dom.value, that); that.s.value = condition.inputValue(that.dom.value, that); if (!that.s.filled) { if (!that.c.enterSearch && !(that.s.dt.settings()[0].oInit.search !== undefined && that.s.dt.settings()[0].oInit.search["return"]) || code === 13) { that.s.dt.draw(); } return; } if (!Array.isArray(that.s.value)) { that.s.value = [that.s.value]; } for (var i = 0; i < that.s.value.length; i++) { // If the value is an array we need to sort it if (Array.isArray(that.s.value[i])) { that.s.value[i].sort(); } // Otherwise replace the decimal place character for i18n else if (that.s.type.includes('num') && (that.s.dt.settings()[0].oLanguage.sDecimal !== '' || that.s.dt.settings()[0].oLanguage.sThousands !== '')) { var splitRD = [that.s.value[i].toString()]; if (that.s.dt.settings()[0].oLanguage.sDecimal !== '') { splitRD = that.s.value[i].split(that.s.dt.settings()[0].oLanguage.sDecimal); } if (that.s.dt.settings()[0].oLanguage.sThousands !== '') { for (var j = 0; j < splitRD.length; j++) { splitRD[j] = splitRD[j].replace(that.s.dt.settings()[0].oLanguage.sThousands, ','); } } that.s.value[i] = splitRD.join('.'); } } // Take note of the cursor position so that we can refocus there later var idx = null; var cursorPos = null; for (var i = 0; i < that.dom.value.length; i++) { if (el === that.dom.value[i][0]) { idx = i; if (el.selectionStart !== undefined) { cursorPos = el.selectionStart; } } } if (!that.c.enterSearch && !(that.s.dt.settings()[0].oInit.search !== undefined && that.s.dt.settings()[0].oInit.search["return"]) || code === 13) { // Trigger a search that.s.dt.draw(); } // Refocus the element and set the correct cursor position if (idx !== null) { that.dom.value[idx].removeClass(that.classes.italic); that.dom.value[idx].focus(); if (cursorPos !== null) { that.dom.value[idx][0].setSelectionRange(cursorPos, cursorPos); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.dateConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); return value === comparison[0]; } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); return value !== comparison[0]; } }, '<': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); return value < comparison[0]; } }, '>': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); return value > comparison[0]; } }, 'between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); if (comparison[0] < comparison[1]) { return comparison[0] <= value && value <= comparison[1]; } else { return comparison[1] <= value && value <= comparison[0]; } } }, // eslint-disable-next-line sort-keys '!between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { value = value.replace(/(\/|-|,)/g, '-'); if (comparison[0] < comparison[1]) { return !(comparison[0] <= value && value <= comparison[1]); } else { return !(comparison[1] <= value && value <= comparison[0]); } } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.momentDateConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return moment()(value, that.s.dateFormat).valueOf() === moment()(comparison[0], that.s.dateFormat).valueOf(); } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return moment()(value, that.s.dateFormat).valueOf() !== moment()(comparison[0], that.s.dateFormat).valueOf(); } }, '<': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return moment()(value, that.s.dateFormat).valueOf() < moment()(comparison[0], that.s.dateFormat).valueOf(); } }, '>': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return moment()(value, that.s.dateFormat).valueOf() > moment()(comparison[0], that.s.dateFormat).valueOf(); } }, 'between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { var val = moment()(value, that.s.dateFormat).valueOf(); var comp0 = moment()(comparison[0], that.s.dateFormat).valueOf(); var comp1 = moment()(comparison[1], that.s.dateFormat).valueOf(); if (comp0 < comp1) { return comp0 <= val && val <= comp1; } else { return comp1 <= val && val <= comp0; } } }, // eslint-disable-next-line sort-keys '!between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { var val = moment()(value, that.s.dateFormat).valueOf(); var comp0 = moment()(comparison[0], that.s.dateFormat).valueOf(); var comp1 = moment()(comparison[1], that.s.dateFormat).valueOf(); if (comp0 < comp1) { return !(+comp0 <= +val && +val <= +comp1); } else { return !(+comp1 <= +val && +val <= +comp0); } } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.luxonDateConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.equals', i18n.conditions.date.equals); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts === luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.not', i18n.conditions.date.not); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts !== luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; } }, '<': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.before', i18n.conditions.date.before); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts < luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; } }, '>': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.after', i18n.conditions.date.after); }, init: Criteria.initDate, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { return luxon().DateTime.fromFormat(value, that.s.dateFormat).ts > luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; } }, 'between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.between', i18n.conditions.date.between); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { var val = luxon().DateTime.fromFormat(value, that.s.dateFormat).ts; var comp0 = luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; var comp1 = luxon().DateTime.fromFormat(comparison[1], that.s.dateFormat).ts; if (comp0 < comp1) { return comp0 <= val && val <= comp1; } else { return comp1 <= val && val <= comp0; } } }, // eslint-disable-next-line sort-keys '!between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notBetween', i18n.conditions.date.notBetween); }, init: Criteria.init2Date, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison, that) { var val = luxon().DateTime.fromFormat(value, that.s.dateFormat).ts; var comp0 = luxon().DateTime.fromFormat(comparison[0], that.s.dateFormat).ts; var comp1 = luxon().DateTime.fromFormat(comparison[1], that.s.dateFormat).ts; if (comp0 < comp1) { return !(+comp0 <= +val && +val <= +comp1); } else { return !(+comp1 <= +val && +val <= +comp0); } } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.empty', i18n.conditions.date.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.date.notEmpty', i18n.conditions.date.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.numConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.equals', i18n.conditions.number.equals); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return +value === +comparison[0]; } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.not', i18n.conditions.number.not); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return +value !== +comparison[0]; } }, '<': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.lt', i18n.conditions.number.lt); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return +value < +comparison[0]; } }, '<=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.lte', i18n.conditions.number.lte); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return +value <= +comparison[0]; } }, '>=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.gte', i18n.conditions.number.gte); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return +value >= +comparison[0]; } }, // eslint-disable-next-line sort-keys '>': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.gt', i18n.conditions.number.gt); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return +value > +comparison[0]; } }, 'between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.between', i18n.conditions.number.between); }, init: Criteria.init2Input, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { if (+comparison[0] < +comparison[1]) { return +comparison[0] <= +value && +value <= +comparison[1]; } else { return +comparison[1] <= +value && +value <= +comparison[0]; } } }, // eslint-disable-next-line sort-keys '!between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.notBetween', i18n.conditions.number.notBetween); }, init: Criteria.init2Input, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { if (+comparison[0] < +comparison[1]) { return !(+comparison[0] <= +value && +value <= +comparison[1]); } else { return !(+comparison[1] <= +value && +value <= +comparison[0]); } } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.empty', i18n.conditions.number.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.notEmpty', i18n.conditions.number.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.numFmtConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.equals', i18n.conditions.number.equals); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return Criteria.parseNumFmt(value) === Criteria.parseNumFmt(comparison[0]); } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.not', i18n.conditions.number.not); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return Criteria.parseNumFmt(value) !== Criteria.parseNumFmt(comparison[0]); } }, '<': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.lt', i18n.conditions.number.lt); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return Criteria.parseNumFmt(value) < Criteria.parseNumFmt(comparison[0]); } }, '<=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.lte', i18n.conditions.number.lte); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return Criteria.parseNumFmt(value) <= Criteria.parseNumFmt(comparison[0]); } }, '>=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.gte', i18n.conditions.number.gte); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return Criteria.parseNumFmt(value) >= Criteria.parseNumFmt(comparison[0]); } }, // eslint-disable-next-line sort-keys '>': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.gt', i18n.conditions.number.gt); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return Criteria.parseNumFmt(value) > Criteria.parseNumFmt(comparison[0]); } }, 'between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.between', i18n.conditions.number.between); }, init: Criteria.init2Input, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { var val = Criteria.parseNumFmt(value); var comp0 = Criteria.parseNumFmt(comparison[0]); var comp1 = Criteria.parseNumFmt(comparison[1]); if (+comp0 < +comp1) { return +comp0 <= +val && +val <= +comp1; } else { return +comp1 <= +val && +val <= +comp0; } } }, // eslint-disable-next-line sort-keys '!between': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.notBetween', i18n.conditions.number.notBetween); }, init: Criteria.init2Input, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { var val = Criteria.parseNumFmt(value); var comp0 = Criteria.parseNumFmt(comparison[0]); var comp1 = Criteria.parseNumFmt(comparison[1]); if (+comp0 < +comp1) { return !(+comp0 <= +val && +val <= +comp1); } else { return !(+comp1 <= +val && +val <= +comp0); } } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.empty', i18n.conditions.number.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.number.notEmpty', i18n.conditions.number.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Has to be in this order so that they are displayed correctly in select elements // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.stringConditions = { '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.equals', i18n.conditions.string.equals); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return value === comparison[0]; } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.not', i18n.conditions.string.not); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return value !== comparison[0]; } }, 'starts': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.startsWith', i18n.conditions.string.startsWith); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return value.toLowerCase().indexOf(comparison[0].toLowerCase()) === 0; } }, // eslint-disable-next-line sort-keys '!starts': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.notStartsWith', i18n.conditions.string.notStartsWith); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return value.toLowerCase().indexOf(comparison[0].toLowerCase()) !== 0; } }, // eslint-disable-next-line sort-keys 'contains': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.contains', i18n.conditions.string.contains); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return value.toLowerCase().includes(comparison[0].toLowerCase()); } }, // eslint-disable-next-line sort-keys '!contains': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.notContains', i18n.conditions.string.notContains); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return !value.toLowerCase().includes(comparison[0].toLowerCase()); } }, 'ends': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.endsWith', i18n.conditions.string.endsWith); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return value.toLowerCase().endsWith(comparison[0].toLowerCase()); } }, // eslint-disable-next-line sort-keys '!ends': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.notEndsWith', i18n.conditions.string.notEndsWith); }, init: Criteria.initInput, inputValue: Criteria.inputValueInput, isInputValid: Criteria.isInputValidInput, search: function (value, comparison) { return !value.toLowerCase().endsWith(comparison[0].toLowerCase()); } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.empty', i18n.conditions.string.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.string.notEmpty', i18n.conditions.string.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return !(value === null || value === undefined || value.length === 0); } } }; // The order of the conditions will make eslint sad :( // Also have to disable member ordering for this as the private methods used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.arrayConditions = { 'contains': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.contains', i18n.conditions.array.contains); }, init: Criteria.initSelectArray, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return value.includes(comparison[0]); } }, 'without': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.without', i18n.conditions.array.without); }, init: Criteria.initSelectArray, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { return value.indexOf(comparison[0]) === -1; } }, // eslint-disable-next-line sort-keys '=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.equals', i18n.conditions.array.equals); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { if (value.length === comparison[0].length) { for (var i = 0; i < value.length; i++) { if (value[i] !== comparison[0][i]) { return false; } } return true; } return false; } }, // eslint-disable-next-line sort-keys '!=': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.not', i18n.conditions.array.not); }, init: Criteria.initSelect, inputValue: Criteria.inputValueSelect, isInputValid: Criteria.isInputValidSelect, search: function (value, comparison) { if (value.length === comparison[0].length) { for (var i = 0; i < value.length; i++) { if (value[i] !== comparison[0][i]) { return true; } } return false; } return true; } }, 'null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.empty', i18n.conditions.array.empty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value === null || value === undefined || value.length === 0; } }, // eslint-disable-next-line sort-keys '!null': { conditionName: function (dt, i18n) { return dt.i18n('searchBuilder.conditions.array.notEmpty', i18n.conditions.array.notEmpty); }, init: Criteria.initNoValue, inputValue: function () { return; }, isInputValid: function () { return true; }, search: function (value) { return value !== null && value !== undefined && value.length !== 0; } } }; // eslint will be sad because we have to disable member ordering for this as the // private static properties used are not yet declared otherwise // eslint-disable-next-line @typescript-eslint/member-ordering Criteria.defaults = { columns: true, conditions: { 'array': Criteria.arrayConditions, 'date': Criteria.dateConditions, 'html': Criteria.stringConditions, 'html-num': Criteria.numConditions, 'html-num-fmt': Criteria.numFmtConditions, 'luxon': Criteria.luxonDateConditions, 'moment': Criteria.momentDateConditions, 'num': Criteria.numConditions, 'num-fmt': Criteria.numFmtConditions, 'string': Criteria.stringConditions }, depthLimit: false, enterSearch: false, filterChanged: undefined, greyscale: false, i18n: { add: 'Add Condition', button: { 0: 'Search Builder', _: 'Search Builder (%d)' }, clearAll: 'Clear All', condition: 'Condition', data: 'Data', "delete": '&times', deleteTitle: 'Delete filtering rule', left: '<', leftTitle: 'Outdent criteria', logicAnd: 'And', logicOr: 'Or', right: '>', rightTitle: 'Indent criteria', title: { 0: 'Custom Search Builder', _: 'Custom Search Builder (%d)' }, value: 'Value', valueJoiner: 'and' }, logic: 'AND', orthogonal: { display: 'display', search: 'filter' }, preDefined: false }; return Criteria; }()); var $$1; var dataTable$1; /** * Sets the value of jQuery for use in the file * * @param jq the instance of jQuery to be set */ function setJQuery$1(jq) { $$1 = jq; dataTable$1 = jq.fn.dataTable; } /** * The Group class is used within SearchBuilder to represent a group of criteria */ var Group = /** @class */ (function () { function Group(table, opts, topGroup, index, isChild, depth, serverData) { if (index === void 0) { index = 0; } if (isChild === void 0) { isChild = false; } if (depth === void 0) { depth = 1; } if (serverData === void 0) { serverData = undefined; } // Check that the required version of DataTables is included if (!dataTable$1 || !dataTable$1.versionCheck || !dataTable$1.versionCheck('1.10.0')) { throw new Error('SearchBuilder requires DataTables 1.10 or newer'); } this.classes = $$1.extend(true, {}, Group.classes); // Get options from user this.c = $$1.extend(true, {}, Group.defaults, opts); this.s = { criteria: [], depth: depth, dt: table, index: index, isChild: isChild, logic: undefined, opts: opts, preventRedraw: false, serverData: serverData, toDrop: undefined, topGroup: topGroup }; this.dom = { add: $$1('<button/>') .addClass(this.classes.add) .addClass(this.classes.button) .attr('type', 'button'), clear: $$1('<button>&times</button>') .addClass(this.classes.button) .addClass(this.classes.clearGroup) .attr('type', 'button'), container: $$1('<div/>') .addClass(this.classes.group), logic: $$1('<button><div/></button>') .addClass(this.classes.logic) .addClass(this.classes.button) .attr('type', 'button'), logicContainer: $$1('<div/>') .addClass(this.classes.logicContainer) }; // A reference to the top level group is maintained throughout any subgroups and criteria that may be created if (this.s.topGroup === undefined) { this.s.topGroup = this.dom.container; } this._setup(); return this; } /** * Destroys the groups buttons, clears the internal criteria and removes it from the dom */ Group.prototype.destroy = function () { // Turn off listeners this.dom.add.off('.dtsb'); this.dom.logic.off('.dtsb'); // Trigger event for groups at a higher level to pick up on this.dom.container .trigger('dtsb-destroy') .remove(); this.s.criteria = []; }; /** * Gets the details required to rebuild the group */ // Eslint upset at empty object but needs to be done // eslint-disable-next-line @typescript-eslint/ban-types Group.prototype.getDetails = function (deFormatDates) { if (deFormatDates === void 0) { deFormatDates = false; } if (this.s.criteria.length === 0) { return {}; } var details = { criteria: [], logic: this.s.logic }; // NOTE here crit could be either a subgroup or a criteria for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; details.criteria.push(crit.criteria.getDetails(deFormatDates)); } return details; }; /** * Getter for the node for the container of the group * * @returns Node for the container of the group */ Group.prototype.getNode = function () { return this.dom.container; }; /** * Rebuilds the group based upon the details passed in * * @param loadedDetails the details required to rebuild the group */ Group.prototype.rebuild = function (loadedDetails) { // If no criteria are stored then just return if (loadedDetails.criteria === undefined || loadedDetails.criteria === null || Array.isArray(loadedDetails.criteria) && loadedDetails.criteria.length === 0) { return; } this.s.logic = loadedDetails.logic; this.dom.logic.children().first().html(this.s.logic === 'OR' ? this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr) : this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd)); // Add all of the criteria, be it a sub group or a criteria if (Array.isArray(loadedDetails.criteria)) { for (var _i = 0, _a = loadedDetails.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.logic !== undefined) { this._addPrevGroup(crit); } else if (crit.logic === undefined) { this._addPrevCriteria(crit); } } } // For all of the criteria children, update the arrows incase they require changing and set the listeners for (var _b = 0, _c = this.s.criteria; _b < _c.length; _b++) { var crit = _c[_b]; if (crit.criteria instanceof Criteria) { crit.criteria.updateArrows(this.s.criteria.length > 1); this._setCriteriaListeners(crit.criteria); } } }; /** * Redraws the Contents of the searchBuilder Groups and Criteria */ Group.prototype.redrawContents = function () { if (this.s.preventRedraw) { return; } // Clear the container out and add the basic elements this.dom.container.children().detach(); this.dom.container .append(this.dom.logicContainer) .append(this.dom.add); // Sort the criteria by index so that they appear in the correct order this.s.criteria.sort(function (a, b) { if (a.criteria.s.index < b.criteria.s.index) { return -1; } else if (a.criteria.s.index > b.criteria.s.index) { return 1; } return 0; }); this.setListeners(); for (var i = 0; i < this.s.criteria.length; i++) { var crit = this.s.criteria[i].criteria; if (crit instanceof Criteria) { // Reset the index to the new value this.s.criteria[i].index = i; this.s.criteria[i].criteria.s.index = i; // Add to the group this.s.criteria[i].criteria.dom.container.insertBefore(this.dom.add); // Set listeners for various points this._setCriteriaListeners(crit); this.s.criteria[i].criteria.s.preventRedraw = this.s.preventRedraw; this.s.criteria[i].criteria.rebuild(this.s.criteria[i].criteria.getDetails()); this.s.criteria[i].criteria.s.preventRedraw = false; } else if (crit instanceof Group && crit.s.criteria.length > 0) { // Reset the index to the new value this.s.criteria[i].index = i; this.s.criteria[i].criteria.s.index = i; // Add the sub group to the group this.s.criteria[i].criteria.dom.container.insertBefore(this.dom.add); // Redraw the contents of the group crit.s.preventRedraw = this.s.preventRedraw; crit.redrawContents(); crit.s.preventRedraw = false; this._setGroupListeners(crit); } else { // The group is empty so remove it this.s.criteria.splice(i, 1); i--; } } this.setupLogic(); }; /** * Resizes the logic button only rather than the entire dom. */ Group.prototype.redrawLogic = function () { for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Group) { crit.criteria.redrawLogic(); } } this.setupLogic(); }; /** * Search method, checking the row data against the criteria in the group * * @param rowData The row data to be compared * @returns boolean The result of the search */ Group.prototype.search = function (rowData, rowIdx) { if (this.s.logic === 'AND') { return this._andSearch(rowData, rowIdx); } else if (this.s.logic === 'OR') { return this._orSearch(rowData, rowIdx); } return true; }; /** * Locates the groups logic button to the correct location on the page */ Group.prototype.setupLogic = function () { // Remove logic button this.dom.logicContainer.remove(); this.dom.clear.remove(); // If there are no criteria in the group then keep the logic removed and return if (this.s.criteria.length < 1) { if (!this.s.isChild) { this.dom.container.trigger('dtsb-destroy'); // Set criteria left margin this.dom.container.css('margin-left', 0); } return; } this.dom.clear.height('0px'); this.dom.logicContainer.append(this.dom.clear); // Prepend logic button this.dom.container.prepend(this.dom.logicContainer); for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Criteria) { crit.criteria.setupButtons(); } } // Set width, take 2 for the border var height = this.dom.container.outerHeight() - 1; this.dom.logicContainer.width(height); this._setLogicListener(); // Set criteria left margin this.dom.container.css('margin-left', this.dom.logicContainer.outerHeight(true)); var logicOffset = this.dom.logicContainer.offset(); // Set horizontal alignment var currentLeft = logicOffset.left; var groupLeft = this.dom.container.offset().left; var shuffleLeft = currentLeft - groupLeft; var newPos = currentLeft - shuffleLeft - this.dom.logicContainer.outerHeight(true); this.dom.logicContainer.offset({ left: newPos }); // Set vertical alignment var firstCrit = this.dom.logicContainer.next(); var currentTop = logicOffset.top; var firstTop = $$1(firstCrit).offset().top; var shuffleTop = currentTop - firstTop; var newTop = currentTop - shuffleTop; this.dom.logicContainer.offset({ top: newTop }); this.dom.clear.outerHeight(this.dom.logicContainer.height()); this._setClearListener(); }; /** * Sets listeners on the groups elements */ Group.prototype.setListeners = function () { var _this = this; this.dom.add.unbind('click'); this.dom.add.on('click.dtsb', function () { // If this is the parent group then the logic button has not been added yet if (!_this.s.isChild) { _this.dom.container.prepend(_this.dom.logicContainer); } _this.addCriteria(); _this.dom.container.trigger('dtsb-add'); _this.s.dt.state.save(); return false; }); for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; crit.criteria.setListeners(); } this._setClearListener(); this._setLogicListener(); }; /** * Adds a criteria to the group * * @param crit Instance of Criteria to be added to the group */ Group.prototype.addCriteria = function (crit) { if (crit === void 0) { crit = null; } var index = crit === null ? this.s.criteria.length : crit.s.index; var criteria = new Criteria(this.s.dt, this.s.opts, this.s.topGroup, index, this.s.depth, this.s.serverData); // If a Criteria has been passed in then set the values to continue that if (crit !== null) { criteria.c = crit.c; criteria.s = crit.s; criteria.s.depth = this.s.depth; criteria.classes = crit.classes; } criteria.populate(); var inserted = false; for (var i = 0; i < this.s.criteria.length; i++) { if (i === 0 && this.s.criteria[i].criteria.s.index > criteria.s.index) { // Add the node for the criteria at the start of the group criteria.getNode().insertBefore(this.s.criteria[i].criteria.dom.container); inserted = true; } else if (i < this.s.criteria.length - 1 && this.s.criteria[i].criteria.s.index < criteria.s.index && this.s.criteria[i + 1].criteria.s.index > criteria.s.index) { // Add the node for the criteria in the correct location criteria.getNode().insertAfter(this.s.criteria[i].criteria.dom.container); inserted = true; } } if (!inserted) { criteria.getNode().insertBefore(this.dom.add); } // Add the details for this criteria to the array this.s.criteria.push({ criteria: criteria, index: index }); this.s.criteria = this.s.criteria.sort(function (a, b) { return a.criteria.s.index - b.criteria.s.index; }); for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var opt = _a[_i]; if (opt.criteria instanceof Criteria) { opt.criteria.updateArrows(this.s.criteria.length > 1); } } this._setCriteriaListeners(criteria); criteria.setListeners(); this.setupLogic(); }; /** * Checks the group to see if it has any filled criteria */ Group.prototype.checkFilled = function () { for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Criteria && crit.criteria.s.filled || crit.criteria instanceof Group && crit.criteria.checkFilled()) { return true; } } return false; }; /** * Gets the count for the number of criteria in this group and any sub groups */ Group.prototype.count = function () { var count = 0; for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Group) { count += crit.criteria.count(); } else { count++; } } return count; }; /** * Rebuilds a sub group that previously existed * * @param loadedGroup The details of a group within this group */ Group.prototype._addPrevGroup = function (loadedGroup) { var idx = this.s.criteria.length; var group = new Group(this.s.dt, this.c, this.s.topGroup, idx, true, this.s.depth + 1, this.s.serverData); // Add the new group to the criteria array this.s.criteria.push({ criteria: group, index: idx, logic: group.s.logic }); // Rebuild it with the previous conditions for that group group.rebuild(loadedGroup); this.s.criteria[idx].criteria = group; this.s.topGroup.trigger('dtsb-redrawContents'); this._setGroupListeners(group); }; /** * Rebuilds a criteria of this group that previously existed * * @param loadedCriteria The details of a criteria within the group */ Group.prototype._addPrevCriteria = function (loadedCriteria) { var idx = this.s.criteria.length; var criteria = new Criteria(this.s.dt, this.s.opts, this.s.topGroup, idx, this.s.depth, this.s.serverData); criteria.populate(); // Add the new criteria to the criteria array this.s.criteria.push({ criteria: criteria, index: idx }); // Rebuild it with the previous conditions for that criteria criteria.s.preventRedraw = this.s.preventRedraw; criteria.rebuild(loadedCriteria); criteria.s.preventRedraw = false; this.s.criteria[idx].criteria = criteria; if (!this.s.preventRedraw) { this.s.topGroup.trigger('dtsb-redrawContents'); } }; /** * Checks And the criteria using AND logic * * @param rowData The row data to be checked against the search criteria * @returns boolean The result of the AND search */ Group.prototype._andSearch = function (rowData, rowIdx) { // If there are no criteria then return true for this group if (this.s.criteria.length === 0) { return true; } for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; // If the criteria is not complete then skip it if (crit.criteria instanceof Criteria && !crit.criteria.s.filled) { continue; } // Otherwise if a single one fails return false else if (!crit.criteria.search(rowData, rowIdx)) { return false; } } // If we get to here then everything has passed, so return true for the group return true; }; /** * Checks And the criteria using OR logic * * @param rowData The row data to be checked against the search criteria * @returns boolean The result of the OR search */ Group.prototype._orSearch = function (rowData, rowIdx) { // If there are no criteria in the group then return true if (this.s.criteria.length === 0) { return true; } // This will check to make sure that at least one criteria in the group is complete var filledfound = false; for (var _i = 0, _a = this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Criteria && crit.criteria.s.filled) { // A completed criteria has been found so set the flag filledfound = true; // If the search passes then return true if (crit.criteria.search(rowData, rowIdx)) { return true; } } else if (crit.criteria instanceof Group && crit.criteria.checkFilled()) { filledfound = true; if (crit.criteria.search(rowData, rowIdx)) { return true; } } } // If we get here we need to return the inverse of filledfound, // as if any have been found and we are here then none have passed return !filledfound; }; /** * Removes a criteria from the group * * @param criteria The criteria instance to be removed */ Group.prototype._removeCriteria = function (criteria, group) { if (group === void 0) { group = false; } // If removing a criteria and there is only then then just destroy the group if (this.s.criteria.length <= 1 && this.s.isChild) { this.destroy(); } else { // Otherwise splice the given criteria out and redo the indexes var last = void 0; for (var i = 0; i < this.s.criteria.length; i++) { if (this.s.criteria[i].index === criteria.s.index && (!group || this.s.criteria[i].criteria instanceof Group)) { last = i; } } // We want to remove the last element with the desired index, as its replacement will be inserted before it if (last !== undefined) { this.s.criteria.splice(last, 1); } for (var i = 0; i < this.s.criteria.length; i++) { this.s.criteria[i].index = i; this.s.criteria[i].criteria.s.index = i; } } }; /** * Sets the listeners in group for a criteria * * @param criteria The criteria for the listeners to be set on */ Group.prototype._setCriteriaListeners = function (criteria) { var _this = this; criteria.dom["delete"] .unbind('click') .on('click.dtsb', function () { _this._removeCriteria(criteria); criteria.dom.container.remove(); for (var _i = 0, _a = _this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; if (crit.criteria instanceof Criteria) { crit.criteria.updateArrows(_this.s.criteria.length > 1); } } criteria.destroy(); _this.s.dt.draw(); _this.s.topGroup.trigger('dtsb-redrawContents'); return false; }); criteria.dom.right .unbind('click') .on('click.dtsb', function () { var idx = criteria.s.index; var group = new Group(_this.s.dt, _this.s.opts, _this.s.topGroup, criteria.s.index, true, _this.s.depth + 1, _this.s.serverData); // Add the criteria that is to be moved to the new group group.addCriteria(criteria); // Update the details in the current groups criteria array _this.s.criteria[idx].criteria = group; _this.s.criteria[idx].logic = 'AND'; _this.s.topGroup.trigger('dtsb-redrawContents'); _this._setGroupListeners(group); return false; }); criteria.dom.left .unbind('click') .on('click.dtsb', function () { _this.s.toDrop = new Criteria(_this.s.dt, _this.s.opts, _this.s.topGroup, criteria.s.index, undefined, _this.s.serverData); _this.s.toDrop.s = criteria.s; _this.s.toDrop.c = criteria.c; _this.s.toDrop.classes = criteria.classes; _this.s.toDrop.populate(); // The dropCriteria event mutates the reference to the index so need to store it var index = _this.s.toDrop.s.index; _this.dom.container.trigger('dtsb-dropCriteria'); criteria.s.index = index; _this._removeCriteria(criteria); // By tracking the top level group we can directly trigger a redraw on it, // bubbling is also possible, but that is slow with deep levelled groups _this.s.topGroup.trigger('dtsb-redrawContents'); _this.s.dt.draw(); return false; }); }; /** * Set's the listeners for the group clear button */ Group.prototype._setClearListener = function () { var _this = this; this.dom.clear .unbind('click') .on('click.dtsb', function () { if (!_this.s.isChild) { _this.dom.container.trigger('dtsb-clearContents'); return false; } _this.destroy(); _this.s.topGroup.trigger('dtsb-redrawContents'); return false; }); }; /** * Sets listeners for sub groups of this group * * @param group The sub group that the listeners are to be set on */ Group.prototype._setGroupListeners = function (group) { var _this = this; // Set listeners for the new group group.dom.add .unbind('click') .on('click.dtsb', function () { _this.setupLogic(); _this.dom.container.trigger('dtsb-add'); return false; }); group.dom.container .unbind('dtsb-add') .on('dtsb-add.dtsb', function () { _this.setupLogic(); _this.dom.container.trigger('dtsb-add'); return false; }); group.dom.container .unbind('dtsb-destroy') .on('dtsb-destroy.dtsb', function () { _this._removeCriteria(group, true); group.dom.container.remove(); _this.setupLogic(); return false; }); group.dom.container .unbind('dtsb-dropCriteria') .on('dtsb-dropCriteria.dtsb', function () { var toDrop = group.s.toDrop; toDrop.s.index = group.s.index; toDrop.updateArrows(_this.s.criteria.length > 1); _this.addCriteria(toDrop); return false; }); group.setListeners(); }; /** * Sets up the Group instance, setting listeners and appending elements */ Group.prototype._setup = function () { this.setListeners(); this.dom.add.html(this.s.dt.i18n('searchBuilder.add', this.c.i18n.add)); this.dom.logic.children().first().html(this.c.logic === 'OR' ? this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr) : this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd)); this.s.logic = this.c.logic === 'OR' ? 'OR' : 'AND'; if (this.c.greyscale) { this.dom.logic.addClass(this.classes.greyscale); } this.dom.logicContainer.append(this.dom.logic).append(this.dom.clear); // Only append the logic button immediately if this is a sub group, // otherwise it will be prepended later when adding a criteria if (this.s.isChild) { this.dom.container.append(this.dom.logicContainer); } this.dom.container.append(this.dom.add); }; /** * Sets the listener for the logic button */ Group.prototype._setLogicListener = function () { var _this = this; this.dom.logic .unbind('click') .on('click.dtsb', function () { _this._toggleLogic(); _this.s.dt.draw(); for (var _i = 0, _a = _this.s.criteria; _i < _a.length; _i++) { var crit = _a[_i]; crit.criteria.setListeners(); } }); }; /** * Toggles the logic for the group */ Group.prototype._toggleLogic = function () { if (this.s.logic === 'OR') { this.s.logic = 'AND'; this.dom.logic.children().first().html(this.s.dt.i18n('searchBuilder.logicAnd', this.c.i18n.logicAnd)); } else if (this.s.logic === 'AND') { this.s.logic = 'OR'; this.dom.logic.children().first().html(this.s.dt.i18n('searchBuilder.logicOr', this.c.i18n.logicOr)); } }; Group.version = '1.1.0'; Group.classes = { add: 'dtsb-add', button: 'dtsb-button', clearGroup: 'dtsb-clearGroup', greyscale: 'dtsb-greyscale', group: 'dtsb-group', inputButton: 'dtsb-iptbtn', logic: 'dtsb-logic', logicContainer: 'dtsb-logicContainer' }; Group.defaults = { columns: true, conditions: { 'date': Criteria.dateConditions, 'html': Criteria.stringConditions, 'html-num': Criteria.numConditions, 'html-num-fmt': Criteria.numFmtConditions, 'luxon': Criteria.luxonDateConditions, 'moment': Criteria.momentDateConditions, 'num': Criteria.numConditions, 'num-fmt': Criteria.numFmtConditions, 'string': Criteria.stringConditions }, depthLimit: false, enterSearch: false, filterChanged: undefined, greyscale: false, i18n: { add: 'Add Condition', button: { 0: 'Search Builder', _: 'Search Builder (%d)' }, clearAll: 'Clear All', condition: 'Condition', data: 'Data', "delete": '&times', deleteTitle: 'Delete filtering rule', left: '<', leftTitle: 'Outdent criteria', logicAnd: 'And', logicOr: 'Or', right: '>', rightTitle: 'Indent criteria', title: { 0: 'Custom Search Builder', _: 'Custom Search Builder (%d)' }, value: 'Value', valueJoiner: 'and' }, logic: 'AND', orthogonal: { display: 'display', search: 'filter' }, preDefined: false }; return Group; }()); var $; var dataTable; /** * Sets the value of jQuery for use in the file * * @param jq the instance of jQuery to be set */ function setJQuery(jq) { $ = jq; dataTable = jq.fn.DataTable; } /** * SearchBuilder class for DataTables. * Allows for complex search queries to be constructed and implemented on a DataTable */ var SearchBuilder = /** @class */ (function () { function SearchBuilder(builderSettings, opts) { var _this = this; // Check that the required version of DataTables is included if (!dataTable || !dataTable.versionCheck || !dataTable.versionCheck('1.10.0')) { throw new Error('SearchBuilder requires DataTables 1.10 or newer'); } var table = new dataTable.Api(builderSettings); this.classes = $.extend(true, {}, SearchBuilder.classes); // Get options from user this.c = $.extend(true, {}, SearchBuilder.defaults, opts); this.dom = { clearAll: $('<button type="button">' + table.i18n('searchBuilder.clearAll', this.c.i18n.clearAll) + '</button>') .addClass(this.classes.clearAll) .addClass(this.classes.button) .attr('type', 'button'), container: $('<div/>') .addClass(this.classes.container), title: $('<div/>') .addClass(this.classes.title), titleRow: $('<div/>') .addClass(this.classes.titleRow), topGroup: undefined }; this.s = { dt: table, opts: opts, search: undefined, serverData: undefined, topGroup: undefined }; // If searchbuilder is already defined for this table then return if (table.settings()[0]._searchBuilder !== undefined) { return; } table.settings()[0]._searchBuilder = this; // If using SSP we want to include the previous state in the very first server call if (this.s.dt.page.info().serverSide) { this.s.dt.on('preXhr.dtsb', function (e, settings, data) { var loadedState = _this.s.dt.state.loaded(); if (loadedState && loadedState.searchBuilder) { data.searchBuilder = _this._collapseArray(loadedState.searchBuilder); } }); this.s.dt.on('xhr.dtsb', function (e, settings, json) { if (json && json.searchBuilder && json.searchBuilder.options) { _this.s.serverData = json.searchBuilder.options; } }); } // Run the remaining setup when the table is initialised if (this.s.dt.settings()[0]._bInitComplete) { this._setUp(); } else { table.one('init.dt', function () { _this._setUp(); }); } return this; } /** * Gets the details required to rebuild the SearchBuilder as it currently is */ // eslint upset at empty object but that is what it is // eslint-disable-next-line @typescript-eslint/ban-types SearchBuilder.prototype.getDetails = function (deFormatDates) { if (deFormatDates === void 0) { deFormatDates = false; } return this.s.topGroup.getDetails(deFormatDates); }; /** * Getter for the node of the container for the searchBuilder * * @returns JQuery<HTMLElement> the node of the container */ SearchBuilder.prototype.getNode = function () { return this.dom.container; }; /** * Rebuilds the SearchBuilder to a state that is provided * * @param details The details required to perform a rebuild */ SearchBuilder.prototype.rebuild = function (details) { this.dom.clearAll.click(); // If there are no details to rebuild then return if (details === undefined || details === null) { return this; } this.s.topGroup.s.preventRedraw = true; this.s.topGroup.rebuild(details); this.s.topGroup.s.preventRedraw = false; this._checkClear(); this._updateTitle(this.s.topGroup.count()); this.s.topGroup.redrawContents(); this.s.dt.draw(false); this.s.topGroup.setListeners(); return this; }; /** * Applies the defaults to preDefined criteria * * @param preDef the array of criteria to be processed. */ SearchBuilder.prototype._applyPreDefDefaults = function (preDef) { var _this = this; if (preDef.criteria !== undefined && preDef.logic === undefined) { preDef.logic = 'AND'; } var _loop_1 = function (crit) { // Apply the defaults to any further criteria if (crit.criteria !== undefined) { crit = this_1._applyPreDefDefaults(crit); } else { this_1.s.dt.columns().every(function (index) { if (_this.s.dt.settings()[0].aoColumns[index].sTitle === crit.data) { crit.dataIdx = index; } }); } }; var this_1 = this; for (var _i = 0, _a = preDef.criteria; _i < _a.length; _i++) { var crit = _a[_i]; _loop_1(crit); } return preDef; }; /** * Set's up the SearchBuilder */ SearchBuilder.prototype._setUp = function (loadState) { var _this = this; if (loadState === void 0) { loadState = true; } // Register an Api method for getting the column type $.fn.DataTable.Api.registerPlural('columns().type()', 'column().type()', function () { return this.iterator('column', function (settings, column) { return settings.aoColumns[column].sType; }, 1); }); // Check that DateTime is included, If not need to check if it could be used // eslint-disable-next-line no-extra-parens if (!dataTable.DateTime) { var types = this.s.dt.columns().type().toArray(); if (types === undefined || types.includes(undefined) || types.includes(null)) { types = []; for (var _i = 0, _a = this.s.dt.settings()[0].aoColumns; _i < _a.length; _i++) { var colInit = _a[_i]; types.push(colInit.searchBuilderType !== undefined ? colInit.searchBuilderType : colInit.sType); } } var columnIdxs = this.s.dt.columns().toArray(); // If the types are not yet set then draw to see if they can be retrieved then if (types === undefined || types.includes(undefined) || types.includes(null)) { $.fn.dataTable.ext.oApi._fnColumnTypes(this.s.dt.settings()[0]); types = this.s.dt.columns().type().toArray(); } for (var i = 0; i < columnIdxs[0].length; i++) { var column = columnIdxs[0][i]; var type = types[column]; if ( // Check if this column can be filtered (this.c.columns === true || Array.isArray(this.c.columns) && this.c.columns.includes(i)) && // Check if the type is one of the restricted types (type.includes('date') || type.includes('moment') || type.includes('luxon'))) { alert('SearchBuilder Requires DateTime when used with dates.'); throw new Error('SearchBuilder requires DateTime'); } } } this.s.topGroup = new Group(this.s.dt, this.c, undefined, undefined, undefined, undefined, this.s.serverData); this._setClearListener(); this.s.dt.on('stateSaveParams.dtsb', function (e, settings, data) { data.searchBuilder = _this.getDetails(); if (!data.scroller) { data.page = _this.s.dt.page(); } else { data.start = _this.s.dt.state().start; } }); this.s.dt.on('stateLoadParams.dtsb', function (e, settings, data) { _this.rebuild(data.searchBuilder); }); this._build(); this.s.dt.on('preXhr.dtsb', function (e, settings, data) { if (_this.s.dt.page.info().serverSide) { data.searchBuilder = _this._collapseArray(_this.getDetails(true)); } }); this.s.dt.on('column-reorder', function () { _this.rebuild(_this.getDetails()); }); if (loadState) { var loadedState = this.s.dt.state.loaded(); // If the loaded State is not null rebuild based on it for statesave if (loadedState !== null && loadedState.searchBuilder !== undefined) { this.s.topGroup.rebuild(loadedState.searchBuilder); this.s.topGroup.dom.container.trigger('dtsb-redrawContents'); // If using SSP we want to restrict the amount of server calls that take place // and this information will already have been processed if (!this.s.dt.page.info().serverSide) { if (loadedState.page) { this.s.dt.page(loadedState.page).draw('page'); } else if (this.s.dt.scroller && loadedState.scroller) { this.s.dt.scroller().scrollToRow(loadedState.scroller.topRow); } } this.s.topGroup.setListeners(); } // Otherwise load any predefined options else if (this.c.preDefined !== false) { this.c.preDefined = this._applyPreDefDefaults(this.c.preDefined); this.rebuild(this.c.preDefined); } } this._setEmptyListener(); this.s.dt.state.save(); }; SearchBuilder.prototype._collapseArray = function (criteria) { if (criteria.logic === undefined) { if (criteria.value !== undefined) { criteria.value.sort(function (a, b) { if (!isNaN(+a)) { a = +a; b = +b; } if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } }); criteria.value1 = criteria.value[0]; criteria.value2 = criteria.value[1]; } } else { for (var i = 0; i < criteria.criteria.length; i++) { criteria.criteria[i] = this._collapseArray(criteria.criteria[i]); } } return criteria; }; /** * Updates the title of the SearchBuilder * * @param count the number of filters in the SearchBuilder */ SearchBuilder.prototype._updateTitle = function (count) { this.dom.title.html(this.s.dt.i18n('searchBuilder.title', this.c.i18n.title, count)); }; /** * Builds all of the dom elements together */ SearchBuilder.prototype._build = function () { var _this = this; // Empty and setup the container this.dom.clearAll.remove(); this.dom.container.empty(); var count = this.s.topGroup.count(); this._updateTitle(count); this.dom.titleRow.append(this.dom.title); this.dom.container.append(this.dom.titleRow); this.dom.topGroup = this.s.topGroup.getNode(); this.dom.container.append(this.dom.topGroup); this._setRedrawListener(); var tableNode = this.s.dt.table(0).node(); if (!$.fn.dataTable.ext.search.includes(this.s.search)) { // Custom search function for SearchBuilder this.s.search = function (settings, searchData, dataIndex) { if (settings.nTable !== tableNode) { return true; } return _this.s.topGroup.search(searchData, dataIndex); }; // Add SearchBuilder search function to the dataTables search array $.fn.dataTable.ext.search.push(this.s.search); } this.s.dt.on('destroy.dtsb', function () { _this.dom.container.remove(); _this.dom.clearAll.remove(); var searchIdx = $.fn.dataTable.ext.search.indexOf(_this.s.search); while (searchIdx !== -1) { $.fn.dataTable.ext.search.splice(searchIdx, 1); searchIdx = $.fn.dataTable.ext.search.indexOf(_this.s.search); } _this.s.dt.off('.dtsb'); $(_this.s.dt.table().node()).off('.dtsb'); }); }; /** * Checks if the clearAll button should be added or not */ SearchBuilder.prototype._checkClear = function () { if (this.s.topGroup.s.criteria.length > 0) { this.dom.clearAll.insertAfter(this.dom.title); this._setClearListener(); } else { this.dom.clearAll.remove(); } }; /** * Update the count in the title/button * * @param count Number of filters applied */ SearchBuilder.prototype._filterChanged = function (count) { var fn = this.c.filterChanged; if (typeof fn === 'function') { fn(count, this.s.dt.i18n('searchBuilder.button', this.c.i18n.button, count)); } }; /** * Set the listener for the clear button */ SearchBuilder.prototype._setClearListener = function () { var _this = this; this.dom.clearAll.unbind('click'); this.dom.clearAll.on('click.dtsb', function () { _this.s.topGroup = new Group(_this.s.dt, _this.c, undefined, undefined, undefined, undefined, _this.s.serverData); _this._build(); _this.s.dt.draw(); _this.s.topGroup.setListeners(); _this.dom.clearAll.remove(); _this._setEmptyListener(); _this._filterChanged(0); return false; }); }; /** * Set the listener for the Redraw event */ SearchBuilder.prototype._setRedrawListener = function () { var _this = this; this.s.topGroup.dom.container.unbind('dtsb-redrawContents'); this.s.topGroup.dom.container.on('dtsb-redrawContents.dtsb', function () { _this._checkClear(); _this.s.topGroup.redrawContents(); _this.s.topGroup.setupLogic(); _this._setEmptyListener(); var count = _this.s.topGroup.count(); _this._updateTitle(count); _this._filterChanged(count); // If using SSP we want to restrict the amount of server calls that take place // and this information will already have been processed if (!_this.s.dt.page.info().serverSide) { _this.s.dt.draw(); } _this.s.dt.state.save(); }); this.s.topGroup.dom.container.unbind('dtsb-redrawContents-noDraw'); this.s.topGroup.dom.container.on('dtsb-redrawContents-noDraw.dtsb', function () { _this._checkClear(); _this.s.topGroup.s.preventRedraw = true; _this.s.topGroup.redrawContents(); _this.s.topGroup.s.preventRedraw = false; _this.s.topGroup.setupLogic(); _this._setEmptyListener(); var count = _this.s.topGroup.count(); _this._updateTitle(count); _this._filterChanged(count); }); this.s.topGroup.dom.container.unbind('dtsb-redrawLogic'); this.s.topGroup.dom.container.on('dtsb-redrawLogic.dtsb', function () { _this.s.topGroup.redrawLogic(); var count = _this.s.topGroup.count(); _this._updateTitle(count); _this._filterChanged(count); }); this.s.topGroup.dom.container.unbind('dtsb-add'); this.s.topGroup.dom.container.on('dtsb-add.dtsb', function () { var count = _this.s.topGroup.count(); _this._updateTitle(count); _this._filterChanged(count); }); this.s.dt.on('postEdit.dtsb postCreate.dtsb postRemove.dtsb', function () { _this.s.topGroup.redrawContents(); }); this.s.topGroup.dom.container.unbind('dtsb-clearContents'); this.s.topGroup.dom.container.on('dtsb-clearContents.dtsb', function () { _this._setUp(false); _this._filterChanged(0); _this.s.dt.draw(); }); }; /** * Sets listeners to check whether clearAll should be added or removed */ SearchBuilder.prototype._setEmptyListener = function () { var _this = this; this.s.topGroup.dom.add.on('click.dtsb', function () { _this._checkClear(); }); this.s.topGroup.dom.container.on('dtsb-destroy.dtsb', function () { _this.dom.clearAll.remove(); }); }; SearchBuilder.version = '1.3.4'; SearchBuilder.classes = { button: 'dtsb-button', clearAll: 'dtsb-clearAll', container: 'dtsb-searchBuilder', inputButton: 'dtsb-iptbtn', title: 'dtsb-title', titleRow: 'dtsb-titleRow' }; SearchBuilder.defaults = { columns: true, conditions: { 'date': Criteria.dateConditions, 'html': Criteria.stringConditions, 'html-num': Criteria.numConditions, 'html-num-fmt': Criteria.numFmtConditions, 'luxon': Criteria.luxonDateConditions, 'moment': Criteria.momentDateConditions, 'num': Criteria.numConditions, 'num-fmt': Criteria.numFmtConditions, 'string': Criteria.stringConditions }, depthLimit: false, enterSearch: false, filterChanged: undefined, greyscale: false, i18n: { add: 'Add Condition', button: { 0: 'Search Builder', _: 'Search Builder (%d)' }, clearAll: 'Clear All', condition: 'Condition', conditions: { array: { contains: 'Contains', empty: 'Empty', equals: 'Equals', not: 'Not', notEmpty: 'Not Empty', without: 'Without' }, date: { after: 'After', before: 'Before', between: 'Between', empty: 'Empty', equals: 'Equals', not: 'Not', notBetween: 'Not Between', notEmpty: 'Not Empty' }, // eslint-disable-next-line id-blacklist number: { between: 'Between', empty: 'Empty', equals: 'Equals', gt: 'Greater Than', gte: 'Greater Than Equal To', lt: 'Less Than', lte: 'Less Than Equal To', not: 'Not', notBetween: 'Not Between', notEmpty: 'Not Empty' }, // eslint-disable-next-line id-blacklist string: { contains: 'Contains', empty: 'Empty', endsWith: 'Ends With', equals: 'Equals', not: 'Not', notContains: 'Does Not Contain', notEmpty: 'Not Empty', notEndsWith: 'Does Not End With', notStartsWith: 'Does Not Start With', startsWith: 'Starts With' } }, data: 'Data', "delete": '&times', deleteTitle: 'Delete filtering rule', left: '<', leftTitle: 'Outdent criteria', logicAnd: 'And', logicOr: 'Or', right: '>', rightTitle: 'Indent criteria', title: { 0: 'Custom Search Builder', _: 'Custom Search Builder (%d)' }, value: 'Value', valueJoiner: 'and' }, logic: 'AND', orthogonal: { display: 'display', search: 'filter' }, preDefined: false }; return SearchBuilder; }()); /*! SearchBuilder 1.3.4 * ©SpryMedia Ltd - datatables.net/license/mit */ // DataTables extensions common UMD. Note that this allows for AMD, CommonJS // (with window and jQuery being allowed as parameters to the returned // function) or just default browser loading. (function (factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'datatables.net'], function ($) { return factory($, window, document); }); } else if (typeof exports === 'object') { // CommonJS module.exports = function (root, $) { if (!root) { root = window; } if (!$ || !$.fn.dataTable) { // eslint-disable-next-line @typescript-eslint/no-var-requires $ = require('datatables.net')(root, $).$; } return factory($, root, root.document); }; } else { // Browser - assume jQuery has already been loaded // eslint-disable-next-line no-extra-parens factory(window.jQuery, window, document); } }(function ($, window, document) { setJQuery($); setJQuery$1($); setJQuery$2($); var dataTable = $.fn.dataTable; // eslint-disable-next-line no-extra-parens $.fn.dataTable.SearchBuilder = SearchBuilder; // eslint-disable-next-line no-extra-parens $.fn.DataTable.SearchBuilder = SearchBuilder; // eslint-disable-next-line no-extra-parens $.fn.dataTable.Group = Group; // eslint-disable-next-line no-extra-parens $.fn.DataTable.Group = Group; // eslint-disable-next-line no-extra-parens $.fn.dataTable.Criteria = Criteria; // eslint-disable-next-line no-extra-parens $.fn.DataTable.Criteria = Criteria; // eslint-disable-next-line no-extra-parens var apiRegister = $.fn.dataTable.Api.register; // Set up object for plugins $.fn.dataTable.ext.searchBuilder = { conditions: {} }; $.fn.dataTable.ext.buttons.searchBuilder = { action: function (e, dt, node, config) { this.popover(config._searchBuilder.getNode(), { align: 'container', span: 'container' }); var topGroup = config._searchBuilder.s.topGroup; // Need to redraw the contents to calculate the correct positions for the elements if (topGroup !== undefined) { topGroup.dom.container.trigger('dtsb-redrawContents-noDraw'); } if (topGroup.s.criteria.length === 0) { $('.' + $.fn.dataTable.Group.classes.add.replace(/ /g, '.')).click(); } }, config: {}, init: function (dt, node, config) { var sb = new $.fn.dataTable.SearchBuilder(dt, $.extend({ filterChanged: function (count, text) { dt.button(node).text(text); } }, config.config)); dt.button(node).text(config.text || dt.i18n('searchBuilder.button', sb.c.i18n.button, 0)); config._searchBuilder = sb; }, text: null }; apiRegister('searchBuilder.getDetails()', function (deFormatDates) { if (deFormatDates === void 0) { deFormatDates = false; } var ctx = this.context[0]; // If SearchBuilder has not been initialised on this instance then return return ctx._searchBuilder ? ctx._searchBuilder.getDetails(deFormatDates) : null; }); apiRegister('searchBuilder.rebuild()', function (details) { var ctx = this.context[0]; // If SearchBuilder has not been initialised on this instance then return if (ctx._searchBuilder === undefined) { return null; } ctx._searchBuilder.rebuild(details); return this; }); apiRegister('searchBuilder.container()', function () { var ctx = this.context[0]; // If SearchBuilder has not been initialised on this instance then return return ctx._searchBuilder ? ctx._searchBuilder.getNode() : null; }); /** * Init function for SearchBuilder * * @param settings the settings to be applied * @param options the options for SearchBuilder * @returns JQUERY<HTMLElement> Returns the node of the SearchBuilder */ function _init(settings, options) { var api = new dataTable.Api(settings); var opts = options ? options : api.init().searchBuilder || dataTable.defaults.searchBuilder; var searchBuilder = new SearchBuilder(api, opts); var node = searchBuilder.getNode(); return node; } // Attach a listener to the document which listens for DataTables initialisation // events so we can automatically initialise $(document).on('preInit.dt.dtsp', function (e, settings) { if (e.namespace !== 'dt') { return; } if (settings.oInit.searchBuilder || dataTable.defaults.searchBuilder) { if (!settings._searchBuilder) { _init(settings); } } }); // DataTables `dom` feature option dataTable.ext.feature.push({ cFeature: 'Q', fnInit: _init }); // DataTables 2 layout feature if (dataTable.ext.features) { dataTable.ext.features.register('searchBuilder', _init); } })); })();