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.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! DataTables
|
|
1
|
+
/*! DataTables
|
|
2
2
|
* Copyright (c) SpryMedia Ltd - datatables.net/license
|
|
3
3
|
*/
|
|
4
4
|
|
|
@@ -535,11 +535,16 @@ function ajax(optionsIn) {
|
|
|
535
535
|
if (options.data instanceof FormData) {
|
|
536
536
|
sendData = options.data;
|
|
537
537
|
}
|
|
538
|
-
else if (method !== 'GET' && options.data
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
538
|
+
else if (method !== 'GET' && options.data) {
|
|
539
|
+
if (typeof options.data === 'string') {
|
|
540
|
+
sendData = options.data;
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
sendData = serialize(options.data, options.traditional);
|
|
544
|
+
sendData = convertSpaces(sendData, options);
|
|
545
|
+
// So beforeSend matches how jQuery behaves
|
|
546
|
+
options.data = sendData;
|
|
547
|
+
}
|
|
543
548
|
}
|
|
544
549
|
xhr.onreadystatechange = function () {
|
|
545
550
|
if (xhr.readyState != 4) {
|
|
@@ -589,6 +594,7 @@ function ajax(optionsIn) {
|
|
|
589
594
|
if (options.beforeSend) {
|
|
590
595
|
if (options.beforeSend.call(options, xhr, options) === false) {
|
|
591
596
|
xhr.abort();
|
|
597
|
+
return xhr;
|
|
592
598
|
}
|
|
593
599
|
}
|
|
594
600
|
xhr.send(sendData);
|
|
@@ -775,7 +781,7 @@ function allUnique(src) {
|
|
|
775
781
|
* @returns Flattened array
|
|
776
782
|
*/
|
|
777
783
|
function flatten(out, val) {
|
|
778
|
-
if (Array.isArray(val)) {
|
|
784
|
+
if (Array.isArray(val) || arrayLike(val)) {
|
|
779
785
|
for (var i = 0; i < val.length; i++) {
|
|
780
786
|
flatten(out, val[i]);
|
|
781
787
|
}
|
|
@@ -1318,7 +1324,7 @@ var timer = /*#__PURE__*/Object.freeze({
|
|
|
1318
1324
|
* @returns true if this version of DataTables is greater or equal to the
|
|
1319
1325
|
* required version, or false if this version of DataTales is not suitable
|
|
1320
1326
|
*/
|
|
1321
|
-
function check(version1, version2) {
|
|
1327
|
+
function check$1(version1, version2) {
|
|
1322
1328
|
let dt = external('datatable');
|
|
1323
1329
|
var parts1 = version2 ? version2.split('.') : dt.ext.version.split('.');
|
|
1324
1330
|
var parts2 = version1.split('.');
|
|
@@ -1338,7 +1344,7 @@ function check(version1, version2) {
|
|
|
1338
1344
|
|
|
1339
1345
|
var version = /*#__PURE__*/Object.freeze({
|
|
1340
1346
|
__proto__: null,
|
|
1341
|
-
check: check
|
|
1347
|
+
check: check$1
|
|
1342
1348
|
});
|
|
1343
1349
|
|
|
1344
1350
|
// Note that the aliased properties are for compatibility with DataTables 2-
|
|
@@ -1556,9 +1562,12 @@ function parseEventName(original) {
|
|
|
1556
1562
|
isFocus = true;
|
|
1557
1563
|
}
|
|
1558
1564
|
else if (name === 'blur') {
|
|
1559
|
-
name = '
|
|
1565
|
+
name = 'focusout';
|
|
1560
1566
|
isFocus = true;
|
|
1561
1567
|
}
|
|
1568
|
+
else if (name === 'ready') {
|
|
1569
|
+
name = 'DOMContentLoaded';
|
|
1570
|
+
}
|
|
1562
1571
|
return {
|
|
1563
1572
|
eventName: name,
|
|
1564
1573
|
isFocus,
|
|
@@ -1595,6 +1604,14 @@ function add(el, nameFull, handler, selector, one) {
|
|
|
1595
1604
|
if (!eventName) {
|
|
1596
1605
|
return;
|
|
1597
1606
|
}
|
|
1607
|
+
// Special handling for the "ready" event - it will trigger when the content
|
|
1608
|
+
// is ready, but also if it is already ready, when added.
|
|
1609
|
+
if (el === document && eventName === 'DOMContentLoaded' && nameFull.includes('ready')) {
|
|
1610
|
+
if (document.readyState === 'complete') {
|
|
1611
|
+
handler(new Event('DOMContentLoaded'));
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1598
1615
|
// Create a function that will be the actual event handler, and performs any
|
|
1599
1616
|
// logic we need, such as delegate handling and adding properties.
|
|
1600
1617
|
let wrapped = function (event) {
|
|
@@ -1620,6 +1637,11 @@ function add(el, nameFull, handler, selector, one) {
|
|
|
1620
1637
|
if (!dTarget) {
|
|
1621
1638
|
return;
|
|
1622
1639
|
}
|
|
1640
|
+
if (isHover &&
|
|
1641
|
+
event.relatedTarget &&
|
|
1642
|
+
dTarget.contains(event.relatedTarget)) {
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1623
1645
|
callScope = dTarget;
|
|
1624
1646
|
}
|
|
1625
1647
|
// Set the properties that jQuery adds to the event object
|
|
@@ -1677,7 +1699,7 @@ function remove(el, nameFull, handler, selector) {
|
|
|
1677
1699
|
wrapped.delegateSelector === selector &&
|
|
1678
1700
|
wrapped.original === handler);
|
|
1679
1701
|
}
|
|
1680
|
-
if (eventName && selector) {
|
|
1702
|
+
else if (eventName && selector) {
|
|
1681
1703
|
removeEvents = stored.filter(wrapped => wrapped.type === eventName &&
|
|
1682
1704
|
wrapped.delegateSelector === selector);
|
|
1683
1705
|
}
|
|
@@ -1908,29 +1930,33 @@ class Dom {
|
|
|
1908
1930
|
if (!content) {
|
|
1909
1931
|
return this;
|
|
1910
1932
|
}
|
|
1911
|
-
if (
|
|
1912
|
-
content
|
|
1913
|
-
return this;
|
|
1933
|
+
if (!arrayLike(content)) {
|
|
1934
|
+
content = [content];
|
|
1914
1935
|
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
el.append(arrayLike[i]);
|
|
1936
|
+
// Generate a flat array of the content to be added, with nulls removed
|
|
1937
|
+
// this means it will be an array of nodes and / or strings
|
|
1938
|
+
let flatContent = flatten([], content).filter(c => !!c);
|
|
1939
|
+
/// Got a string somewhere in it, so need to use insertAdjacentHTML
|
|
1940
|
+
if (flatContent.find(val => typeof val === 'string')) {
|
|
1941
|
+
return this.each(el => {
|
|
1942
|
+
for (let i = 0; i < flatContent.length; i++) {
|
|
1943
|
+
if (typeof flatContent[i] === 'string') {
|
|
1944
|
+
el.insertAdjacentHTML('beforeend', flatContent[i]);
|
|
1945
|
+
}
|
|
1946
|
+
else {
|
|
1947
|
+
el.append(flatContent[i]);
|
|
1948
|
+
}
|
|
1929
1949
|
}
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
// Otherwise we can use a document fragment for a single mutation
|
|
1953
|
+
// on the main document
|
|
1954
|
+
return this.each(el => {
|
|
1955
|
+
let fragment = new DocumentFragment();
|
|
1956
|
+
for (let i = 0; i < flatContent.length; i++) {
|
|
1957
|
+
fragment.append(flatContent[i]);
|
|
1930
1958
|
}
|
|
1931
|
-
|
|
1932
|
-
el.append(content);
|
|
1933
|
-
}
|
|
1959
|
+
el.append(fragment);
|
|
1934
1960
|
});
|
|
1935
1961
|
}
|
|
1936
1962
|
/**
|
|
@@ -2097,9 +2123,7 @@ class Dom {
|
|
|
2097
2123
|
css(rule, value) {
|
|
2098
2124
|
// String getter
|
|
2099
2125
|
if (typeof rule === 'string' && value === undefined) {
|
|
2100
|
-
return this.length
|
|
2101
|
-
? getComputedStyle(this[0])[rule]
|
|
2102
|
-
: null;
|
|
2126
|
+
return this.length ? getComputedStyle(this[0])[rule] : null;
|
|
2103
2127
|
}
|
|
2104
2128
|
return this.each(el => {
|
|
2105
2129
|
if (typeof rule === 'string') {
|
|
@@ -2127,11 +2151,11 @@ class Dom {
|
|
|
2127
2151
|
return this.length ? dataConvert(this[0].dataset[name]) : null;
|
|
2128
2152
|
}
|
|
2129
2153
|
if (typeof name === 'string') {
|
|
2130
|
-
this.each(el => el.dataset[name] = JSON.stringify(value));
|
|
2154
|
+
this.each(el => (el.dataset[name] = JSON.stringify(value)));
|
|
2131
2155
|
}
|
|
2132
2156
|
else {
|
|
2133
2157
|
each(name, (key, val) => {
|
|
2134
|
-
this.each(el => el.dataset[key] = JSON.stringify(val));
|
|
2158
|
+
this.each(el => (el.dataset[key] = JSON.stringify(val)));
|
|
2135
2159
|
});
|
|
2136
2160
|
}
|
|
2137
2161
|
return this;
|
|
@@ -3855,7 +3879,7 @@ const ext = {
|
|
|
3855
3879
|
* Software version
|
|
3856
3880
|
* @type string
|
|
3857
3881
|
*/
|
|
3858
|
-
version: '3.0.0
|
|
3882
|
+
version: '3.0.0'
|
|
3859
3883
|
};
|
|
3860
3884
|
//
|
|
3861
3885
|
// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
|
|
@@ -3870,7 +3894,7 @@ Object.assign(ext, {
|
|
|
3870
3894
|
oStdClasses: ext.classes,
|
|
3871
3895
|
oPagination: ext.pager,
|
|
3872
3896
|
sVersion: ext.version,
|
|
3873
|
-
fnVersionCheck: check
|
|
3897
|
+
fnVersionCheck: check$1
|
|
3874
3898
|
});
|
|
3875
3899
|
|
|
3876
3900
|
/**
|
|
@@ -4099,7 +4123,7 @@ function arrayApply(arr, data) {
|
|
|
4099
4123
|
function listener(that, name, src) {
|
|
4100
4124
|
let srcArr = Array.isArray(src) ? src : [src];
|
|
4101
4125
|
for (var i = 0; i < srcArr.length; i++) {
|
|
4102
|
-
that.on(name + '.dt', srcArr[i]);
|
|
4126
|
+
that.on(name + '.dt.DT', srcArr[i]);
|
|
4103
4127
|
}
|
|
4104
4128
|
}
|
|
4105
4129
|
/**
|
|
@@ -4214,10 +4238,12 @@ function __mlHelper(localeString) {
|
|
|
4214
4238
|
// gives milliseconds epoch
|
|
4215
4239
|
return d.valueOf();
|
|
4216
4240
|
}
|
|
4217
|
-
}
|
|
4218
|
-
className: 'dt-right'
|
|
4241
|
+
}
|
|
4219
4242
|
});
|
|
4220
4243
|
}
|
|
4244
|
+
if (!store.className[typeName]) {
|
|
4245
|
+
store.className[typeName] = 'dt-right';
|
|
4246
|
+
}
|
|
4221
4247
|
return function (d, type) {
|
|
4222
4248
|
// Allow for a default value
|
|
4223
4249
|
if (d === null || d === undefined) {
|
|
@@ -4318,10 +4344,12 @@ function datetime(format, locale) {
|
|
|
4318
4344
|
pre: function (d) {
|
|
4319
4345
|
return __mldObj(d, format, locale) || 0;
|
|
4320
4346
|
}
|
|
4321
|
-
}
|
|
4322
|
-
className: 'dt-right'
|
|
4347
|
+
}
|
|
4323
4348
|
});
|
|
4324
4349
|
}
|
|
4350
|
+
if (!store.className[typeName]) {
|
|
4351
|
+
store.className[typeName] = 'dt-right';
|
|
4352
|
+
}
|
|
4325
4353
|
}
|
|
4326
4354
|
/**
|
|
4327
4355
|
* Helpers for `columns.render`.
|
|
@@ -4990,6 +5018,7 @@ function invalidate(settings, rowIdx, src, colIdx) {
|
|
|
4990
5018
|
// Update DataTables special `DT_*` attributes for the row
|
|
4991
5019
|
rowAttributes(settings, row);
|
|
4992
5020
|
}
|
|
5021
|
+
callbackFire(settings, null, 'rowInvalidate', [settings, rowIdx, colIdx], false);
|
|
4993
5022
|
}
|
|
4994
5023
|
/**
|
|
4995
5024
|
* Get the cells and data for a given row - from a <tr> element
|
|
@@ -5335,9 +5364,9 @@ function getWideStrings(settings, colIdx) {
|
|
|
5335
5364
|
// Don't want script, dialog or template tags in the width
|
|
5336
5365
|
// calculations as they are hidden content
|
|
5337
5366
|
cellString = cellString
|
|
5338
|
-
.replace(/<script[\s\S]*?<\/script
|
|
5339
|
-
.replace(/<dialog[\s\S]*?<\/dialog
|
|
5340
|
-
.replace(/<template[\s\S]*?<\/template
|
|
5367
|
+
.replace(/<script[\s\S]*?<\/script(?:\s[^>]*)?>/gi, ' ')
|
|
5368
|
+
.replace(/<dialog[\s\S]*?<\/dialog(?:\s[^>]*)?>/gi, ' ')
|
|
5369
|
+
.replace(/<template[\s\S]*?<\/template(?:\s[^>]*)?>/gi, ' ');
|
|
5341
5370
|
var noHtml = util.string
|
|
5342
5371
|
.stripHtml(cellString, ' ')
|
|
5343
5372
|
.replace(/ /g, ' ');
|
|
@@ -5938,6 +5967,7 @@ function columnTypes(settings) {
|
|
|
5938
5967
|
var types = ext.type.detect;
|
|
5939
5968
|
var i, iLen, j, jen, k, ken;
|
|
5940
5969
|
var col, detectedType, cache;
|
|
5970
|
+
var originalTypes = columns.map(c => c.type).join(',');
|
|
5941
5971
|
// For each column, spin over the data type detection functions, seeing if
|
|
5942
5972
|
// one matches
|
|
5943
5973
|
for (i = 0, iLen = columns.length; i < iLen; i++) {
|
|
@@ -6035,6 +6065,10 @@ function columnTypes(settings) {
|
|
|
6035
6065
|
_columnAutoRender(settings, i);
|
|
6036
6066
|
}
|
|
6037
6067
|
}
|
|
6068
|
+
var newTypes = columns.map(c => c.type).join(',');
|
|
6069
|
+
if (newTypes !== originalTypes) {
|
|
6070
|
+
callbackFire(settings, null, 'columnTypes', [settings], false);
|
|
6071
|
+
}
|
|
6038
6072
|
}
|
|
6039
6073
|
/**
|
|
6040
6074
|
* Apply an auto detected renderer to data which doesn't yet have a renderer
|
|
@@ -7236,13 +7270,13 @@ function implementState(settings, s, callback) {
|
|
|
7236
7270
|
let idx = currentNames.indexOf(col[0]);
|
|
7237
7271
|
if (idx < 0) {
|
|
7238
7272
|
// If the column was not found ignore it and continue
|
|
7239
|
-
|
|
7273
|
+
continue;
|
|
7240
7274
|
}
|
|
7241
7275
|
set[0] = idx;
|
|
7242
7276
|
}
|
|
7243
7277
|
else if (set[0] >= columns.length) {
|
|
7244
7278
|
// If the column index is out of bounds ignore it and continue
|
|
7245
|
-
|
|
7279
|
+
continue;
|
|
7246
7280
|
}
|
|
7247
7281
|
settings.order.push(set);
|
|
7248
7282
|
}
|
|
@@ -9560,12 +9594,13 @@ function selectCells(settings, selector, opts) {
|
|
|
9560
9594
|
// Otherwise the selector is a node, and there is one last option - the
|
|
9561
9595
|
// element might be a child of an element which has dt-row and dt-column
|
|
9562
9596
|
// data attributes
|
|
9563
|
-
|
|
9564
|
-
|
|
9597
|
+
let rowHost = Dom.s(s).closest('*[data-dt-row]');
|
|
9598
|
+
let columnHost = Dom.s(s).closest('*[data-dt-column]');
|
|
9599
|
+
return rowHost.count()
|
|
9565
9600
|
? [
|
|
9566
9601
|
{
|
|
9567
|
-
row:
|
|
9568
|
-
column:
|
|
9602
|
+
row: parseInt(rowHost.attr('data-dt-row')),
|
|
9603
|
+
column: parseInt(columnHost.attr('data-dt-column'))
|
|
9569
9604
|
}
|
|
9570
9605
|
]
|
|
9571
9606
|
: [];
|
|
@@ -9878,7 +9913,7 @@ function selectColumns(settings, selector, opts) {
|
|
|
9878
9913
|
// Otherwise a node which might have a `dt-column` data attribute, or be
|
|
9879
9914
|
// a child or such an element
|
|
9880
9915
|
var host = Dom.s(s).closest('*[data-dt-column]');
|
|
9881
|
-
return host.count() ? [host.
|
|
9916
|
+
return host.count() ? [parseInt(host.attr('data-dt-column'))] : [];
|
|
9882
9917
|
};
|
|
9883
9918
|
var selected = selectorRun('column', selector, run, settings, opts);
|
|
9884
9919
|
return opts.columnOrder && opts.columnOrder === 'index'
|
|
@@ -10075,18 +10110,19 @@ registerPlural('columns().widths()', 'column().width()', function () {
|
|
|
10075
10110
|
// Injects a fake row into the table for just a moment so the widths can
|
|
10076
10111
|
// be read, regardless of colspan in the header and rows being present
|
|
10077
10112
|
// in the body
|
|
10078
|
-
var columns = this.columns(':visible')
|
|
10113
|
+
var columns = this.columns(':visible');
|
|
10079
10114
|
var row = Dom
|
|
10080
10115
|
.c('tr')
|
|
10081
|
-
.html('<td>' + Array(columns).join('</td><td>') + '</td>');
|
|
10116
|
+
.html('<td>' + Array(columns.count()).join('</td><td>') + '</td>');
|
|
10082
10117
|
Dom.s(this.table().body()).append(row);
|
|
10083
|
-
var widths =
|
|
10084
|
-
|
|
10118
|
+
var widths = [];
|
|
10119
|
+
var indexes = columns.indexes();
|
|
10120
|
+
row.children().each((el, idx) => {
|
|
10121
|
+
widths[indexes[idx]] = Dom.s(el).width('outer');
|
|
10085
10122
|
});
|
|
10086
10123
|
row.remove();
|
|
10087
|
-
return this.iterator('column',
|
|
10088
|
-
|
|
10089
|
-
return visIdx !== null ? widths[visIdx] : 0;
|
|
10124
|
+
return this.iterator('column', (settings, column) => {
|
|
10125
|
+
return widths[column] || 0;
|
|
10090
10126
|
}, true);
|
|
10091
10127
|
});
|
|
10092
10128
|
registerPlural('columns().indexes()', 'column().index()', function (type) {
|
|
@@ -10558,7 +10594,7 @@ function selectRows(settings, selector, opts) {
|
|
|
10558
10594
|
}
|
|
10559
10595
|
else {
|
|
10560
10596
|
var host = Dom.s(sel).closest('*[data-dt-row]');
|
|
10561
|
-
return host.count() ? [host.
|
|
10597
|
+
return host.count() ? [parseInt(host.attr('data-dt-row'))] : [];
|
|
10562
10598
|
}
|
|
10563
10599
|
}
|
|
10564
10600
|
// ID selector. Want to always be able to select rows by id, regardless
|
|
@@ -10590,8 +10626,7 @@ function selectRows(settings, selector, opts) {
|
|
|
10590
10626
|
// Get nodes in the order from the `rows` array with null values removed
|
|
10591
10627
|
var nodes = util.array.removeEmpty(util.array.pluckOrder(settings.data, rows, 'tr'));
|
|
10592
10628
|
// Selector - selector string, array of nodes or jQuery object.
|
|
10593
|
-
return Dom
|
|
10594
|
-
.s(nodes)
|
|
10629
|
+
return Dom.s(nodes)
|
|
10595
10630
|
.filter(sel)
|
|
10596
10631
|
.mapTo((el) => el._DT_RowIndex);
|
|
10597
10632
|
};
|
|
@@ -10736,7 +10771,7 @@ register('row().data()', function (data) {
|
|
|
10736
10771
|
util.set(ctx[0].rowId)(data, row.tr.id);
|
|
10737
10772
|
}
|
|
10738
10773
|
// Automatically invalidate
|
|
10739
|
-
invalidate(ctx[0], this[0], 'data');
|
|
10774
|
+
invalidate(ctx[0], this[0][0], 'data');
|
|
10740
10775
|
return this;
|
|
10741
10776
|
});
|
|
10742
10777
|
register('row().node()', function () {
|
|
@@ -11054,10 +11089,10 @@ register('caption()', function (value, side) {
|
|
|
11054
11089
|
caption.css('caption-side', side);
|
|
11055
11090
|
caption.get(0)._captionSide = side;
|
|
11056
11091
|
}
|
|
11057
|
-
if (container.find('div.
|
|
11058
|
-
var selector = side === 'top' ? '
|
|
11092
|
+
if (container.find('div.dt-scroll').count()) {
|
|
11093
|
+
var selector = side === 'top' ? 'head' : 'foot';
|
|
11059
11094
|
container
|
|
11060
|
-
.find('div.
|
|
11095
|
+
.find('div.dt-scroll-' + selector + ' table')
|
|
11061
11096
|
.prepend(caption);
|
|
11062
11097
|
}
|
|
11063
11098
|
else {
|
|
@@ -11070,6 +11105,272 @@ register('caption.node()', function () {
|
|
|
11070
11105
|
return ctx.length ? ctx[0].captionNode : null;
|
|
11071
11106
|
});
|
|
11072
11107
|
|
|
11108
|
+
/**
|
|
11109
|
+
* What's this!? "DataTables Plus" is a commercial set of extensions for
|
|
11110
|
+
* DataTables, such as Editor, and the functions in this file allow a license
|
|
11111
|
+
* key to be provided (`DataTable.key(...)`) to unlock those features.
|
|
11112
|
+
*
|
|
11113
|
+
* This is the modal that I've selected to make DataTables sustainable, open
|
|
11114
|
+
* source core, with some commercial extensions available.
|
|
11115
|
+
*
|
|
11116
|
+
* Please support DataTables and open source by purchasing a Plus license from
|
|
11117
|
+
* https://datatables.net/plus .
|
|
11118
|
+
*/
|
|
11119
|
+
let _ready = false;
|
|
11120
|
+
let _notice;
|
|
11121
|
+
let _processingKey = false;
|
|
11122
|
+
let _delayedReleaseDate = null;
|
|
11123
|
+
let _delayedSoftware = null;
|
|
11124
|
+
const _licenseInfo = {
|
|
11125
|
+
developers: 0,
|
|
11126
|
+
type: null,
|
|
11127
|
+
expires: null,
|
|
11128
|
+
valid: null
|
|
11129
|
+
};
|
|
11130
|
+
const _wm = Dom.c('div');
|
|
11131
|
+
const _publicKey = 'BE1A9w9D9U/4s4/TogY+1sW/dLJ8IquzK1PmV70J93ZTIvXMZ0eV2NAb52ntpgwVFySSB2fOI7geLNO737rQAyo=';
|
|
11132
|
+
/**
|
|
11133
|
+
* Convert a base64 string to a binary array
|
|
11134
|
+
*
|
|
11135
|
+
* @param b64 Source string
|
|
11136
|
+
* @returns Array
|
|
11137
|
+
*/
|
|
11138
|
+
function b64ToBuf(b64) {
|
|
11139
|
+
return Uint8Array.from(atob(b64), c => c.charCodeAt(0));
|
|
11140
|
+
}
|
|
11141
|
+
/**
|
|
11142
|
+
* Logic to check the trial and plus license expiry and display messages if
|
|
11143
|
+
* needed. There is particular consideration for checking a release date of
|
|
11144
|
+
* software, as the license for DataTables Plus is perpetual for the version
|
|
11145
|
+
* purchased, and it shouldn't show a message for the purchased version ever.
|
|
11146
|
+
*
|
|
11147
|
+
* @param releaseDate The date the software was released on.
|
|
11148
|
+
* @param software The software name being validated. Can be null for a general
|
|
11149
|
+
* "Plus" check.
|
|
11150
|
+
* @returns true if valid, false otherwise
|
|
11151
|
+
*/
|
|
11152
|
+
function check(releaseDate, software) {
|
|
11153
|
+
let expires = _licenseInfo.expires;
|
|
11154
|
+
if (_licenseInfo.valid === false) {
|
|
11155
|
+
noticePrep('License key invalid');
|
|
11156
|
+
noticeDisplay();
|
|
11157
|
+
}
|
|
11158
|
+
else if (_licenseInfo.type === 'trial') {
|
|
11159
|
+
// Trail is for plus, so the software type isn't taken into account
|
|
11160
|
+
let remaining = expires
|
|
11161
|
+
? Math.ceil((expires.getTime() - new Date().getTime()) / 86400000)
|
|
11162
|
+
: -1;
|
|
11163
|
+
if (remaining < 0) {
|
|
11164
|
+
// Trial expires
|
|
11165
|
+
consoleMsg('Your trial has now expired - https://datatables.net/plus', 'warn');
|
|
11166
|
+
noticePrep('Trial expired');
|
|
11167
|
+
noticeDisplay();
|
|
11168
|
+
return false;
|
|
11169
|
+
}
|
|
11170
|
+
else {
|
|
11171
|
+
// Let the user know when it is going to expire with a console
|
|
11172
|
+
// message.
|
|
11173
|
+
consoleMsg('Your trial expires in ' +
|
|
11174
|
+
remaining +
|
|
11175
|
+
' day' +
|
|
11176
|
+
(remaining === 1 ? '' : 's'));
|
|
11177
|
+
return true;
|
|
11178
|
+
}
|
|
11179
|
+
}
|
|
11180
|
+
else if (_licenseInfo.type === 'plus' ||
|
|
11181
|
+
(_licenseInfo.type === 'editor' && software === 'editor')) {
|
|
11182
|
+
if (!expires || new Date(releaseDate) > expires) {
|
|
11183
|
+
noticePrep('Upgrade required for this version');
|
|
11184
|
+
noticeDisplay();
|
|
11185
|
+
return false;
|
|
11186
|
+
}
|
|
11187
|
+
return true;
|
|
11188
|
+
}
|
|
11189
|
+
else if (_licenseInfo.type === 'editor' && software !== 'editor') {
|
|
11190
|
+
noticePrep('License for Editor only. Upgrade for Plus');
|
|
11191
|
+
noticeDisplay();
|
|
11192
|
+
return false;
|
|
11193
|
+
}
|
|
11194
|
+
noticePrep();
|
|
11195
|
+
noticeDisplay();
|
|
11196
|
+
return false;
|
|
11197
|
+
}
|
|
11198
|
+
/**
|
|
11199
|
+
* Common log message handling
|
|
11200
|
+
*
|
|
11201
|
+
* @param msg Message to show
|
|
11202
|
+
* @param level Log level
|
|
11203
|
+
*/
|
|
11204
|
+
function consoleMsg(msg, level = 'log') {
|
|
11205
|
+
let fn = level === 'log' ? console.log : console.warn;
|
|
11206
|
+
fn('%cDataTables Plus%c ' + msg, 'background: #007bff; color: #fff; padding: 2px 5px;', 'color: inherit;');
|
|
11207
|
+
}
|
|
11208
|
+
/**
|
|
11209
|
+
* Set the DataTables Plus key to use
|
|
11210
|
+
*
|
|
11211
|
+
* @param key DataTables Plus key - obtain from https://datatables.net/account .
|
|
11212
|
+
*/
|
|
11213
|
+
const key = function (key) {
|
|
11214
|
+
_processingKey = true;
|
|
11215
|
+
// Run the verification of the key
|
|
11216
|
+
verify(key)
|
|
11217
|
+
.then(result => {
|
|
11218
|
+
_processingKey = false;
|
|
11219
|
+
check(_delayedReleaseDate, _delayedSoftware);
|
|
11220
|
+
})
|
|
11221
|
+
.catch(() => {
|
|
11222
|
+
_processingKey = false;
|
|
11223
|
+
check(_delayedReleaseDate, _delayedSoftware);
|
|
11224
|
+
});
|
|
11225
|
+
};
|
|
11226
|
+
/**
|
|
11227
|
+
* Build the notice
|
|
11228
|
+
*
|
|
11229
|
+
* @returns
|
|
11230
|
+
*/
|
|
11231
|
+
function noticePrep(text) {
|
|
11232
|
+
if (!_ready) {
|
|
11233
|
+
let shadow = _wm[0].attachShadow({ mode: 'closed' });
|
|
11234
|
+
let notice = Dom.c('div').css({
|
|
11235
|
+
position: 'fixed',
|
|
11236
|
+
bottom: '1em',
|
|
11237
|
+
right: '1em',
|
|
11238
|
+
border: '1px solid #ffc107',
|
|
11239
|
+
background: '#fff3cd',
|
|
11240
|
+
color: '#856404',
|
|
11241
|
+
padding: '0.5em 1em',
|
|
11242
|
+
'font-family': 'sans-serif',
|
|
11243
|
+
'font-size': '12px',
|
|
11244
|
+
'border-radius': '4px',
|
|
11245
|
+
'z-index': '10000',
|
|
11246
|
+
'box-shadow': '0 2px 5px rgba(0,0,0,0.2)'
|
|
11247
|
+
});
|
|
11248
|
+
Dom.c('a')
|
|
11249
|
+
.attr('href', 'https://datatables.net/tn/25')
|
|
11250
|
+
.attr('target', '_blank')
|
|
11251
|
+
.css({
|
|
11252
|
+
color: 'inherit',
|
|
11253
|
+
'text-decoration': 'none'
|
|
11254
|
+
})
|
|
11255
|
+
.appendTo(notice);
|
|
11256
|
+
if (!text) {
|
|
11257
|
+
text = 'License key required';
|
|
11258
|
+
}
|
|
11259
|
+
shadow.appendChild(notice[0]);
|
|
11260
|
+
_notice = notice;
|
|
11261
|
+
_ready = true;
|
|
11262
|
+
}
|
|
11263
|
+
if (text) {
|
|
11264
|
+
_notice
|
|
11265
|
+
.find('a')
|
|
11266
|
+
.html('DataTables Plus: ' + text + ' - learn more »');
|
|
11267
|
+
}
|
|
11268
|
+
}
|
|
11269
|
+
/**
|
|
11270
|
+
* Display the license notice
|
|
11271
|
+
*/
|
|
11272
|
+
function noticeDisplay() {
|
|
11273
|
+
if (!_processingKey && !document.body.contains(_wm[0])) {
|
|
11274
|
+
document.body.appendChild(_wm[0]);
|
|
11275
|
+
}
|
|
11276
|
+
}
|
|
11277
|
+
/**
|
|
11278
|
+
* Validate the license string, which is in two parts - the first is a payload
|
|
11279
|
+
* that provides a small amount of information about the license, and the second
|
|
11280
|
+
* which is the license key.
|
|
11281
|
+
*
|
|
11282
|
+
* @param licenseString Key to validate
|
|
11283
|
+
* @returns Promise with validation information
|
|
11284
|
+
*/
|
|
11285
|
+
function verify(licenseString) {
|
|
11286
|
+
return new Promise(function (resolve) {
|
|
11287
|
+
try {
|
|
11288
|
+
var parts = licenseString.split(':');
|
|
11289
|
+
if (parts.length !== 2) {
|
|
11290
|
+
_licenseInfo.valid = false;
|
|
11291
|
+
return resolve();
|
|
11292
|
+
}
|
|
11293
|
+
var payload = parts[0];
|
|
11294
|
+
var signatureB64 = parts[1];
|
|
11295
|
+
// Backwards compat for old browsers
|
|
11296
|
+
var cryptoObj = window.crypto || window.msCrypto;
|
|
11297
|
+
var subtle = cryptoObj.subtle || cryptoObj.webkitSubtle;
|
|
11298
|
+
var rawKey = b64ToBuf(_publicKey);
|
|
11299
|
+
var rawSig = b64ToBuf(signatureB64);
|
|
11300
|
+
var data = new TextEncoder().encode(payload);
|
|
11301
|
+
subtle
|
|
11302
|
+
.importKey('raw', rawKey, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify'])
|
|
11303
|
+
.then(function (key) {
|
|
11304
|
+
return subtle.verify({ name: 'ECDSA', hash: { name: 'SHA-256' } }, key, rawSig, data);
|
|
11305
|
+
})
|
|
11306
|
+
.then(function (isValid) {
|
|
11307
|
+
if (!isValid) {
|
|
11308
|
+
_licenseInfo.valid = false;
|
|
11309
|
+
return resolve();
|
|
11310
|
+
}
|
|
11311
|
+
// Extract the payload to be useful
|
|
11312
|
+
var payloadParts = payload.match(/(plus|trial|editor)_(\d+)_(\d{4})(\d{2})(\d{2})/);
|
|
11313
|
+
if (!payloadParts || payloadParts.length !== 6) {
|
|
11314
|
+
_licenseInfo.valid = false;
|
|
11315
|
+
return resolve();
|
|
11316
|
+
}
|
|
11317
|
+
_licenseInfo.valid = true;
|
|
11318
|
+
_licenseInfo.type = payloadParts[1];
|
|
11319
|
+
_licenseInfo.developers = parseInt(payloadParts[2]);
|
|
11320
|
+
_licenseInfo.expires = new Date(payloadParts[3] +
|
|
11321
|
+
'-' +
|
|
11322
|
+
payloadParts[4] +
|
|
11323
|
+
'-' +
|
|
11324
|
+
payloadParts[5]);
|
|
11325
|
+
resolve();
|
|
11326
|
+
})
|
|
11327
|
+
.catch(function () {
|
|
11328
|
+
_licenseInfo.valid = false;
|
|
11329
|
+
resolve();
|
|
11330
|
+
});
|
|
11331
|
+
}
|
|
11332
|
+
catch (e) {
|
|
11333
|
+
_licenseInfo.valid = false;
|
|
11334
|
+
resolve();
|
|
11335
|
+
}
|
|
11336
|
+
});
|
|
11337
|
+
}
|
|
11338
|
+
/**
|
|
11339
|
+
* Create the `plus` function on `DataTable` which Plus extensions can call to
|
|
11340
|
+
* determine if the license key is valid and in date for the release. The
|
|
11341
|
+
* resulting function is called like this: `DataTable.plus('2026-12-25')` and
|
|
11342
|
+
* will return `true` or `false` depending on the key that was given (or not).
|
|
11343
|
+
*
|
|
11344
|
+
* @param DataTable The DataTable host object
|
|
11345
|
+
*/
|
|
11346
|
+
function plus (DataTable) {
|
|
11347
|
+
Object.defineProperty(DataTable, 'plus', {
|
|
11348
|
+
value: function (releaseDate, software = null) {
|
|
11349
|
+
// Unsecure sites are only useful for development, so allow there
|
|
11350
|
+
// and on the site.
|
|
11351
|
+
let host = window.location.hostname;
|
|
11352
|
+
let isDev = host === '192.168.234.234' ||
|
|
11353
|
+
host.endsWith('.datatables.net') ||
|
|
11354
|
+
host === 'datatables.net';
|
|
11355
|
+
if (isDev) {
|
|
11356
|
+
return true;
|
|
11357
|
+
}
|
|
11358
|
+
if (_processingKey) {
|
|
11359
|
+
// The validation of the key is async, so there is a chance that
|
|
11360
|
+
// it could still be happening when this runs. We just queue the
|
|
11361
|
+
// last one if that is the case.
|
|
11362
|
+
_delayedReleaseDate = releaseDate;
|
|
11363
|
+
_delayedSoftware = software;
|
|
11364
|
+
return true;
|
|
11365
|
+
}
|
|
11366
|
+
return check(releaseDate, software);
|
|
11367
|
+
},
|
|
11368
|
+
configurable: false,
|
|
11369
|
+
enumerable: false,
|
|
11370
|
+
writable: false
|
|
11371
|
+
});
|
|
11372
|
+
}
|
|
11373
|
+
|
|
11073
11374
|
/**
|
|
11074
11375
|
* CommonJS factory function pass through. This will check if the arguments
|
|
11075
11376
|
* given are a window object or a jQuery object. If so they are set accordingly.
|
|
@@ -11429,8 +11730,7 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11429
11730
|
}
|
|
11430
11731
|
// Wrapper element - use a span as a holder for where the select will go
|
|
11431
11732
|
var tmpId = 'tmp-' + +new Date();
|
|
11432
|
-
var div = Dom
|
|
11433
|
-
.c('div')
|
|
11733
|
+
var div = Dom.c('div')
|
|
11434
11734
|
.classAdd(classes.container)
|
|
11435
11735
|
.html(str.replace('_MENU_', '<span id="' + tmpId + '"></span>'));
|
|
11436
11736
|
// Save text node content for macro updating
|
|
@@ -11452,9 +11752,9 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11452
11752
|
});
|
|
11453
11753
|
};
|
|
11454
11754
|
// Next, the select itself, along with the options
|
|
11455
|
-
var select = Dom
|
|
11456
|
-
.c('select')
|
|
11755
|
+
var select = Dom.c('select')
|
|
11457
11756
|
.attr('aria-controls', tableId)
|
|
11757
|
+
.attr('autocomplete', 'off')
|
|
11458
11758
|
.classAdd(classes.select);
|
|
11459
11759
|
for (i = 0; i < lengths.length; i++) {
|
|
11460
11760
|
// Attempt to look up the length from the i18n options
|
|
@@ -11485,7 +11785,26 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11485
11785
|
// Update node value whenever anything changes the table's length
|
|
11486
11786
|
Dom.s(settings.table).on('length.dt.DT', function (e, s, len) {
|
|
11487
11787
|
if (settings === s) {
|
|
11488
|
-
div.find('select')
|
|
11788
|
+
let localSelect = div.find('select');
|
|
11789
|
+
// Remove any temporary values
|
|
11790
|
+
localSelect.find('option[data-dt-len-tmp]').remove();
|
|
11791
|
+
let option = localSelect.find('option[value="' + len + '"]');
|
|
11792
|
+
// If the select list doesn't have the target value, then we
|
|
11793
|
+
// need to add it for display.
|
|
11794
|
+
if (!option.length) {
|
|
11795
|
+
let after = findInsertBeforePoint(select, len);
|
|
11796
|
+
let tempOption = Dom.c('option')
|
|
11797
|
+
.val(len)
|
|
11798
|
+
.text(len)
|
|
11799
|
+
.attr('data-dt-len-tmp', true);
|
|
11800
|
+
if (after && after.length) {
|
|
11801
|
+
tempOption.insertBefore(after);
|
|
11802
|
+
}
|
|
11803
|
+
else {
|
|
11804
|
+
localSelect.append(tempOption);
|
|
11805
|
+
}
|
|
11806
|
+
}
|
|
11807
|
+
localSelect.val(len);
|
|
11489
11808
|
// Resolve plurals in the text for the new length
|
|
11490
11809
|
updateEntries(len);
|
|
11491
11810
|
}
|
|
@@ -11493,6 +11812,19 @@ register$2('pageLength', function (settings, optsIn) {
|
|
|
11493
11812
|
updateEntries(settings.pageLength);
|
|
11494
11813
|
return div;
|
|
11495
11814
|
}, 'l');
|
|
11815
|
+
/**
|
|
11816
|
+
* Find the element to insert the temporary option before to keep the sequence.
|
|
11817
|
+
*
|
|
11818
|
+
* @param select Select element
|
|
11819
|
+
* @param insertValue Page length value
|
|
11820
|
+
* @returns Target option or null if not found
|
|
11821
|
+
*/
|
|
11822
|
+
function findInsertBeforePoint(select, insertValue) {
|
|
11823
|
+
let options = select.find('option');
|
|
11824
|
+
let values = options.mapTo(el => parseInt(el.value));
|
|
11825
|
+
let idx = values.findIndex(val => val > insertValue);
|
|
11826
|
+
return idx < -1 ? null : options.eq(idx);
|
|
11827
|
+
}
|
|
11496
11828
|
|
|
11497
11829
|
let __searchCounter = 0;
|
|
11498
11830
|
register$2('search', function (settings, optsIn) {
|
|
@@ -11503,7 +11835,9 @@ register$2('search', function (settings, optsIn) {
|
|
|
11503
11835
|
let classes = settings.classes.search;
|
|
11504
11836
|
let tableId = settings.tableId;
|
|
11505
11837
|
let language = settings.language;
|
|
11506
|
-
let input = '<input type="search" class="' +
|
|
11838
|
+
let input = '<input type="search" class="' +
|
|
11839
|
+
classes.input +
|
|
11840
|
+
'" autocomplete="off"/>';
|
|
11507
11841
|
let opts = util.object.assignDeep({
|
|
11508
11842
|
columns: '*',
|
|
11509
11843
|
placeholder: language.searchPlaceholder,
|
|
@@ -12325,6 +12659,8 @@ DataTable.datetime = datetime;
|
|
|
12325
12659
|
DataTable.__browser = browser;
|
|
12326
12660
|
DataTable.Dom = Dom;
|
|
12327
12661
|
DataTable.ajax = util.ajax;
|
|
12662
|
+
DataTable.key = key;
|
|
12663
|
+
plus(DataTable);
|
|
12328
12664
|
/**
|
|
12329
12665
|
* Private data store, containing all of the settings objects that are created
|
|
12330
12666
|
* for the tables on a given page.
|