LaravelTest
3171 строка · 153.8 Кб
1/*! SearchPanes 1.4.0
2* 2019-2020 SpryMedia Ltd - datatables.net/license
3*/
4(function () {5'use strict';6
7var $;8var dataTable;9function setJQuery(jq) {10$ = jq;11dataTable = jq.fn.dataTable;12}13var SearchPane = /** @class */ (function () {14/**15* Creates the panes, sets up the search function
16*
17* @param paneSettings The settings for the searchPanes
18* @param opts The options for the default features
19* @param idx the index of the column for this pane
20* @returns {object} the pane that has been created, including the table and the index of the pane
21*/
22function SearchPane(paneSettings, opts, idx, layout, panesContainer, panes) {23var _this = this;24if (panes === void 0) { panes = null; }25// Check that the required version of DataTables is included26if (!dataTable || !dataTable.versionCheck || !dataTable.versionCheck('1.10.0')) {27throw new Error('SearchPane requires DataTables 1.10 or newer');28}29// Check that Select is included30// eslint-disable-next-line no-extra-parens31if (!dataTable.select) {32throw new Error('SearchPane requires Select');33}34var table = new dataTable.Api(paneSettings);35this.classes = $.extend(true, {}, SearchPane.classes);36// Get options from user37this.c = $.extend(true, {}, SearchPane.defaults, opts);38if (opts !== undefined && opts.hideCount !== undefined && opts.viewCount === undefined) {39this.c.viewCount = !this.c.hideCount;40}41this.customPaneSettings = panes;42this.s = {43cascadeRegen: false,44clearing: false,45colOpts: [],46deselect: false,47displayed: false,48dt: table,49dtPane: undefined,50filteringActive: false,51firstSet: true,52forceViewTotal: false,53index: idx,54indexes: [],55lastCascade: false,56lastSelect: false,57listSet: false,58name: undefined,59redraw: false,60rowData: {61arrayFilter: [],62arrayOriginal: [],63arrayTotals: [],64bins: {},65binsOriginal: {},66binsTotal: {},67filterMap: new Map(),68totalOptions: 069},70scrollTop: 0,71searchFunction: undefined,72selectPresent: false,73serverSelect: [],74serverSelecting: false,75showFiltered: false,76tableLength: null,77updating: false78};79var rowLength = table.columns().eq(0).toArray().length;80this.colExists = this.s.index < rowLength;81// Add extra elements to DOM object including clear and hide buttons82this.c.layout = layout;83var layVal = parseInt(layout.split('-')[1], 10);84this.dom = {85buttonGroup: $('<div/>').addClass(this.classes.buttonGroup),86clear: $('<button type="button">×</button>')87.addClass(this.classes.disabledButton)88.attr('disabled', 'true')89.addClass(this.classes.paneButton)90.addClass(this.classes.clearButton),91collapseButton: $('<button type="button"><span class="dtsp-caret">^</span></button>')92.addClass(this.classes.paneButton)93.addClass(this.classes.collapseButton),94container: $('<div/>')95.addClass(this.classes.container)96.addClass(this.classes.layout +97(layVal < 10 ? layout : layout.split('-')[0] + '-9')),98countButton: $('<button type="button"></button>')99.addClass(this.classes.paneButton)100.addClass(this.classes.countButton),101dtP: $('<table><thead><tr><th>' +102(this.colExists103? $(table.column(this.colExists ? this.s.index : 0).header()).text()104: this.customPaneSettings.header || 'Custom Pane') + '</th><th/></tr></thead></table>'),105lower: $('<div/>').addClass(this.classes.subRow2).addClass(this.classes.narrowButton),106nameButton: $('<button type="button"></button>')107.addClass(this.classes.paneButton)108.addClass(this.classes.nameButton),109panesContainer: panesContainer,110searchBox: $('<input/>').addClass(this.classes.paneInputButton).addClass(this.classes.search),111searchButton: $('<button type = "button" class="' + this.classes.searchIcon + '"></button>')112.addClass(this.classes.paneButton),113searchCont: $('<div/>').addClass(this.classes.searchCont),114searchLabelCont: $('<div/>').addClass(this.classes.searchLabelCont),115topRow: $('<div/>').addClass(this.classes.topRow),116upper: $('<div/>').addClass(this.classes.subRow1).addClass(this.classes.narrowSearch)117};118this.s.displayed = false;119table = this.s.dt;120this.selections = [];121this.s.colOpts = this.colExists ? this._getOptions() : this._getBonusOptions();122var colOpts = this.s.colOpts;123var clear = $('<button type="button">X</button>').addClass(this.classes.paneButton);124clear.text(table.i18n('searchPanes.clearPane', this.c.i18n.clearPane));125this.dom.container.addClass(colOpts.className);126this.dom.container.addClass(this.customPaneSettings !== null && this.customPaneSettings.className !== undefined127? this.customPaneSettings.className128: '');129// Set the value of name incase ordering is desired130if (this.s.colOpts.name !== undefined) {131this.s.name = this.s.colOpts.name;132}133else if (this.customPaneSettings !== null && this.customPaneSettings.name !== undefined) {134this.s.name = this.customPaneSettings.name;135}136else {137this.s.name = this.colExists ?138$(table.column(this.s.index).header()).text() :139this.customPaneSettings.header || 'Custom Pane';140}141$(panesContainer).append(this.dom.container);142var tableNode = table.table(0).node();143// Custom search function for table144this.s.searchFunction = function (settings, searchData, dataIndex, origData) {145// If no data has been selected then show all146if (_this.selections.length === 0) {147return true;148}149if (settings.nTable !== tableNode) {150return true;151}152var filter = null;153if (_this.colExists) {154// Get the current filtered data155filter = searchData[_this.s.index];156if (colOpts.orthogonal.filter !== 'filter') {157// get the filter value from the map158filter = _this.s.rowData.filterMap.get(dataIndex);159if (filter instanceof $.fn.dataTable.Api) {160// eslint-disable-next-line no-extra-parens161filter = filter.toArray();162}163}164}165return _this._search(filter, dataIndex);166};167$.fn.dataTable.ext.search.push(this.s.searchFunction);168// If the clear button for this pane is clicked clear the selections169if (this.c.clear) {170clear.on('click', function () {171var searches = _this.dom.container.find('.' + _this.classes.search.replace(/\s+/g, '.'));172searches.each(function () {173$(this).val('');174$(this).trigger('input');175});176_this.clearPane();177});178}179// Sometimes the top row of the panes containing the search box and ordering buttons appears180// weird if the width of the panes is lower than expected, this fixes the design.181// Equally this may occur when the table is resized.182table.on('draw.dtsp', function () {183_this.adjustTopRow();184});185table.on('buttons-action', function () {186_this.adjustTopRow();187});188// When column-reorder is present and the columns are moved, it is necessary to189// reassign all of the panes indexes to the new index of the column.190table.on('column-reorder.dtsp', function (e, settings, details) {191_this.s.index = details.mapping[_this.s.index];192});193return this;194}195/**196* Adds a row to the panes table
197*
198* @param display the value to be displayed to the user
199* @param filter the value to be filtered on when searchpanes is implemented
200* @param shown the number of rows in the table that are currently visible matching this criteria
201* @param total the total number of rows in the table that match this criteria
202* @param sort the value to be sorted in the pane table
203* @param type the value of which the type is to be derived from
204*/
205SearchPane.prototype.addRow = function (display, filter, shown, total, sort, type, className) {206var index;207for (var _i = 0, _a = this.s.indexes; _i < _a.length; _i++) {208var entry = _a[_i];209if (entry.filter === filter) {210index = entry.index;211}212}213if (index === undefined) {214index = this.s.indexes.length;215this.s.indexes.push({ filter: filter, index: index });216}217return this.s.dtPane.row.add({218className: className,219display: display !== '' ?220display :221this.emptyMessage(),222filter: filter,223index: index,224shown: shown,225sort: sort,226total: total,227type: type228});229};230/**231* Adjusts the layout of the top row when the screen is resized
232*/
233SearchPane.prototype.adjustTopRow = function () {234var subContainers = this.dom.container.find('.' + this.classes.subRowsContainer.replace(/\s+/g, '.'));235var subRow1 = this.dom.container.find('.' + this.classes.subRow1.replace(/\s+/g, '.'));236var subRow2 = this.dom.container.find('.' + this.classes.subRow2.replace(/\s+/g, '.'));237var topRow = this.dom.container.find('.' + this.classes.topRow.replace(/\s+/g, '.'));238// If the width is 0 then it is safe to assume that the pane has not yet been displayed.239// Even if it has, if the width is 0 it won't make a difference if it has the narrow class or not240if (($(subContainers[0]).width() < 252 || $(topRow[0]).width() < 252) && $(subContainers[0]).width() !== 0) {241$(subContainers[0]).addClass(this.classes.narrow);242$(subRow1[0]).addClass(this.classes.narrowSub).removeClass(this.classes.narrowSearch);243$(subRow2[0]).addClass(this.classes.narrowSub).removeClass(this.classes.narrowButton);244}245else {246$(subContainers[0]).removeClass(this.classes.narrow);247$(subRow1[0]).removeClass(this.classes.narrowSub).addClass(this.classes.narrowSearch);248$(subRow2[0]).removeClass(this.classes.narrowSub).addClass(this.classes.narrowButton);249}250};251/**252* In the case of a rebuild there is potential for new data to have been included or removed
253* so all of the rowData must be reset as a precaution.
254*/
255SearchPane.prototype.clearData = function () {256this.s.rowData = {257arrayFilter: [],258arrayOriginal: [],259arrayTotals: [],260bins: {},261binsOriginal: {},262binsTotal: {},263filterMap: new Map(),264totalOptions: 0265};266};267/**268* Clear the selections in the pane
269*/
270SearchPane.prototype.clearPane = function () {271// Deselect all rows which are selected and update the table and filter count.272this.s.dtPane.rows({ selected: true }).deselect();273this.updateTable();274return this;275};276/**277* Collapses the pane so that only the header is displayed
278*/
279SearchPane.prototype.collapse = function () {280var _this = this;281if (!this.s.displayed ||282(!this.c.collapse && this.s.colOpts.collapse !== true ||283this.s.colOpts.collapse === false)) {284return;285}286this.dom.collapseButton.addClass(this.classes.rotated);287$(this.s.dtPane.table().container()).addClass(this.classes.hidden);288this.dom.topRow.addClass(this.classes.bordered);289this.dom.countButton.addClass(this.classes.disabledButton);290this.dom.nameButton.addClass(this.classes.disabledButton);291this.dom.searchButton.addClass(this.classes.disabledButton);292this.dom.topRow.one('click', function () {293_this.show();294});295};296/**297* Strips all of the SearchPanes elements from the document and turns all of the listeners for the buttons off
298*/
299SearchPane.prototype.destroy = function () {300if (this.s.dtPane !== undefined) {301this.s.dtPane.off('.dtsp');302}303this.dom.nameButton.off('.dtsp');304this.dom.collapseButton.off('.dtsp');305this.dom.countButton.off('.dtsp');306this.dom.clear.off('.dtsp');307this.dom.searchButton.off('.dtsp');308this.dom.container.remove();309var searchIdx = $.fn.dataTable.ext.search.indexOf(this.s.searchFunction);310while (searchIdx !== -1) {311$.fn.dataTable.ext.search.splice(searchIdx, 1);312searchIdx = $.fn.dataTable.ext.search.indexOf(this.s.searchFunction);313}314// If the datatables have been defined for the panes then also destroy these315if (this.s.dtPane !== undefined) {316this.s.dtPane.destroy();317}318this.s.listSet = false;319};320/**321* Getting the legacy message is a little complex due a legacy parameter
322*/
323SearchPane.prototype.emptyMessage = function () {324var def = this.c.i18n.emptyMessage;325// Legacy parameter support326if (this.c.emptyMessage) {327def = this.c.emptyMessage;328}329// Override per column330if (this.s.colOpts.emptyMessage !== false && this.s.colOpts.emptyMessage !== null) {331def = this.s.colOpts.emptyMessage;332}333return this.s.dt.i18n('searchPanes.emptyMessage', def);334};335/**336* Updates the number of filters that have been applied in the title
337*/
338SearchPane.prototype.getPaneCount = function () {339return this.s.dtPane !== undefined ?340this.s.dtPane.rows({ selected: true }).data().toArray().length :3410;342};343/**344* Rebuilds the panes from the start having deleted the old ones
345*
346* @param? last boolean to indicate if this is the last pane a selection was made in
347* @param? dataIn data to be used in buildPane
348* @param? init Whether this is the initial draw or not
349* @param? maintainSelection Whether the current selections are to be maintained over rebuild
350*/
351SearchPane.prototype.rebuildPane = function (last, dataIn, init, maintainSelection) {352if (last === void 0) { last = false; }353if (dataIn === void 0) { dataIn = null; }354if (init === void 0) { init = null; }355if (maintainSelection === void 0) { maintainSelection = false; }356this.clearData();357var selectedRows = [];358this.s.serverSelect = [];359var prevEl = null;360// When rebuilding strip all of the HTML Elements out of the container and start from scratch361if (this.s.dtPane !== undefined) {362if (maintainSelection) {363if (!this.s.dt.page.info().serverSide) {364selectedRows = this.s.dtPane.rows({ selected: true }).data().toArray();365}366else {367this.s.serverSelect = this.s.dtPane.rows({ selected: true }).data().toArray();368}369}370this.s.dtPane.clear().destroy();371prevEl = this.dom.container.prev();372this.destroy();373this.s.dtPane = undefined;374$.fn.dataTable.ext.search.push(this.s.searchFunction);375}376this.dom.container.removeClass(this.classes.hidden);377this.s.displayed = false;378this._buildPane(!this.s.dt.page.info().serverSide ?379selectedRows :380this.s.serverSelect, last, dataIn, init, prevEl);381return this;382};383/**384* removes the pane from the page and sets the displayed property to false.
385*/
386SearchPane.prototype.removePane = function () {387this.s.displayed = false;388this.dom.container.hide();389};390/**391* Resizes the pane based on the layout that is passed in
392*
393* @param layout the layout to be applied to this pane
394*/
395SearchPane.prototype.resize = function (layout) {396this.c.layout = layout;397var layVal = parseInt(layout.split('-')[1], 10);398this.dom.container399.removeClass()400.addClass(this.classes.container)401.addClass(this.classes.layout +402(layVal < 10 ? layout : layout.split('-')[0] + '-9'))403.addClass(this.s.colOpts.className)404.addClass(this.customPaneSettings !== null && this.customPaneSettings.className !== undefined405? this.customPaneSettings.className406: '')407.addClass(this.classes.show);408this.adjustTopRow();409};410/**411* Sets the cascadeRegen property of the pane. Accessible from above because as SearchPanes.ts
412* deals with the rebuilds.
413*
414* @param val the boolean value that the cascadeRegen property is to be set to
415*/
416SearchPane.prototype.setCascadeRegen = function (val) {417this.s.cascadeRegen = val;418};419/**420* This function allows the clearing property to be assigned. This is used when implementing cascadePane.
421* In setting this to true for the clearing of the panes selection on the deselects it forces the pane to
422* repopulate from the entire dataset not just the displayed values.
423*
424* @param val the boolean value which the clearing property is to be assigned
425*/
426SearchPane.prototype.setClear = function (val) {427this.s.clearing = val;428};429/**430* Expands the pane from the collapsed state
431*/
432SearchPane.prototype.show = function () {433if (!this.s.displayed) {434return;435}436this.dom.collapseButton.removeClass(this.classes.rotated);437$(this.s.dtPane.table().container()).removeClass(this.classes.hidden);438this.dom.topRow.removeClass(this.classes.bordered);439this.dom.countButton.removeClass(this.classes.disabledButton);440this.dom.nameButton.removeClass(this.classes.disabledButton);441this.dom.searchButton.removeClass(this.classes.disabledButton);442};443/**444* Updates the values of all of the panes
445*
446* @param draw whether this has been triggered by a draw event or not
447*/
448SearchPane.prototype.updatePane = function (draw) {449if (draw === void 0) { draw = false; }450this.s.updating = true;451this._updateCommon(draw);452this.s.updating = false;453};454/**455* Updates the panes if one of the options to do so has been set to true
456* rather than the filtered message when using viewTotal.
457*/
458SearchPane.prototype.updateTable = function () {459var selectedRows = this.s.dtPane.rows({ selected: true }).data().toArray();460this.selections = selectedRows;461this._searchExtras();462// If either of the options that effect how the panes are displayed are selected then update the Panes463if (this.c.cascadePanes || this.c.viewTotal) {464this.updatePane();465}466};467/**468* Sets the listeners for the pane.
469*
470* Having it in it's own function makes it easier to only set them once
471*/
472SearchPane.prototype._setListeners = function () {473var _this = this;474var rowData = this.s.rowData;475var t0;476// When an item is selected on the pane, add these to the array which holds selected items.477// Custom search will perform.478this.s.dtPane.off('select.dtsp');479this.s.dtPane.on('select.dtsp', function () {480clearTimeout(t0);481if (_this.s.dt.page.info().serverSide && !_this.s.updating) {482if (!_this.s.serverSelecting) {483_this.s.serverSelect = _this.s.dtPane.rows({ selected: true }).data().toArray();484_this.s.scrollTop = $(_this.s.dtPane.table().node()).parent()[0].scrollTop;485_this.s.selectPresent = true;486_this.s.dt.draw(false);487}488}489else if (!_this.s.updating) {490_this.s.selectPresent = true;491_this._makeSelection();492_this.s.selectPresent = false;493}494_this.dom.clear.removeClass(_this.classes.disabledButton).removeAttr('disabled');495});496// When an item is deselected on the pane, re add the currently selected items to the array497// which holds selected items. Custom search will be performed.498this.s.dtPane.off('deselect.dtsp');499this.s.dtPane.on('deselect.dtsp', function () {500t0 = setTimeout(function () {501_this.s.scrollTop = $(_this.s.dtPane.table().node()).parent()[0].scrollTop;502if (_this.s.dt.page.info().serverSide && !_this.s.updating) {503if (!_this.s.serverSelecting) {504_this.s.serverSelect = _this.s.dtPane.rows({ selected: true }).data().toArray();505_this.s.deselect = true;506_this.s.dt.draw(false);507}508}509else {510_this.s.deselect = true;511_this._makeSelection();512_this.s.deselect = false;513}514if (_this.s.dtPane.rows({ selected: true }).data().toArray().length === 0) {515_this.dom.clear.addClass(_this.classes.disabledButton).attr('disabled', 'true');516}517}, 50);518});519// If we attempty to turn off this event then it will ruin behaviour in other panes520// so need to make sure that it is only done once521if (this.s.firstSet) {522this.s.firstSet = false;523// When saving the state store all of the selected rows for preselection next time around524this.s.dt.on('stateSaveParams.dtsp', function (e, settings, data) {525// If the data being passed in is empty then state clear must have occured526// so clear the panes state as well527if ($.isEmptyObject(data)) {528_this.s.dtPane.state.clear();529return;530}531var selected = [];532var searchTerm;533var order;534var bins;535var arrayFilter;536var collapsed;537// Get all of the data needed for the state save from the pane538if (_this.s.dtPane !== undefined) {539selected = _this.s.dtPane540.rows({ selected: true })541.data()542.map(function (item) { return item.filter.toString(); })543.toArray();544searchTerm = _this.dom.searchBox.val();545order = _this.s.dtPane.order();546bins = rowData.binsOriginal;547arrayFilter = rowData.arrayOriginal;548collapsed = _this.dom.collapseButton.hasClass(_this.classes.rotated);549}550if (data.searchPanes === undefined) {551data.searchPanes = {};552}553if (data.searchPanes.panes === undefined) {554data.searchPanes.panes = [];555}556for (var i = 0; i < data.searchPanes.panes.length; i++) {557if (data.searchPanes.panes[i].id === _this.s.index) {558data.searchPanes.panes.splice(i, 1);559i--;560}561}562// Add the panes data to the state object563data.searchPanes.panes.push({564arrayFilter: arrayFilter,565bins: bins,566collapsed: collapsed,567id: _this.s.index,568order: order,569searchTerm: searchTerm,570selected: selected571});572});573}574this.s.dtPane.off('user-select.dtsp');575this.s.dtPane.on('user-select.dtsp', function (e, _dt, type, cell, originalEvent) {576originalEvent.stopPropagation();577});578this.s.dtPane.off('draw.dtsp');579this.s.dtPane.on('draw.dtsp', function () {580_this.adjustTopRow();581});582// When the button to order by the name of the options is clicked then583// change the ordering to whatever it isn't currently584this.dom.nameButton.off('click.dtsp');585this.dom.nameButton.on('click.dtsp', function () {586var currentOrder = _this.s.dtPane.order()[0][1];587_this.s.dtPane.order([0, currentOrder === 'asc' ? 'desc' : 'asc']).draw();588// This state save is required so that the ordering of the panes is maintained589_this.s.dt.state.save();590});591// When the button to order by the number of entries in the column is clicked then592// change the ordering to whatever it isn't currently593this.dom.countButton.off('click.dtsp');594this.dom.countButton.on('click.dtsp', function () {595var currentOrder = _this.s.dtPane.order()[0][1];596_this.s.dtPane.order([1, currentOrder === 'asc' ? 'desc' : 'asc']).draw();597// This state save is required so that the ordering of the panes is maintained598_this.s.dt.state.save();599});600// When the button to order by the number of entries in the column is clicked then601// change the ordering to whatever it isn't currently602this.dom.collapseButton.off('click.dtsp');603this.dom.collapseButton.on('click.dtsp', function (e) {604e.stopPropagation();605var container = $(_this.s.dtPane.table().container());606// Toggle the classes607_this.dom.collapseButton.toggleClass(_this.classes.rotated);608container.toggleClass(_this.classes.hidden);609_this.dom.topRow.toggleClass(_this.classes.bordered);610_this.dom.countButton.toggleClass(_this.classes.disabledButton);611_this.dom.nameButton.toggleClass(_this.classes.disabledButton);612_this.dom.searchButton.toggleClass(_this.classes.disabledButton);613if (container.hasClass(_this.classes.hidden)) {614_this.dom.topRow.on('click', function () { return _this.dom.collapseButton.click(); });615}616else {617_this.dom.topRow.off('click');618}619_this.s.dt.state.save();620return;621});622// When the clear button is clicked reset the pane623this.dom.clear.off('click.dtsp');624this.dom.clear.on('click.dtsp', function () {625var searches = _this.dom.container.find('.' + _this.classes.search.replace(/ /g, '.'));626searches.each(function () {627// set the value of the search box to be an empty string and then search on that, effectively reseting628$(this).val('');629$(this).trigger('input');630});631_this.clearPane();632});633// When the search button is clicked then draw focus to the search box634this.dom.searchButton.off('click.dtsp');635this.dom.searchButton.on('click.dtsp', function () {636_this.dom.searchBox.focus();637});638// When a character is inputted into the searchbox search the pane for matching values.639// Doing it this way means that no button has to be clicked to trigger a search, it is done asynchronously640this.dom.searchBox.off('click.dtsp');641this.dom.searchBox.on('input.dtsp', function () {642var searchval = _this.dom.searchBox.val();643_this.s.dtPane.search(searchval).draw();644if (typeof searchval === 'string' &&645(searchval.length > 0 ||646searchval.length === 0 && _this.s.dtPane.rows({ selected: true }).data().toArray().length > 0)) {647_this.dom.clear.removeClass(_this.classes.disabledButton).removeAttr('disabled');648}649else {650_this.dom.clear.addClass(_this.classes.disabledButton).attr('disabled', 'true');651}652// This state save is required so that the searching on the panes is maintained653_this.s.dt.state.save();654});655return true;656};657/**658* Takes in potentially undetected rows and adds them to the array if they are not yet featured
659*
660* @param filter the filter value of the potential row
661* @param display the display value of the potential row
662* @param sort the sort value of the potential row
663* @param type the type value of the potential row
664* @param arrayFilter the array to be populated
665* @param bins the bins to be populated
666*/
667SearchPane.prototype._addOption = function (filter, display, sort, type, arrayFilter, bins) {668// If the filter is an array then take a note of this, and add the elements to the arrayFilter array669if (Array.isArray(filter) || filter instanceof dataTable.Api) {670// Convert to an array so that we can work with it671if (filter instanceof dataTable.Api) {672filter = filter.toArray();673display = display.toArray();674}675if (filter.length === display.length) {676for (var i = 0; i < filter.length; i++) {677// If we haven't seen this row before add it678if (!bins[filter[i]]) {679bins[filter[i]] = 1;680arrayFilter.push({681display: display[i],682filter: filter[i],683sort: sort[i],684type: type[i]685});686}687// Otherwise just increment the count688else {689bins[filter[i]]++;690}691this.s.rowData.totalOptions++;692}693return;694}695else {696throw new Error('display and filter not the same length');697}698}699// If the values were affected by othogonal data and are not an array then check if it is already present700else if (typeof this.s.colOpts.orthogonal === 'string') {701if (!bins[filter]) {702bins[filter] = 1;703arrayFilter.push({704display: display,705filter: filter,706sort: sort,707type: type708});709this.s.rowData.totalOptions++;710}711else {712bins[filter]++;713this.s.rowData.totalOptions++;714return;715}716}717// Otherwise we must just be adding an option718else {719arrayFilter.push({720display: display,721filter: filter,722sort: sort,723type: type724});725}726};727/**728* Method to construct the actual pane.
729*
730* @param selectedRows previously selected Rows to be reselected
731* @last boolean to indicate whether this pane was the last one to have a selection made
732*/
733SearchPane.prototype._buildPane = function (selectedRows, last, dataIn, init, prevEl) {734var _this = this;735if (selectedRows === void 0) { selectedRows = []; }736if (last === void 0) { last = false; }737if (dataIn === void 0) { dataIn = null; }738if (init === void 0) { init = null; }739if (prevEl === void 0) { prevEl = null; }740// Aliases741this.selections = [];742var table = this.s.dt;743var column = table.column(this.colExists ? this.s.index : 0);744var colOpts = this.s.colOpts;745var rowData = this.s.rowData;746// Other Variables747var countMessage = table.i18n('searchPanes.count', this.c.i18n.count);748var filteredMessage = table.i18n('searchPanes.countFiltered', this.c.i18n.countFiltered);749var loadedFilter = table.state.loaded();750// If the listeners have not been set yet then using the latest state may result in funny errors751if (this.s.listSet) {752loadedFilter = table.state();753}754// If it is not a custom pane in place755if (this.colExists) {756var idx = -1;757if (loadedFilter && loadedFilter.searchPanes && loadedFilter.searchPanes.panes) {758for (var i = 0; i < loadedFilter.searchPanes.panes.length; i++) {759if (loadedFilter.searchPanes.panes[i].id === this.s.index) {760idx = i;761break;762}763}764}765// Perform checks that do not require populate pane to run766if ((colOpts.show === false ||767colOpts.show !== undefined && colOpts.show !== true) &&768idx === -1) {769this.dom.container.addClass(this.classes.hidden);770this.s.displayed = false;771return false;772}773else if (colOpts.show === true || idx !== -1) {774this.s.displayed = true;775}776if (!this.s.dt.page.info().serverSide &&777(dataIn === null ||778dataIn.searchPanes === null ||779dataIn.searchPanes.options === null)) {780// Only run populatePane if the data has not been collected yet781if (rowData.arrayFilter.length === 0) {782this._populatePane(last);783this.s.rowData.totalOptions = 0;784this._detailsPane();785rowData.arrayOriginal = rowData.arrayTotals;786rowData.binsOriginal = rowData.binsTotal;787}788var binLength = Object.keys(rowData.binsOriginal).length;789var uniqueRatio = this._uniqueRatio(binLength, table.rows()[0].length);790// Don't show the pane if there isn't enough variance in the data, or there is only 1 entry791// for that pane792if (this.s.displayed === false &&793((colOpts.show === undefined && colOpts.threshold === null ?794uniqueRatio > this.c.threshold :795uniqueRatio > colOpts.threshold) ||796colOpts.show !== true && binLength <= 1)) {797this.dom.container.addClass(this.classes.hidden);798this.s.displayed = false;799return;800}801// If the option viewTotal is true then find802// the total count for the whole table to display alongside the displayed count803if (this.c.viewTotal && rowData.arrayTotals.length === 0) {804this.s.rowData.totalOptions = 0;805this._detailsPane();806}807else {808rowData.binsTotal = rowData.bins;809}810this.dom.container.addClass(this.classes.show);811this.s.displayed = true;812}813else if (dataIn !== null && dataIn.searchPanes !== null && dataIn.searchPanes.options !== null) {814if (dataIn.tableLength !== undefined) {815this.s.tableLength = dataIn.tableLength;816this.s.rowData.totalOptions = this.s.tableLength;817}818else if (this.s.tableLength === null || table.rows()[0].length > this.s.tableLength) {819this.s.tableLength = table.rows()[0].length;820this.s.rowData.totalOptions = this.s.tableLength;821}822var colTitle = table.column(this.s.index).dataSrc();823if (dataIn.searchPanes.options[colTitle] !== undefined) {824for (var _i = 0, _a = dataIn.searchPanes.options[colTitle]; _i < _a.length; _i++) {825var dataPoint = _a[_i];826this.s.rowData.arrayFilter.push({827display: dataPoint.label,828filter: dataPoint.value,829sort: dataPoint.label,830type: dataPoint.label831});832this.s.rowData.bins[dataPoint.value] = this.c.viewTotal || this.c.cascadePanes ?833dataPoint.count :834dataPoint.total;835this.s.rowData.binsTotal[dataPoint.value] = dataPoint.total;836}837}838var binLength = Object.keys(rowData.binsTotal).length;839var uniqueRatio = this._uniqueRatio(binLength, this.s.tableLength);840// Don't show the pane if there isnt enough variance in the data, or there is only 1 entry for that pane841if (this.s.displayed === false &&842((colOpts.show === undefined && colOpts.threshold === null ?843uniqueRatio > this.c.threshold :844uniqueRatio > colOpts.threshold) ||845colOpts.show !== true && binLength <= 1)) {846this.dom.container.addClass(this.classes.hidden);847this.s.displayed = false;848return;849}850this.s.rowData.arrayOriginal = this.s.rowData.arrayFilter;851this.s.rowData.binsOriginal = this.s.rowData.bins;852this.s.displayed = true;853}854}855else {856this.s.displayed = true;857}858// If the variance is accceptable then display the search pane859this._displayPane();860if (!this.s.listSet) {861// Here, when the state is loaded if the data object on the original table is empty,862// then a state.clear() must have occurred, so delete all of the panes tables state objects too.863this.dom.dtP.on('stateLoadParams.dt', function (e, settings, data) {864if ($.isEmptyObject(table.state.loaded())) {865$.each(data, function (index, value) {866delete data[index];867});868}869});870}871// Add the container to the document in its original location872if (prevEl !== null && this.dom.panesContainer.has(prevEl).length > 0) {873this.dom.container.insertAfter(prevEl);874}875else {876this.dom.panesContainer.prepend(this.dom.container);877}878// Declare the datatable for the pane879var errMode = $.fn.dataTable.ext.errMode;880$.fn.dataTable.ext.errMode = 'none';881// eslint-disable-next-line no-extra-parens882var haveScroller = dataTable.Scroller;883this.s.dtPane = this.dom.dtP.DataTable($.extend(true, {884columnDefs: [885{886className: 'dtsp-nameColumn',887data: 'display',888render: function (data, type, row) {889if (type === 'sort') {890return row.sort;891}892else if (type === 'type') {893return row.type;894}895var message;896message =897(_this.s.filteringActive || _this.s.showFiltered) && _this.c.viewTotal ||898_this.c.viewTotal && _this.s.forceViewTotal ?899filteredMessage.replace(/{total}/, row.total) :900countMessage.replace(/{total}/, row.total);901message = message.replace(/{shown}/, row.shown);902while (message.includes('{total}')) {903message = message.replace(/{total}/, row.total);904}905while (message.includes('{shown}')) {906message = message.replace(/{shown}/, row.shown);907}908// We are displaying the count in the same columne as the name of the search option.909// This is so that there is not need to call columns.adjust()910// which in turn speeds up the code911var pill = '<span class="' + _this.classes.pill + '">' + message + '</span>';912if (!_this.c.viewCount || !colOpts.viewCount) {913pill = '';914}915if (type === 'filter') {916return typeof data === 'string' && data.match(/<[^>]*>/) !== null ?917data.replace(/<[^>]*>/g, '') :918data;919}920return '<div class="' + _this.classes.nameCont + '"><span title="' +921(typeof data === 'string' && data.match(/<[^>]*>/) !== null ?922data.replace(/<[^>]*>/g, '') :923data) +924'" class="' + _this.classes.name + '">' +925data + '</span>' +926pill + '</div>';927},928targets: 0,929// Accessing the private datatables property to set type based on the original table.930// This is null if not defined by the user, meaning that automatic type detection931// would take place932type: table.settings()[0].aoColumns[this.s.index] !== undefined ?933table.settings()[0].aoColumns[this.s.index]._sManualType :934null935},936{937className: 'dtsp-countColumn ' + this.classes.badgePill,938data: 'shown',939orderData: [1, 2],940searchable: false,941targets: 1,942visible: false943},944{945data: 'total',946searchable: false,947targets: 2,948visible: false949}950],951deferRender: true,952dom: 't',953info: false,954language: this.s.dt.settings()[0].oLanguage,955paging: haveScroller ? true : false,956scrollX: false,957scrollY: '200px',958scroller: haveScroller ? true : false,959select: true,960stateSave: table.settings()[0].oFeatures.bStateSave ? true : false961}, this.c.dtOpts, colOpts !== undefined ? colOpts.dtOpts : {}, this.s.colOpts.options !== undefined || !this.colExists ?962{963createdRow: function (row, data, dataIndex) {964$(row).addClass(data.className);965}966} :967undefined, this.customPaneSettings !== null && this.customPaneSettings.dtOpts !== undefined ?968this.customPaneSettings.dtOpts :969{}, $.fn.dataTable.versionCheck('2')970? {971layout: {972bottomLeft: null,973bottomRight: null,974topLeft: null,975topRight: null976}977}978: {}));979this.dom.dtP.addClass(this.classes.table);980// Getting column titles is a little messy981var headerText = 'Custom Pane';982if (this.customPaneSettings && this.customPaneSettings.header) {983headerText = this.customPaneSettings.header;984}985else if (colOpts.header) {986headerText = colOpts.header;987}988else if (this.colExists) {989headerText = $.fn.dataTable.versionCheck('2')990? table.column(this.s.index).title()991: table.settings()[0].aoColumns[this.s.index].sTitle;992}993this.dom.searchBox.attr('placeholder', headerText);994// As the pane table is not in the document yet we must initialise select ourselves995// eslint-disable-next-line no-extra-parens996$.fn.dataTable.select.init(this.s.dtPane);997$.fn.dataTable.ext.errMode = errMode;998// If it is not a custom pane999if (this.colExists) {1000// On initialisation, do we need to set a filtering value from a1001// saved state or init option?1002var search = column.search();1003search = search ? search.substr(1, search.length - 2).split('|') : [];1004// Count the number of empty cells1005var count_1 = 0;1006rowData.arrayFilter.forEach(function (element) {1007if (element.filter === '') {1008count_1++;1009}1010});1011// Add all of the search options to the pane1012for (var i = 0, ien = rowData.arrayFilter.length; i < ien; i++) {1013var selected = false;1014for (var _b = 0, _c = this.s.serverSelect; _b < _c.length; _b++) {1015var option = _c[_b];1016if (option.filter === rowData.arrayFilter[i].filter) {1017selected = true;1018}1019}1020if (this.s.dt.page.info().serverSide &&1021(!this.c.cascadePanes ||1022this.c.cascadePanes && rowData.bins[rowData.arrayFilter[i].filter] !== 0 ||1023this.c.cascadePanes && init !== null ||1024selected)) {1025var row = this.addRow(rowData.arrayFilter[i].display, rowData.arrayFilter[i].filter, init ?1026rowData.binsTotal[rowData.arrayFilter[i].filter] :1027rowData.bins[rowData.arrayFilter[i].filter], this.c.viewTotal || init1028? String(rowData.binsTotal[rowData.arrayFilter[i].filter])1029: rowData.bins[rowData.arrayFilter[i].filter], rowData.arrayFilter[i].sort, rowData.arrayFilter[i].type);1030for (var _d = 0, _e = this.s.serverSelect; _d < _e.length; _d++) {1031var option = _e[_d];1032if (option.filter === rowData.arrayFilter[i].filter) {1033this.s.serverSelecting = true;1034row.select();1035this.s.serverSelecting = false;1036}1037}1038}1039else if (!this.s.dt.page.info().serverSide &&1040rowData.arrayFilter[i] &&1041(rowData.bins[rowData.arrayFilter[i].filter] !== undefined || !this.c.cascadePanes)) {1042this.addRow(rowData.arrayFilter[i].display, rowData.arrayFilter[i].filter, rowData.bins[rowData.arrayFilter[i].filter], rowData.binsTotal[rowData.arrayFilter[i].filter], rowData.arrayFilter[i].sort, rowData.arrayFilter[i].type);1043}1044else if (!this.s.dt.page.info().serverSide) {1045// Just pass an empty string as the message will be calculated based on that in addRow()1046this.addRow('', count_1, count_1, '', '', '');1047}1048}1049}1050// eslint-disable-next-line no-extra-parens1051dataTable.select.init(this.s.dtPane);1052// If there are custom options set or it is a custom pane then get them1053if (colOpts.options !== undefined ||1054this.customPaneSettings !== null && this.customPaneSettings.options !== undefined) {1055this._getComparisonRows();1056}1057// Display the pane1058this.s.dtPane.draw();1059this.s.dtPane.table().node().parentNode.scrollTop = this.s.scrollTop;1060this.adjustTopRow();1061if (!this.s.listSet) {1062this._setListeners();1063this.s.listSet = true;1064}1065for (var _f = 0, selectedRows_1 = selectedRows; _f < selectedRows_1.length; _f++) {1066var selection = selectedRows_1[_f];1067if (selection !== undefined) {1068for (var _g = 0, _h = this.s.dtPane.rows().indexes().toArray(); _g < _h.length; _g++) {1069var row = _h[_g];1070if (this.s.dtPane.row(row).data() !== undefined &&1071selection.filter === this.s.dtPane.row(row).data().filter) {1072// If this is happening when serverSide processing is happening then1073// different behaviour is needed1074if (this.s.dt.page.info().serverSide) {1075this.s.serverSelecting = true;1076this.s.dtPane.row(row).select();1077this.s.serverSelecting = false;1078}1079else {1080this.s.dtPane.row(row).select();1081}1082}1083}1084}1085}1086// If SSP and the table is ready, apply the search for the pane1087if (this.s.dt.page.info().serverSide) {1088this.s.dtPane.search(this.dom.searchBox.val()).draw();1089}1090if ((this.c.initCollapsed && this.s.colOpts.initCollapsed !== false ||1091this.s.colOpts.initCollapsed) &&1092(this.c.collapse && this.s.colOpts.collapse !== false ||1093this.s.colOpts.collapse)) {1094this.collapse();1095}1096// Reload the selection, searchbox entry and ordering from the previous state1097// Need to check here if SSP that this is the first draw, otherwise it will infinite loop1098if (loadedFilter &&1099loadedFilter.searchPanes &&1100loadedFilter.searchPanes.panes &&1101(dataIn === null ||1102dataIn.draw === 1)) {1103if (!this.c.cascadePanes) {1104this._reloadSelect(loadedFilter);1105}1106for (var _j = 0, _k = loadedFilter.searchPanes.panes; _j < _k.length; _j++) {1107var pane = _k[_j];1108if (pane.id === this.s.index) {1109// Save some time by only triggering an input if there is a value1110if (pane.searchTerm && pane.searchTerm.length > 0) {1111this.dom.searchBox.val(pane.searchTerm);1112this.dom.searchBox.trigger('input');1113}1114this.s.dtPane.order(pane.order).draw();1115// Is the pane to be hidden or shown?1116if (pane.collapsed) {1117this.collapse();1118}1119else {1120this.show();1121}1122}1123}1124}1125return true;1126};1127/**1128* Update the array which holds the display and filter values for the table
1129*/
1130SearchPane.prototype._detailsPane = function () {1131var table = this.s.dt;1132this.s.rowData.arrayTotals = [];1133this.s.rowData.binsTotal = {};1134var settings = this.s.dt.settings()[0];1135var indexArray = table.rows().indexes();1136if (!this.s.dt.page.info().serverSide) {1137for (var _i = 0, indexArray_1 = indexArray; _i < indexArray_1.length; _i++) {1138var rowIdx = indexArray_1[_i];1139this._populatePaneArray(rowIdx, this.s.rowData.arrayTotals, settings, this.s.rowData.binsTotal);1140}1141}1142};1143/**1144* Appends all of the HTML elements to their relevant parent Elements
1145*/
1146SearchPane.prototype._displayPane = function () {1147var container = this.dom.container;1148var colOpts = this.s.colOpts;1149var layVal = parseInt(this.c.layout.split('-')[1], 10);1150// Empty everything to start again1151this.dom.topRow.empty();1152this.dom.dtP.empty();1153this.dom.topRow.addClass(this.classes.topRow);1154// If there are more than 3 columns defined then make there be a smaller gap between the panes1155if (layVal > 3) {1156this.dom.container.addClass(this.classes.smallGap);1157}1158this.dom.topRow.addClass(this.classes.subRowsContainer);1159this.dom.upper.appendTo(this.dom.topRow);1160this.dom.lower.appendTo(this.dom.topRow);1161this.dom.searchCont.appendTo(this.dom.upper);1162this.dom.buttonGroup.appendTo(this.dom.lower);1163// If no selections have been made in the pane then disable the clear button1164if (this.c.dtOpts.searching === false ||1165colOpts.dtOpts !== undefined && colOpts.dtOpts.searching === false ||1166(!this.c.controls || !colOpts.controls) ||1167this.customPaneSettings !== null &&1168this.customPaneSettings.dtOpts !== undefined &&1169this.customPaneSettings.dtOpts.searching !== undefined &&1170!this.customPaneSettings.dtOpts.searching) {1171this.dom.searchBox1172.removeClass(this.classes.paneInputButton)1173.addClass(this.classes.disabledButton)1174.attr('disabled', 'true');1175}1176this.dom.searchBox.appendTo(this.dom.searchCont);1177// Create the contents of the searchCont div. Worth noting that this function will change when using semantic ui1178this._searchContSetup();1179// If the clear button is allowed to show then display it1180if (this.c.clear && this.c.controls && colOpts.controls) {1181this.dom.clear.appendTo(this.dom.buttonGroup);1182}1183if (this.c.orderable && colOpts.orderable && this.c.controls && colOpts.controls) {1184this.dom.nameButton.appendTo(this.dom.buttonGroup);1185}1186// If the count column is hidden then don't display the ordering button for it1187if (this.c.viewCount &&1188colOpts.viewCount &&1189this.c.orderable &&1190colOpts.orderable &&1191this.c.controls &&1192colOpts.controls) {1193this.dom.countButton.appendTo(this.dom.buttonGroup);1194}1195if ((this.c.collapse && this.s.colOpts.collapse !== false ||1196this.s.colOpts.collapse) &&1197this.c.controls && colOpts.controls) {1198this.dom.collapseButton.appendTo(this.dom.buttonGroup);1199}1200this.dom.topRow.prependTo(this.dom.container);1201container.append(this.dom.dtP);1202container.show();1203};1204/**1205* Gets the options for the row for the customPanes
1206*
1207* @returns {object} The options for the row extended to include the options from the user.
1208*/
1209SearchPane.prototype._getBonusOptions = function () {1210// We need to reset the thresholds as if they have a value in colOpts then that value will be used1211var defaultMutator = {1212orthogonal: {1213threshold: null1214},1215threshold: null1216};1217return $.extend(true, {}, SearchPane.defaults, defaultMutator, this.c !== undefined ? this.c : {});1218};1219/**1220* Adds the custom options to the pane
1221*
1222* @returns {Array} Returns the array of rows which have been added to the pane
1223*/
1224SearchPane.prototype._getComparisonRows = function () {1225var colOpts = this.s.colOpts;1226// Find the appropriate options depending on whether this is a pane for a specific column or a custom pane1227var options = colOpts.options !== undefined1228? colOpts.options1229: this.customPaneSettings !== null && this.customPaneSettings.options !== undefined1230? this.customPaneSettings.options1231: undefined;1232if (options === undefined) {1233return;1234}1235var tableVals = this.s.dt.rows({ search: 'applied' }).data().toArray();1236var appRows = this.s.dt.rows({ search: 'applied' });1237var tableValsTotal = this.s.dt.rows().data().toArray();1238var allRows = this.s.dt.rows();1239var rows = [];1240// Clear all of the other rows from the pane, only custom options are to be displayed when they are defined1241this.s.dtPane.clear();1242for (var _i = 0, options_1 = options; _i < options_1.length; _i++) {1243var comp = options_1[_i];1244// Initialise the object which is to be placed in the row1245var insert = comp.label !== '' ?1246comp.label :1247this.emptyMessage();1248var comparisonObj = {1249className: comp.className,1250display: insert,1251filter: typeof comp.value === 'function' ? comp.value : [],1252shown: 0,1253sort: insert,1254total: 0,1255type: insert1256};1257// If a custom function is in place1258if (typeof comp.value === 'function') {1259// Count the number of times the function evaluates to true for the data currently being displayed1260for (var tVal = 0; tVal < tableVals.length; tVal++) {1261if (comp.value.call(this.s.dt, tableVals[tVal], appRows[0][tVal])) {1262comparisonObj.shown++;1263}1264}1265// Count the number of times the function evaluates to true for the original data in the Table1266for (var i = 0; i < tableValsTotal.length; i++) {1267if (comp.value.call(this.s.dt, tableValsTotal[i], allRows[0][i])) {1268comparisonObj.total++;1269}1270}1271// Update the comparisonObj1272if (typeof comparisonObj.filter !== 'function') {1273comparisonObj.filter.push(comp.filter);1274}1275}1276// If cascadePanes is not active or if it is and the comparisonObj should be shown then add it to the pane1277if (!this.c.cascadePanes || this.c.cascadePanes && comparisonObj.shown !== 0) {1278rows.push(this.addRow(comparisonObj.display, comparisonObj.filter, comparisonObj.shown, comparisonObj.total, comparisonObj.sort, comparisonObj.type, comparisonObj.className));1279}1280}1281return rows;1282};1283/**1284* Gets the options for the row for the customPanes
1285*
1286* @returns {object} The options for the row extended to include the options from the user.
1287*/
1288SearchPane.prototype._getOptions = function () {1289var table = this.s.dt;1290// We need to reset the thresholds as if they have a value in colOpts then that value will be used1291var defaultMutator = {1292collapse: null,1293emptyMessage: false,1294initCollapsed: null,1295orthogonal: {1296threshold: null1297},1298threshold: null1299};1300var columnOptions = table.settings()[0].aoColumns[this.s.index].searchPanes;1301var colOpts = $.extend(true, {}, SearchPane.defaults, defaultMutator, columnOptions);1302if (columnOptions !== undefined &&1303columnOptions.hideCount !== undefined &&1304columnOptions.viewCount === undefined) {1305colOpts.viewCount = !columnOptions.hideCount;1306}1307return colOpts;1308};1309/**1310* This method allows for changes to the panes and table to be made when a selection or a deselection occurs
1311*
1312* @param select Denotes whether a selection has been made or not
1313*/
1314SearchPane.prototype._makeSelection = function () {1315this.updateTable();1316this.s.updating = true;1317this.s.dt.draw();1318this.s.updating = false;1319};1320/**1321* Fill the array with the values that are currently being displayed in the table
1322*
1323* @param last boolean to indicate whether this was the last pane a selection was made in
1324*/
1325SearchPane.prototype._populatePane = function (last) {1326if (last === void 0) { last = false; }1327var table = this.s.dt;1328this.s.rowData.arrayFilter = [];1329this.s.rowData.bins = {};1330var settings = this.s.dt.settings()[0];1331// If cascadePanes or viewTotal are active it is necessary to get the data which is currently1332// being displayed for their functionality.1333// Also make sure that this was not the last pane to have a selection made1334if (!this.s.dt.page.info().serverSide) {1335var indexArray = (this.c.cascadePanes || this.c.viewTotal) && (!this.s.clearing && !last) ?1336table.rows({ search: 'applied' }).indexes() :1337table.rows().indexes();1338for (var _i = 0, _a = indexArray.toArray(); _i < _a.length; _i++) {1339var index = _a[_i];1340this._populatePaneArray(index, this.s.rowData.arrayFilter, settings);1341}1342}1343};1344/**1345* Populates an array with all of the data for the table
1346*
1347* @param rowIdx The current row index to be compared
1348* @param arrayFilter The array that is to be populated with row Details
1349* @param bins The bins object that is to be populated with the row counts
1350*/
1351SearchPane.prototype._populatePaneArray = function (rowIdx, arrayFilter, settings, bins) {1352if (bins === void 0) { bins = this.s.rowData.bins; }1353var colOpts = this.s.colOpts;1354// Retrieve the rendered data from the cell using the fnGetCellData function1355// rather than the cell().render API method for optimisation1356if (typeof colOpts.orthogonal === 'string') {1357var rendered = settings.oApi._fnGetCellData(settings, rowIdx, this.s.index, colOpts.orthogonal);1358this.s.rowData.filterMap.set(rowIdx, rendered);1359this._addOption(rendered, rendered, rendered, rendered, arrayFilter, bins);1360}1361else {1362var filter = settings.oApi._fnGetCellData(settings, rowIdx, this.s.index, colOpts.orthogonal.search);1363// Null and empty string are to be considered the same value1364if (filter === null) {1365filter = '';1366}1367if (typeof filter === 'string') {1368filter = filter.replace(/<[^>]*>/g, '');1369}1370this.s.rowData.filterMap.set(rowIdx, filter);1371if (!bins[filter]) {1372bins[filter] = 1;1373this._addOption(filter, settings.oApi._fnGetCellData(settings, rowIdx, this.s.index, colOpts.orthogonal.display), settings.oApi._fnGetCellData(settings, rowIdx, this.s.index, colOpts.orthogonal.sort), settings.oApi._fnGetCellData(settings, rowIdx, this.s.index, colOpts.orthogonal.type), arrayFilter, bins);1374this.s.rowData.totalOptions++;1375}1376else {1377bins[filter]++;1378this.s.rowData.totalOptions++;1379return;1380}1381}1382};1383/**1384* Reloads all of the previous selects into the panes
1385*
1386* @param loadedFilter The loaded filters from a previous state
1387*/
1388SearchPane.prototype._reloadSelect = function (loadedFilter) {1389// If the state was not saved don't selected any1390if (loadedFilter === undefined) {1391return;1392}1393var idx;1394// For each pane, check that the loadedFilter list exists and is not null,1395// find the id of each search item and set it to be selected.1396for (var i = 0; i < loadedFilter.searchPanes.panes.length; i++) {1397if (loadedFilter.searchPanes.panes[i].id === this.s.index) {1398idx = i;1399break;1400}1401}1402if (idx !== undefined) {1403var table = this.s.dtPane;1404var rows = table.rows({ order: 'index' }).data().map(function (item) { return item.filter !== null ?1405item.filter.toString() :1406null; }).toArray();1407for (var _i = 0, _a = loadedFilter.searchPanes.panes[idx].selected; _i < _a.length; _i++) {1408var filter = _a[_i];1409var id = -1;1410if (filter !== null) {1411id = rows.indexOf(filter.toString());1412}1413if (id > -1) {1414this.s.serverSelecting = true;1415table.row(id).select();1416this.s.serverSelecting = false;1417}1418}1419}1420};1421/**1422* This method decides whether a row should contribute to the pane or not
1423*
1424* @param filter the value that the row is to be filtered on
1425* @param dataIndex the row index
1426*/
1427SearchPane.prototype._search = function (filter, dataIndex) {1428var colOpts = this.s.colOpts;1429var table = this.s.dt;1430// For each item selected in the pane, check if it is available in the cell1431for (var _i = 0, _a = this.selections; _i < _a.length; _i++) {1432var colSelect = _a[_i];1433if (typeof colSelect.filter === 'string' && typeof filter === 'string') {1434// The filter value will not have the & in place but a &,1435// so we need to do a replace to make sure that they will match1436colSelect.filter = colSelect.filter1437.replace(/&/g, '&')1438.replace(/</g, '<')1439.replace(/>/g, '>')1440.replace(/"/g, '"');1441}1442// if the filter is an array then is the column present in it1443if (Array.isArray(filter)) {1444if (filter.includes(colSelect.filter)) {1445return true;1446}1447}1448// if the filter is a function then does it meet the criteria of that function or not1449else if (typeof colSelect.filter === 'function') {1450if (colSelect.filter.call(table, table.row(dataIndex).data(), dataIndex)) {1451if (colOpts.combiner === 'or') {1452return true;1453}1454}1455// If the combiner is an "and" then we need to check against all possible selections1456// so if it fails here then the and is not met and return false1457else if (colOpts.combiner === 'and') {1458return false;1459}1460}1461// otherwise if the two filter values are equal then return true1462else if (filter === colSelect.filter ||1463// Loose type checking incase number type in column comparing to a string1464// eslint-disable-next-line eqeqeq1465!(typeof filter === 'string' && filter.length === 0) && filter == colSelect.filter ||1466colSelect.filter === null && typeof filter === 'string' && filter === '') {1467return true;1468}1469}1470// If the combiner is an and then we need to check against all possible selections1471// so return true here if so because it would have returned false earlier if it had failed1472if (colOpts.combiner === 'and') {1473return true;1474}1475// Otherwise it hasn't matched with anything by this point so it must be false1476else {1477return false;1478}1479};1480/**1481* Creates the contents of the searchCont div
1482*
1483* NOTE This is overridden when semantic ui styling in order to integrate the search button into the text box.
1484*/
1485SearchPane.prototype._searchContSetup = function () {1486if (this.c.controls && this.s.colOpts.controls) {1487this.dom.searchButton.appendTo(this.dom.searchLabelCont);1488}1489if (!(this.c.dtOpts.searching === false ||1490this.s.colOpts.dtOpts.searching === false ||1491this.customPaneSettings !== null &&1492this.customPaneSettings.dtOpts !== undefined &&1493this.customPaneSettings.dtOpts.searching !== undefined &&1494!this.customPaneSettings.dtOpts.searching)) {1495this.dom.searchLabelCont.appendTo(this.dom.searchCont);1496}1497};1498/**1499* Adds outline to the pane when a selection has been made
1500*/
1501SearchPane.prototype._searchExtras = function () {1502var updating = this.s.updating;1503this.s.updating = true;1504var filters = this.s.dtPane.rows({ selected: true }).data().pluck('filter').toArray();1505var nullIndex = filters.indexOf(this.emptyMessage());1506var container = $(this.s.dtPane.table().container());1507// If null index is found then search for empty cells as a filter.1508if (nullIndex > -1) {1509filters[nullIndex] = '';1510}1511// If a filter has been applied then outline the respective pane, remove it when it no longer is.1512if (filters.length > 0) {1513container.addClass(this.classes.selected);1514}1515else if (filters.length === 0) {1516container.removeClass(this.classes.selected);1517}1518this.s.updating = updating;1519};1520/**1521* Finds the ratio of the number of different options in the table to the number of rows
1522*
1523* @param bins the number of different options in the table
1524* @param rowCount the total number of rows in the table
1525* @returns {number} returns the ratio
1526*/
1527SearchPane.prototype._uniqueRatio = function (bins, rowCount) {1528if (rowCount > 0 &&1529(this.s.rowData.totalOptions > 0 && !this.s.dt.page.info().serverSide ||1530this.s.dt.page.info().serverSide && this.s.tableLength > 0)) {1531return bins / this.s.rowData.totalOptions;1532}1533else {1534return 1;1535}1536};1537/**1538* updates the options within the pane
1539*
1540* @param draw a flag to define whether this has been called due to a draw event or not
1541*/
1542SearchPane.prototype._updateCommon = function (draw) {1543if (draw === void 0) { draw = false; }1544// Update the panes if doing a deselect. if doing a select then1545// update all of the panes except for the one causing the change1546if (!this.s.dt.page.info().serverSide &&1547this.s.dtPane !== undefined &&1548(!this.s.filteringActive || this.c.cascadePanes || draw === true) &&1549(this.c.cascadePanes !== true || this.s.selectPresent !== true) &&1550(!this.s.lastSelect || !this.s.lastCascade)) {1551var colOpts = this.s.colOpts;1552var selected = this.s.dtPane.rows({ selected: true }).data().toArray();1553var rowData = this.s.rowData;1554// Clear the pane in preparation for adding the updated search options1555this.s.dtPane.clear();1556// If it is not a custom pane1557if (this.colExists) {1558// Only run populatePane if the data has not been collected yet1559if (rowData.arrayFilter.length === 0) {1560this._populatePane(!this.s.filteringActive);1561}1562// If cascadePanes is active and the table has returned to its default state then1563// there is a need to update certain parts ofthe rowData.1564else if (this.c.cascadePanes &&1565this.s.dt.rows().data().toArray().length ===1566this.s.dt.rows({ search: 'applied' }).data().toArray().length) {1567rowData.arrayFilter = rowData.arrayOriginal;1568rowData.bins = rowData.binsOriginal;1569}1570// Otherwise if viewTotal or cascadePanes is active then the data from the table must be read.1571else if (this.c.viewTotal || this.c.cascadePanes) {1572this._populatePane(!this.s.filteringActive);1573}1574// If the viewTotal option is selected then find the totals for the table1575if (this.c.viewTotal) {1576this._detailsPane();1577}1578else {1579rowData.binsTotal = rowData.bins;1580}1581if (this.c.viewTotal && !this.c.cascadePanes) {1582rowData.arrayFilter = rowData.arrayTotals;1583}1584var _loop_1 = function (dataP) {1585// If both view Total and cascadePanes have been selected and the count of the row1586// is not 0 then add it to pane1587// Do this also if the viewTotal option has been selected and cascadePanes has not1588if (dataP &&1589(rowData.bins[dataP.filter] !== undefined &&1590rowData.bins[dataP.filter] !== 0 &&1591this_1.c.cascadePanes ||1592!this_1.c.cascadePanes ||1593this_1.s.clearing)) {1594var row = this_1.addRow(dataP.display, dataP.filter, !this_1.c.viewTotal ?1595rowData.bins[dataP.filter] :1596rowData.bins[dataP.filter] !== undefined ?1597rowData.bins[dataP.filter] :15980, this_1.c.viewTotal ?1599String(rowData.binsTotal[dataP.filter]) :1600rowData.bins[dataP.filter], dataP.sort, dataP.type);1601// Find out if the filter was selected in the previous search,1602// if so select it and remove from array.1603var selectIndex = selected.findIndex(function (element) {1604return element.filter === dataP.filter;1605});1606if (selectIndex !== -1) {1607row.select();1608selected.splice(selectIndex, 1);1609}1610}1611};1612var this_1 = this;1613for (var _i = 0, _a = rowData.arrayFilter; _i < _a.length; _i++) {1614var dataP = _a[_i];1615_loop_1(dataP);1616}1617}1618if (colOpts.searchPanes !== undefined && colOpts.searchPanes.options !== undefined ||1619colOpts.options !== undefined ||1620this.customPaneSettings !== null && this.customPaneSettings.options !== undefined) {1621var rows = this._getComparisonRows();1622var _loop_2 = function (row) {1623var selectIndex = selected.findIndex(function (element) {1624if (element.display === row.data().display) {1625return true;1626}1627});1628if (selectIndex !== -1) {1629row.select();1630selected.splice(selectIndex, 1);1631}1632};1633for (var _b = 0, rows_1 = rows; _b < rows_1.length; _b++) {1634var row = rows_1[_b];1635_loop_2(row);1636}1637}1638// Add search options which were previously selected but whos results are no1639// longer present in the resulting data set.1640for (var _c = 0, selected_1 = selected; _c < selected_1.length; _c++) {1641var selectedEl = selected_1[_c];1642var row = this.addRow(selectedEl.display, selectedEl.filter, 0, this.c.viewTotal1643? selectedEl.total1644: 0, selectedEl.display, selectedEl.display);1645this.s.updating = true;1646row.select();1647this.s.updating = false;1648}1649this.s.dtPane.draw();1650this.s.dtPane.table().node().parentNode.scrollTop = this.s.scrollTop;1651}1652};1653SearchPane.version = '1.3.0';1654SearchPane.classes = {1655bordered: 'dtsp-bordered',1656buttonGroup: 'dtsp-buttonGroup',1657buttonSub: 'dtsp-buttonSub',1658clear: 'dtsp-clear',1659clearAll: 'dtsp-clearAll',1660clearButton: 'clearButton',1661collapseAll: 'dtsp-collapseAll',1662collapseButton: 'dtsp-collapseButton',1663container: 'dtsp-searchPane',1664countButton: 'dtsp-countButton',1665disabledButton: 'dtsp-disabledButton',1666hidden: 'dtsp-hidden',1667hide: 'dtsp-hide',1668layout: 'dtsp-',1669name: 'dtsp-name',1670nameButton: 'dtsp-nameButton',1671nameCont: 'dtsp-nameCont',1672narrow: 'dtsp-narrow',1673paneButton: 'dtsp-paneButton',1674paneInputButton: 'dtsp-paneInputButton',1675pill: 'dtsp-pill',1676rotated: 'dtsp-rotated',1677search: 'dtsp-search',1678searchCont: 'dtsp-searchCont',1679searchIcon: 'dtsp-searchIcon',1680searchLabelCont: 'dtsp-searchButtonCont',1681selected: 'dtsp-selected',1682smallGap: 'dtsp-smallGap',1683subRow1: 'dtsp-subRow1',1684subRow2: 'dtsp-subRow2',1685subRowsContainer: 'dtsp-subRowsContainer',1686title: 'dtsp-title',1687topRow: 'dtsp-topRow'1688};1689// Define SearchPanes default options1690SearchPane.defaults = {1691cascadePanes: false,1692clear: true,1693collapse: true,1694combiner: 'or',1695container: function (dt) {1696return dt.table().container();1697},1698controls: true,1699dtOpts: {},1700emptyMessage: null,1701hideCount: false,1702i18n: {1703clearPane: '×',1704count: '{total}',1705countFiltered: '{shown} ({total})',1706emptyMessage: '<em>No data</em>'1707},1708initCollapsed: false,1709layout: 'auto',1710name: undefined,1711orderable: true,1712orthogonal: {1713display: 'display',1714filter: 'filter',1715hideCount: false,1716search: 'filter',1717show: undefined,1718sort: 'sort',1719threshold: 0.6,1720type: 'type',1721viewCount: true1722},1723preSelect: [],1724threshold: 0.6,1725viewCount: true,1726viewTotal: false1727};1728return SearchPane;1729}());1730
1731var $$1;1732var dataTable$1;1733function setJQuery$1(jq) {1734$$1 = jq;1735dataTable$1 = jq.fn.dataTable;1736}1737var SearchPanes = /** @class */ (function () {1738function SearchPanes(paneSettings, opts, fromInit) {1739var _this = this;1740if (fromInit === void 0) { fromInit = false; }1741this.regenerating = false;1742// Check that the required version of DataTables is included1743if (!dataTable$1 || !dataTable$1.versionCheck || !dataTable$1.versionCheck('1.10.0')) {1744throw new Error('SearchPane requires DataTables 1.10 or newer');1745}1746// Check that Select is included1747// eslint-disable-next-line no-extra-parens1748if (!dataTable$1.select) {1749throw new Error('SearchPane requires Select');1750}1751var table = new dataTable$1.Api(paneSettings);1752this.classes = $$1.extend(true, {}, SearchPanes.classes);1753// Get options from user1754this.c = $$1.extend(true, {}, SearchPanes.defaults, opts);1755// Add extra elements to DOM object including clear1756this.dom = {1757clearAll: $$1('<button type="button">Clear All</button>').addClass(this.classes.clearAll),1758collapseAll: $$1('<button type="button">Collapse All</button>').addClass(this.classes.collapseAll),1759container: $$1('<div/>').addClass(this.classes.panes).text(table.i18n('searchPanes.loadMessage', this.c.i18n.loadMessage)),1760emptyMessage: $$1('<div/>').addClass(this.classes.emptyMessage),1761options: $$1('<div/>').addClass(this.classes.container),1762panes: $$1('<div/>').addClass(this.classes.container),1763showAll: $$1('<button type="button">Show All</button>')1764.addClass(this.classes.showAll)1765.addClass(this.classes.disabledButton)1766.attr('disabled', 'true'),1767title: $$1('<div/>').addClass(this.classes.title),1768titleRow: $$1('<div/>').addClass(this.classes.titleRow),1769wrapper: $$1('<div/>')1770};1771this.s = {1772colOpts: [],1773dt: table,1774filterCount: 0,1775filterPane: -1,1776page: 0,1777paging: false,1778panes: [],1779selectionList: [],1780serverData: {},1781stateRead: false,1782updating: false1783};1784if (table.settings()[0]._searchPanes !== undefined) {1785return;1786}1787this._getState();1788if (this.s.dt.page.info().serverSide) {1789table.on('preXhr.dt', function (e, settings, data) {1790if (data.searchPanes === undefined) {1791data.searchPanes = {};1792}1793if (data.searchPanes_null === undefined) {1794data.searchPanes_null = {};1795}1796for (var _i = 0, _a = _this.s.selectionList; _i < _a.length; _i++) {1797var selection = _a[_i];1798var src = _this.s.dt.column(selection.index).dataSrc();1799if (data.searchPanes[src] === undefined) {1800data.searchPanes[src] = {};1801}1802if (data.searchPanes_null[src] === undefined) {1803data.searchPanes_null[src] = {};1804}1805for (var i = 0; i < selection.rows.length; i++) {1806data.searchPanes[src][i] = selection.rows[i].filter;1807if (data.searchPanes[src][i] === null) {1808data.searchPanes_null[src][i] = true;1809}1810}1811}1812});1813}1814// We are using the xhr event to rebuild the panes if required due to viewTotal being enabled1815// If viewTotal is not enabled then we simply update the data from the server1816table.on('xhr', function (e, settings, json, xhr) {1817if (json && json.searchPanes && json.searchPanes.options) {1818_this.s.serverData = json;1819_this.s.serverData.tableLength = json.recordsTotal;1820_this._serverTotals();1821}1822});1823table.settings()[0]._searchPanes = this;1824this.dom.clearAll.text(table.i18n('searchPanes.clearMessage', this.c.i18n.clearMessage));1825this.dom.collapseAll.text(table.i18n('searchPanes.collapseMessage', this.c.i18n.collapseMessage));1826this.dom.showAll.text(table.i18n('searchPanes.showMessage', this.c.i18n.showMessage));1827if (this.s.dt.settings()[0]._bInitComplete || fromInit) {1828this._paneDeclare(table, paneSettings, opts);1829}1830else {1831table.one('preInit.dt', function (settings) {1832_this._paneDeclare(table, paneSettings, opts);1833});1834}1835return this;1836}1837/**1838* Clear the selections of all of the panes
1839*/
1840SearchPanes.prototype.clearSelections = function () {1841// Load in all of the searchBoxes in the documents1842var searches = this.dom.container.find('.' + this.classes.search.replace(/\s+/g, '.'));1843// For each searchBox set the input text to be empty and then trigger1844// an input on them so that they no longer filter the panes1845searches.each(function () {1846$$1(this).val('');1847$$1(this).trigger('input');1848});1849var returnArray = [];1850// Clear the selectionList to prevent cascadePanes from reselecting rows1851this.s.selectionList = [];1852// For every pane, clear the selections in the pane1853for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {1854var pane = _a[_i];1855if (pane.s.dtPane !== undefined) {1856returnArray.push(pane.clearPane());1857}1858}1859return returnArray;1860};1861/**1862* returns the container node for the searchPanes
1863*/
1864SearchPanes.prototype.getNode = function () {1865return this.dom.container;1866};1867/**1868* rebuilds all of the panes
1869*/
1870SearchPanes.prototype.rebuild = function (targetIdx, maintainSelection) {1871if (targetIdx === void 0) { targetIdx = false; }1872if (maintainSelection === void 0) { maintainSelection = false; }1873this.dom.emptyMessage.remove();1874// As a rebuild from scratch is required, empty the searchpanes container.1875var returnArray = [];1876// Rebuild each pane individually, if a specific pane has been selected then only rebuild that one1877if (targetIdx === false) {1878this.dom.panes.empty();1879}1880for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {1881var pane = _a[_i];1882if (targetIdx !== false && pane.s.index !== targetIdx) {1883continue;1884}1885pane.clearData();1886returnArray.push(1887// Pass a boolean to say whether this is the last choice made for maintaining selections when rebuilding1888pane.rebuildPane(this.s.selectionList[this.s.selectionList.length - 1] !== undefined ?1889pane.s.index === this.s.selectionList[this.s.selectionList.length - 1].index :1890false, this.s.dt.page.info().serverSide ?1891this.s.serverData :1892undefined, null, maintainSelection));1893this.dom.panes.append(pane.dom.container);1894}1895if (this.c.cascadePanes || this.c.viewTotal) {1896this.redrawPanes(true);1897}1898else {1899this._updateSelection();1900}1901// Attach panes, clear buttons, and title bar to the document1902this._updateFilterCount();1903this._attachPaneContainer();1904// If the selections are to be maintained, then it is safe to assume that paging is also to be maintained1905// Otherwise, the paging should be reset1906this.s.dt.draw(!maintainSelection);1907// Resize the panes incase there has been a change1908this.resizePanes();1909// If a single pane has been rebuilt then return only that pane1910if (returnArray.length === 1) {1911return returnArray[0];1912}1913// Otherwise return all of the panes that have been rebuilt1914else {1915return returnArray;1916}1917};1918/**1919* Redraws all of the panes
1920*/
1921SearchPanes.prototype.redrawPanes = function (rebuild) {1922if (rebuild === void 0) { rebuild = false; }1923var table = this.s.dt;1924// Only do this if the redraw isn't being triggered by the panes updating themselves1925if (!this.s.updating && !this.s.dt.page.info().serverSide) {1926var filterActive = true;1927var filterPane = this.s.filterPane;1928var selectTotal = null;1929for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {1930var pane = _a[_i];1931if (pane.s.dtPane !== undefined) {1932selectTotal += pane.s.dtPane.rows({ selected: true }).data().toArray().length;1933}1934}1935// If the number of rows currently visible is equal to the number of rows in the table1936// then there can't be any filtering taking place1937if (selectTotal === 0 &&1938table.rows({ search: 'applied' }).data().toArray().length === table.rows().data().toArray().length) {1939filterActive = false;1940}1941// Otherwise if viewTotal is active then it is necessary to determine which panes a select is present in.1942// If there is only one pane with a selection present then it should not show the filtered message as1943// more selections may be made in that pane.1944else if (this.c.viewTotal) {1945for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {1946var pane = _c[_b];1947if (pane.s.dtPane !== undefined) {1948var selectLength = pane.s.dtPane.rows({ selected: true }).data().toArray().length;1949if (selectLength === 0) {1950for (var _d = 0, _e = this.s.selectionList; _d < _e.length; _d++) {1951var selection = _e[_d];1952if (selection.index === pane.s.index && selection.rows.length !== 0) {1953selectLength = selection.rows.length;1954}1955}1956}1957// If filterPane === -1 then a pane with a selection has not been found yet,1958// so set filterPane to that panes index1959if (selectLength > 0 && filterPane === -1) {1960filterPane = pane.s.index;1961}1962// Then if another pane is found with a selection then set filterPane to null to1963// show that multiple panes have selections present1964else if (selectLength > 0) {1965filterPane = null;1966}1967}1968}1969// If the searchbox is in place and filtering is applied then need to cascade down anyway1970if (selectTotal === 0) {1971filterPane = null;1972}1973}1974var deselectIdx = void 0;1975var newSelectionList = [];1976// Don't run this if it is due to the panes regenerating1977if (!this.regenerating) {1978for (var _f = 0, _g = this.s.panes; _f < _g.length; _f++) {1979var pane = _g[_f];1980// Identify the pane where a selection or deselection has been made and add it to the list.1981if (pane.s.selectPresent) {1982this.s.selectionList.push({1983index: pane.s.index,1984protect: false,1985rows: pane.s.dtPane.rows({ selected: true }).data().toArray()1986});1987break;1988}1989else if (pane.s.deselect) {1990deselectIdx = pane.s.index;1991var selectedData = pane.s.dtPane.rows({ selected: true }).data().toArray();1992if (selectedData.length > 0) {1993this.s.selectionList.push({1994index: pane.s.index,1995protect: true,1996rows: selectedData1997});1998}1999}2000}2001if (this.s.selectionList.length > 0) {2002var last = this.s.selectionList[this.s.selectionList.length - 1].index;2003for (var _h = 0, _j = this.s.panes; _h < _j.length; _h++) {2004var pane = _j[_h];2005pane.s.lastSelect = pane.s.index === last;2006}2007}2008// Remove selections from the list from the pane where a deselect has taken place2009for (var i = 0; i < this.s.selectionList.length; i++) {2010if (this.s.selectionList[i].index !== deselectIdx || this.s.selectionList[i].protect === true) {2011var further = false;2012// Find out if this selection is the last one in the list for that pane2013for (var j = i + 1; j < this.s.selectionList.length; j++) {2014if (this.s.selectionList[j].index === this.s.selectionList[i].index) {2015further = true;2016}2017}2018// If there are no selections for this pane in the list then just push this one2019if (!further) {2020newSelectionList.push(this.s.selectionList[i]);2021this.s.selectionList[i].protect = false;2022}2023}2024}2025var solePane = -1;2026if (newSelectionList.length === 1 && selectTotal !== null && selectTotal !== 0) {2027solePane = newSelectionList[0].index;2028}2029// Update all of the panes to reflect the current state of the filters2030for (var _k = 0, _l = this.s.panes; _k < _l.length; _k++) {2031var pane = _l[_k];2032if (pane.s.dtPane !== undefined) {2033var tempFilter = true;2034pane.s.filteringActive = true;2035if (filterPane !== -1 && filterPane !== null && filterPane === pane.s.index ||2036filterActive === false ||2037pane.s.index === solePane) {2038tempFilter = false;2039pane.s.filteringActive = false;2040}2041pane.updatePane(!tempFilter ? false : filterActive);2042}2043}2044// If the length of the selections are different then some of them have been2045// removed and a deselect has occured2046if (newSelectionList.length > 0 && (newSelectionList.length < this.s.selectionList.length || rebuild)) {2047this._cascadeRegen(newSelectionList, selectTotal);2048var last = newSelectionList[newSelectionList.length - 1].index;2049for (var _m = 0, _o = this.s.panes; _m < _o.length; _m++) {2050var pane = _o[_m];2051pane.s.lastSelect = pane.s.index === last;2052}2053}2054else if (newSelectionList.length > 0) {2055// Update all of the other panes as you would just making a normal selection2056for (var _p = 0, _q = this.s.panes; _p < _q.length; _p++) {2057var paneUpdate = _q[_p];2058if (paneUpdate.s.dtPane !== undefined) {2059var tempFilter = true;2060paneUpdate.s.filteringActive = true;2061if (filterPane !== -1 && filterPane !== null && filterPane === paneUpdate.s.index ||2062filterActive === false ||2063paneUpdate.s.index === solePane) {2064tempFilter = false;2065paneUpdate.s.filteringActive = false;2066}2067paneUpdate.updatePane(!tempFilter ? tempFilter : filterActive);2068}2069}2070}2071// Update the label that shows how many filters are in place2072this._updateFilterCount();2073}2074else {2075var solePane = -1;2076if (newSelectionList.length === 1 && selectTotal !== null && selectTotal !== 0) {2077solePane = newSelectionList[0].index;2078}2079for (var _r = 0, _s = this.s.panes; _r < _s.length; _r++) {2080var pane = _s[_r];2081if (pane.s.dtPane !== undefined) {2082var tempFilter = true;2083pane.s.filteringActive = true;2084if (filterPane !== -1 && filterPane !== null && filterPane === pane.s.index ||2085filterActive === false ||2086pane.s.index === solePane) {2087tempFilter = false;2088pane.s.filteringActive = false;2089}2090pane.updatePane(!tempFilter ? tempFilter : filterActive);2091}2092}2093// Update the label that shows how many filters are in place2094this._updateFilterCount();2095}2096if (!filterActive || selectTotal === 0) {2097this.s.selectionList = [];2098}2099}2100};2101/**2102* Resizes all of the panes
2103*/
2104SearchPanes.prototype.resizePanes = function () {2105if (this.c.layout === 'auto') {2106var contWidth = $$1(this.s.dt.searchPanes.container()).width();2107var target = Math.floor(contWidth / 260.0); // The neatest number of panes per row2108var highest = 1;2109var highestmod = 0;2110var dispIndex = [];2111// Get the indexes of all of the displayed panes2112for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2113var pane = _a[_i];2114if (pane.s.displayed) {2115dispIndex.push(pane.s.index);2116}2117}2118var displayCount = dispIndex.length;2119// If the neatest number is the number we have then use this.2120if (target === displayCount) {2121highest = target;2122}2123else {2124// Go from the target down and find the value with the most panes left over, this will be the best fit2125for (var ppr = target; ppr > 1; ppr--) {2126var rem = displayCount % ppr;2127if (rem === 0) {2128highest = ppr;2129highestmod = 0;2130break;2131}2132// If there are more left over at this amount of panes per row (ppr)2133// then it fits better so new values2134else if (rem > highestmod) {2135highest = ppr;2136highestmod = rem;2137}2138}2139}2140// If there is a perfect fit then none are to be wider2141var widerIndexes = highestmod !== 0 ? dispIndex.slice(dispIndex.length - highestmod, dispIndex.length) : [];2142for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {2143var pane = _c[_b];2144// Resize the pane with the new layout2145if (pane.s.displayed) {2146var layout = 'columns-' + (!widerIndexes.includes(pane.s.index) ? highest : highestmod);2147pane.resize(layout);2148}2149}2150}2151else {2152for (var _d = 0, _e = this.s.panes; _d < _e.length; _d++) {2153var pane = _e[_d];2154pane.adjustTopRow();2155}2156}2157return this;2158};2159/**2160* Attach the panes, buttons and title to the document
2161*/
2162SearchPanes.prototype._attach = function () {2163var _this = this;2164this.dom.container.removeClass(this.classes.hide);2165this.dom.titleRow.removeClass(this.classes.hide);2166this.dom.titleRow.remove();2167this.dom.title.appendTo(this.dom.titleRow);2168// If the clear button is permitted attach it2169if (this.c.clear) {2170this.dom.clearAll.appendTo(this.dom.titleRow);2171this.dom.clearAll.on('click.dtsps', function () {2172_this.clearSelections();2173});2174}2175if (this.c.collapse) {2176this._setCollapseListener();2177}2178this.dom.titleRow.appendTo(this.dom.container);2179// Attach the container for each individual pane to the overall container2180for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2181var pane = _a[_i];2182pane.dom.container.appendTo(this.dom.panes);2183}2184// Attach everything to the document2185this.dom.panes.appendTo(this.dom.container);2186if ($$1('div.' + this.classes.container).length === 0) {2187this.dom.container.prependTo(this.s.dt);2188}2189return this.dom.container;2190};2191/**2192* Attach the top row containing the filter count and clear all button
2193*/
2194SearchPanes.prototype._attachExtras = function () {2195this.dom.container.removeClass(this.classes.hide);2196this.dom.titleRow.removeClass(this.classes.hide);2197this.dom.titleRow.remove();2198this.dom.title.appendTo(this.dom.titleRow);2199// If the clear button is permitted attach it2200if (this.c.clear) {2201this.dom.clearAll.appendTo(this.dom.titleRow);2202}2203// If collapsing is permitted attach those buttons2204if (this.c.collapse) {2205this.dom.showAll.appendTo(this.dom.titleRow);2206this.dom.collapseAll.appendTo(this.dom.titleRow);2207}2208this.dom.titleRow.appendTo(this.dom.container);2209return this.dom.container;2210};2211/**2212* If there are no panes to display then this method is called to either
2213* display a message in their place or hide them completely.
2214*/
2215SearchPanes.prototype._attachMessage = function () {2216// Create a message to display on the screen2217var message;2218try {2219message = this.s.dt.i18n('searchPanes.emptyPanes', this.c.i18n.emptyPanes);2220}2221catch (error) {2222message = null;2223}2224// If the message is an empty string then searchPanes.emptyPanes is undefined,2225// therefore the pane container should be removed from the display2226if (message === null) {2227this.dom.container.addClass(this.classes.hide);2228this.dom.titleRow.removeClass(this.classes.hide);2229return;2230}2231else {2232this.dom.container.removeClass(this.classes.hide);2233this.dom.titleRow.addClass(this.classes.hide);2234}2235// Otherwise display the message2236this.dom.emptyMessage.text(message);2237this.dom.emptyMessage.appendTo(this.dom.container);2238return this.dom.container;2239};2240/**2241* Attaches the panes to the document and displays a message or hides if there are none
2242*/
2243SearchPanes.prototype._attachPaneContainer = function () {2244// If a pane is to be displayed then attach the normal pane output2245for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2246var pane = _a[_i];2247if (pane.s.displayed === true) {2248return this._attach();2249}2250}2251// Otherwise attach the custom message or remove the container from the display2252return this._attachMessage();2253};2254/**2255* Prepares the panes for selections to be made when cascade is active and a deselect has occured
2256*
2257* @param newSelectionList the list of selections which are to be made
2258*/
2259SearchPanes.prototype._cascadeRegen = function (newSelectionList, selectTotal) {2260// Set this to true so that the actions taken do not cause this to run until it is finished2261this.regenerating = true;2262// If only one pane has been selected then take note of its index2263var solePane = -1;2264if (newSelectionList.length === 1 && selectTotal !== null && selectTotal !== 0) {2265solePane = newSelectionList[0].index;2266}2267// Let the pane know that a cascadeRegen is taking place to avoid unexpected behaviour2268// and clear all of the previous selections in the pane2269for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2270var pane = _a[_i];2271pane.setCascadeRegen(true);2272pane.setClear(true);2273// If this is the same as the pane with the only selection then pass it as a parameter into clearPane2274if (pane.s.dtPane !== undefined && pane.s.index === solePane || pane.s.dtPane !== undefined) {2275pane.clearPane();2276}2277pane.setClear(false);2278}2279// Rebin panes2280this.s.dt.draw();2281// While all of the selections have been removed, check the table lengths2282// If they are different, another filter is in place and we need to force viewTotal to be used2283var noSelectionsTableLength = this.s.dt.rows({ search: 'applied' }).data().toArray().length;2284var tableLength = this.s.dt.rows().data().toArray().length;2285if (tableLength !== noSelectionsTableLength) {2286for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {2287var pane = _c[_b];2288pane.s.forceViewTotal = true;2289}2290}2291for (var _d = 0, _e = this.s.panes; _d < _e.length; _d++) {2292var pane = _e[_d];2293pane.updatePane(true);2294}2295// Remake Selections2296this._makeCascadeSelections(newSelectionList);2297// Set the selection list property to be the list without the selections from the deselect pane2298this.s.selectionList = newSelectionList;2299// The regeneration of selections is over so set it back to false2300for (var _f = 0, _g = this.s.panes; _f < _g.length; _f++) {2301var pane = _g[_f];2302pane.setCascadeRegen(false);2303}2304this.regenerating = false;2305// ViewTotal has already been forced at this point so can cancel that for future2306if (tableLength !== noSelectionsTableLength) {2307for (var _h = 0, _j = this.s.panes; _h < _j.length; _h++) {2308var pane = _j[_h];2309pane.s.forceViewTotal = false;2310}2311}2312};2313/**2314* Attaches the message to the document but does not add any panes
2315*/
2316SearchPanes.prototype._checkMessage = function () {2317// If a pane is to be displayed then attach the normal pane output2318for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2319var pane = _a[_i];2320if (pane.s.displayed === true) {2321// Ensure that the empty message is removed if a pane is displayed2322this.dom.emptyMessage.remove();2323this.dom.titleRow.removeClass(this.classes.hide);2324return;2325}2326}2327// Otherwise attach the custom message or remove the container from the display2328return this._attachMessage();2329};2330/**2331* Checks which panes are collapsed and then performs relevant actions to the collapse/show all buttons
2332*
2333* @param pane The pane to be checked
2334*/
2335SearchPanes.prototype._checkCollapse = function () {2336var disableClose = true;2337var disableShow = true;2338for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2339var pane = _a[_i];2340if (pane.s.displayed) {2341// It the pane is not collapsed2342if (!pane.dom.collapseButton.hasClass(pane.classes.rotated)) {2343// Enable the collapse all button2344this.dom.collapseAll.removeClass(this.classes.disabledButton).removeAttr('disabled');2345disableClose = false;2346}2347else {2348// Otherwise enable the show all button2349this.dom.showAll.removeClass(this.classes.disabledButton).removeAttr('disabled');2350disableShow = false;2351}2352}2353}2354// If this flag is still true, no panes are open so the close button should be disabled2355if (disableClose) {2356this.dom.collapseAll.addClass(this.classes.disabledButton).attr('disabled', 'true');2357}2358// If this flag is still true, no panes are closed so the show button should be disabled2359if (disableShow) {2360this.dom.showAll.addClass(this.classes.disabledButton).attr('disabled', 'true');2361}2362};2363/**2364* Collapses all of the panes
2365*/
2366SearchPanes.prototype._collapseAll = function () {2367for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2368var pane = _a[_i];2369pane.collapse();2370}2371};2372/**2373* Gets the selection list from the previous state and stores it in the selectionList Property
2374*/
2375SearchPanes.prototype._getState = function () {2376var loadedFilter = this.s.dt.state.loaded();2377if (loadedFilter && loadedFilter.searchPanes && loadedFilter.searchPanes.selectionList !== undefined) {2378this.s.selectionList = loadedFilter.searchPanes.selectionList;2379}2380};2381/**2382* Makes all of the selections when cascade is active
2383*
2384* @param newSelectionList the list of selections to be made, in the order they were originally selected
2385*/
2386SearchPanes.prototype._makeCascadeSelections = function (newSelectionList) {2387// make selections in the order they were made previously,2388// excluding those from the pane where a deselect was made2389for (var i = 0; i < newSelectionList.length; i++) {2390var _loop_1 = function (pane) {2391if (pane.s.index === newSelectionList[i].index && pane.s.dtPane !== undefined) {2392// When regenerating the cascade selections we need this flag so that2393// the panes are only ignored if it2394// is the last selection and the pane for that selection2395if (i === newSelectionList.length - 1) {2396pane.s.lastCascade = true;2397}2398// if there are any selections currently in the pane then2399// deselect them as we are about to make our new selections2400if (pane.s.dtPane.rows({ selected: true }).data().toArray().length > 0 && pane.s.dtPane !== undefined) {2401pane.setClear(true);2402pane.clearPane();2403pane.setClear(false);2404}2405var _loop_2 = function (row) {2406var found = false;2407pane.s.dtPane.rows().every(function (rowIdx) {2408if (pane.s.dtPane.row(rowIdx).data() !== undefined &&2409row !== undefined &&2410pane.s.dtPane.row(rowIdx).data().filter === row.filter) {2411found = true;2412pane.s.dtPane.row(rowIdx).select();2413}2414});2415if (!found) {2416var newRow = pane.addRow(row.display, row.filter, 0, row.total, row.sort, row.type, row.className);2417newRow.select();2418}2419};2420// select every row in the pane that was selected previously2421for (var _i = 0, _a = newSelectionList[i].rows; _i < _a.length; _i++) {2422var row = _a[_i];2423_loop_2(row);2424}2425pane.s.scrollTop = $$1(pane.s.dtPane.table().node()).parent()[0].scrollTop;2426pane.s.dtPane.draw();2427pane.s.dtPane.table().node().parentNode.scrollTop = pane.s.scrollTop;2428pane.s.lastCascade = false;2429}2430};2431// As the selections may have been made across the panes2432// in a different order to the pane index we must identify2433// which pane has the index of the selection. This is also important for colreorder etc2434for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2435var pane = _a[_i];2436_loop_1(pane);2437}2438}2439};2440/**2441* Declares the instances of individual searchpanes dependant on the number of columns.
2442* It is necessary to run this once preInit has completed otherwise no panes will be
2443* created as the column count will be 0.
2444*
2445* @param table the DataTable api for the parent table
2446* @param paneSettings the settings passed into the constructor
2447* @param opts the options passed into the constructor
2448*/
2449SearchPanes.prototype._paneDeclare = function (table, paneSettings, opts) {2450var _this = this;2451// Create Panes2452table
2453.columns(this.c.columns.length > 0 ? this.c.columns : undefined)2454.eq(0)2455.each(function (idx) {2456_this.s.panes.push(new SearchPane(paneSettings, opts, idx, _this.c.layout, _this.dom.panes));2457});2458// If there is any extra custom panes defined then create panes for them too2459var rowLength = table.columns().eq(0).toArray().length;2460var paneLength = this.c.panes.length;2461for (var i = 0; i < paneLength; i++) {2462var id = rowLength + i;2463this.s.panes.push(new SearchPane(paneSettings, opts, id, this.c.layout, this.dom.panes, this.c.panes[i]));2464}2465// If a custom ordering is being used2466if (this.c.order.length > 0) {2467// Make a new Array of panes based upon the order2468var newPanes = this.c.order.map(function (name, index, values) { return _this._findPane(name); });2469// Remove the old panes from the dom2470this.dom.panes.empty();2471this.s.panes = newPanes;2472// Append the panes in the correct order2473for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2474var pane = _a[_i];2475this.dom.panes.append(pane.dom.container);2476}2477}2478// If this internal property is true then the DataTable has been initialised already2479if (this.s.dt.settings()[0]._bInitComplete) {2480this._startup(table);2481}2482else {2483// Otherwise add the paneStartup function to the list of functions2484// that are to be run when the table is initialised. This will garauntee that the2485// panes are initialised before the init event and init Complete callback is fired2486this.s.dt.settings()[0].aoInitComplete.push({ fn: function () {2487_this._startup(table);2488} });2489}2490};2491/**2492* Finds a pane based upon the name of that pane
2493*
2494* @param name string representing the name of the pane
2495* @returns SearchPane The pane which has that name
2496*/
2497SearchPanes.prototype._findPane = function (name) {2498for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2499var pane = _a[_i];2500if (name === pane.s.name) {2501return pane;2502}2503}2504};2505/**2506* Works out which panes to update when data is recieved from the server and viewTotal is active
2507*/
2508SearchPanes.prototype._serverTotals = function () {2509var selectPresent = false;2510var deselectPresent = false;2511var table = this.s.dt;2512for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2513var pane = _a[_i];2514// Identify the pane where a selection or deselection has been made and add it to the list.2515if (pane.s.selectPresent) {2516this.s.selectionList.push({2517index: pane.s.index,2518protect: false,2519rows: pane.s.dtPane.rows({ selected: true }).data().toArray()2520});2521pane.s.selectPresent = false;2522selectPresent = true;2523break;2524}2525else if (pane.s.deselect) {2526var selectedData = pane.s.dtPane.rows({ selected: true }).data().toArray();2527if (selectedData.length > 0) {2528this.s.selectionList.push({2529index: pane.s.index,2530protect: true,2531rows: selectedData2532});2533}2534selectPresent = true;2535deselectPresent = true;2536}2537}2538// Build an updated list based on any selections or deselections added2539if (!selectPresent) {2540this.s.selectionList = [];2541}2542else {2543var newSelectionList = [];2544for (var i = 0; i < this.s.selectionList.length; i++) {2545var further = false;2546// Find out if this selection is the last one in the list for that pane2547for (var j = i + 1; j < this.s.selectionList.length; j++) {2548if (this.s.selectionList[j].index === this.s.selectionList[i].index) {2549further = true;2550}2551}2552// If there are no selections for this pane in the list then just push this one2553if (!further) {2554var push = false;2555for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {2556var pane = _c[_b];2557if (pane.s.index === this.s.selectionList[i].index &&2558pane.s.dtPane.rows({ selected: true }).data().toArray().length > 0) {2559push = true;2560}2561}2562if (push) {2563newSelectionList.push(this.s.selectionList[i]);2564}2565}2566}2567this.s.selectionList = newSelectionList;2568}2569var initIdx = -1;2570// If there has been a deselect and only one pane has a selection then update everything2571if (deselectPresent && this.s.selectionList.length === 1) {2572for (var _d = 0, _e = this.s.panes; _d < _e.length; _d++) {2573var pane = _e[_d];2574pane.s.lastSelect = false;2575pane.s.deselect = false;2576if (pane.s.dtPane !== undefined && pane.s.dtPane.rows({ selected: true }).data().toArray().length > 0) {2577initIdx = pane.s.index;2578}2579}2580}2581// Otherwise if there are more 1 selections then find the last one and set it to not update that pane2582else if (this.s.selectionList.length > 0) {2583var last = this.s.selectionList[this.s.selectionList.length - 1].index;2584for (var _f = 0, _g = this.s.panes; _f < _g.length; _f++) {2585var pane = _g[_f];2586pane.s.lastSelect = pane.s.index === last;2587pane.s.deselect = false;2588}2589}2590// Otherwise if there are no selections then find where that took place and do not update to maintain scrolling2591else if (this.s.selectionList.length === 0) {2592for (var _h = 0, _j = this.s.panes; _h < _j.length; _h++) {2593var pane = _j[_h];2594// pane.s.lastSelect = (pane.s.deselect === true);2595pane.s.lastSelect = false;2596pane.s.deselect = false;2597}2598}2599this.dom.panes.empty();2600// Rebuild the desired panes2601for (var _k = 0, _l = this.s.panes; _k < _l.length; _k++) {2602var pane = _l[_k];2603if (!pane.s.lastSelect) {2604pane.rebuildPane(undefined, this.s.dt.page.info().serverSide ? this.s.serverData : undefined, pane.s.index === initIdx ? true : null, true);2605}2606else {2607pane._setListeners();2608}2609// append all of the panes and enable select2610this.dom.panes.append(pane.dom.container);2611if (pane.s.dtPane !== undefined) {2612$$1(pane.s.dtPane.table().node()).parent()[0].scrollTop = pane.s.scrollTop;2613// eslint-disable-next-line no-extra-parens2614$$1.fn.dataTable.select.init(pane.s.dtPane);2615}2616}2617this._updateSelection();2618};2619/**2620* Sets the listeners for the collapse and show all buttons
2621* Also sets and performs checks on current panes to see if they are collapsed
2622*/
2623SearchPanes.prototype._setCollapseListener = function () {2624var _this = this;2625this.dom.collapseAll.on('click.dtsps', function () {2626_this._collapseAll();2627_this.dom.collapseAll.addClass(_this.classes.disabledButton).attr('disabled', 'true');2628_this.dom.showAll.removeClass(_this.classes.disabledButton).removeAttr('disabled');2629_this.s.dt.state.save();2630});2631this.dom.showAll.on('click.dtsps', function () {2632_this._showAll();2633_this.dom.showAll.addClass(_this.classes.disabledButton).attr('disabled', 'true');2634_this.dom.collapseAll.removeClass(_this.classes.disabledButton).removeAttr('disabled');2635_this.s.dt.state.save();2636});2637for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2638var pane = _a[_i];2639// We want to make the same check whenever there is a collapse/expand2640pane.dom.collapseButton.on('click', function () { return _this._checkCollapse(); });2641}2642this._checkCollapse();2643};2644/**2645* Shows all of the panes
2646*/
2647SearchPanes.prototype._showAll = function () {2648for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2649var pane = _a[_i];2650pane.show();2651}2652};2653/**2654* Initialises the tables previous/preset selections and initialises callbacks for events
2655*
2656* @param table the parent table for which the searchPanes are being created
2657*/
2658SearchPanes.prototype._startup = function (table) {2659var _this = this;2660this.dom.container.text('');2661// Attach clear button and title bar to the document2662this._attachExtras();2663this.dom.container.append(this.dom.panes);2664this.dom.panes.empty();2665var loadedFilter = this.s.dt.state.loaded();2666if (this.c.viewTotal && !this.c.cascadePanes) {2667if (loadedFilter !== null &&2668loadedFilter !== undefined &&2669loadedFilter.searchPanes !== undefined &&2670loadedFilter.searchPanes.panes !== undefined) {2671var filterActive = false;2672for (var _i = 0, _a = loadedFilter.searchPanes.panes; _i < _a.length; _i++) {2673var pane = _a[_i];2674if (pane.selected.length > 0) {2675filterActive = true;2676break;2677}2678}2679if (filterActive) {2680for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {2681var pane = _c[_b];2682pane.s.showFiltered = true;2683}2684}2685}2686}2687for (var _d = 0, _e = this.s.panes; _d < _e.length; _d++) {2688var pane = _e[_d];2689pane.rebuildPane(undefined, Object.keys(this.s.serverData).length > 0 ? this.s.serverData : undefined);2690this.dom.panes.append(pane.dom.container);2691}2692// If the layout is set to auto then the panes need to be resized to their best fit2693if (this.c.layout === 'auto') {2694this.resizePanes();2695}2696// Reset the paging if that has been saved in the state2697if (!this.s.stateRead && loadedFilter !== null && loadedFilter !== undefined) {2698this.s.dt.page(loadedFilter.start / this.s.dt.page.len());2699this.s.dt.draw('page');2700}2701this.s.stateRead = true;2702if (this.c.viewTotal && !this.c.cascadePanes) {2703for (var _f = 0, _g = this.s.panes; _f < _g.length; _f++) {2704var pane = _g[_f];2705pane.updatePane();2706}2707}2708this._checkMessage();2709// When a draw is called on the DataTable, update all of the panes incase the data in the DataTable has changed2710table.on('preDraw.dtsps', function () {2711// Check that the panes are not updating to avoid infinite loops2712// Also check that this draw is not due to paging2713if (!_this.s.updating && !_this.s.paging) {2714if ((_this.c.cascadePanes || _this.c.viewTotal) && !_this.s.dt.page.info().serverSide) {2715_this.redrawPanes(_this.c.viewTotal);2716}2717else {2718_this._updateFilterCount();2719_this._updateSelection();2720}2721_this.s.filterPane = -1;2722}2723// Paging flag reset - we only need to dodge the draw once2724_this.s.paging = false;2725});2726$$1(window).on('resize.dtsp', dataTable$1.util.throttle(function () {2727_this.resizePanes();2728}));2729// Whenever a state save occurs store the selection list in the state object2730this.s.dt.on('stateSaveParams.dtsp', function (e, settings, data) {2731if (data.searchPanes === undefined) {2732data.searchPanes = {};2733}2734data.searchPanes.selectionList = _this.s.selectionList;2735});2736// Listener for paging on main table2737table.off('page');2738table.on('page', function () {2739_this.s.paging = true;2740_this.s.page = _this.s.dt.page();2741});2742if (this.s.dt.page.info().serverSide) {2743table.off('preXhr.dt');2744table.on('preXhr.dt', function (e, settings, data) {2745if (data.searchPanes === undefined) {2746data.searchPanes = {};2747}2748if (data.searchPanes_null === undefined) {2749data.searchPanes_null = {};2750}2751// Count how many filters are being applied2752var filterCount = 0;2753for (var _i = 0, _a = _this.s.panes; _i < _a.length; _i++) {2754var pane = _a[_i];2755var src = _this.s.dt.column(pane.s.index).dataSrc();2756if (data.searchPanes[src] === undefined) {2757data.searchPanes[src] = {};2758}2759if (data.searchPanes_null[src] === undefined) {2760data.searchPanes_null[src] = {};2761}2762if (pane.s.dtPane !== undefined) {2763var rowData = pane.s.dtPane.rows({ selected: true }).data().toArray();2764for (var i = 0; i < rowData.length; i++) {2765data.searchPanes[src][i] = rowData[i].filter;2766if (data.searchPanes[src][i] === null) {2767data.searchPanes_null[src][i] = true;2768}2769filterCount++;2770}2771}2772}2773if (_this.c.viewTotal) {2774_this._prepViewTotal(filterCount);2775}2776// If there is a filter to be applied, then we need to read from the start of the result set2777// and set the paging to 0. This matches the behaviour of client side processing2778if (filterCount > 0) {2779// If the number of filters has changed we need to read from the start of the2780// result set and reset the paging2781if (filterCount !== _this.s.filterCount) {2782data.start = 0;2783_this.s.page = 0;2784}2785// Otherwise it is a paging request and we need to read from whatever the paging has been set to2786else {2787data.start = _this.s.page * _this.s.dt.page.len();2788}2789_this.s.dt.page(_this.s.page);2790_this.s.filterCount = filterCount;2791}2792});2793}2794else {2795table.on('preXhr.dt', function (e, settings, data) {2796for (var _i = 0, _a = _this.s.panes; _i < _a.length; _i++) {2797var pane = _a[_i];2798pane.clearData();2799}2800});2801}2802// If the data is reloaded from the server then it is possible that it has changed completely,2803// so we need to rebuild the panes2804this.s.dt.on('xhr', function (e, settings, json, xhr) {2805if (settings.nTable !== _this.s.dt.table().node()) {2806return;2807}2808var processing = false;2809if (!_this.s.dt.page.info().serverSide) {2810_this.s.dt.one('preDraw', function () {2811if (processing) {2812return;2813}2814var page = _this.s.dt.page();2815processing = true;2816_this.s.updating = true;2817_this.dom.panes.empty();2818for (var _i = 0, _a = _this.s.panes; _i < _a.length; _i++) {2819var pane = _a[_i];2820pane.clearData(); // Clears all of the bins and will mean that the data has to be re-read2821// Pass a boolean to say whether this is the last choice made for maintaining selections2822// when rebuilding2823pane.rebuildPane(_this.s.selectionList[_this.s.selectionList.length - 1] !== undefined ?2824pane.s.index === _this.s.selectionList[_this.s.selectionList.length - 1].index :2825false, undefined, undefined, true);2826_this.dom.panes.append(pane.dom.container);2827}2828if (!_this.s.dt.page.info().serverSide) {2829_this.s.dt.draw();2830}2831_this.s.updating = false;2832if (_this.c.cascadePanes || _this.c.viewTotal) {2833_this.redrawPanes(_this.c.cascadePanes);2834}2835else {2836_this._updateSelection();2837}2838_this._checkMessage();2839_this.s.dt.one('draw', function () {2840_this.s.updating = true;2841_this.s.dt.page(page).draw(false);2842_this.s.updating = false;2843});2844});2845}2846});2847// PreSelect any selections which have been defined using the preSelect option2848for (var _h = 0, _j = this.s.panes; _h < _j.length; _h++) {2849var pane = _j[_h];2850if (pane !== undefined &&2851pane.s.dtPane !== undefined &&2852(pane.s.colOpts.preSelect !== undefined && pane.s.colOpts.preSelect.length > 0 ||2853pane.customPaneSettings !== null &&2854pane.customPaneSettings.preSelect !== undefined &&2855pane.customPaneSettings.preSelect.length > 0)) {2856var tableLength = pane.s.dtPane.rows().data().toArray().length;2857for (var i = 0; i < tableLength; i++) {2858if (pane.s.colOpts.preSelect.includes(pane.s.dtPane.cell(i, 0).data()) ||2859pane.customPaneSettings !== null &&2860pane.customPaneSettings.preSelect !== undefined &&2861pane.customPaneSettings.preSelect.includes(pane.s.dtPane.cell(i, 0).data())) {2862pane.s.dtPane.row(i).select();2863}2864}2865pane.updateTable();2866}2867}2868if (this.s.selectionList !== undefined && this.s.selectionList.length > 0) {2869var last = this.s.selectionList[this.s.selectionList.length - 1].index;2870for (var _k = 0, _l = this.s.panes; _k < _l.length; _k++) {2871var pane = _l[_k];2872pane.s.lastSelect = pane.s.index === last;2873}2874}2875// If cascadePanes is active then make the previous selections in the order they were previously2876if (this.s.selectionList.length > 0 && this.c.cascadePanes) {2877this._cascadeRegen(this.s.selectionList, this.s.selectionList.length);2878}2879// Update the title bar to show how many filters have been selected2880this._updateFilterCount();2881// If the table is destroyed and restarted then clear the selections so that they do not persist.2882table.on('destroy.dtsps', function () {2883for (var _i = 0, _a = _this.s.panes; _i < _a.length; _i++) {2884var pane = _a[_i];2885pane.destroy();2886}2887table.off('.dtsps');2888_this.dom.collapseAll.off('.dtsps');2889_this.dom.showAll.off('.dtsps');2890_this.dom.clearAll.off('.dtsps');2891_this.dom.container.remove();2892_this.clearSelections();2893});2894if (this.c.collapse) {2895this._setCollapseListener();2896}2897// When the clear All button has been pressed clear all of the selections in the panes2898if (this.c.clear) {2899this.dom.clearAll.on('click.dtsps', function () {2900_this.clearSelections();2901});2902}2903table.settings()[0]._searchPanes = this;2904// This state save is required so that state is maintained over multiple refreshes if no actions are made2905this.s.dt.state.save();2906};2907SearchPanes.prototype._prepViewTotal = function (selectTotal) {2908var filterPane = this.s.filterPane;2909var filterActive = false;2910for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2911var pane = _a[_i];2912if (pane.s.dtPane !== undefined) {2913var selectLength = pane.s.dtPane.rows({ selected: true }).data().toArray().length;2914// If filterPane === -1 then a pane with a selection has not been found yet,2915// so set filterPane to that panes index2916if (selectLength > 0 && filterPane === -1) {2917filterPane = pane.s.index;2918filterActive = true;2919}2920// Then if another pane is found with a selection then set filterPane to null to2921// show that multiple panes have selections present2922else if (selectLength > 0) {2923filterPane = null;2924}2925}2926}2927if (selectTotal !== null && selectTotal !== 0) {2928filterPane = null;2929}2930// Update all of the panes to reflect the current state of the filters2931for (var _b = 0, _c = this.s.panes; _b < _c.length; _b++) {2932var pane = _c[_b];2933if (pane.s.dtPane !== undefined) {2934pane.s.filteringActive = true;2935if (filterPane !== -1 && filterPane !== null && filterPane === pane.s.index ||2936filterActive === false) {2937pane.s.filteringActive = false;2938}2939}2940}2941};2942/**2943* Updates the number of filters that have been applied in the title
2944*/
2945SearchPanes.prototype._updateFilterCount = function () {2946var filterCount = 0;2947// Add the number of all of the filters throughout the panes2948for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2949var pane = _a[_i];2950if (pane.s.dtPane !== undefined) {2951filterCount += pane.getPaneCount();2952}2953}2954// Run the message through the internationalisation method to improve readability2955var message = this.s.dt.i18n('searchPanes.title', this.c.i18n.title, filterCount);2956this.dom.title.text(message);2957if (this.c.filterChanged !== undefined && typeof this.c.filterChanged === 'function') {2958this.c.filterChanged.call(this.s.dt, filterCount);2959}2960if (filterCount === 0) {2961this.dom.clearAll.addClass(this.classes.disabledButton).attr('disabled', 'true');2962}2963else {2964this.dom.clearAll.removeClass(this.classes.disabledButton).removeAttr('disabled');2965}2966};2967/**2968* Updates the selectionList when cascade is not in place
2969*/
2970SearchPanes.prototype._updateSelection = function () {2971this.s.selectionList = [];2972for (var _i = 0, _a = this.s.panes; _i < _a.length; _i++) {2973var pane = _a[_i];2974if (pane.s.dtPane !== undefined) {2975this.s.selectionList.push({2976index: pane.s.index,2977protect: false,2978rows: pane.s.dtPane.rows({ selected: true }).data().toArray()2979});2980}2981}2982};2983SearchPanes.version = '1.4.0';2984SearchPanes.classes = {2985clear: 'dtsp-clear',2986clearAll: 'dtsp-clearAll',2987collapseAll: 'dtsp-collapseAll',2988container: 'dtsp-searchPanes',2989disabledButton: 'dtsp-disabledButton',2990emptyMessage: 'dtsp-emptyMessage',2991hide: 'dtsp-hidden',2992panes: 'dtsp-panesContainer',2993search: 'dtsp-search',2994showAll: 'dtsp-showAll',2995title: 'dtsp-title',2996titleRow: 'dtsp-titleRow'2997};2998// Define SearchPanes default options2999SearchPanes.defaults = {3000cascadePanes: false,3001clear: true,3002collapse: true,3003columns: [],3004container: function (dt) {3005return dt.table().container();3006},3007filterChanged: undefined,3008i18n: {3009clearMessage: 'Clear All',3010clearPane: '×',3011collapse: {30120: 'SearchPanes',3013_: 'SearchPanes (%d)'3014},3015collapseMessage: 'Collapse All',3016count: '{total}',3017countFiltered: '{shown} ({total})',3018emptyMessage: '<em>No data</em>',3019emptyPanes: 'No SearchPanes',3020loadMessage: 'Loading Search Panes...',3021showMessage: 'Show All',3022title: 'Filters Active - %d'3023},3024layout: 'auto',3025order: [],3026panes: [],3027viewTotal: false3028};3029return SearchPanes;3030}());3031
3032/*! SearchPanes 1.4.03033* 2019-2020 SpryMedia Ltd - datatables.net/license
3034*/
3035// DataTables extensions common UMD. Note that this allows for AMD, CommonJS3036// (with window and jQuery being allowed as parameters to the returned3037// function) or just default browser loading.3038(function (factory) {3039if (typeof define === 'function' && define.amd) {3040// AMD3041define(['jquery', 'datatables.net'], function ($) {3042return factory($, window, document);3043});3044}3045else if (typeof exports === 'object') {3046// CommonJS3047module.exports = function (root, $) {3048if (!root) {3049root = window;3050}3051if (!$ || !$.fn.dataTable) {3052// eslint-disable-next-line @typescript-eslint/no-var-requires3053$ = require('datatables.net')(root, $).$;3054}3055return factory($, root, root.document);3056};3057}3058else {3059// Browser - assume jQuery has already been loaded3060// eslint-disable-next-line no-extra-parens3061factory(window.jQuery, window, document);3062}3063}(function ($, window, document) {3064setJQuery($);3065setJQuery$1($);3066var dataTable = $.fn.dataTable;3067// eslint-disable-next-line no-extra-parens3068$.fn.dataTable.SearchPanes = SearchPanes;3069// eslint-disable-next-line no-extra-parens3070$.fn.DataTable.SearchPanes = SearchPanes;3071// eslint-disable-next-line no-extra-parens3072$.fn.dataTable.SearchPane = SearchPane;3073// eslint-disable-next-line no-extra-parens3074$.fn.DataTable.SearchPane = SearchPane;3075// eslint-disable-next-line no-extra-parens3076var apiRegister = $.fn.dataTable.Api.register;3077apiRegister('searchPanes()', function () {3078return this;3079});3080apiRegister('searchPanes.clearSelections()', function () {3081return this.iterator('table', function (ctx) {3082if (ctx._searchPanes) {3083ctx._searchPanes.clearSelections();3084}3085});3086});3087apiRegister('searchPanes.rebuildPane()', function (targetIdx, maintainSelections) {3088return this.iterator('table', function (ctx) {3089if (ctx._searchPanes) {3090ctx._searchPanes.rebuild(targetIdx, maintainSelections);3091}3092});3093});3094apiRegister('searchPanes.resizePanes()', function () {3095var ctx = this.context[0];3096return ctx._searchPanes ?3097ctx._searchPanes.resizePanes() :3098null;3099});3100apiRegister('searchPanes.container()', function () {3101var ctx = this.context[0];3102return ctx._searchPanes3103? ctx._searchPanes.getNode()3104: null;3105});3106$.fn.dataTable.ext.buttons.searchPanesClear = {3107action: function (e, dt, node, config) {3108dt.searchPanes.clearSelections();3109},3110text: 'Clear Panes'3111};3112$.fn.dataTable.ext.buttons.searchPanes = {3113action: function (e, dt, node, config) {3114e.stopPropagation();3115this.popover(config._panes.getNode(), {3116align: 'dt-container'3117});3118config._panes.rebuild(undefined, true);3119},3120config: {},3121init: function (dt, node, config) {3122var panes = new $.fn.dataTable.SearchPanes(dt, $.extend({3123filterChanged: function (count) {3124// console.log(dt.context[0])3125dt.button(node).text(dt.i18n('searchPanes.collapse', dt.context[0].oLanguage.searchPanes !== undefined ?3126dt.context[0].oLanguage.searchPanes.collapse :3127dt.context[0]._searchPanes.c.i18n.collapse, count));3128}3129}, config.config));3130var message = dt.i18n('searchPanes.collapse', panes.c.i18n.collapse, 0);3131dt.button(node).text(message);3132config._panes = panes;3133},3134text: 'Search Panes'3135};3136function _init(settings, options, fromPre) {3137if (options === void 0) { options = null; }3138if (fromPre === void 0) { fromPre = false; }3139var api = new dataTable.Api(settings);3140var opts = options3141? options3142: api.init().searchPanes || dataTable.defaults.searchPanes;3143var searchPanes = new SearchPanes(api, opts, fromPre);3144var node = searchPanes.getNode();3145return node;3146}3147// Attach a listener to the document which listens for DataTables initialisation3148// events so we can automatically initialise3149$(document).on('preInit.dt.dtsp', function (e, settings, json) {3150if (e.namespace !== 'dt') {3151return;3152}3153if (settings.oInit.searchPanes ||3154dataTable.defaults.searchPanes) {3155if (!settings._searchPanes) {3156_init(settings, null, true);3157}3158}3159});3160// DataTables `dom` feature option3161dataTable.ext.feature.push({3162cFeature: 'P',3163fnInit: _init3164});3165// DataTables 2 layout feature3166if (dataTable.ext.features) {3167dataTable.ext.features.register('searchPanes', _init);3168}3169}));3170
3171}());3172