datatables.net 3.0.0-beta.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/dataTables.js +409 -73
- package/js/dataTables.min.js +2 -2
- package/js/dataTables.min.mjs +2 -2
- package/js/dataTables.mjs +409 -73
- package/package.json +3 -2
- package/types/types.d.ts +14 -1
package/js/dataTables.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! DataTables
|
|
1
|
+
/*! DataTables
|
|
2
2
|
* Copyright (c) SpryMedia Ltd - datatables.net/license
|
|
3
3
|
*/
|
|
4
4
|
|
|
@@ -569,11 +569,16 @@ function ajax(optionsIn) {
|
|
|
569
569
|
if (options.data instanceof FormData) {
|
|
570
570
|
sendData = options.data;
|
|
571
571
|
}
|
|
572
|
-
else if (method !== 'GET' && options.data
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
572
|
+
else if (method !== 'GET' && options.data) {
|
|
573
|
+
if (typeof options.data === 'string') {
|
|
574
|
+
sendData = options.data;
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
sendData = serialize(options.data, options.traditional);
|
|
578
|
+
sendData = convertSpaces(sendData, options);
|
|
579
|
+
// So beforeSend matches how jQuery behaves
|
|
580
|
+
options.data = sendData;
|
|
581
|
+
}
|
|
577
582
|
}
|
|
578
583
|
xhr.onreadystatechange = function () {
|
|
579
584
|
if (xhr.readyState != 4) {
|
|
@@ -623,6 +628,7 @@ function ajax(optionsIn) {
|
|
|
623
628
|
if (options.beforeSend) {
|
|
624
629
|
if (options.beforeSend.call(options, xhr, options) === false) {
|
|
625
630
|
xhr.abort();
|
|
631
|
+
return xhr;
|
|
626
632
|
}
|
|
627
633
|
}
|
|
628
634
|
xhr.send(sendData);
|
|
@@ -809,7 +815,7 @@ function allUnique(src) {
|
|
|
809
815
|
* @returns Flattened array
|
|
810
816
|
*/
|
|
811
817
|
function flatten(out, val) {
|
|
812
|
-
if (Array.isArray(val)) {
|
|
818
|
+
if (Array.isArray(val) || arrayLike(val)) {
|
|
813
819
|
for (var i = 0; i < val.length; i++) {
|
|
814
820
|
flatten(out, val[i]);
|
|
815
821
|
}
|
|
@@ -1352,7 +1358,7 @@ var timer = /*#__PURE__*/Object.freeze({
|
|
|
1352
1358
|
* @returns true if this version of DataTables is greater or equal to the
|
|
1353
1359
|
* required version, or false if this version of DataTales is not suitable
|
|
1354
1360
|
*/
|
|
1355
|
-
function check(version1, version2) {
|
|
1361
|
+
function check$1(version1, version2) {
|
|
1356
1362
|
let dt = external('datatable');
|
|
1357
1363
|
var parts1 = version2 ? version2.split('.') : dt.ext.version.split('.');
|
|
1358
1364
|
var parts2 = version1.split('.');
|
|
@@ -1372,7 +1378,7 @@ function check(version1, version2) {
|
|
|
1372
1378
|
|
|
1373
1379
|
var version = /*#__PURE__*/Object.freeze({
|
|
1374
1380
|
__proto__: null,
|
|
1375
|
-
check: check
|
|
1381
|
+
check: check$1
|
|
1376
1382
|
});
|
|
1377
1383
|
|
|
1378
1384
|
// Note that the aliased properties are for compatibility with DataTables 2-
|
|
@@ -1590,9 +1596,12 @@ function parseEventName(original) {
|
|
|
1590
1596
|
isFocus = true;
|
|
1591
1597
|
}
|
|
1592
1598
|
else if (name === 'blur') {
|
|
1593
|
-
name = '
|
|
1599
|
+
name = 'focusout';
|
|
1594
1600
|
isFocus = true;
|
|
1595
1601
|
}
|
|
1602
|
+
else if (name === 'ready') {
|
|
1603
|
+
name = 'DOMContentLoaded';
|
|
1604
|
+
}
|
|
1596
1605
|
return {
|
|
1597
1606
|
eventName: name,
|
|
1598
1607
|
isFocus,
|
|
@@ -1629,6 +1638,14 @@ function add(el, nameFull, handler, selector, one) {
|
|
|
1629
1638
|
if (!eventName) {
|
|
1630
1639
|
return;
|
|
1631
1640
|
}
|
|
1641
|
+
// Special handling for the "ready" event - it will trigger when the content
|
|
1642
|
+
// is ready, but also if it is already ready, when added.
|
|
1643
|
+
if (el === document && eventName === 'DOMContentLoaded' && nameFull.includes('ready')) {
|
|
1644
|
+
if (document.readyState === 'complete') {
|
|
1645
|
+
handler(new Event('DOMContentLoaded'));
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1632
1649
|
// Create a function that will be the actual event handler, and performs any
|
|
1633
1650
|
// logic we need, such as delegate handling and adding properties.
|
|
1634
1651
|
let wrapped = function (event) {
|
|
@@ -1654,6 +1671,11 @@ function add(el, nameFull, handler, selector, one) {
|
|
|
1654
1671
|
if (!dTarget) {
|
|
1655
1672
|
return;
|
|
1656
1673
|
}
|
|
1674
|
+
if (isHover &&
|
|
1675
|
+
event.relatedTarget &&
|
|
1676
|
+
dTarget.contains(event.relatedTarget)) {
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1657
1679
|
callScope = dTarget;
|
|
1658
1680
|
}
|
|
1659
1681
|
// Set the properties that jQuery adds to the event object
|
|
@@ -1711,7 +1733,7 @@ function remove(el, nameFull, handler, selector) {
|
|
|
1711
1733
|
wrapped.delegateSelector === selector &&
|
|
1712
1734
|
wrapped.original === handler);
|
|
1713
1735
|
}
|
|
1714
|
-
if (eventName && selector) {
|
|
1736
|
+
else if (eventName && selector) {
|
|
1715
1737
|
removeEvents = stored.filter(wrapped => wrapped.type === eventName &&
|
|
1716
1738
|
wrapped.delegateSelector === selector);
|
|
1717
1739
|
}
|
|
@@ -1942,29 +1964,33 @@ class Dom {
|
|
|
1942
1964
|
if (!content) {
|
|
1943
1965
|
return this;
|
|
1944
1966
|
}
|
|
1945
|
-
if (
|
|
1946
|
-
content
|
|
1947
|
-
return this;
|
|
1967
|
+
if (!arrayLike(content)) {
|
|
1968
|
+
content = [content];
|
|
1948
1969
|
}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
el.append(arrayLike[i]);
|
|
1970
|
+
// Generate a flat array of the content to be added, with nulls removed
|
|
1971
|
+
// this means it will be an array of nodes and / or strings
|
|
1972
|
+
let flatContent = flatten([], content).filter(c => !!c);
|
|
1973
|
+
/// Got a string somewhere in it, so need to use insertAdjacentHTML
|
|
1974
|
+
if (flatContent.find(val => typeof val === 'string')) {
|
|
1975
|
+
return this.each(el => {
|
|
1976
|
+
for (let i = 0; i < flatContent.length; i++) {
|
|
1977
|
+
if (typeof flatContent[i] === 'string') {
|
|
1978
|
+
el.insertAdjacentHTML('beforeend', flatContent[i]);
|
|
1979
|
+
}
|
|
1980
|
+
else {
|
|
1981
|
+
el.append(flatContent[i]);
|
|
1982
|
+
}
|
|
1963
1983
|
}
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
// Otherwise we can use a document fragment for a single mutation
|
|
1987
|
+
// on the main document
|
|
1988
|
+
return this.each(el => {
|
|
1989
|
+
let fragment = new DocumentFragment();
|
|
1990
|
+
for (let i = 0; i < flatContent.length; i++) {
|
|
1991
|
+
fragment.append(flatContent[i]);
|
|
1964
1992
|
}
|
|
1965
|
-
|
|
1966
|
-
el.append(content);
|
|
1967
|
-
}
|
|
1993
|
+
el.append(fragment);
|
|
1968
1994
|
});
|
|
1969
1995
|
}
|
|
1970
1996
|
/**
|
|
@@ -2131,9 +2157,7 @@ class Dom {
|
|
|
2131
2157
|
css(rule, value) {
|
|
2132
2158
|
// String getter
|
|
2133
2159
|
if (typeof rule === 'string' && value === undefined) {
|
|
2134
|
-
return this.length
|
|
2135
|
-
? getComputedStyle(this[0])[rule]
|
|
2136
|
-
: null;
|
|
2160
|
+
return this.length ? getComputedStyle(this[0])[rule] : null;
|
|
2137
2161
|
}
|
|
2138
2162
|
return this.each(el => {
|
|
2139
2163
|
if (typeof rule === 'string') {
|
|
@@ -2161,11 +2185,11 @@ class Dom {
|
|
|
2161
2185
|
return this.length ? dataConvert(this[0].dataset[name]) : null;
|
|
2162
2186
|
}
|
|
2163
2187
|
if (typeof name === 'string') {
|
|
2164
|
-
this.each(el => el.dataset[name] = JSON.stringify(value));
|
|
2188
|
+
this.each(el => (el.dataset[name] = JSON.stringify(value)));
|
|
2165
2189
|
}
|
|
2166
2190
|
else {
|
|
2167
2191
|
each(name, (key, val) => {
|
|
2168
|
-
this.each(el => el.dataset[key] = JSON.stringify(val));
|
|
2192
|
+
this.each(el => (el.dataset[key] = JSON.stringify(val)));
|
|
2169
2193
|
});
|
|
2170
2194
|
}
|
|
2171
2195
|
return this;
|
|
@@ -3889,7 +3913,7 @@ const ext = {
|
|
|
3889
3913
|
* Software version
|
|
3890
3914
|
* @type string
|
|
3891
3915
|
*/
|
|
3892
|
-
version: '3.0.0
|
|
3916
|
+
version: '3.0.0'
|
|
3893
3917
|
};
|
|
3894
3918
|
//
|
|
3895
3919
|
// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
|
|
@@ -3904,7 +3928,7 @@ Object.assign(ext, {
|
|
|
3904
3928
|
oStdClasses: ext.classes,
|
|
3905
3929
|
oPagination: ext.pager,
|
|
3906
3930
|
sVersion: ext.version,
|
|
3907
|
-
fnVersionCheck: check
|
|
3931
|
+
fnVersionCheck: check$1
|
|
3908
3932
|
});
|
|
3909
3933
|
|
|
3910
3934
|
/**
|
|
@@ -4133,7 +4157,7 @@ function arrayApply(arr, data) {
|
|
|
4133
4157
|
function listener(that, name, src) {
|
|
4134
4158
|
let srcArr = Array.isArray(src) ? src : [src];
|
|
4135
4159
|
for (var i = 0; i < srcArr.length; i++) {
|
|
4136
|
-
that.on(name + '.dt', srcArr[i]);
|
|
4160
|
+
that.on(name + '.dt.DT', srcArr[i]);
|
|
4137
4161
|
}
|
|
4138
4162
|
}
|
|
4139
4163
|
/**
|
|
@@ -4248,10 +4272,12 @@ function __mlHelper(localeString) {
|
|
|
4248
4272
|
// gives milliseconds epoch
|
|
4249
4273
|
return d.valueOf();
|
|
4250
4274
|
}
|
|
4251
|
-
}
|
|
4252
|
-
className: 'dt-right'
|
|
4275
|
+
}
|
|
4253
4276
|
});
|
|
4254
4277
|
}
|
|
4278
|
+
if (!store.className[typeName]) {
|
|
4279
|
+
store.className[typeName] = 'dt-right';
|
|
4280
|
+
}
|
|
4255
4281
|
return function (d, type) {
|
|
4256
4282
|
// Allow for a default value
|
|
4257
4283
|
if (d === null || d === undefined) {
|
|
@@ -4352,10 +4378,12 @@ function datetime(format, locale) {
|
|
|
4352
4378
|
pre: function (d) {
|
|
4353
4379
|
return __mldObj(d, format, locale) || 0;
|
|
4354
4380
|
}
|
|
4355
|
-
}
|
|
4356
|
-
className: 'dt-right'
|
|
4381
|
+
}
|
|
4357
4382
|
});
|
|
4358
4383
|
}
|
|
4384
|
+
if (!store.className[typeName]) {
|
|
4385
|
+
store.className[typeName] = 'dt-right';
|
|
4386
|
+
}
|
|
4359
4387
|
}
|
|
4360
4388
|
/**
|
|
4361
4389
|
* Helpers for `columns.render`.
|
|
@@ -5024,6 +5052,7 @@ function invalidate(settings, rowIdx, src, colIdx) {
|
|
|
5024
5052
|
// Update DataTables special `DT_*` attributes for the row
|
|
5025
5053
|
rowAttributes(settings, row);
|
|
5026
5054
|
}
|
|
5055
|
+
callbackFire(settings, null, 'rowInvalidate', [settings, rowIdx, colIdx], false);
|
|
5027
5056
|
}
|
|
5028
5057
|
/**
|
|
5029
5058
|
* Get the cells and data for a given row - from a <tr> element
|
|
@@ -5369,9 +5398,9 @@ function getWideStrings(settings, colIdx) {
|
|
|
5369
5398
|
// Don't want script, dialog or template tags in the width
|
|
5370
5399
|
// calculations as they are hidden content
|
|
5371
5400
|
cellString = cellString
|
|
5372
|
-
.replace(/<script[\s\S]*?<\/script
|
|
5373
|
-
.replace(/<dialog[\s\S]*?<\/dialog
|
|
5374
|
-
.replace(/<template[\s\S]*?<\/template
|
|
5401
|
+
.replace(/<script[\s\S]*?<\/script(?:\s[^>]*)?>/gi, ' ')
|
|
5402
|
+
.replace(/<dialog[\s\S]*?<\/dialog(?:\s[^>]*)?>/gi, ' ')
|
|
5403
|
+
.replace(/<template[\s\S]*?<\/template(?:\s[^>]*)?>/gi, ' ');
|
|
5375
5404
|
var noHtml = util.string
|
|
5376
5405
|
.stripHtml(cellString, ' ')
|
|
5377
5406
|
.replace(/ /g, ' ');
|
|
@@ -5972,6 +6001,7 @@ function columnTypes(settings) {
|
|
|
5972
6001
|
var types = ext.type.detect;
|
|
5973
6002
|
var i, iLen, j, jen, k, ken;
|
|
5974
6003
|
var col, detectedType, cache;
|
|
6004
|
+
var originalTypes = columns.map(c => c.type).join(',');
|
|
5975
6005
|
// For each column, spin over the data type detection functions, seeing if
|
|
5976
6006
|
// one matches
|
|
5977
6007
|
for (i = 0, iLen = columns.length; i < iLen; i++) {
|
|
@@ -6069,6 +6099,10 @@ function columnTypes(settings) {
|
|
|
6069
6099
|
_columnAutoRender(settings, i);
|
|
6070
6100
|
}
|
|
6071
6101
|
}
|
|
6102
|
+
var newTypes = columns.map(c => c.type).join(',');
|
|
6103
|
+
if (newTypes !== originalTypes) {
|
|
6104
|
+
callbackFire(settings, null, 'columnTypes', [settings], false);
|
|
6105
|
+
}
|
|
6072
6106
|
}
|
|
6073
6107
|
/**
|
|
6074
6108
|
* Apply an auto detected renderer to data which doesn't yet have a renderer
|
|
@@ -7270,13 +7304,13 @@ function implementState(settings, s, callback) {
|
|
|
7270
7304
|
let idx = currentNames.indexOf(col[0]);
|
|
7271
7305
|
if (idx < 0) {
|
|
7272
7306
|
// If the column was not found ignore it and continue
|
|
7273
|
-
|
|
7307
|
+
continue;
|
|
7274
7308
|
}
|
|
7275
7309
|
set[0] = idx;
|
|
7276
7310
|
}
|
|
7277
7311
|
else if (set[0] >= columns.length) {
|
|
7278
7312
|
// If the column index is out of bounds ignore it and continue
|
|
7279
|
-
|
|
7313
|
+
continue;
|
|
7280
7314
|
}
|
|
7281
7315
|
settings.order.push(set);
|
|
7282
7316
|
}
|
|
@@ -9594,12 +9628,13 @@ function selectCells(settings, selector, opts) {
|
|
|
9594
9628
|
// Otherwise the selector is a node, and there is one last option - the
|
|
9595
9629
|
// element might be a child of an element which has dt-row and dt-column
|
|
9596
9630
|
// data attributes
|
|
9597
|
-
|
|
9598
|
-
|
|
9631
|
+
let rowHost = Dom.s(s).closest('*[data-dt-row]');
|
|
9632
|
+
let columnHost = Dom.s(s).closest('*[data-dt-column]');
|
|
9633
|
+
return rowHost.count()
|
|
9599
9634
|
? [
|
|
9600
9635
|
{
|
|
9601
|
-
row:
|
|
9602
|
-
column:
|
|
9636
|
+
row: parseInt(rowHost.attr('data-dt-row')),
|
|
9637
|
+
column: parseInt(columnHost.attr('data-dt-column'))
|
|
9603
9638
|
}
|
|
9604
9639
|
]
|
|
9605
9640
|
: [];
|
|
@@ -9912,7 +9947,7 @@ function selectColumns(settings, selector, opts) {
|
|
|
9912
9947
|
// Otherwise a node which might have a `dt-column` data attribute, or be
|
|
9913
9948
|
// a child or such an element
|
|
9914
9949
|
var host = Dom.s(s).closest('*[data-dt-column]');
|
|
9915
|
-
return host.count() ? [host.
|
|
9950
|
+
return host.count() ? [parseInt(host.attr('data-dt-column'))] : [];
|
|
9916
9951
|
};
|
|
9917
9952
|
var selected = selectorRun('column', selector, run, settings, opts);
|
|
9918
9953
|
return opts.columnOrder && opts.columnOrder === 'index'
|
|
@@ -10109,18 +10144,19 @@ registerPlural('columns().widths()', 'column().width()', function () {
|
|
|
10109
10144
|
// Injects a fake row into the table for just a moment so the widths can
|
|
10110
10145
|
// be read, regardless of colspan in the header and rows being present
|
|
10111
10146
|
// in the body
|
|
10112
|
-
var columns = this.columns(':visible')
|
|
10147
|
+
var columns = this.columns(':visible');
|
|
10113
10148
|
var row = Dom
|
|
10114
10149
|
.c('tr')
|
|
10115
|
-
.html('<td>' + Array(columns).join('</td><td>') + '</td>');
|
|
10150
|
+
.html('<td>' + Array(columns.count()).join('</td><td>') + '</td>');
|
|
10116
10151
|
Dom.s(this.table().body()).append(row);
|
|
10117
|
-
var widths =
|
|
10118
|
-
|
|
10152
|
+
var widths = [];
|
|
10153
|
+
var indexes = columns.indexes();
|
|
10154
|
+
row.children().each((el, idx) => {
|
|
10155
|
+
widths[indexes[idx]] = Dom.s(el).width('outer');
|
|
10119
10156
|
});
|
|
10120
10157
|
row.remove();
|
|
10121
|
-
return this.iterator('column',
|
|
10122
|
-
|
|
10123
|
-
return visIdx !== null ? widths[visIdx] : 0;
|
|
10158
|
+
return this.iterator('column', (settings, column) => {
|
|
10159
|
+
return widths[column] || 0;
|
|
10124
10160
|
}, true);
|
|
10125
10161
|
});
|
|
10126
10162
|
registerPlural('columns().indexes()', 'column().index()', function (type) {
|
|
@@ -10592,7 +10628,7 @@ function selectRows(settings, selector, opts) {
|
|
|
10592
10628
|
}
|
|
10593
10629
|
else {
|
|
10594
10630
|
var host = Dom.s(sel).closest('*[data-dt-row]');
|
|
10595
|
-
return host.count() ? [host.
|
|
10631
|
+
return host.count() ? [parseInt(host.attr('data-dt-row'))] : [];
|
|
10596
10632
|
}
|
|
10597
10633
|
}
|
|
10598
10634
|
// ID selector. Want to always be able to select rows by id, regardless
|
|
@@ -10624,8 +10660,7 @@ function selectRows(settings, selector, opts) {
|
|
|
10624
10660
|
// Get nodes in the order from the `rows` array with null values removed
|
|
10625
10661
|
var nodes = util.array.removeEmpty(util.array.pluckOrder(settings.data, rows, 'tr'));
|
|
10626
10662
|
// Selector - selector string, array of nodes or jQuery object.
|
|
10627
|
-
return Dom
|
|
10628
|
-
.s(nodes)
|
|
10663
|
+
return Dom.s(nodes)
|
|
10629
10664
|
.filter(sel)
|
|
10630
10665
|
.mapTo((el) => el._DT_RowIndex);
|
|
10631
10666
|
};
|
|
@@ -10770,7 +10805,7 @@ register('row().data()', function (data) {
|
|
|
10770
10805
|
util.set(ctx[0].rowId)(data, row.tr.id);
|
|
10771
10806
|
}
|
|
10772
10807
|
// Automatically invalidate
|
|
10773
|
-
invalidate(ctx[0], this[0], 'data');
|
|
10808
|
+
invalidate(ctx[0], this[0][0], 'data');
|
|
10774
10809
|
return this;
|
|
10775
10810
|
});
|
|
10776
10811
|
register('row().node()', function () {
|
|
@@ -11088,10 +11123,10 @@ register('caption()', function (value, side) {
|
|
|
11088
11123
|
caption.css('caption-side', side);
|
|
11089
11124
|
caption.get(0)._captionSide = side;
|
|
11090
11125
|
}
|
|
11091
|
-
if (container.find('div.
|
|
11092
|
-
var selector = side === 'top' ? '
|
|
11126
|
+
if (container.find('div.dt-scroll').count()) {
|
|
11127
|
+
var selector = side === 'top' ? 'head' : 'foot';
|
|
11093
11128
|
container
|
|
11094
|
-
.find('div.
|
|
11129
|
+
.find('div.dt-scroll-' + selector + ' table')
|
|
11095
11130
|
.prepend(caption);
|
|
11096
11131
|
}
|
|
11097
11132
|
else {
|
|
@@ -11104,6 +11139,272 @@ register('caption.node()', function () {
|
|
|
11104
11139
|
return ctx.length ? ctx[0].captionNode : null;
|
|
11105
11140
|
});
|
|
11106
11141
|
|
|
11142
|
+
/**
|
|
11143
|
+
* What's this!? "DataTables Plus" is a commercial set of extensions for
|
|
11144
|
+
* DataTables, such as Editor, and the functions in this file allow a license
|
|
11145
|
+
* key to be provided (`DataTable.key(...)`) to unlock those features.
|
|
11146
|
+
*
|
|
11147
|
+
* This is the modal that I've selected to make DataTables sustainable, open
|
|
11148
|
+
* source core, with some commercial extensions available.
|
|
11149
|
+
*
|
|
11150
|
+
* Please support DataTables and open source by purchasing a Plus license from
|
|
11151
|
+
* https://datatables.net/plus .
|
|
11152
|
+
*/
|
|
11153
|
+
let _ready = false;
|
|
11154
|
+
let _notice;
|
|
11155
|
+
let _processingKey = false;
|
|
11156
|
+
let _delayedReleaseDate = null;
|
|
11157
|
+
let _delayedSoftware = null;
|
|
11158
|
+
const _licenseInfo = {
|
|
11159
|
+
developers: 0,
|
|
11160
|
+
type: null,
|
|
11161
|
+
expires: null,
|
|
11162
|
+
valid: null
|
|
11163
|
+
};
|
|
11164
|
+
const _wm = Dom.c('div');
|
|
11165
|
+
const _publicKey = 'BE1A9w9D9U/4s4/TogY+1sW/dLJ8IquzK1PmV70J93ZTIvXMZ0eV2NAb52ntpgwVFySSB2fOI7geLNO737rQAyo=';
|
|
11166
|
+
/**
|
|
11167
|
+
* Convert a base64 string to a binary array
|
|
11168
|
+
*
|
|
11169
|
+
* @param b64 Source string
|
|
11170
|
+
* @returns Array
|
|
11171
|
+
*/
|
|
11172
|
+
function b64ToBuf(b64) {
|
|
11173
|
+
return Uint8Array.from(atob(b64), c => c.charCodeAt(0));
|
|
11174
|
+
}
|
|
11175
|
+
/**
|
|
11176
|
+
* Logic to check the trial and plus license expiry and display messages if
|
|
11177
|
+
* needed. There is particular consideration for checking a release date of
|
|
11178
|
+
* software, as the license for DataTables Plus is perpetual for the version
|
|
11179
|
+
* purchased, and it shouldn't show a message for the purchased version ever.
|
|
11180
|
+
*
|
|
11181
|
+
* @param releaseDate The date the software was released on.
|
|
11182
|
+
* @param software The software name being validated. Can be null for a general
|
|
11183
|
+
* "Plus" check.
|
|
11184
|
+
* @returns true if valid, false otherwise
|
|
11185
|
+
*/
|
|
11186
|
+
function check(releaseDate, software) {
|
|
11187
|
+
let expires = _licenseInfo.expires;
|
|
11188
|
+
if (_licenseInfo.valid === false) {
|
|
11189
|
+
noticePrep('License key invalid');
|
|
11190
|
+
noticeDisplay();
|
|
11191
|
+
}
|
|
11192
|
+
else if (_licenseInfo.type === 'trial') {
|
|
11193
|
+
// Trail is for plus, so the software type isn't taken into account
|
|
11194
|
+
let remaining = expires
|
|
11195
|
+
? Math.ceil((expires.getTime() - new Date().getTime()) / 86400000)
|
|
11196
|
+
: -1;
|
|
11197
|
+
if (remaining < 0) {
|
|
11198
|
+
// Trial expires
|
|
11199
|
+
consoleMsg('Your trial has now expired - https://datatables.net/plus', 'warn');
|
|
11200
|
+
noticePrep('Trial expired');
|
|
11201
|
+
noticeDisplay();
|
|
11202
|
+
return false;
|
|
11203
|
+
}
|
|
11204
|
+
else {
|
|
11205
|
+
// Let the user know when it is going to expire with a console
|
|
11206
|
+
// message.
|
|
11207
|
+
consoleMsg('Your trial expires in ' +
|
|
11208
|
+
remaining +
|
|
11209
|
+
' day' +
|
|
11210
|
+
(remaining === 1 ? '' : 's'));
|
|
11211
|
+
return true;
|
|
11212
|
+
}
|
|
11213
|
+
}
|
|
11214
|
+
else if (_licenseInfo.type === 'plus' ||
|
|
11215
|
+
(_licenseInfo.type === 'editor' && software === 'editor')) {
|
|
11216
|
+
if (!expires || new Date(releaseDate) > expires) {
|
|
11217
|
+
noticePrep('Upgrade required for this version');
|
|
11218
|
+
noticeDisplay();
|
|
11219
|
+
return false;
|
|
11220
|
+
}
|
|
11221
|
+
return true;
|
|
11222
|
+
}
|
|
11223
|
+
else if (_licenseInfo.type === 'editor' && software !== 'editor') {
|
|
11224
|
+
noticePrep('License for Editor only. Upgrade for Plus');
|
|
11225
|
+
noticeDisplay();
|
|
11226
|
+
return false;
|
|
11227
|
+
}
|
|
11228
|
+
noticePrep();
|
|
11229
|
+
noticeDisplay();
|
|
11230
|
+
return false;
|
|
11231
|
+
}
|
|
11232
|
+
/**
|
|
11233
|
+
* Common log message handling
|
|
11234
|
+
*
|
|
11235
|
+
* @param msg Message to show
|
|
11236
|
+
* @param level Log level
|
|
11237
|
+
*/
|
|
11238
|
+
function consoleMsg(msg, level = 'log') {
|
|
11239
|
+
let fn = level === 'log' ? console.log : console.warn;
|
|
11240
|
+
fn('%cDataTables Plus%c ' + msg, 'background: #007bff; color: #fff; padding: 2px 5px;', 'color: inherit;');
|
|
11241
|
+
}
|
|
11242
|
+
/**
|
|
11243
|
+
* Set the DataTables Plus key to use
|
|
11244
|
+
*
|
|
11245
|
+
* @param key DataTables Plus key - obtain from https://datatables.net/account .
|
|
11246
|
+
*/
|
|
11247
|
+
const key = function (key) {
|
|
11248
|
+
_processingKey = true;
|
|
11249
|
+
// Run the verification of the key
|
|
11250
|
+
verify(key)
|
|
11251
|
+
.then(result => {
|
|
11252
|
+
_processingKey = false;
|
|
11253
|
+
check(_delayedReleaseDate, _delayedSoftware);
|
|
11254
|
+
})
|
|
11255
|
+
.catch(() => {
|
|
11256
|
+
_processingKey = false;
|
|
11257
|
+
check(_delayedReleaseDate, _delayedSoftware);
|
|
11258
|
+
});
|
|
11259
|
+
};
|
|
11260
|
+
/**
|
|
11261
|
+
* Build the notice
|
|
11262
|
+
*
|
|
11263
|
+
* @returns
|
|
11264
|
+
*/
|
|
11265
|
+
function noticePrep(text) {
|
|
11266
|
+
if (!_ready) {
|
|
11267
|
+
let shadow = _wm[0].attachShadow({ mode: 'closed' });
|
|
11268
|
+
let notice = Dom.c('div').css({
|
|
11269
|
+
position: 'fixed',
|
|
11270
|
+
bottom: '1em',
|
|
11271
|
+
right: '1em',
|
|
11272
|
+
border: '1px solid #ffc107',
|
|
11273
|
+
background: '#fff3cd',
|
|
11274
|
+
color: '#856404',
|
|
11275
|
+
padding: '0.5em 1em',
|
|
11276
|
+
'font-family': 'sans-serif',
|
|
11277
|
+
'font-size': '12px',
|
|
11278
|
+
'border-radius': '4px',
|
|
11279
|
+
'z-index': '10000',
|
|
11280
|
+
'box-shadow': '0 2px 5px rgba(0,0,0,0.2)'
|
|
11281
|
+
});
|
|
11282
|
+
Dom.c('a')
|
|
11283
|
+
.attr('href', 'https://datatables.net/tn/25')
|
|
11284
|
+
.attr('target', '_blank')
|
|
11285
|
+
.css({
|
|
11286
|
+
color: 'inherit',
|
|
11287
|
+
'text-decoration': 'none'
|
|
11288
|
+
})
|
|
11289
|
+
.appendTo(notice);
|
|
11290
|
+
if (!text) {
|
|
11291
|
+
text = 'License key required';
|
|
11292
|
+
}
|
|
11293
|
+
shadow.appendChild(notice[0]);
|
|
11294
|
+
_notice = notice;
|
|
11295
|
+
_ready = true;
|
|
11296
|
+
}
|
|
11297
|
+
if (text) {
|
|
11298
|
+
_notice
|
|
11299
|
+
.find('a')
|
|
11300
|
+
.html('DataTables Plus: ' + text + ' - learn more »');
|
|
11301
|
+
}
|
|
11302
|
+
}
|
|
11303
|
+
/**
|
|
11304
|
+
* Display the license notice
|
|
11305
|
+
*/
|
|
11306
|
+
function noticeDisplay() {
|
|
11307
|
+
if (!_processingKey && !document.body.contains(_wm[0])) {
|
|
11308
|
+
document.body.appendChild(_wm[0]);
|
|
11309
|
+
}
|
|
11310
|
+
}
|
|
11311
|
+
/**
|
|
11312
|
+
* Validate the license string, which is in two parts - the first is a payload
|
|
11313
|
+
* that provides a small amount of information about the license, and the second
|
|
11314
|
+
* which is the license key.
|
|
11315
|
+
*
|
|
11316
|
+
* @param licenseString Key to validate
|
|
11317
|
+
* @returns Promise with validation information
|
|
11318
|
+
*/
|
|
11319
|
+
function verify(licenseString) {
|
|
11320
|
+
return new Promise(function (resolve) {
|
|
11321
|
+
try {
|
|
11322
|
+
var parts = licenseString.split(':');
|
|
11323
|
+
if (parts.length !== 2) {
|
|
11324
|
+
_licenseInfo.valid = false;
|
|
11325
|
+
return resolve();
|
|
11326
|
+
}
|
|
11327
|
+
var payload = parts[0];
|
|
11328
|
+
var signatureB64 = parts[1];
|
|
11329
|
+
// Backwards compat for old browsers
|
|
11330
|
+
var cryptoObj = window.crypto || window.msCrypto;
|
|
11331
|
+
var subtle = cryptoObj.subtle || cryptoObj.webkitSubtle;
|
|
11332
|
+
var rawKey = b64ToBuf(_publicKey);
|
|
11333
|
+
var rawSig = b64ToBuf(signatureB64);
|
|
11334
|
+
var data = new TextEncoder().encode(payload);
|
|
11335
|
+
subtle
|
|
11336
|
+
.importKey('raw', rawKey, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify'])
|
|
11337
|
+
.then(function (key) {
|
|
11338
|
+
return subtle.verify({ name: 'ECDSA', hash: { name: 'SHA-256' } }, key, rawSig, data);
|
|
11339
|
+
})
|
|
11340
|
+
.then(function (isValid) {
|
|
11341
|
+
if (!isValid) {
|
|
11342
|
+
_licenseInfo.valid = false;
|
|
11343
|
+
return resolve();
|
|
11344
|
+
}
|
|
11345
|
+
// Extract the payload to be useful
|
|
11346
|
+
var payloadParts = payload.match(/(plus|trial|editor)_(\d+)_(\d{4})(\d{2})(\d{2})/);
|
|
11347
|
+
if (!payloadParts || payloadParts.length !== 6) {
|
|
11348
|
+
_licenseInfo.valid = false;
|
|
11349
|
+
return resolve();
|
|
11350
|
+
}
|
|
11351
|
+
_licenseInfo.valid = true;
|
|
11352
|
+
_licenseInfo.type = payloadParts[1];
|
|
11353
|
+
_licenseInfo.developers = parseInt(payloadParts[2]);
|
|
11354
|
+
_licenseInfo.expires = new Date(payloadParts[3] +
|
|
11355
|
+
'-' +
|
|
11356
|
+
payloadParts[4] +
|
|
11357
|
+
'-' +
|
|
11358
|
+
payloadParts[5]);
|
|
11359
|
+
resolve();
|
|
11360
|
+
})
|
|
11361
|
+
.catch(function () {
|
|
11362
|
+
_licenseInfo.valid = false;
|
|
11363
|
+
resolve();
|
|
11364
|
+
});
|
|
11365
|
+
}
|
|
11366
|
+
catch (e) {
|
|
11367
|
+
_licenseInfo.valid = false;
|
|
11368
|
+
resolve();
|
|
11369
|
+
}
|
|
11370
|
+
});
|
|
11371
|
+
}
|
|
11372
|
+
/**
|
|
11373
|
+
* Create the `plus` function on `DataTable` which Plus extensions can call to
|
|
11374
|
+
* determine if the license key is valid and in date for the release. The
|
|
11375
|
+
* resulting function is called like this: `DataTable.plus('2026-12-25')` and
|
|
11376
|
+
* will return `true` or `false` depending on the key that was given (or not).
|
|
11377
|
+
*
|
|
11378
|
+
* @param DataTable The DataTable host object
|
|
11379
|
+
*/
|
|
11380
|
+
function plus (DataTable) {
|
|
11381
|
+
Object.defineProperty(DataTable, 'plus', {
|
|
11382
|
+
value: function (releaseDate, software = null) {
|
|
11383
|
+
// Unsecure sites are only useful for development, so allow there
|
|
11384
|
+
// and on the site.
|
|
11385
|
+
let host = window.location.hostname;
|
|
11386
|
+
let isDev = host === '192.168.234.234' ||
|
|
11387
|
+
host.endsWith('.datatables.net') ||
|
|
11388
|
+
host === 'datatables.net';
|
|
11389
|
+
if (isDev) {
|
|
11390
|
+
return true;
|
|
11391
|
+
}
|
|
11392
|
+
if (_processingKey) {
|
|
11393
|
+
// The validation of the key is async, so there is a chance that
|
|
11394
|
+
// it could still be happening when this runs. We just queue the
|
|
11395
|
+
// last one if that is the case.
|
|
11396
|
+
_delayedReleaseDate = releaseDate;
|
|
11397
|
+
_delayedSoftware = software;
|
|
11398
|
+
return true;
|
|
11399
|
+
}
|
|
11400
|
+
return check(releaseDate, software);
|
|
11401
|
+
},
|
|
11402
|
+
configurable: false,
|
|
11403
|
+
enumerable: false,
|
|
11404
|
+
writable: false
|
|
11405
|
+
});
|
|
11406
|
+
}
|
|
11407
|
+
|
|
11107
11408
|
/**
|
|
11108
11409
|
* CommonJS factory function pass through. This will check if the arguments
|
|
11109
11410
|
* given are a window object or a jQuery object. If so they are set accordingly.
|
|
@@ -11463,8 +11764,7 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11463
11764
|
}
|
|
11464
11765
|
// Wrapper element - use a span as a holder for where the select will go
|
|
11465
11766
|
var tmpId = 'tmp-' + +new Date();
|
|
11466
|
-
var div = Dom
|
|
11467
|
-
.c('div')
|
|
11767
|
+
var div = Dom.c('div')
|
|
11468
11768
|
.classAdd(classes.container)
|
|
11469
11769
|
.html(str.replace('_MENU_', '<span id="' + tmpId + '"></span>'));
|
|
11470
11770
|
// Save text node content for macro updating
|
|
@@ -11486,9 +11786,9 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11486
11786
|
});
|
|
11487
11787
|
};
|
|
11488
11788
|
// Next, the select itself, along with the options
|
|
11489
|
-
var select = Dom
|
|
11490
|
-
.c('select')
|
|
11789
|
+
var select = Dom.c('select')
|
|
11491
11790
|
.attr('aria-controls', tableId)
|
|
11791
|
+
.attr('autocomplete', 'off')
|
|
11492
11792
|
.classAdd(classes.select);
|
|
11493
11793
|
for (i = 0; i < lengths.length; i++) {
|
|
11494
11794
|
// Attempt to look up the length from the i18n options
|
|
@@ -11519,7 +11819,26 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11519
11819
|
// Update node value whenever anything changes the table's length
|
|
11520
11820
|
Dom.s(settings.table).on('length.dt.DT', function (e, s, len) {
|
|
11521
11821
|
if (settings === s) {
|
|
11522
|
-
div.find('select')
|
|
11822
|
+
let localSelect = div.find('select');
|
|
11823
|
+
// Remove any temporary values
|
|
11824
|
+
localSelect.find('option[data-dt-len-tmp]').remove();
|
|
11825
|
+
let option = localSelect.find('option[value="' + len + '"]');
|
|
11826
|
+
// If the select list doesn't have the target value, then we
|
|
11827
|
+
// need to add it for display.
|
|
11828
|
+
if (!option.length) {
|
|
11829
|
+
let after = findInsertBeforePoint(select, len);
|
|
11830
|
+
let tempOption = Dom.c('option')
|
|
11831
|
+
.val(len)
|
|
11832
|
+
.text(len)
|
|
11833
|
+
.attr('data-dt-len-tmp', true);
|
|
11834
|
+
if (after && after.length) {
|
|
11835
|
+
tempOption.insertBefore(after);
|
|
11836
|
+
}
|
|
11837
|
+
else {
|
|
11838
|
+
localSelect.append(tempOption);
|
|
11839
|
+
}
|
|
11840
|
+
}
|
|
11841
|
+
localSelect.val(len);
|
|
11523
11842
|
// Resolve plurals in the text for the new length
|
|
11524
11843
|
updateEntries(len);
|
|
11525
11844
|
}
|
|
@@ -11527,6 +11846,19 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11527
11846
|
updateEntries(settings.pageLength);
|
|
11528
11847
|
return div;
|
|
11529
11848
|
}, 'l');
|
|
11849
|
+
/**
|
|
11850
|
+
* Find the element to insert the temporary option before to keep the sequence.
|
|
11851
|
+
*
|
|
11852
|
+
* @param select Select element
|
|
11853
|
+
* @param insertValue Page length value
|
|
11854
|
+
* @returns Target option or null if not found
|
|
11855
|
+
*/
|
|
11856
|
+
function findInsertBeforePoint(select, insertValue) {
|
|
11857
|
+
let options = select.find('option');
|
|
11858
|
+
let values = options.mapTo(el => parseInt(el.value));
|
|
11859
|
+
let idx = values.findIndex(val => val > insertValue);
|
|
11860
|
+
return idx < -1 ? null : options.eq(idx);
|
|
11861
|
+
}
|
|
11530
11862
|
|
|
11531
11863
|
let __searchCounter = 0;
|
|
11532
11864
|
register$2('search', function (settings, optsIn) {
|
|
@@ -11537,7 +11869,9 @@ register$2('search', function (settings, optsIn) {
|
|
|
11537
11869
|
let classes = settings.classes.search;
|
|
11538
11870
|
let tableId = settings.tableId;
|
|
11539
11871
|
let language = settings.language;
|
|
11540
|
-
let input = '<input type="search" class="' +
|
|
11872
|
+
let input = '<input type="search" class="' +
|
|
11873
|
+
classes.input +
|
|
11874
|
+
'" autocomplete="off"/>';
|
|
11541
11875
|
let opts = util.object.assignDeep({
|
|
11542
11876
|
columns: '*',
|
|
11543
11877
|
placeholder: language.searchPlaceholder,
|
|
@@ -12359,6 +12693,8 @@ DataTable.datetime = datetime;
|
|
|
12359
12693
|
DataTable.__browser = browser;
|
|
12360
12694
|
DataTable.Dom = Dom;
|
|
12361
12695
|
DataTable.ajax = util.ajax;
|
|
12696
|
+
DataTable.key = key;
|
|
12697
|
+
plus(DataTable);
|
|
12362
12698
|
/**
|
|
12363
12699
|
* Private data store, containing all of the settings objects that are created
|
|
12364
12700
|
* for the tables on a given page.
|