Show More
Commit Description:
announcement
Commit Description:
announcement
References:
File last commit:
Show/Diff file:
Action:
vendor/javascript/datatables/StateRestore-1.1.1/js/dataTables.stateRestore.js
| 2318 lines
| 108.2 KiB
| application/javascript
| JavascriptLexer
|
r866 | /*! StateRestore 1.1.1 | |||
* 2019-2022 SpryMedia Ltd - datatables.net/license | ||||
*/ | ||||
(function () { | ||||
'use strict'; | ||||
var $$1; | ||||
var dataTable$1; | ||||
function setJQuery$1(jq) { | ||||
$$1 = jq; | ||||
dataTable$1 = jq.fn.dataTable; | ||||
} | ||||
var StateRestore = /** @class */ (function () { | ||||
function StateRestore(settings, opts, identifier, state, isPreDefined, successCallback) { | ||||
if (state === void 0) { state = undefined; } | ||||
if (isPreDefined === void 0) { isPreDefined = false; } | ||||
if (successCallback === void 0) { successCallback = function () { return null; }; } | ||||
// Check that the required version of DataTables is included | ||||
if (!dataTable$1 || !dataTable$1.versionCheck || !dataTable$1.versionCheck('1.10.0')) { | ||||
throw new Error('StateRestore requires DataTables 1.10 or newer'); | ||||
} | ||||
// Check that Select is included | ||||
// eslint-disable-next-line no-extra-parens | ||||
if (!dataTable$1.Buttons) { | ||||
throw new Error('StateRestore requires Buttons'); | ||||
} | ||||
var table = new dataTable$1.Api(settings); | ||||
this.classes = $$1.extend(true, {}, StateRestore.classes); | ||||
// Get options from user | ||||
this.c = $$1.extend(true, {}, StateRestore.defaults, opts); | ||||
this.s = { | ||||
dt: table, | ||||
identifier: identifier, | ||||
isPreDefined: isPreDefined, | ||||
savedState: null, | ||||
tableId: state && state.stateRestore ? state.stateRestore.tableId : undefined | ||||
}; | ||||
this.dom = { | ||||
background: $$1('<div class="' + this.classes.background + '"/>'), | ||||
closeButton: $$1('<div class="' + this.classes.closeButton + '">x</div>'), | ||||
confirmation: $$1('<div class="' + this.classes.confirmation + '"/>'), | ||||
confirmationButton: $$1('<button class="' + this.classes.confirmationButton + ' ' + this.classes.dtButton + '">'), | ||||
confirmationTitleRow: $$1('<div class="' + this.classes.confirmationTitleRow + '"></div>'), | ||||
dtContainer: $$1(this.s.dt.table().container()), | ||||
duplicateError: $$1('<span class="' + this.classes.modalError + '">' + | ||||
this.s.dt.i18n('stateRestore.duplicateError', this.c.i18n.duplicateError) + | ||||
'</span>'), | ||||
emptyError: $$1('<span class="' + this.classes.modalError + '">' + | ||||
this.s.dt.i18n('stateRestore.emptyError', this.c.i18n.emptyError) + | ||||
'</span>'), | ||||
removeContents: $$1('<div class="' + this.classes.confirmationText + '"><span>' + | ||||
this.s.dt | ||||
.i18n('stateRestore.removeConfirm', this.c.i18n.removeConfirm) | ||||
.replace(/%s/g, this.s.identifier) + | ||||
'</span></div>'), | ||||
removeError: $$1('<span class="' + this.classes.modalError + '">' + | ||||
this.s.dt.i18n('stateRestore.removeError', this.c.i18n.removeError) + | ||||
'</span>'), | ||||
removeTitle: $$1('<h2 class="' + this.classes.confirmationTitle + '">' + | ||||
this.s.dt.i18n('stateRestore.removeTitle', this.c.i18n.removeTitle) + | ||||
'</h2>'), | ||||
renameContents: $$1('<div class="' + this.classes.confirmationText + ' ' + this.classes.renameModal + '">' + | ||||
'<label class="' + this.classes.confirmationMessage + '">' + | ||||
this.s.dt | ||||
.i18n('stateRestore.renameLabel', this.c.i18n.renameLabel) | ||||
.replace(/%s/g, this.s.identifier) + | ||||
'</label>' + | ||||
'</div>'), | ||||
renameInput: $$1('<input class="' + this.classes.input + '" type="text"></input>'), | ||||
renameTitle: $$1('<h2 class="' + this.classes.confirmationTitle + '">' + | ||||
this.s.dt.i18n('stateRestore.renameTitle', this.c.i18n.renameTitle) + | ||||
'</h2>') | ||||
}; | ||||
// When a StateRestore instance is created the current state of the table should also be saved. | ||||
this.save(state, successCallback); | ||||
} | ||||
/** | ||||
* Removes a state from storage and then triggers the dtsr-remove event | ||||
* so that the StateRestoreCollection class can remove it's references as well. | ||||
* | ||||
* @param skipModal Flag to indicate if the modal should be skipped or not | ||||
*/ | ||||
StateRestore.prototype.remove = function (skipModal) { | ||||
var _a; | ||||
var _this = this; | ||||
if (skipModal === void 0) { skipModal = false; } | ||||
// Check if removal of states is allowed | ||||
if (!this.c.remove) { | ||||
return false; | ||||
} | ||||
var removeFunction; | ||||
var ajaxData = { | ||||
action: 'remove', | ||||
stateRestore: (_a = {}, | ||||
_a[this.s.identifier] = this.s.savedState, | ||||
_a) | ||||
}; | ||||
var successCallback = function () { | ||||
_this.dom.confirmation.trigger('dtsr-remove'); | ||||
$$1(_this.s.dt.table().node()).trigger('stateRestore-change'); | ||||
_this.dom.background.click(); | ||||
_this.dom.confirmation.remove(); | ||||
$$1(document).unbind('keyup', function (e) { return _this._keyupFunction(e); }); | ||||
_this.dom.confirmationButton.off('click'); | ||||
}; | ||||
// If the remove is not happening over ajax remove it from local storage and then trigger the event | ||||
if (!this.c.ajax) { | ||||
removeFunction = function () { | ||||
try { | ||||
localStorage.removeItem('DataTables_stateRestore_' + _this.s.identifier + '_' + location.pathname + | ||||
(_this.s.tableId ? '_' + _this.s.tableId : '')); | ||||
successCallback(); | ||||
} | ||||
catch (e) { | ||||
_this.dom.confirmation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.confirmation.append(_this.dom.removeError); | ||||
return 'remove'; | ||||
} | ||||
return true; | ||||
}; | ||||
} | ||||
// Ajax property has to be a string, not just true | ||||
// Also only want to save if the table has been initialised and the states have been loaded in | ||||
else if (typeof this.c.ajax === 'string' && this.s.dt.settings()[0]._bInitComplete) { | ||||
removeFunction = function () { | ||||
$$1.ajax({ | ||||
data: ajaxData, | ||||
success: successCallback, | ||||
type: 'POST', | ||||
url: _this.c.ajax | ||||
}); | ||||
return true; | ||||
}; | ||||
} | ||||
else if (typeof this.c.ajax === 'function') { | ||||
removeFunction = function () { | ||||
if (typeof _this.c.ajax === 'function') { | ||||
_this.c.ajax.call(_this.s.dt, ajaxData, successCallback); | ||||
} | ||||
return true; | ||||
}; | ||||
} | ||||
// If the modal is to be skipped then remove straight away | ||||
if (skipModal) { | ||||
this.dom.confirmation.appendTo(this.dom.dtContainer); | ||||
$$1(this.s.dt.table().node()).trigger('dtsr-modal-inserted'); | ||||
removeFunction(); | ||||
this.dom.confirmation.remove(); | ||||
} | ||||
// Otherwise display the modal | ||||
else { | ||||
this._newModal(this.dom.removeTitle, this.s.dt.i18n('stateRestore.removeSubmit', this.c.i18n.removeSubmit), removeFunction, this.dom.removeContents); | ||||
} | ||||
return true; | ||||
}; | ||||
/** | ||||
* Compares the state held within this instance with a state that is passed in | ||||
* | ||||
* @param state The state that is to be compared against | ||||
* @returns boolean indicating if the states match | ||||
*/ | ||||
StateRestore.prototype.compare = function (state) { | ||||
// Order | ||||
if (!this.c.saveState.order) { | ||||
state.order = undefined; | ||||
} | ||||
// Search | ||||
if (!this.c.saveState.search) { | ||||
state.search = undefined; | ||||
} | ||||
// Columns | ||||
if (this.c.saveState.columns && state.columns) { | ||||
for (var i = 0, ien = state.columns.length; i < ien; i++) { | ||||
// Visibility | ||||
if (typeof this.c.saveState.columns !== 'boolean' && !this.c.saveState.columns.visible) { | ||||
state.columns[i].visible = undefined; | ||||
} | ||||
// Search | ||||
if (typeof this.c.saveState.columns !== 'boolean' && !this.c.saveState.columns.search) { | ||||
state.columns[i].search = undefined; | ||||
} | ||||
} | ||||
} | ||||
else if (!this.c.saveState.columns) { | ||||
state.columns = undefined; | ||||
} | ||||
// Paging | ||||
if (!this.c.saveState.paging) { | ||||
state.page = undefined; | ||||
} | ||||
// SearchBuilder | ||||
if (!this.c.saveState.searchBuilder) { | ||||
state.searchBuilder = undefined; | ||||
} | ||||
// SearchPanes | ||||
if (!this.c.saveState.searchPanes) { | ||||
state.searchPanes = undefined; | ||||
} | ||||
// Select | ||||
if (!this.c.saveState.select) { | ||||
state.select = undefined; | ||||
} | ||||
// ColReorder | ||||
if (!this.c.saveState.colReorder) { | ||||
state.ColReorder = undefined; | ||||
} | ||||
// Scroller | ||||
if (!this.c.saveState.scroller) { | ||||
state.scroller = undefined; | ||||
if (dataTable$1.Scroller !== undefined) { | ||||
state.start = 0; | ||||
} | ||||
} | ||||
// Paging | ||||
if (!this.c.saveState.paging) { | ||||
state.start = 0; | ||||
} | ||||
// Page Length | ||||
if (!this.c.saveState.length) { | ||||
state.length = undefined; | ||||
} | ||||
// Need to delete properties that we do not want to compare | ||||
delete state.time; | ||||
var copyState = this.s.savedState; | ||||
delete copyState.time; | ||||
delete copyState.c; | ||||
delete copyState.stateRestore; | ||||
// Perform a deep compare of the two state objects | ||||
return this._deepCompare(state, copyState); | ||||
}; | ||||
/** | ||||
* Removes all of the dom elements from the document | ||||
*/ | ||||
StateRestore.prototype.destroy = function () { | ||||
Object.values(this.dom).forEach(function (node) { return node.off().remove(); }); | ||||
}; | ||||
/** | ||||
* Loads the state referenced by the identifier from storage | ||||
* | ||||
* @param state The identifier of the state that should be loaded | ||||
* @returns the state that has been loaded | ||||
*/ | ||||
StateRestore.prototype.load = function () { | ||||
var _this = this; | ||||
var loadedState = this.s.savedState; | ||||
var settings = this.s.dt.settings()[0]; | ||||
// Always want the states stored here to be loaded in - regardless of when they were created | ||||
loadedState.time = +new Date(); | ||||
settings.oLoadedState = $$1.extend(true, {}, loadedState); | ||||
// Click on a background if there is one to shut the collection | ||||
$$1('div.dt-button-background').click(); | ||||
// Call the internal datatables function to implement the state on the table | ||||
$$1.fn.dataTable.ext.oApi._fnImplementState(settings, loadedState, function () { | ||||
var correctPaging = function (e, preSettings) { | ||||
setTimeout(function () { | ||||
var currpage = preSettings._iDisplayStart / preSettings._iDisplayLength; | ||||
var intendedPage = loadedState.start / loadedState.length; | ||||
// If the paging is incorrect then we have to set it again so that it is correct | ||||
// This happens when a searchpanes filter is removed | ||||
// This has to happen in a timeout because searchpanes only deselects after a timeout | ||||
if (currpage >= 0 && intendedPage >= 0 && currpage !== intendedPage) { | ||||
_this.s.dt.page(intendedPage).draw(false); | ||||
} | ||||
}, 50); | ||||
}; | ||||
_this.s.dt.one('preDraw', correctPaging); | ||||
_this.s.dt.draw(false); | ||||
}); | ||||
return loadedState; | ||||
}; | ||||
/** | ||||
* Shows a modal that allows a state to be renamed | ||||
* | ||||
* @param newIdentifier Optional. The new identifier for this state | ||||
*/ | ||||
StateRestore.prototype.rename = function (newIdentifier, currentIdentifiers) { | ||||
var _this = this; | ||||
if (newIdentifier === void 0) { newIdentifier = null; } | ||||
// Check if renaming of states is allowed | ||||
if (!this.c.rename) { | ||||
return; | ||||
} | ||||
var renameFunction = function () { | ||||
var _a; | ||||
if (newIdentifier === null) { | ||||
var tempIdentifier = $$1('input.' + _this.classes.input.replace(/ /g, '.')).val(); | ||||
if (tempIdentifier.length === 0) { | ||||
_this.dom.confirmation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.confirmation.append(_this.dom.emptyError); | ||||
return 'empty'; | ||||
} | ||||
else if (currentIdentifiers.includes(tempIdentifier)) { | ||||
_this.dom.confirmation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.confirmation.append(_this.dom.duplicateError); | ||||
return 'duplicate'; | ||||
} | ||||
else { | ||||
newIdentifier = tempIdentifier; | ||||
} | ||||
} | ||||
var ajaxData = { | ||||
action: 'rename', | ||||
stateRestore: (_a = {}, | ||||
_a[_this.s.identifier] = newIdentifier, | ||||
_a) | ||||
}; | ||||
var successCallback = function () { | ||||
_this.s.identifier = newIdentifier; | ||||
_this.save(_this.s.savedState, function () { return null; }, false); | ||||
_this.dom.removeContents = $$1('<div class="' + _this.classes.confirmationText + '"><span>' + | ||||
_this.s.dt | ||||
.i18n('stateRestore.removeConfirm', _this.c.i18n.removeConfirm) | ||||
.replace(/%s/g, _this.s.identifier) + | ||||
'</span></div>'); | ||||
_this.dom.confirmation.trigger('dtsr-rename'); | ||||
_this.dom.background.click(); | ||||
_this.dom.confirmation.remove(); | ||||
$$1(document).unbind('keyup', function (e) { return _this._keyupFunction(e); }); | ||||
_this.dom.confirmationButton.off('click'); | ||||
}; | ||||
if (!_this.c.ajax) { | ||||
try { | ||||
localStorage.removeItem('DataTables_stateRestore_' + _this.s.identifier + '_' + location.pathname + | ||||
(_this.s.tableId ? '_' + _this.s.tableId : '')); | ||||
successCallback(); | ||||
} | ||||
catch (e) { | ||||
_this.dom.confirmation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.confirmation.append(_this.dom.removeError); | ||||
return false; | ||||
} | ||||
} | ||||
else if (typeof _this.c.ajax === 'string' && _this.s.dt.settings()[0]._bInitComplete) { | ||||
$$1.ajax({ | ||||
data: ajaxData, | ||||
success: successCallback, | ||||
type: 'POST', | ||||
url: _this.c.ajax | ||||
}); | ||||
} | ||||
else if (typeof _this.c.ajax === 'function') { | ||||
_this.c.ajax.call(_this.s.dt, ajaxData, successCallback); | ||||
} | ||||
return true; | ||||
}; | ||||
// Check if a new identifier has been provided, if so no need for a modal | ||||
if (newIdentifier !== null) { | ||||
if (currentIdentifiers.includes(newIdentifier)) { | ||||
throw new Error(this.s.dt.i18n('stateRestore.duplicateError', this.c.i18n.duplicateError)); | ||||
} | ||||
else if (newIdentifier.length === 0) { | ||||
throw new Error(this.s.dt.i18n('stateRestore.emptyError', this.c.i18n.emptyError)); | ||||
} | ||||
else { | ||||
this.dom.confirmation.appendTo(this.dom.dtContainer); | ||||
$$1(this.s.dt.table().node()).trigger('dtsr-modal-inserted'); | ||||
renameFunction(); | ||||
this.dom.confirmation.remove(); | ||||
} | ||||
} | ||||
else { | ||||
this.dom.renameInput.val(this.s.identifier); | ||||
this.dom.renameContents.append(this.dom.renameInput); | ||||
this._newModal(this.dom.renameTitle, this.s.dt.i18n('stateRestore.renameButton', this.c.i18n.renameButton), renameFunction, this.dom.renameContents); | ||||
} | ||||
}; | ||||
/** | ||||
* Saves the tables current state using the identifier that is passed in. | ||||
* | ||||
* @param state Optional. If provided this is the state that will be saved rather than using the current state | ||||
*/ | ||||
StateRestore.prototype.save = function (state, passedSuccessCallback, callAjax) { | ||||
var _a; | ||||
var _this = this; | ||||
if (callAjax === void 0) { callAjax = true; } | ||||
// Check if saving states is allowed | ||||
if (!this.c.save) { | ||||
if (passedSuccessCallback) { | ||||
passedSuccessCallback.call(this); | ||||
} | ||||
return; | ||||
} | ||||
// this.s.dt.state.save(); | ||||
var savedState; | ||||
// If no state has been provided then create a new one from the current state | ||||
this.s.dt.state.save(); | ||||
if (state === undefined) { | ||||
savedState = this.s.dt.state(); | ||||
} | ||||
else if (typeof state !== 'object') { | ||||
return; | ||||
} | ||||
else { | ||||
savedState = state; | ||||
} | ||||
if (savedState.stateRestore) { | ||||
savedState.stateRestore.isPreDefined = this.s.isPreDefined; | ||||
savedState.stateRestore.state = this.s.identifier; | ||||
savedState.stateRestore.tableId = this.s.tableId; | ||||
} | ||||
else { | ||||
savedState.stateRestore = { | ||||
isPreDefined: this.s.isPreDefined, | ||||
state: this.s.identifier, | ||||
tableId: this.s.tableId | ||||
}; | ||||
} | ||||
this.s.savedState = savedState; | ||||
// Order | ||||
if (!this.c.saveState.order) { | ||||
this.s.savedState.order = undefined; | ||||
} | ||||
// Search | ||||
if (!this.c.saveState.search) { | ||||
this.s.savedState.search = undefined; | ||||
} | ||||
// Columns | ||||
if (this.c.saveState.columns && this.s.savedState.columns) { | ||||
for (var i = 0, ien = this.s.savedState.columns.length; i < ien; i++) { | ||||
// Visibility | ||||
if (typeof this.c.saveState.columns !== 'boolean' && !this.c.saveState.columns.visible) { | ||||
this.s.savedState.columns[i].visible = undefined; | ||||
} | ||||
// Search | ||||
if (typeof this.c.saveState.columns !== 'boolean' && !this.c.saveState.columns.search) { | ||||
this.s.savedState.columns[i].search = undefined; | ||||
} | ||||
} | ||||
} | ||||
else if (!this.c.saveState.columns) { | ||||
this.s.savedState.columns = undefined; | ||||
} | ||||
// SearchBuilder | ||||
if (!this.c.saveState.searchBuilder) { | ||||
this.s.savedState.searchBuilder = undefined; | ||||
} | ||||
// SearchPanes | ||||
if (!this.c.saveState.searchPanes) { | ||||
this.s.savedState.searchPanes = undefined; | ||||
} | ||||
// Select | ||||
if (!this.c.saveState.select) { | ||||
this.s.savedState.select = undefined; | ||||
} | ||||
// ColReorder | ||||
if (!this.c.saveState.colReorder) { | ||||
this.s.savedState.ColReorder = undefined; | ||||
} | ||||
// Scroller | ||||
if (!this.c.saveState.scroller) { | ||||
this.s.savedState.scroller = undefined; | ||||
if (dataTable$1.Scroller !== undefined) { | ||||
this.s.savedState.start = 0; | ||||
} | ||||
} | ||||
// Paging | ||||
if (!this.c.saveState.paging) { | ||||
this.s.savedState.start = 0; | ||||
} | ||||
// Page Length | ||||
if (!this.c.saveState.length) { | ||||
this.s.savedState.length = undefined; | ||||
} | ||||
this.s.savedState.c = this.c; | ||||
// Need to remove the parent reference before we save the state | ||||
// Its not needed to rebuild, but it does cause a circular reference when converting to JSON | ||||
if (this.s.savedState.c.splitSecondaries.length) { | ||||
for (var _i = 0, _b = this.s.savedState.c.splitSecondaries; _i < _b.length; _i++) { | ||||
var secondary = _b[_i]; | ||||
if (secondary.parent) { | ||||
secondary.parent = undefined; | ||||
} | ||||
} | ||||
} | ||||
// If the state is predefined there is no need to save it over ajax or to local storage | ||||
if (this.s.isPreDefined) { | ||||
if (passedSuccessCallback) { | ||||
passedSuccessCallback.call(this); | ||||
} | ||||
return; | ||||
} | ||||
var ajaxData = { | ||||
action: 'save', | ||||
stateRestore: (_a = {}, | ||||
_a[this.s.identifier] = this.s.savedState, | ||||
_a) | ||||
}; | ||||
var successCallback = function () { | ||||
if (passedSuccessCallback) { | ||||
passedSuccessCallback.call(_this); | ||||
} | ||||
_this.dom.confirmation.trigger('dtsr-save'); | ||||
$$1(_this.s.dt.table().node()).trigger('stateRestore-change'); | ||||
}; | ||||
if (!this.c.ajax) { | ||||
localStorage.setItem('DataTables_stateRestore_' + this.s.identifier + '_' + location.pathname + | ||||
(this.s.tableId ? '_' + this.s.tableId : ''), JSON.stringify(this.s.savedState)); | ||||
successCallback(); | ||||
} | ||||
else if (typeof this.c.ajax === 'string' && callAjax) { | ||||
if (this.s.dt.settings()[0]._bInitComplete) { | ||||
$$1.ajax({ | ||||
data: ajaxData, | ||||
success: successCallback, | ||||
type: 'POST', | ||||
url: this.c.ajax | ||||
}); | ||||
} | ||||
else { | ||||
this.s.dt.one('init', function () { | ||||
$$1.ajax({ | ||||
data: ajaxData, | ||||
success: successCallback, | ||||
type: 'POST', | ||||
url: _this.c.ajax | ||||
}); | ||||
}); | ||||
} | ||||
} | ||||
else if (typeof this.c.ajax === 'function' && callAjax) { | ||||
this.c.ajax.call(this.s.dt, ajaxData, successCallback); | ||||
} | ||||
}; | ||||
/** | ||||
* Performs a deep compare of two state objects, returning true if they match | ||||
* | ||||
* @param state1 The first object to compare | ||||
* @param state2 The second object to compare | ||||
* @returns boolean indicating if the objects match | ||||
*/ | ||||
StateRestore.prototype._deepCompare = function (state1, state2) { | ||||
// Put keys and states into arrays as this makes the later code easier to work | ||||
var states = [state1, state2]; | ||||
var keys = [Object.keys(state1).sort(), Object.keys(state2).sort()]; | ||||
// If scroller is included then we need to remove the start value | ||||
// as it can be different but yield the same results | ||||
if (keys[0].includes('scroller')) { | ||||
var startIdx = keys[0].indexOf('start'); | ||||
if (startIdx) { | ||||
keys[0].splice(startIdx, 1); | ||||
} | ||||
} | ||||
if (keys[1].includes('scroller')) { | ||||
var startIdx = keys[1].indexOf('start'); | ||||
if (startIdx) { | ||||
keys[1].splice(startIdx, 1); | ||||
} | ||||
} | ||||
// We want to remove any private properties within the states | ||||
for (var i = 0; i < keys[0].length; i++) { | ||||
if (keys[0][i].indexOf('_') === 0) { | ||||
keys[0].splice(i, 1); | ||||
i--; | ||||
continue; | ||||
} | ||||
// If scroller is included then we need to remove the following values | ||||
// as they can be different but yield the same results | ||||
if (keys[0][i] === 'baseRowTop' || | ||||
keys[0][i] === 'baseScrollTop' || | ||||
keys[0][i] === 'scrollTop' || | ||||
(!this.c.saveState.paging && keys[0][i] === 'page')) { | ||||
keys[0].splice(i, 1); | ||||
i--; | ||||
continue; | ||||
} | ||||
} | ||||
for (var i = 0; i < keys[1].length; i++) { | ||||
if (keys[1][i].indexOf('_') === 0) { | ||||
keys[1].splice(i, 1); | ||||
i--; | ||||
continue; | ||||
} | ||||
if (keys[1][i] === 'baseRowTop' || | ||||
keys[1][i] === 'baseScrollTop' || | ||||
keys[1][i] === 'scrollTop' || | ||||
(!this.c.saveState.paging && keys[0][i] === 'page')) { | ||||
keys[1].splice(i, 1); | ||||
i--; | ||||
continue; | ||||
} | ||||
} | ||||
if (keys[0].length === 0 && keys[1].length > 0 || | ||||
keys[1].length === 0 && keys[0].length > 0) { | ||||
return false; | ||||
} | ||||
// We are only going to compare the keys that are common between both states | ||||
for (var i = 0; i < keys[0].length; i++) { | ||||
if (!keys[1].includes(keys[0][i])) { | ||||
keys[0].splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
for (var i = 0; i < keys[1].length; i++) { | ||||
if (!keys[0].includes(keys[1][i])) { | ||||
keys[1].splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
// Then each key and value has to be checked against each other | ||||
for (var i = 0; i < keys[0].length; i++) { | ||||
// If the keys dont equal, or their corresponding types are different we can return false | ||||
if (keys[0][i] !== keys[1][i] || typeof states[0][keys[0][i]] !== typeof states[1][keys[1][i]]) { | ||||
return false; | ||||
} | ||||
// If the type is an object then further deep comparisons are required | ||||
if (typeof states[0][keys[0][i]] === 'object') { | ||||
if (!this._deepCompare(states[0][keys[0][i]], states[1][keys[1][i]])) { | ||||
return false; | ||||
} | ||||
} | ||||
else if (typeof states[0][keys[0][i]] === 'number' && typeof states[1][keys[1][i]] === 'number') { | ||||
if (Math.round(states[0][keys[0][i]]) !== Math.round(states[1][keys[1][i]])) { | ||||
return false; | ||||
} | ||||
} | ||||
// Otherwise we can just check the value | ||||
else if (states[0][keys[0][i]] !== states[1][keys[1][i]]) { | ||||
return false; | ||||
} | ||||
} | ||||
// If we get all the way to here there are no differences so return true for this object | ||||
return true; | ||||
}; | ||||
StateRestore.prototype._keyupFunction = function (e) { | ||||
// If enter same action as pressing the button | ||||
if (e.key === 'Enter') { | ||||
this.dom.confirmationButton.click(); | ||||
} | ||||
// If escape close modal | ||||
else if (e.key === 'Escape') { | ||||
$$1('div.' + this.classes.background.replace(/ /g, '.')).click(); | ||||
} | ||||
}; | ||||
/** | ||||
* Creates a new confirmation modal for the user to approve an action | ||||
* | ||||
* @param title The title that is to be displayed at the top of the modal | ||||
* @param buttonText The text that is to be displayed in the confirmation button of the modal | ||||
* @param buttonAction The action that should be taken when the confirmation button is pressed | ||||
* @param modalContents The contents for the main body of the modal | ||||
*/ | ||||
StateRestore.prototype._newModal = function (title, buttonText, buttonAction, modalContents) { | ||||
var _this = this; | ||||
this.dom.background.appendTo(this.dom.dtContainer); | ||||
this.dom.confirmationTitleRow.empty().append(title); | ||||
this.dom.confirmationButton.html(buttonText); | ||||
this.dom.confirmation | ||||
.empty() | ||||
.append(this.dom.confirmationTitleRow) | ||||
.append(modalContents) | ||||
.append($$1('<div class="' + this.classes.confirmationButtons + '"></div>') | ||||
.append(this.dom.confirmationButton)) | ||||
.appendTo(this.dom.dtContainer); | ||||
$$1(this.s.dt.table().node()).trigger('dtsr-modal-inserted'); | ||||
var inputs = modalContents.children('input'); | ||||
// If there is an input focus on that | ||||
if (inputs.length > 0) { | ||||
$$1(inputs[0]).focus(); | ||||
} | ||||
// Otherwise focus on the confirmation button | ||||
else { | ||||
this.dom.confirmationButton.focus(); | ||||
} | ||||
var background = $$1('div.' + this.classes.background.replace(/ /g, '.')); | ||||
if (this.c.modalCloseButton) { | ||||
this.dom.confirmation.append(this.dom.closeButton); | ||||
this.dom.closeButton.on('click', function () { return background.click(); }); | ||||
} | ||||
// When the button is clicked, call the appropriate action, | ||||
// remove the background and modal from the screen and unbind the keyup event. | ||||
this.dom.confirmationButton.on('click', function () { return buttonAction(); }); | ||||
this.dom.confirmation.on('click', function (e) { | ||||
e.stopPropagation(); | ||||
}); | ||||
// When the button is clicked, remove the background and modal from the screen and unbind the keyup event. | ||||
background.one('click', function () { | ||||
_this.dom.background.remove(); | ||||
_this.dom.confirmation.remove(); | ||||
$$1(document).unbind('keyup', function (e) { return _this._keyupFunction(e); }); | ||||
}); | ||||
$$1(document).on('keyup', function (e) { return _this._keyupFunction(e); }); | ||||
}; | ||||
/** | ||||
* Convert from camelCase notation to the internal Hungarian. | ||||
* We could use the Hungarian convert function here, but this is cleaner | ||||
* | ||||
* @param {object} obj Object to convert | ||||
* @returns {object} Inverted object | ||||
* @memberof DataTable#oApi | ||||
*/ | ||||
StateRestore.prototype._searchToHung = function (obj) { | ||||
return { | ||||
bCaseInsensitive: obj.caseInsensitive, | ||||
bRegex: obj.regex, | ||||
bSmart: obj.smart, | ||||
sSearch: obj.search | ||||
}; | ||||
}; | ||||
StateRestore.version = '1.1.1'; | ||||
StateRestore.classes = { | ||||
background: 'dtsr-background', | ||||
closeButton: 'dtsr-popover-close', | ||||
confirmation: 'dtsr-confirmation', | ||||
confirmationButton: 'dtsr-confirmation-button', | ||||
confirmationButtons: 'dtsr-confirmation-buttons', | ||||
confirmationMessage: 'dtsr-confirmation-message dtsr-name-label', | ||||
confirmationText: 'dtsr-confirmation-text', | ||||
confirmationTitle: 'dtsr-confirmation-title', | ||||
confirmationTitleRow: 'dtsr-confirmation-title-row', | ||||
dtButton: 'dt-button', | ||||
input: 'dtsr-input', | ||||
modalError: 'dtsr-modal-error', | ||||
renameModal: 'dtsr-rename-modal' | ||||
}; | ||||
StateRestore.defaults = { | ||||
_createInSaved: false, | ||||
ajax: false, | ||||
create: true, | ||||
creationModal: false, | ||||
i18n: { | ||||
creationModal: { | ||||
button: 'Create', | ||||
colReorder: 'Column Order:', | ||||
columns: { | ||||
search: 'Column Search:', | ||||
visible: 'Column Visibility:' | ||||
}, | ||||
length: 'Page Length:', | ||||
name: 'Name:', | ||||
order: 'Sorting:', | ||||
paging: 'Paging:', | ||||
scroller: 'Scroll Position:', | ||||
search: 'Search:', | ||||
searchBuilder: 'SearchBuilder:', | ||||
searchPanes: 'SearchPanes:', | ||||
select: 'Select:', | ||||
title: 'Create New State', | ||||
toggleLabel: 'Includes:' | ||||
}, | ||||
duplicateError: 'A state with this name already exists.', | ||||
emptyError: 'Name cannot be empty.', | ||||
emptyStates: 'No saved states', | ||||
removeConfirm: 'Are you sure you want to remove %s?', | ||||
removeError: 'Failed to remove state.', | ||||
removeJoiner: ' and ', | ||||
removeSubmit: 'Remove', | ||||
removeTitle: 'Remove State', | ||||
renameButton: 'Rename', | ||||
renameLabel: 'New Name for %s:', | ||||
renameTitle: 'Rename State' | ||||
}, | ||||
modalCloseButton: true, | ||||
remove: true, | ||||
rename: true, | ||||
save: true, | ||||
saveState: { | ||||
colReorder: true, | ||||
columns: { | ||||
search: true, | ||||
visible: true | ||||
}, | ||||
length: true, | ||||
order: true, | ||||
paging: true, | ||||
scroller: true, | ||||
search: true, | ||||
searchBuilder: true, | ||||
searchPanes: true, | ||||
select: true | ||||
}, | ||||
splitSecondaries: [ | ||||
'updateState', | ||||
'renameState', | ||||
'removeState' | ||||
], | ||||
toggle: { | ||||
colReorder: false, | ||||
columns: { | ||||
search: false, | ||||
visible: false | ||||
}, | ||||
length: false, | ||||
order: false, | ||||
paging: false, | ||||
scroller: false, | ||||
search: false, | ||||
searchBuilder: false, | ||||
searchPanes: false, | ||||
select: false | ||||
} | ||||
}; | ||||
return StateRestore; | ||||
}()); | ||||
var $; | ||||
var dataTable; | ||||
function setJQuery(jq) { | ||||
$ = jq; | ||||
dataTable = jq.fn.dataTable; | ||||
} | ||||
var StateRestoreCollection = /** @class */ (function () { | ||||
function StateRestoreCollection(settings, opts) { | ||||
var _this = this; | ||||
// Check that the required version of DataTables is included | ||||
if (!dataTable || !dataTable.versionCheck || !dataTable.versionCheck('1.10.0')) { | ||||
throw new Error('StateRestore requires DataTables 1.10 or newer'); | ||||
} | ||||
// Check that Select is included | ||||
// eslint-disable-next-line no-extra-parens | ||||
if (!dataTable.Buttons) { | ||||
throw new Error('StateRestore requires Buttons'); | ||||
} | ||||
var table = new dataTable.Api(settings); | ||||
this.classes = $.extend(true, {}, StateRestoreCollection.classes); | ||||
if (table.settings()[0]._stateRestore !== undefined) { | ||||
return; | ||||
} | ||||
// Get options from user | ||||
this.c = $.extend(true, {}, StateRestoreCollection.defaults, opts); | ||||
this.s = { | ||||
dt: table, | ||||
hasColReorder: dataTable.ColReorder !== undefined, | ||||
hasScroller: dataTable.Scroller !== undefined, | ||||
hasSearchBuilder: dataTable.SearchBuilder !== undefined, | ||||
hasSearchPanes: dataTable.SearchPanes !== undefined, | ||||
hasSelect: dataTable.select !== undefined, | ||||
states: [] | ||||
}; | ||||
this.s.dt.on('xhr', function (e, xhrsettings, json) { | ||||
// Has staterestore been used before? Is there anything to load? | ||||
if (json && json.stateRestore) { | ||||
_this._addPreDefined(json.stateRestore); | ||||
} | ||||
}); | ||||
this.dom = { | ||||
background: $('<div class="' + this.classes.background + '"/>'), | ||||
closeButton: $('<div class="' + this.classes.closeButton + '">x</div>'), | ||||
colReorderToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.colReorderToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.colReorder', this.c.i18n.creationModal.colReorder) + | ||||
'</label>' + | ||||
'</div>'), | ||||
columnsSearchToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.columnsSearchToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.columns.search', this.c.i18n.creationModal.columns.search) + | ||||
'</label>' + | ||||
'</div>'), | ||||
columnsVisibleToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + ' ' + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.columnsVisibleToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.columns.visible', this.c.i18n.creationModal.columns.visible) + | ||||
'</label>' + | ||||
'</div>'), | ||||
confirmation: $('<div class="' + this.classes.confirmation + '"/>'), | ||||
confirmationTitleRow: $('<div class="' + this.classes.confirmationTitleRow + '"></div>'), | ||||
createButtonRow: $('<div class="' + this.classes.formRow + ' ' + this.classes.modalFoot + '">' + | ||||
'<button class="' + this.classes.creationButton + ' ' + this.classes.dtButton + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.button', this.c.i18n.creationModal.button) + | ||||
'</button>' + | ||||
'</div>'), | ||||
creation: $('<div class="' + this.classes.creation + '"/>'), | ||||
creationForm: $('<div class="' + this.classes.creationForm + '"/>'), | ||||
creationTitle: $('<div class="' + this.classes.creationText + '">' + | ||||
'<h2 class="' + this.classes.creationTitle + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.title', this.c.i18n.creationModal.title) + | ||||
'</h2>' + | ||||
'</div>'), | ||||
dtContainer: $(this.s.dt.table().container()), | ||||
duplicateError: $('<span class="' + this.classes.modalError + '">' + | ||||
this.s.dt.i18n('stateRestore.duplicateError', this.c.i18n.duplicateError) + | ||||
'</span>'), | ||||
emptyError: $('<span class="' + this.classes.modalError + '">' + | ||||
this.s.dt.i18n('stateRestore.emptyError', this.c.i18n.emptyError) + | ||||
'</span>'), | ||||
lengthToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.lengthToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.length', this.c.i18n.creationModal.length) + | ||||
'</label>' + | ||||
'</div>'), | ||||
nameInputRow: $('<div class="' + this.classes.formRow + '">' + | ||||
'<label class="' + this.classes.nameLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.name', this.c.i18n.creationModal.name) + | ||||
'</label>' + | ||||
'<input class="' + this.classes.nameInput + '" type="text">' + | ||||
'</div>'), | ||||
orderToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.orderToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.order', this.c.i18n.creationModal.order) + | ||||
'</label>' + | ||||
'</div>'), | ||||
pagingToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.pagingToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.paging', this.c.i18n.creationModal.paging) + | ||||
'</label>' + | ||||
'</div>'), | ||||
removeContents: $('<div class="' + this.classes.confirmationText + '"><span></span></div>'), | ||||
removeTitle: $('<div class="' + this.classes.creationText + '">' + | ||||
'<h2 class="' + this.classes.creationTitle + '">' + | ||||
this.s.dt.i18n('stateRestore.removeTitle', this.c.i18n.removeTitle) + | ||||
'</h2>' + | ||||
'</div>'), | ||||
scrollerToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.scrollerToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.scroller', this.c.i18n.creationModal.scroller) + | ||||
'</label>' + | ||||
'</div>'), | ||||
searchBuilderToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.searchBuilderToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.searchBuilder', this.c.i18n.creationModal.searchBuilder) + | ||||
'</label>' + | ||||
'</div>'), | ||||
searchPanesToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.searchPanesToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.searchPanes', this.c.i18n.creationModal.searchPanes) + | ||||
'</label>' + | ||||
'</div>'), | ||||
searchToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.searchToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.search', this.c.i18n.creationModal.search) + | ||||
'</label>' + | ||||
'</div>'), | ||||
selectToggle: $('<div class="' + this.classes.formRow + ' ' + this.classes.checkRow + '">' + | ||||
'<input type="checkbox" class="' + | ||||
this.classes.selectToggle + ' ' + | ||||
this.classes.checkBox + | ||||
'" checked>' + | ||||
'<label class="' + this.classes.checkLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.select', this.c.i18n.creationModal.select) + | ||||
'</label>' + | ||||
'</div>'), | ||||
toggleLabel: $('<label class="' + this.classes.nameLabel + ' ' + this.classes.toggleLabel + '">' + | ||||
this.s.dt.i18n('stateRestore.creationModal.toggleLabel', this.c.i18n.creationModal.toggleLabel) + | ||||
'</label>') | ||||
}; | ||||
table.settings()[0]._stateRestore = this; | ||||
this._searchForStates(); | ||||
// Has staterestore been used before? Is there anything to load? | ||||
this._addPreDefined(this.c.preDefined); | ||||
var ajaxFunction; | ||||
var ajaxData = { | ||||
action: 'load' | ||||
}; | ||||
if (typeof this.c.ajax === 'function') { | ||||
ajaxFunction = function () { | ||||
if (typeof _this.c.ajax === 'function') { | ||||
_this.c.ajax.call(_this.s.dt, ajaxData, function (s) { return _this._addPreDefined(s); }); | ||||
} | ||||
}; | ||||
} | ||||
else if (typeof this.c.ajax === 'string') { | ||||
ajaxFunction = function () { | ||||
$.ajax({ | ||||
data: ajaxData, | ||||
success: function (data) { | ||||
_this._addPreDefined(data); | ||||
}, | ||||
type: 'POST', | ||||
url: _this.c.ajax | ||||
}); | ||||
}; | ||||
} | ||||
if (typeof ajaxFunction === 'function') { | ||||
if (this.s.dt.settings()[0]._bInitComplete) { | ||||
ajaxFunction(); | ||||
} | ||||
else { | ||||
this.s.dt.one('preInit.dtsr', function () { | ||||
ajaxFunction(); | ||||
}); | ||||
} | ||||
} | ||||
this.s.dt.on('destroy.dtsr', function () { | ||||
_this.destroy(); | ||||
}); | ||||
this.s.dt.on('draw.dtsr buttons-action.dtsr', function () { return _this.findActive(); }); | ||||
return this; | ||||
} | ||||
/** | ||||
* Adds a new StateRestore instance to the collection based on the current properties of the table | ||||
* | ||||
* @param identifier The value that is used to identify a state. | ||||
* @returns The state that has been created | ||||
*/ | ||||
StateRestoreCollection.prototype.addState = function (identifier, currentIdentifiers, options) { | ||||
var _this = this; | ||||
// If creation/saving is not allowed then return | ||||
if (!this.c.create || !this.c.save) { | ||||
return; | ||||
} | ||||
// Check if the state exists before creating a new ones | ||||
var state = this.getState(identifier); | ||||
var createFunction = function (id, toggles) { | ||||
if (id.length === 0) { | ||||
return 'empty'; | ||||
} | ||||
else if (currentIdentifiers.includes(id)) { | ||||
return 'duplicate'; | ||||
} | ||||
_this.s.dt.state.save(); | ||||
var that = _this; | ||||
var successCallback = function () { | ||||
that.s.states.push(this); | ||||
that._collectionRebuild(); | ||||
}; | ||||
var currState = _this.s.dt.state(); | ||||
currState.stateRestore = { | ||||
isPredefined: false, | ||||
state: id, | ||||
tableId: _this.s.dt.table().node().id | ||||
}; | ||||
if (toggles.saveState) { | ||||
var opts = _this.c.saveState; | ||||
// We don't want to extend, but instead AND all properties of the saveState option | ||||
for (var _i = 0, _a = Object.keys(toggles.saveState); _i < _a.length; _i++) { | ||||
var key = _a[_i]; | ||||
if (!toggles.saveState[key]) { | ||||
opts[key] = false; | ||||
} | ||||
} | ||||
_this.c.saveState = opts; | ||||
} | ||||
var newState = new StateRestore(_this.s.dt.settings()[0], $.extend(true, {}, _this.c, options), id, currState, false, successCallback); | ||||
$(_this.s.dt.table().node()).on('dtsr-modal-inserted', function () { | ||||
newState.dom.confirmation.one('dtsr-remove', function () { return _this._removeCallback(newState.s.identifier); }); | ||||
newState.dom.confirmation.one('dtsr-rename', function () { return _this._collectionRebuild(); }); | ||||
newState.dom.confirmation.one('dtsr-save', function () { return _this._collectionRebuild(); }); | ||||
}); | ||||
return true; | ||||
}; | ||||
// If there isn't already a state with this identifier | ||||
if (state === null) { | ||||
if (this.c.creationModal || options !== undefined && options.creationModal) { | ||||
this._creationModal(createFunction, identifier, options); | ||||
} | ||||
else { | ||||
var success = createFunction(identifier, {}); | ||||
if (success === 'empty') { | ||||
throw new Error(this.s.dt.i18n('stateRestore.emptyError', this.c.i18n.emptyError)); | ||||
} | ||||
else if (success === 'duplicate') { | ||||
throw new Error(this.s.dt.i18n('stateRestore.duplicateError', this.c.i18n.duplicateError)); | ||||
} | ||||
} | ||||
} | ||||
else { | ||||
throw new Error(this.s.dt.i18n('stateRestore.duplicateError', this.c.i18n.duplicateError)); | ||||
} | ||||
}; | ||||
/** | ||||
* Removes all of the states, showing a modal to the user for confirmation | ||||
* | ||||
* @param removeFunction The action to be taken when the action is confirmed | ||||
*/ | ||||
StateRestoreCollection.prototype.removeAll = function (removeFunction) { | ||||
// There are no states to remove so just return | ||||
if (this.s.states.length === 0) { | ||||
return; | ||||
} | ||||
var ids = this.s.states.map(function (state) { return state.s.identifier; }); | ||||
var replacementString = ids[0]; | ||||
if (ids.length > 1) { | ||||
replacementString = ids.slice(0, -1).join(', ') + | ||||
this.s.dt.i18n('stateRestore.removeJoiner', this.c.i18n.removeJoiner) + | ||||
ids.slice(-1); | ||||
} | ||||
$(this.dom.removeContents.children('span')).html(this.s.dt | ||||
.i18n('stateRestore.removeConfirm', this.c.i18n.removeConfirm) | ||||
.replace(/%s/g, replacementString)); | ||||
this._newModal(this.dom.removeTitle, this.s.dt.i18n('stateRestore.removeSubmit', this.c.i18n.removeSubmit), removeFunction, this.dom.removeContents); | ||||
}; | ||||
/** | ||||
* Removes all of the dom elements from the document for the collection and the stored states | ||||
*/ | ||||
StateRestoreCollection.prototype.destroy = function () { | ||||
for (var _i = 0, _a = this.s.states; _i < _a.length; _i++) { | ||||
var state = _a[_i]; | ||||
state.destroy(); | ||||
} | ||||
Object.values(this.dom).forEach(function (node) { | ||||
node.off(); | ||||
node.remove(); | ||||
}); | ||||
this.s.states = []; | ||||
this.s.dt.off('.dtsr'); | ||||
$(this.s.dt.table().node()).off('.dtsr'); | ||||
}; | ||||
/** | ||||
* Identifies active states and updates their button to reflect this. | ||||
* | ||||
* @returns An array containing objects with the details of currently active states | ||||
*/ | ||||
StateRestoreCollection.prototype.findActive = function () { | ||||
// Make sure that the state is up to date | ||||
this.s.dt.state.save(); | ||||
var currState = this.s.dt.state(); | ||||
// Make all of the buttons inactive so that only any that match will be marked as active | ||||
var buttons = $('button.' + $.fn.DataTable.Buttons.defaults.dom.button.className.replace(/ /g, '.')); | ||||
// Some of the styling libraries use a tags instead of buttons | ||||
if (buttons.length === 0) { | ||||
buttons = $('a.' + $.fn.DataTable.Buttons.defaults.dom.button.className.replace(/ /g, '.')); | ||||
} | ||||
for (var _i = 0, buttons_1 = buttons; _i < buttons_1.length; _i++) { | ||||
var button = buttons_1[_i]; | ||||
this.s.dt.button($(button).parent()[0]).active(false); | ||||
} | ||||
var results = []; | ||||
// Go through all of the states comparing if their state is the same to the current one | ||||
for (var _a = 0, _b = this.s.states; _a < _b.length; _a++) { | ||||
var state = _b[_a]; | ||||
if (state.compare(currState)) { | ||||
results.push({ | ||||
data: state.s.savedState, | ||||
name: state.s.identifier | ||||
}); | ||||
// If so, find the corresponding button and mark it as active | ||||
for (var _c = 0, buttons_2 = buttons; _c < buttons_2.length; _c++) { | ||||
var button = buttons_2[_c]; | ||||
if ($(button).text() === state.s.identifier) { | ||||
this.s.dt.button($(button).parent()[0]).active(true); | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
return results; | ||||
}; | ||||
/** | ||||
* Gets a single state that has the identifier matching that which is passed in | ||||
* | ||||
* @param identifier The value that is used to identify a state | ||||
* @returns The state that has been identified or null if no states have been identified | ||||
*/ | ||||
StateRestoreCollection.prototype.getState = function (identifier) { | ||||
for (var _i = 0, _a = this.s.states; _i < _a.length; _i++) { | ||||
var state = _a[_i]; | ||||
if (state.s.identifier === identifier) { | ||||
return state; | ||||
} | ||||
} | ||||
return null; | ||||
}; | ||||
/** | ||||
* Gets an array of all of the states | ||||
* | ||||
* @returns Any states that have been identified | ||||
*/ | ||||
StateRestoreCollection.prototype.getStates = function (ids) { | ||||
if (ids === undefined) { | ||||
return this.s.states; | ||||
} | ||||
else { | ||||
var states = []; | ||||
for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) { | ||||
var id = ids_1[_i]; | ||||
var found = false; | ||||
for (var _a = 0, _b = this.s.states; _a < _b.length; _a++) { | ||||
var state = _b[_a]; | ||||
if (id === state.s.identifier) { | ||||
states.push(state); | ||||
found = true; | ||||
break; | ||||
} | ||||
} | ||||
if (!found) { | ||||
states.push(undefined); | ||||
} | ||||
} | ||||
return states; | ||||
} | ||||
}; | ||||
/** | ||||
* Reloads states that are set via datatables config or over ajax | ||||
* | ||||
* @param preDefined Object containing the predefined states that are to be reintroduced | ||||
*/ | ||||
StateRestoreCollection.prototype._addPreDefined = function (preDefined) { | ||||
var _this = this; | ||||
// There is a potential issue here if sorting where the string parts of the name are the same, | ||||
// only the number differs and there are many states - but this wouldn't be usfeul naming so | ||||
// more of a priority to sort alphabetically | ||||
var states = Object.keys(preDefined).sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); | ||||
var _loop_1 = function (state) { | ||||
for (var i = 0; i < this_1.s.states.length; i++) { | ||||
if (this_1.s.states[i].s.identifier === state) { | ||||
this_1.s.states.splice(i, 1); | ||||
} | ||||
} | ||||
var that = this_1; | ||||
var successCallback = function () { | ||||
that.s.states.push(this); | ||||
that._collectionRebuild(); | ||||
}; | ||||
var loadedState = preDefined[state]; | ||||
var newState = new StateRestore(this_1.s.dt, $.extend(true, {}, this_1.c, loadedState.c !== undefined ? | ||||
{ saveState: loadedState.c.saveState } : | ||||
undefined, true), state, loadedState, true, successCallback); | ||||
newState.s.savedState = loadedState; | ||||
$(this_1.s.dt.table().node()).on('dtsr-modal-inserted', function () { | ||||
newState.dom.confirmation.one('dtsr-remove', function () { return _this._removeCallback(newState.s.identifier); }); | ||||
newState.dom.confirmation.one('dtsr-rename', function () { return _this._collectionRebuild(); }); | ||||
newState.dom.confirmation.one('dtsr-save', function () { return _this._collectionRebuild(); }); | ||||
}); | ||||
}; | ||||
var this_1 = this; | ||||
for (var _i = 0, states_1 = states; _i < states_1.length; _i++) { | ||||
var state = states_1[_i]; | ||||
_loop_1(state); | ||||
} | ||||
}; | ||||
/** | ||||
* Rebuilds all of the buttons in the collection of states to make sure that states and text is up to date | ||||
*/ | ||||
StateRestoreCollection.prototype._collectionRebuild = function () { | ||||
var button = this.s.dt.button('SaveStateRestore:name'); | ||||
var stateButtons = button[0] !== undefined && button[0].inst.c.buttons[0].buttons !== undefined ? | ||||
button[0].inst.c.buttons[0].buttons : | ||||
[]; | ||||
// remove any states from the previous rebuild - if they are still there they will be added later | ||||
for (var i = 0; i < stateButtons.length; i++) { | ||||
if (stateButtons[i].extend === 'stateRestore') { | ||||
stateButtons.splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
if (this.c._createInSaved) { | ||||
stateButtons.push('createState'); | ||||
} | ||||
var emptyText = '<span class="' + this.classes.emptyStates + '">' + | ||||
this.s.dt.i18n('stateRestore.emptyStates', this.c.i18n.emptyStates) + | ||||
'</span>'; | ||||
// If there are no states display an empty message | ||||
if (this.s.states.length === 0) { | ||||
// Don't want the empty text included more than twice | ||||
if (!stateButtons.includes(emptyText)) { | ||||
stateButtons.push(emptyText); | ||||
} | ||||
} | ||||
else { | ||||
// There are states to add so there shouldn't be any empty text left! | ||||
while (stateButtons.includes(emptyText)) { | ||||
stateButtons.splice(stateButtons.indexOf(emptyText), 1); | ||||
} | ||||
// There is a potential issue here if sorting where the string parts of the name are the same, | ||||
// only the number differs and there are many states - but this wouldn't be usfeul naming so | ||||
// more of a priority to sort alphabetically | ||||
this.s.states = this.s.states.sort(function (a, b) { | ||||
var aId = a.s.identifier; | ||||
var bId = b.s.identifier; | ||||
return aId > bId ? | ||||
1 : | ||||
aId < bId ? | ||||
-1 : | ||||
0; | ||||
}); | ||||
// Construct the split property of each button | ||||
for (var _i = 0, _a = this.s.states; _i < _a.length; _i++) { | ||||
var state = _a[_i]; | ||||
var split = Object.assign([], this.c.splitSecondaries); | ||||
if (split.includes('updateState') && (!this.c.save || !state.c.save)) { | ||||
split.splice(split.indexOf('updateState'), 1); | ||||
} | ||||
if (split.includes('renameState') && | ||||
(!this.c.save || !state.c.save || !this.c.rename || !state.c.rename)) { | ||||
split.splice(split.indexOf('renameState'), 1); | ||||
} | ||||
if (split.includes('removeState') && (!this.c.remove || !state.c.remove)) { | ||||
split.splice(split.indexOf('removeState'), 1); | ||||
} | ||||
if (split.length > 0 && | ||||
!split.includes('<h3>' + state.s.identifier + '</h3>')) { | ||||
split.unshift('<h3>' + state.s.identifier + '</h3>'); | ||||
} | ||||
stateButtons.push({ | ||||
_stateRestore: state, | ||||
attr: { | ||||
title: state.s.identifier | ||||
}, | ||||
config: { | ||||
split: split | ||||
}, | ||||
extend: 'stateRestore', | ||||
text: state.s.identifier | ||||
}); | ||||
} | ||||
} | ||||
button.collectionRebuild(stateButtons); | ||||
// Need to disable the removeAllStates button if there are no states and it is present | ||||
var buttons = this.s.dt.buttons(); | ||||
for (var _b = 0, buttons_3 = buttons; _b < buttons_3.length; _b++) { | ||||
var butt = buttons_3[_b]; | ||||
if ($(butt.node).hasClass('dtsr-removeAllStates')) { | ||||
if (this.s.states.length === 0) { | ||||
this.s.dt.button(butt.node).disable(); | ||||
} | ||||
else { | ||||
this.s.dt.button(butt.node).enable(); | ||||
} | ||||
} | ||||
} | ||||
}; | ||||
/** | ||||
* Displays a modal that is used to get information from the user to create a new state. | ||||
* | ||||
* @param buttonAction The action that should be taken when the button is pressed | ||||
* @param identifier The default identifier for the next new state | ||||
*/ | ||||
StateRestoreCollection.prototype._creationModal = function (buttonAction, identifier, options) { | ||||
var _this = this; | ||||
this.dom.creation.empty(); | ||||
this.dom.creationForm.empty(); | ||||
this.dom.nameInputRow.children('input').val(identifier); | ||||
this.dom.creationForm.append(this.dom.nameInputRow); | ||||
var tableConfig = this.s.dt.settings()[0].oInit; | ||||
var togglesToInsert = []; | ||||
var toggleDefined = options !== undefined && options.toggle !== undefined; | ||||
// Order toggle - check toggle and saving enabled | ||||
if (((!toggleDefined || options.toggle.order === undefined) && this.c.toggle.order || | ||||
toggleDefined && options.toggle.order) && | ||||
this.c.saveState.order && | ||||
(tableConfig.ordering === undefined || tableConfig.ordering)) { | ||||
togglesToInsert.push(this.dom.orderToggle); | ||||
} | ||||
// Search toggle - check toggle and saving enabled | ||||
if (((!toggleDefined || options.toggle.search === undefined) && this.c.toggle.search || | ||||
toggleDefined && options.toggle.search) && | ||||
this.c.saveState.search && | ||||
(tableConfig.searching === undefined || tableConfig.searching)) { | ||||
togglesToInsert.push(this.dom.searchToggle); | ||||
} | ||||
// Paging toggle - check toggle and saving enabled | ||||
if (((!toggleDefined || options.toggle.paging === undefined) && this.c.toggle.paging || | ||||
toggleDefined && options.toggle.paging) && | ||||
this.c.saveState.paging && | ||||
(tableConfig.paging === undefined || tableConfig.paging)) { | ||||
togglesToInsert.push(this.dom.pagingToggle); | ||||
} | ||||
// Page Length toggle - check toggle and saving enabled | ||||
if (((!toggleDefined || options.toggle.length === undefined) && this.c.toggle.length || | ||||
toggleDefined && options.toggle.length) && | ||||
this.c.saveState.length && | ||||
(tableConfig.length === undefined || tableConfig.length)) { | ||||
togglesToInsert.push(this.dom.lengthToggle); | ||||
} | ||||
// ColReorder toggle - check toggle and saving enabled | ||||
if (this.s.hasColReorder && | ||||
((!toggleDefined || options.toggle.colReorder === undefined) && this.c.toggle.colReorder || | ||||
toggleDefined && options.toggle.colReorder) && | ||||
this.c.saveState.colReorder) { | ||||
togglesToInsert.push(this.dom.colReorderToggle); | ||||
} | ||||
// Scroller toggle - check toggle and saving enabled | ||||
if (this.s.hasScroller && | ||||
((!toggleDefined || options.toggle.scroller === undefined) && this.c.toggle.scroller || | ||||
toggleDefined && options.toggle.scroller) && | ||||
this.c.saveState.scroller) { | ||||
togglesToInsert.push(this.dom.scrollerToggle); | ||||
} | ||||
// SearchBuilder toggle - check toggle and saving enabled | ||||
if (this.s.hasSearchBuilder && | ||||
((!toggleDefined || options.toggle.searchBuilder === undefined) && this.c.toggle.searchBuilder || | ||||
toggleDefined && options.toggle.searchBuilder) && | ||||
this.c.saveState.searchBuilder) { | ||||
togglesToInsert.push(this.dom.searchBuilderToggle); | ||||
} | ||||
// SearchPanes toggle - check toggle and saving enabled | ||||
if (this.s.hasSearchPanes && | ||||
((!toggleDefined || options.toggle.searchPanes === undefined) && this.c.toggle.searchPanes || | ||||
toggleDefined && options.toggle.searchPanes) && | ||||
this.c.saveState.searchPanes) { | ||||
togglesToInsert.push(this.dom.searchPanesToggle); | ||||
} | ||||
// Select toggle - check toggle and saving enabled | ||||
if (this.s.hasSelect && | ||||
((!toggleDefined || options.toggle.select === undefined) && this.c.toggle.select || | ||||
toggleDefined && options.toggle.select) && | ||||
this.c.saveState.select) { | ||||
togglesToInsert.push(this.dom.selectToggle); | ||||
} | ||||
// Columns toggle - check toggle and saving enabled | ||||
if (typeof this.c.toggle.columns === 'boolean' && | ||||
((!toggleDefined || options.toggle.order === undefined) && this.c.toggle.columns || | ||||
toggleDefined && options.toggle.order) && | ||||
this.c.saveState.columns) { | ||||
togglesToInsert.push(this.dom.columnsSearchToggle); | ||||
togglesToInsert.push(this.dom.columnsVisibleToggle); | ||||
} | ||||
else if ((!toggleDefined || options.toggle.columns === undefined) && typeof this.c.toggle.columns !== 'boolean' || | ||||
typeof options.toggle.order !== 'boolean') { | ||||
if (typeof this.c.saveState.columns !== 'boolean' && this.c.saveState.columns) { | ||||
// Column search toggle - check toggle and saving enabled | ||||
if (( | ||||
// columns.search is defined when passed in | ||||
toggleDefined && | ||||
options.toggle.columns !== undefined && | ||||
typeof options.toggle.columns !== 'boolean' && | ||||
options.toggle.columns.search || | ||||
// Columns search is not defined when passed in but is in defaults | ||||
(!toggleDefined || | ||||
options.toggle.columns === undefined || | ||||
typeof options.toggle.columns !== 'boolean' && options.toggle.columns.search === undefined) && | ||||
typeof this.c.toggle.columns !== 'boolean' && | ||||
this.c.toggle.columns.search) && | ||||
this.c.saveState.columns.search) { | ||||
togglesToInsert.push(this.dom.columnsSearchToggle); | ||||
} | ||||
// Column visiblity toggle - check toggle and saving enabled | ||||
if (( | ||||
// columns.visible is defined when passed in | ||||
toggleDefined && | ||||
options.toggle.columns !== undefined && | ||||
typeof options.toggle.columns !== 'boolean' && | ||||
options.toggle.columns.visible || | ||||
// Columns visible is not defined when passed in but is in defaults | ||||
(!toggleDefined || | ||||
options.toggle.columns === undefined || | ||||
typeof options.toggle.columns !== 'boolean' && options.toggle.columns.visible === undefined) && | ||||
typeof this.c.toggle.columns !== 'boolean' && | ||||
this.c.toggle.columns.visible) && | ||||
this.c.saveState.columns.visible) { | ||||
togglesToInsert.push(this.dom.columnsVisibleToggle); | ||||
} | ||||
} | ||||
else if (this.c.saveState.columns) { | ||||
togglesToInsert.push(this.dom.columnsSearchToggle); | ||||
togglesToInsert.push(this.dom.columnsVisibleToggle); | ||||
} | ||||
} | ||||
// Make sure that the toggles are displayed alphabetically | ||||
togglesToInsert.sort(function (a, b) { | ||||
var aVal = a.children('label.dtsr-check-label')[0].innerHTML; | ||||
var bVal = b.children('label.dtsr-check-label')[0].innerHTML; | ||||
if (aVal < bVal) { | ||||
return -1; | ||||
} | ||||
else if (aVal > bVal) { | ||||
return 1; | ||||
} | ||||
else { | ||||
return 0; | ||||
} | ||||
}); | ||||
// Append all of the toggles that are to be inserted | ||||
for (var _i = 0, togglesToInsert_1 = togglesToInsert; _i < togglesToInsert_1.length; _i++) { | ||||
var toggle = togglesToInsert_1[_i]; | ||||
this.dom.creationForm.append(toggle); | ||||
} | ||||
// Insert the toggle label next to the first check box | ||||
$(this.dom.creationForm.children('div.' + this.classes.checkRow)[0]).prepend(this.dom.toggleLabel); | ||||
// Insert the creation modal and the background | ||||
this.dom.background.appendTo(this.dom.dtContainer); | ||||
this.dom.creation | ||||
.append(this.dom.creationTitle) | ||||
.append(this.dom.creationForm) | ||||
.append(this.dom.createButtonRow) | ||||
.appendTo(this.dom.dtContainer); | ||||
$(this.s.dt.table().node()).trigger('dtsr-modal-inserted'); | ||||
var _loop_2 = function (toggle) { | ||||
$(toggle.children('label:last-child')).on('click', function () { | ||||
toggle.children('input').prop('checked', !toggle.children('input').prop('checked')); | ||||
}); | ||||
}; | ||||
// Allow the label to be clicked to toggle the checkbox | ||||
for (var _a = 0, togglesToInsert_2 = togglesToInsert; _a < togglesToInsert_2.length; _a++) { | ||||
var toggle = togglesToInsert_2[_a]; | ||||
_loop_2(toggle); | ||||
} | ||||
var creationButton = $('button.' + this.classes.creationButton.replace(/ /g, '.')); | ||||
var inputs = this.dom.creationForm.find('input'); | ||||
// If there is an input focus on that | ||||
if (inputs.length > 0) { | ||||
$(inputs[0]).focus(); | ||||
} | ||||
// Otherwise focus on the confirmation button | ||||
else { | ||||
creationButton.focus(); | ||||
} | ||||
var background = $('div.' + this.classes.background.replace(/ /g, '.')); | ||||
var keyupFunction = function (e) { | ||||
if (e.key === 'Enter') { | ||||
creationButton.click(); | ||||
} | ||||
else if (e.key === 'Escape') { | ||||
background.click(); | ||||
} | ||||
}; | ||||
if (this.c.modalCloseButton) { | ||||
this.dom.creation.append(this.dom.closeButton); | ||||
this.dom.closeButton.on('click', function () { return background.click(); }); | ||||
} | ||||
creationButton.on('click', function () { | ||||
// Get the values of the checkBoxes | ||||
var saveState = { | ||||
colReorder: _this.dom.colReorderToggle.children('input').is(':checked'), | ||||
columns: { | ||||
search: _this.dom.columnsSearchToggle.children('input').is(':checked'), | ||||
visible: _this.dom.columnsVisibleToggle.children('input').is(':checked') | ||||
}, | ||||
length: _this.dom.lengthToggle.children('input').is(':checked'), | ||||
order: _this.dom.orderToggle.children('input').is(':checked'), | ||||
paging: _this.dom.pagingToggle.children('input').is(':checked'), | ||||
scroller: _this.dom.scrollerToggle.children('input').is(':checked'), | ||||
search: _this.dom.searchToggle.children('input').is(':checked'), | ||||
searchBuilder: _this.dom.searchBuilderToggle.children('input').is(':checked'), | ||||
searchPanes: _this.dom.searchPanesToggle.children('input').is(':checked'), | ||||
select: _this.dom.selectToggle.children('input').is(':checked') | ||||
}; | ||||
// Call the buttons functionality passing in the identifier and what should be saved | ||||
var success = buttonAction($('input.' + _this.classes.nameInput.replace(/ /g, '.')).val(), { saveState: saveState }); | ||||
if (success === true) { | ||||
// Remove the dom elements as operation has completed | ||||
_this.dom.background.remove(); | ||||
_this.dom.creation.remove(); | ||||
// Unbind the keyup function - don't want it to run unnecessarily on every keypress that occurs | ||||
$(document).unbind('keyup', keyupFunction); | ||||
} | ||||
else { | ||||
_this.dom.creation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.creation.append(_this.dom[success + 'Error']); | ||||
} | ||||
}); | ||||
background.one('click', function () { | ||||
// Remove the dome elements as operation has been cancelled | ||||
_this.dom.background.remove(); | ||||
_this.dom.creation.remove(); | ||||
// Unbind the keyup function - don't want it to run unnecessarily on every keypress that occurs | ||||
$(document).unbind('keyup', keyupFunction); | ||||
// Rebuild the collection to ensure that the latest changes are present | ||||
_this._collectionRebuild(); | ||||
}); | ||||
// Have to listen to the keyup event as `escape` doesn't trigger keypress | ||||
$(document).on('keyup', keyupFunction); | ||||
// Need to save the state before the focus is lost when the modal is interacted with | ||||
this.s.dt.state.save(); | ||||
}; | ||||
/** | ||||
* This callback is called when a state is removed. | ||||
* This removes the state from storage and also strips it's button from the container | ||||
* | ||||
* @param identifier The value that is used to identify a state | ||||
*/ | ||||
StateRestoreCollection.prototype._removeCallback = function (identifier) { | ||||
for (var i = 0; i < this.s.states.length; i++) { | ||||
if (this.s.states[i].s.identifier === identifier) { | ||||
this.s.states.splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
this._collectionRebuild(); | ||||
return true; | ||||
}; | ||||
/** | ||||
* Creates a new confirmation modal for the user to approve an action | ||||
* | ||||
* @param title The title that is to be displayed at the top of the modal | ||||
* @param buttonText The text that is to be displayed in the confirmation button of the modal | ||||
* @param buttonAction The action that should be taken when the confirmation button is pressed | ||||
* @param modalContents The contents for the main body of the modal | ||||
*/ | ||||
StateRestoreCollection.prototype._newModal = function (title, buttonText, buttonAction, modalContents) { | ||||
var _this = this; | ||||
this.dom.background.appendTo(this.dom.dtContainer); | ||||
this.dom.confirmationTitleRow.empty().append(title); | ||||
var confirmationButton = $('<button class="' + this.classes.confirmationButton + ' ' + this.classes.dtButton + '">' + | ||||
buttonText + | ||||
'</button>'); | ||||
this.dom.confirmation | ||||
.empty() | ||||
.append(this.dom.confirmationTitleRow) | ||||
.append(modalContents) | ||||
.append($('<div class="' + this.classes.confirmationButtons + '"></div>') | ||||
.append(confirmationButton)) | ||||
.appendTo(this.dom.dtContainer); | ||||
$(this.s.dt.table().node()).trigger('dtsr-modal-inserted'); | ||||
var inputs = modalContents.children('input'); | ||||
// If there is an input focus on that | ||||
if (inputs.length > 0) { | ||||
$(inputs[0]).focus(); | ||||
} | ||||
// Otherwise focus on the confirmation button | ||||
else { | ||||
confirmationButton.focus(); | ||||
} | ||||
var background = $('div.' + this.classes.background.replace(/ /g, '.')); | ||||
var keyupFunction = function (e) { | ||||
// If enter same action as pressing the button | ||||
if (e.key === 'Enter') { | ||||
confirmationButton.click(); | ||||
} | ||||
// If escape close modal | ||||
else if (e.key === 'Escape') { | ||||
background.click(); | ||||
} | ||||
}; | ||||
// When the button is clicked, call the appropriate action, | ||||
// remove the background and modal from the screen and unbind the keyup event. | ||||
confirmationButton.on('click', function () { | ||||
var success = buttonAction(true); | ||||
if (success === true) { | ||||
_this.dom.background.remove(); | ||||
_this.dom.confirmation.remove(); | ||||
$(document).unbind('keyup', keyupFunction); | ||||
confirmationButton.off('click'); | ||||
} | ||||
else { | ||||
_this.dom.confirmation.children('.' + _this.classes.modalError).remove(); | ||||
_this.dom.confirmation.append(_this.dom[success + 'Error']); | ||||
} | ||||
}); | ||||
this.dom.confirmation.on('click', function (e) { | ||||
e.stopPropagation(); | ||||
}); | ||||
// When the button is clicked, remove the background and modal from the screen and unbind the keyup event. | ||||
background.one('click', function () { | ||||
_this.dom.background.remove(); | ||||
_this.dom.confirmation.remove(); | ||||
$(document).unbind('keyup', keyupFunction); | ||||
}); | ||||
$(document).on('keyup', keyupFunction); | ||||
}; | ||||
/** | ||||
* Private method that checks for previously created states on initialisation | ||||
*/ | ||||
StateRestoreCollection.prototype._searchForStates = function () { | ||||
var _this = this; | ||||
var keys = Object.keys(localStorage); | ||||
var _loop_3 = function (key) { | ||||
// eslint-disable-next-line no-useless-escape | ||||
if (key.match(new RegExp('^DataTables_stateRestore_.*_' + location.pathname.replace(/\//g, '/') + '$')) || | ||||
key.match(new RegExp('^DataTables_stateRestore_.*_' + location.pathname.replace(/\//g, '/') + | ||||
'_' + this_2.s.dt.table().node().id + '$'))) { | ||||
var loadedState_1 = JSON.parse(localStorage.getItem(key)); | ||||
if (loadedState_1.stateRestore.isPreDefined || | ||||
(loadedState_1.stateRestore.tableId && | ||||
loadedState_1.stateRestore.tableId !== this_2.s.dt.table().node().id)) { | ||||
return "continue"; | ||||
} | ||||
var that_1 = this_2; | ||||
var successCallback = function () { | ||||
this.s.savedState = loadedState_1; | ||||
that_1.s.states.push(this); | ||||
that_1._collectionRebuild(); | ||||
}; | ||||
var newState_1 = new StateRestore(this_2.s.dt, $.extend(true, {}, this_2.c, { saveState: loadedState_1.c.saveState }), loadedState_1.stateRestore.state, loadedState_1, false, successCallback); | ||||
$(this_2.s.dt.table().node()).on('dtsr-modal-inserted', function () { | ||||
newState_1.dom.confirmation.one('dtsr-remove', function () { return _this._removeCallback(newState_1.s.identifier); }); | ||||
newState_1.dom.confirmation.one('dtsr-rename', function () { return _this._collectionRebuild(); }); | ||||
newState_1.dom.confirmation.one('dtsr-save', function () { return _this._collectionRebuild(); }); | ||||
}); | ||||
} | ||||
}; | ||||
var this_2 = this; | ||||
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { | ||||
var key = keys_1[_i]; | ||||
_loop_3(key); | ||||
} | ||||
}; | ||||
StateRestoreCollection.version = '1.0.0'; | ||||
StateRestoreCollection.classes = { | ||||
background: 'dtsr-background', | ||||
checkBox: 'dtsr-check-box', | ||||
checkLabel: 'dtsr-check-label', | ||||
checkRow: 'dtsr-check-row', | ||||
closeButton: 'dtsr-popover-close', | ||||
colReorderToggle: 'dtsr-colReorder-toggle', | ||||
columnsSearchToggle: 'dtsr-columns-search-toggle', | ||||
columnsVisibleToggle: 'dtsr-columns-visible-toggle', | ||||
confirmation: 'dtsr-confirmation', | ||||
confirmationButton: 'dtsr-confirmation-button', | ||||
confirmationButtons: 'dtsr-confirmation-buttons', | ||||
confirmationMessage: 'dtsr-confirmation-message dtsr-name-label', | ||||
confirmationText: 'dtsr-confirmation-text', | ||||
confirmationTitle: 'dtsr-confirmation-title', | ||||
confirmationTitleRow: 'dtsr-confirmation-title-row', | ||||
creation: 'dtsr-creation', | ||||
creationButton: 'dtsr-creation-button', | ||||
creationForm: 'dtsr-creation-form', | ||||
creationText: 'dtsr-creation-text', | ||||
creationTitle: 'dtsr-creation-title', | ||||
dtButton: 'dt-button', | ||||
emptyStates: 'dtsr-emptyStates', | ||||
formRow: 'dtsr-form-row', | ||||
leftSide: 'dtsr-left', | ||||
lengthToggle: 'dtsr-length-toggle', | ||||
modalError: 'dtsr-modal-error', | ||||
modalFoot: 'dtsr-modal-foot', | ||||
nameInput: 'dtsr-name-input', | ||||
nameLabel: 'dtsr-name-label', | ||||
orderToggle: 'dtsr-order-toggle', | ||||
pagingToggle: 'dtsr-paging-toggle', | ||||
rightSide: 'dtsr-right', | ||||
scrollerToggle: 'dtsr-scroller-toggle', | ||||
searchBuilderToggle: 'dtsr-searchBuilder-toggle', | ||||
searchPanesToggle: 'dtsr-searchPanes-toggle', | ||||
searchToggle: 'dtsr-search-toggle', | ||||
selectToggle: 'dtsr-select-toggle', | ||||
toggleLabel: 'dtsr-toggle-title' | ||||
}; | ||||
StateRestoreCollection.defaults = { | ||||
_createInSaved: false, | ||||
ajax: false, | ||||
create: true, | ||||
creationModal: false, | ||||
i18n: { | ||||
creationModal: { | ||||
button: 'Create', | ||||
colReorder: 'Column Order', | ||||
columns: { | ||||
search: 'Column Search', | ||||
visible: 'Column Visibility' | ||||
}, | ||||
length: 'Page Length', | ||||
name: 'Name:', | ||||
order: 'Sorting', | ||||
paging: 'Paging', | ||||
scroller: 'Scroll Position', | ||||
search: 'Search', | ||||
searchBuilder: 'SearchBuilder', | ||||
searchPanes: 'SearchPanes', | ||||
select: 'Select', | ||||
title: 'Create New State', | ||||
toggleLabel: 'Includes:' | ||||
}, | ||||
duplicateError: 'A state with this name already exists.', | ||||
emptyError: 'Name cannot be empty.', | ||||
emptyStates: 'No saved states', | ||||
removeConfirm: 'Are you sure you want to remove %s?', | ||||
removeError: 'Failed to remove state.', | ||||
removeJoiner: ' and ', | ||||
removeSubmit: 'Remove', | ||||
removeTitle: 'Remove State', | ||||
renameButton: 'Rename', | ||||
renameLabel: 'New Name for %s:', | ||||
renameTitle: 'Rename State' | ||||
}, | ||||
modalCloseButton: true, | ||||
preDefined: {}, | ||||
remove: true, | ||||
rename: true, | ||||
save: true, | ||||
saveState: { | ||||
colReorder: true, | ||||
columns: { | ||||
search: true, | ||||
visible: true | ||||
}, | ||||
length: true, | ||||
order: true, | ||||
paging: true, | ||||
scroller: true, | ||||
search: true, | ||||
searchBuilder: true, | ||||
searchPanes: true, | ||||
select: true | ||||
}, | ||||
splitSecondaries: [ | ||||
'updateState', | ||||
'renameState', | ||||
'removeState' | ||||
], | ||||
toggle: { | ||||
colReorder: false, | ||||
columns: { | ||||
search: false, | ||||
visible: false | ||||
}, | ||||
length: false, | ||||
order: false, | ||||
paging: false, | ||||
scroller: false, | ||||
search: false, | ||||
searchBuilder: false, | ||||
searchPanes: false, | ||||
select: false | ||||
} | ||||
}; | ||||
return StateRestoreCollection; | ||||
}()); | ||||
/*! StateRestore 1.1.1 | ||||
* 2019-2022 SpryMedia Ltd - datatables.net/license | ||||
*/ | ||||
// DataTables extensions common UMD. Note that this allows for AMD, CommonJS | ||||
// (with window and jQuery being allowed as parameters to the returned | ||||
// function) or just default browser loading. | ||||
(function (factory) { | ||||
if (typeof define === 'function' && define.amd) { | ||||
// AMD | ||||
define(['jquery', 'datatables.net'], function ($) { | ||||
return factory($, window, document); | ||||
}); | ||||
} | ||||
else if (typeof exports === 'object') { | ||||
// CommonJS | ||||
module.exports = function (root, $) { | ||||
if (!root) { | ||||
root = window; | ||||
} | ||||
if (!$ || !$.fn.dataTable) { | ||||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||||
$ = require('datatables.net')(root, $).$; | ||||
} | ||||
return factory($, root, root.document); | ||||
}; | ||||
} | ||||
else { | ||||
// Browser - assume jQuery has already been loaded | ||||
factory(window.jQuery, window, document); | ||||
} | ||||
}(function ($, window, document) { | ||||
setJQuery$1($); | ||||
setJQuery($); | ||||
var dataTable = $.fn.dataTable; | ||||
$.fn.dataTable.StateRestore = StateRestore; | ||||
$.fn.DataTable.StateRestore = StateRestore; | ||||
$.fn.dataTable.StateRestoreCollection = StateRestoreCollection; | ||||
$.fn.DataTable.StateRestoreCollection = StateRestoreCollection; | ||||
var apiRegister = $.fn.dataTable.Api.register; | ||||
apiRegister('stateRestore()', function () { | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state()', function (identifier) { | ||||
var ctx = this.context[0]; | ||||
if (!ctx._stateRestore) { | ||||
var api = $.fn.DataTable.Api(ctx); | ||||
var src = new $.fn.dataTable.StateRestoreCollection(api, {}); | ||||
_stateRegen(api, src); | ||||
} | ||||
this[0] = ctx._stateRestore.getState(identifier); | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state.add()', function (identifier, options) { | ||||
var ctx = this.context[0]; | ||||
if (!ctx._stateRestore) { | ||||
var api = $.fn.DataTable.Api(ctx); | ||||
var src = new $.fn.dataTable.StateRestoreCollection(api, {}); | ||||
_stateRegen(api, src); | ||||
} | ||||
if (!ctx._stateRestore.c.create) { | ||||
return this; | ||||
} | ||||
if (ctx._stateRestore.addState) { | ||||
var states = ctx._stateRestore.s.states; | ||||
var ids = []; | ||||
for (var _i = 0, states_1 = states; _i < states_1.length; _i++) { | ||||
var intState = states_1[_i]; | ||||
ids.push(intState.s.identifier); | ||||
} | ||||
ctx._stateRestore.addState(identifier, ids, options); | ||||
return this; | ||||
} | ||||
}); | ||||
apiRegister('stateRestore.states()', function (ids) { | ||||
var ctx = this.context[0]; | ||||
if (!ctx._stateRestore) { | ||||
var api = $.fn.DataTable.Api(ctx); | ||||
var src = new $.fn.dataTable.StateRestoreCollection(api, {}); | ||||
_stateRegen(api, src); | ||||
} | ||||
this.length = 0; | ||||
this.push.apply(this, ctx._stateRestore.getStates(ids)); | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state().save()', function () { | ||||
var ctx = this[0]; | ||||
// Check if saving states is allowed | ||||
if (ctx.c.save) { | ||||
ctx.save(); | ||||
} | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state().rename()', function (newIdentifier) { | ||||
var ctx = this.context[0]; | ||||
var state = this[0]; | ||||
// Check if renaming states is allowed | ||||
if (state.c.save) { | ||||
var states = ctx._stateRestore.s.states; | ||||
var ids = []; | ||||
for (var _i = 0, states_2 = states; _i < states_2.length; _i++) { | ||||
var intState = states_2[_i]; | ||||
ids.push(intState.s.identifier); | ||||
} | ||||
state.rename(newIdentifier, ids); | ||||
} | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state().load()', function () { | ||||
var ctx = this[0]; | ||||
ctx.load(); | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.state().remove()', function (skipModal) { | ||||
var ctx = this[0]; | ||||
// Check if removal of states is allowed | ||||
if (ctx.c.remove) { | ||||
ctx.remove(skipModal); | ||||
} | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.states().remove()', function (skipModal) { | ||||
var _this = this; | ||||
var removeAllCallBack = function (skipModalIn) { | ||||
var success = true; | ||||
var that = _this.toArray(); | ||||
while (that.length > 0) { | ||||
var set = that[0]; | ||||
if (set !== undefined && set.c.remove) { | ||||
var tempSuccess = set.remove(skipModalIn); | ||||
if (tempSuccess !== true) { | ||||
success = tempSuccess; | ||||
} | ||||
else { | ||||
that.splice(0, 1); | ||||
} | ||||
} | ||||
else { | ||||
break; | ||||
} | ||||
} | ||||
return success; | ||||
}; | ||||
if (this.context[0]._stateRestore.c.remove) { | ||||
if (skipModal) { | ||||
removeAllCallBack(skipModal); | ||||
} | ||||
else { | ||||
this.context[0]._stateRestore.removeAll(removeAllCallBack); | ||||
} | ||||
} | ||||
return this; | ||||
}); | ||||
apiRegister('stateRestore.activeStates()', function () { | ||||
var ctx = this.context[0]; | ||||
this.length = 0; | ||||
if (!ctx._stateRestore) { | ||||
var api = $.fn.DataTable.Api(ctx); | ||||
var src = new $.fn.dataTable.StateRestoreCollection(api, {}); | ||||
_stateRegen(api, src); | ||||
} | ||||
if (ctx._stateRestore) { | ||||
this.push.apply(this, ctx._stateRestore.findActive()); | ||||
} | ||||
return this; | ||||
}); | ||||
$.fn.dataTable.ext.buttons.stateRestore = { | ||||
action: function (e, dt, node, config) { | ||||
config._stateRestore.load(); | ||||
node.blur(); | ||||
}, | ||||
config: { | ||||
split: ['updateState', 'renameState', 'removeState'] | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.stateRestore', 'State %d', dt.stateRestore.states()[0].length + 1); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.updateState = { | ||||
action: function (e, dt, node, config) { | ||||
$('div.dt-button-background').click(); | ||||
config.parent._stateRestore.save(); | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.updateState', 'Update'); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.savedStates = { | ||||
buttons: [], | ||||
extend: 'collection', | ||||
init: function (dt, node, config) { | ||||
dt.on('stateRestore-change', function () { | ||||
dt.button(node).text(dt.i18n('buttons.savedStates', 'Saved States', dt.stateRestore.states().length)); | ||||
}); | ||||
if (dt.settings()[0]._stateRestore === undefined) { | ||||
_buttonInit(dt, config); | ||||
} | ||||
}, | ||||
name: 'SaveStateRestore', | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.savedStates', 'Saved States', 0); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.savedStatesCreate = { | ||||
buttons: [], | ||||
extend: 'collection', | ||||
init: function (dt, node, config) { | ||||
dt.on('stateRestore-change', function () { | ||||
dt.button(node).text(dt.i18n('buttons.savedStates', 'Saved States', dt.stateRestore.states().length)); | ||||
}); | ||||
if (dt.settings()[0]._stateRestore === undefined) { | ||||
if (config.config === undefined) { | ||||
config.config = {}; | ||||
} | ||||
config.config._createInSaved = true; | ||||
_buttonInit(dt, config); | ||||
} | ||||
}, | ||||
name: 'SaveStateRestore', | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.savedStates', 'Saved States', 0); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.createState = { | ||||
action: function (e, dt, node, config) { | ||||
e.stopPropagation(); | ||||
var stateRestoreOpts = dt.settings()[0]._stateRestore.c; | ||||
var language = dt.settings()[0].oLanguage; | ||||
// If creation/saving is not allowed then return | ||||
if (!stateRestoreOpts.create || !stateRestoreOpts.save) { | ||||
return; | ||||
} | ||||
var prevStates = dt.stateRestore.states().toArray(); | ||||
// Create a replacement regex based on the i18n values | ||||
var defaultString = language.buttons !== undefined && language.buttons.stateRestore !== undefined ? | ||||
language.buttons.stateRestore : | ||||
'State '; | ||||
var replaceRegex; | ||||
if (defaultString.indexOf('%d') === defaultString.length - 3) { | ||||
replaceRegex = new RegExp(defaultString.replace(/%d/g, '')); | ||||
} | ||||
else { | ||||
var splitString = defaultString.split('%d'); | ||||
replaceRegex = []; | ||||
for (var _i = 0, splitString_1 = splitString; _i < splitString_1.length; _i++) { | ||||
var split = splitString_1[_i]; | ||||
replaceRegex.push(new RegExp(split)); | ||||
} | ||||
} | ||||
var getId = function (identifier) { | ||||
var id; | ||||
if (Array.isArray(replaceRegex)) { | ||||
id = identifier; | ||||
for (var _i = 0, replaceRegex_1 = replaceRegex; _i < replaceRegex_1.length; _i++) { | ||||
var reg = replaceRegex_1[_i]; | ||||
id = id.replace(reg, ''); | ||||
} | ||||
} | ||||
else { | ||||
id = identifier.replace(replaceRegex, ''); | ||||
} | ||||
// If the id after replacement is not a number, or the length is the same as before, | ||||
// it has been customised so return 0 | ||||
if (isNaN(+id) || id.length === identifier) { | ||||
return 0; | ||||
} | ||||
// Otherwise return the number that has been assigned previously | ||||
else { | ||||
return +id; | ||||
} | ||||
}; | ||||
// Extract the numbers from the identifiers that use the standard naming convention | ||||
var identifiers = prevStates | ||||
.map(function (state) { return getId(state.s.identifier); }) | ||||
.sort(function (a, b) { return +a < +b ? | ||||
1 : | ||||
+a > +b ? | ||||
-1 : | ||||
0; }); | ||||
var lastNumber = identifiers[0]; | ||||
dt.stateRestore.state.add(dt.i18n('buttons.stateRestore', 'State %d', lastNumber !== undefined ? lastNumber + 1 : 1), config.config); | ||||
var states = dt.stateRestore.states().sort(function (a, b) { | ||||
var aId = +getId(a.s.identifier); | ||||
var bId = +getId(b.s.identifier); | ||||
return aId > bId ? | ||||
1 : | ||||
aId < bId ? | ||||
-1 : | ||||
0; | ||||
}); | ||||
var button = dt.button('SaveStateRestore:name'); | ||||
var stateButtons = button[0] !== undefined && button[0].inst.c.buttons[0].buttons !== undefined ? | ||||
button[0].inst.c.buttons[0].buttons : | ||||
[]; | ||||
// remove any states from the previous rebuild - if they are still there they will be added later | ||||
for (var i = 0; i < stateButtons.length; i++) { | ||||
if (stateButtons[i].extend === 'stateRestore') { | ||||
stateButtons.splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
if (stateRestoreOpts._createInSaved) { | ||||
stateButtons.push('createState'); | ||||
stateButtons.push(''); | ||||
} | ||||
for (var _a = 0, states_3 = states; _a < states_3.length; _a++) { | ||||
var state = states_3[_a]; | ||||
var split = Object.assign([], stateRestoreOpts.splitSecondaries); | ||||
if (split.includes('updateState') && !stateRestoreOpts.save) { | ||||
split.splice(split.indexOf('updateState'), 1); | ||||
} | ||||
if (split.includes('renameState') && | ||||
(!stateRestoreOpts.save || !stateRestoreOpts.rename)) { | ||||
split.splice(split.indexOf('renameState'), 1); | ||||
} | ||||
if (split.includes('removeState') && !stateRestoreOpts.remove) { | ||||
split.splice(split.indexOf('removeState'), 1); | ||||
} | ||||
if (split.length > 0 && | ||||
!split.includes('<h3>' + state.s.identifier + '</h3>')) { | ||||
split.unshift('<h3>' + state.s.identifier + '</h3>'); | ||||
} | ||||
stateButtons.push({ | ||||
_stateRestore: state, | ||||
attr: { | ||||
title: state.s.identifier | ||||
}, | ||||
config: { | ||||
split: split | ||||
}, | ||||
extend: 'stateRestore', | ||||
text: state.s.identifier | ||||
}); | ||||
} | ||||
dt.button('SaveStateRestore:name').collectionRebuild(stateButtons); | ||||
node.blur(); | ||||
// Need to disable the removeAllStates button if there are no states and it is present | ||||
var buttons = dt.buttons(); | ||||
for (var _b = 0, buttons_1 = buttons; _b < buttons_1.length; _b++) { | ||||
var butt = buttons_1[_b]; | ||||
if ($(butt.node).hasClass('dtsr-removeAllStates')) { | ||||
if (states.length === 0) { | ||||
dt.button(butt.node).disable(); | ||||
} | ||||
else { | ||||
dt.button(butt.node).enable(); | ||||
} | ||||
} | ||||
} | ||||
}, | ||||
init: function (dt, node, config) { | ||||
if (dt.settings()[0]._stateRestore === undefined && dt.button('SaveStateRestore:name').length > 1) { | ||||
_buttonInit(dt, config); | ||||
} | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.createState', 'Create State'); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.removeState = { | ||||
action: function (e, dt, node, config) { | ||||
config.parent._stateRestore.remove(); | ||||
node.blur(); | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.removeState', 'Remove'); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.removeAllStates = { | ||||
action: function (e, dt, node) { | ||||
dt.stateRestore.states().remove(true); | ||||
node.blur(); | ||||
}, | ||||
className: 'dt-button dtsr-removeAllStates', | ||||
init: function (dt, node) { | ||||
if (dt.stateRestore.states().length === 0) { | ||||
$(node).addClass('disabled'); | ||||
} | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.removeAllStates', 'Remove All States'); | ||||
} | ||||
}; | ||||
$.fn.dataTable.ext.buttons.renameState = { | ||||
action: function (e, dt, node, config) { | ||||
var states = dt.settings()[0]._stateRestore.s.states; | ||||
var ids = []; | ||||
for (var _i = 0, states_4 = states; _i < states_4.length; _i++) { | ||||
var state = states_4[_i]; | ||||
ids.push(state.s.identifier); | ||||
} | ||||
config.parent._stateRestore.rename(undefined, ids); | ||||
node.blur(); | ||||
}, | ||||
text: function (dt) { | ||||
return dt.i18n('buttons.renameState', 'Rename'); | ||||
} | ||||
}; | ||||
function _init(settings, options) { | ||||
if (options === void 0) { options = null; } | ||||
var api = new dataTable.Api(settings); | ||||
var opts = options | ||||
? options | ||||
: api.init().stateRestore || dataTable.defaults.stateRestore; | ||||
var stateRestore = new StateRestoreCollection(api, opts); | ||||
_stateRegen(api, stateRestore); | ||||
return stateRestore; | ||||
} | ||||
/** | ||||
* Initialisation function if initialising using a button | ||||
* | ||||
* @param dt The datatables instance | ||||
* @param config the config for the button | ||||
*/ | ||||
function _buttonInit(dt, config) { | ||||
var SRC = new $.fn.dataTable.StateRestoreCollection(dt, config.config); | ||||
_stateRegen(dt, SRC); | ||||
} | ||||
function _stateRegen(dt, src) { | ||||
var states = dt.stateRestore.states(); | ||||
var button = dt.button('SaveStateRestore:name'); | ||||
var stateButtons = button[0] !== undefined && button[0].inst.c.buttons[0].buttons !== undefined ? | ||||
button[0].inst.c.buttons[0].buttons : | ||||
[]; | ||||
var stateRestoreOpts = dt.settings()[0]._stateRestore.c; | ||||
// remove any states from the previous rebuild - if they are still there they will be added later | ||||
for (var i = 0; i < stateButtons.length; i++) { | ||||
if (stateButtons[i].extend === 'stateRestore') { | ||||
stateButtons.splice(i, 1); | ||||
i--; | ||||
} | ||||
} | ||||
if (stateRestoreOpts._createInSaved) { | ||||
stateButtons.push('createState'); | ||||
} | ||||
if (states === undefined || states.length === 0) { | ||||
stateButtons.push('<span class="' + src.classes.emptyStates + '">' + | ||||
dt.i18n('stateRestore.emptyStates', src.c.i18n.emptyStates) + | ||||
'</span>'); | ||||
} | ||||
else { | ||||
for (var _i = 0, states_5 = states; _i < states_5.length; _i++) { | ||||
var state = states_5[_i]; | ||||
var split = Object.assign([], stateRestoreOpts.splitSecondaries); | ||||
if (split.includes('updateState') && !stateRestoreOpts.save) { | ||||
split.splice(split.indexOf('updateState'), 1); | ||||
} | ||||
if (split.includes('renameState') && | ||||
(!stateRestoreOpts.save || !stateRestoreOpts.rename)) { | ||||
split.splice(split.indexOf('renameState'), 1); | ||||
} | ||||
if (split.includes('removeState') && !stateRestoreOpts.remove) { | ||||
split.splice(split.indexOf('removeState'), 1); | ||||
} | ||||
if (split.length > 0 && | ||||
!split.includes('<h3>' + state.s.identifier + '</h3>')) { | ||||
split.unshift('<h3>' + state.s.identifier + '</h3>'); | ||||
} | ||||
stateButtons.push({ | ||||
_stateRestore: state, | ||||
attr: { | ||||
title: state.s.identifier | ||||
}, | ||||
config: { | ||||
split: split | ||||
}, | ||||
extend: 'stateRestore', | ||||
text: state.s.identifier | ||||
}); | ||||
} | ||||
} | ||||
dt.button('SaveStateRestore:name').collectionRebuild(stateButtons); | ||||
// Need to disable the removeAllStates button if there are no states and it is present | ||||
var buttons = dt.buttons(); | ||||
for (var _a = 0, buttons_2 = buttons; _a < buttons_2.length; _a++) { | ||||
var butt = buttons_2[_a]; | ||||
if ($(butt.node).hasClass('dtsr-removeAllStates')) { | ||||
if (states.length === 0) { | ||||
dt.button(butt.node).disable(); | ||||
} | ||||
else { | ||||
dt.button(butt.node).enable(); | ||||
} | ||||
} | ||||
} | ||||
} | ||||
// Attach a listener to the document which listens for DataTables initialisation | ||||
// events so we can automatically initialise | ||||
$(document).on('preInit.dt.dtsr', function (e, settings) { | ||||
if (e.namespace !== 'dt') { | ||||
return; | ||||
} | ||||
if (settings.oInit.stateRestore || | ||||
dataTable.defaults.stateRestore) { | ||||
if (!settings._stateRestore) { | ||||
_init(settings, null); | ||||
} | ||||
} | ||||
}); | ||||
})); | ||||
})(); | ||||