oxidized-web 0.14.0 → 0.15.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.
Potentially problematic release.
This version of oxidized-web might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -3
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -6
- data/CHANGELOG.md +18 -0
- data/Rakefile +1 -0
- data/docs/development.md +16 -4
- data/lib/oxidized/web/public/scripts/oxidized.js +0 -36
- data/lib/oxidized/web/public/weblibs/buttons.bootstrap5.css +77 -80
- data/lib/oxidized/web/public/weblibs/buttons.bootstrap5.js +4 -7
- data/lib/oxidized/web/public/weblibs/dataTables.bootstrap5.css +45 -15
- data/lib/oxidized/web/public/weblibs/dataTables.bootstrap5.js +12 -37
- data/lib/oxidized/web/public/weblibs/dataTables.buttons.js +139 -23
- data/lib/oxidized/web/public/weblibs/dataTables.js +1190 -518
- data/lib/oxidized/web/version.rb +1 -1
- data/lib/oxidized/web/views/layout.haml +0 -4
- data/lib/oxidized/web/webapp.rb +20 -35
- data/oxidized-web.gemspec +16 -15
- data/package-lock.json +14 -14
- data/spec/node_spec.rb +3 -47
- data/spec/node_version_spec.rb +102 -0
- data/spec/nodes_spec.rb +57 -0
- data/spec/spec_helper.rb +3 -0
- metadata +30 -35
- data/lib/oxidized/web/mig.rb +0 -140
- data/lib/oxidized/web/public/scripts/script-migration.js +0 -15
- data/lib/oxidized/web/views/migration.haml +0 -53
@@ -1,25 +1,7 @@
|
|
1
|
-
/*! DataTables 2.
|
1
|
+
/*! DataTables 2.2.2
|
2
2
|
* © SpryMedia Ltd - datatables.net/license
|
3
3
|
*/
|
4
4
|
|
5
|
-
/**
|
6
|
-
* @summary DataTables
|
7
|
-
* @description Paginate, search and order HTML tables
|
8
|
-
* @version 2.0.8
|
9
|
-
* @author SpryMedia Ltd
|
10
|
-
* @contact www.datatables.net
|
11
|
-
* @copyright SpryMedia Ltd.
|
12
|
-
*
|
13
|
-
* This source file is free software, available under the following license:
|
14
|
-
* MIT license - https://datatables.net/license
|
15
|
-
*
|
16
|
-
* This source file is distributed in the hope that it will be useful, but
|
17
|
-
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
18
|
-
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
19
|
-
*
|
20
|
-
* For details please refer to: https://www.datatables.net
|
21
|
-
*/
|
22
|
-
|
23
5
|
(function( factory ) {
|
24
6
|
"use strict";
|
25
7
|
|
@@ -104,7 +86,6 @@
|
|
104
86
|
|
105
87
|
var i=0, iLen;
|
106
88
|
var sId = this.getAttribute( 'id' );
|
107
|
-
var bInitHandedOff = false;
|
108
89
|
var defaults = DataTable.defaults;
|
109
90
|
var $this = $(this);
|
110
91
|
|
@@ -254,6 +235,8 @@
|
|
254
235
|
"rowId",
|
255
236
|
"caption",
|
256
237
|
"layout",
|
238
|
+
"orderDescReverse",
|
239
|
+
"typeDetect",
|
257
240
|
[ "iCookieDuration", "iStateDuration" ], // backwards compat
|
258
241
|
[ "oSearch", "oPreviousSearch" ],
|
259
242
|
[ "aoSearchCols", "aoPreSearchCols" ],
|
@@ -300,38 +283,14 @@
|
|
300
283
|
oSettings._iDisplayStart = oInit.iDisplayStart;
|
301
284
|
}
|
302
285
|
|
303
|
-
|
304
|
-
|
305
|
-
$.extend( true, oLanguage, oInit.oLanguage );
|
306
|
-
|
307
|
-
if ( oLanguage.sUrl )
|
286
|
+
var defer = oInit.iDeferLoading;
|
287
|
+
if ( defer !== null )
|
308
288
|
{
|
309
|
-
|
310
|
-
* get async to the remainder of this function we use bInitHandedOff to indicate that
|
311
|
-
* _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
|
312
|
-
*/
|
313
|
-
$.ajax( {
|
314
|
-
dataType: 'json',
|
315
|
-
url: oLanguage.sUrl,
|
316
|
-
success: function ( json ) {
|
317
|
-
_fnCamelToHungarian( defaults.oLanguage, json );
|
318
|
-
$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
|
289
|
+
oSettings.deferLoading = true;
|
319
290
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
error: function () {
|
324
|
-
// Error occurred loading language file
|
325
|
-
_fnLog( oSettings, 0, 'i18n file loading error', 21 );
|
326
|
-
|
327
|
-
// continue on as best we can
|
328
|
-
_fnInitialise( oSettings );
|
329
|
-
}
|
330
|
-
} );
|
331
|
-
bInitHandedOff = true;
|
332
|
-
}
|
333
|
-
else {
|
334
|
-
_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
|
291
|
+
var tmp = Array.isArray(defer);
|
292
|
+
oSettings._iRecordsDisplay = tmp ? defer[0] : defer;
|
293
|
+
oSettings._iRecordsTotal = tmp ? defer[1] : defer;
|
335
294
|
}
|
336
295
|
|
337
296
|
/*
|
@@ -398,113 +357,110 @@
|
|
398
357
|
} );
|
399
358
|
}
|
400
359
|
|
360
|
+
// Must be done after everything which can be overridden by the state saving!
|
361
|
+
_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState );
|
362
|
+
|
401
363
|
var features = oSettings.oFeatures;
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
*/
|
364
|
+
if ( oInit.bStateSave )
|
365
|
+
{
|
366
|
+
features.bStateSave = true;
|
367
|
+
}
|
407
368
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
}
|
369
|
+
// If aaSorting is not defined, then we use the first indicator in asSorting
|
370
|
+
// in case that has been altered, so the default sort reflects that option
|
371
|
+
if ( oInit.aaSorting === undefined ) {
|
372
|
+
var sorting = oSettings.aaSorting;
|
373
|
+
for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
|
374
|
+
sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
|
415
375
|
}
|
376
|
+
}
|
416
377
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
_fnSortingClasses( oSettings );
|
421
|
-
|
422
|
-
_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
423
|
-
if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
|
424
|
-
_fnSortingClasses( oSettings );
|
425
|
-
}
|
426
|
-
} );
|
378
|
+
// Do a first pass on the sorting classes (allows any size changes to be taken into
|
379
|
+
// account, and also will apply sorting disabled classes if disabled
|
380
|
+
_fnSortingClasses( oSettings );
|
427
381
|
|
382
|
+
_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
383
|
+
if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
|
384
|
+
_fnSortingClasses( oSettings );
|
385
|
+
}
|
386
|
+
} );
|
428
387
|
|
429
|
-
/*
|
430
|
-
* Final init
|
431
|
-
* Cache the header, body and footer as required, creating them if needed
|
432
|
-
*/
|
433
|
-
var caption = $this.children('caption');
|
434
388
|
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
389
|
+
/*
|
390
|
+
* Table HTML init
|
391
|
+
* Cache the header, body and footer as required, creating them if needed
|
392
|
+
*/
|
393
|
+
var caption = $this.children('caption');
|
439
394
|
|
440
|
-
|
395
|
+
if ( oSettings.caption ) {
|
396
|
+
if ( caption.length === 0 ) {
|
397
|
+
caption = $('<caption/>').appendTo( $this );
|
441
398
|
}
|
442
399
|
|
443
|
-
|
444
|
-
|
445
|
-
if (caption.length) {
|
446
|
-
caption[0]._captionSide = caption.css('caption-side');
|
447
|
-
oSettings.captionNode = caption[0];
|
448
|
-
}
|
400
|
+
caption.html( oSettings.caption );
|
401
|
+
}
|
449
402
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
403
|
+
// Store the caption side, so we can remove the element from the document
|
404
|
+
// when creating the element
|
405
|
+
if (caption.length) {
|
406
|
+
caption[0]._captionSide = caption.css('caption-side');
|
407
|
+
oSettings.captionNode = caption[0];
|
408
|
+
}
|
455
409
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
oSettings.nTBody = tbody[0];
|
410
|
+
if ( thead.length === 0 ) {
|
411
|
+
thead = $('<thead/>').appendTo($this);
|
412
|
+
}
|
413
|
+
oSettings.nTHead = thead[0];
|
461
414
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
}
|
468
|
-
oSettings.nTFoot = tfoot[0];
|
469
|
-
$('tr', tfoot).addClass(oClasses.tfoot.row);
|
415
|
+
var tbody = $this.children('tbody');
|
416
|
+
if ( tbody.length === 0 ) {
|
417
|
+
tbody = $('<tbody/>').insertAfter(thead);
|
418
|
+
}
|
419
|
+
oSettings.nTBody = tbody[0];
|
470
420
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
// Grab the data from the page
|
479
|
-
_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
|
480
|
-
}
|
421
|
+
var tfoot = $this.children('tfoot');
|
422
|
+
if ( tfoot.length === 0 ) {
|
423
|
+
// If we are a scrolling table, and no footer has been given, then we need to create
|
424
|
+
// a tfoot element for the caption element to be appended to
|
425
|
+
tfoot = $('<tfoot/>').appendTo($this);
|
426
|
+
}
|
427
|
+
oSettings.nTFoot = tfoot[0];
|
481
428
|
|
482
|
-
|
483
|
-
|
429
|
+
// Copy the data index array
|
430
|
+
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
|
484
431
|
|
485
|
-
|
486
|
-
|
432
|
+
// Initialisation complete - table can be drawn
|
433
|
+
oSettings.bInitialised = true;
|
487
434
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
if ( bInitHandedOff === false ) {
|
492
|
-
_fnInitialise( oSettings );
|
493
|
-
}
|
494
|
-
};
|
435
|
+
// Language definitions
|
436
|
+
var oLanguage = oSettings.oLanguage;
|
437
|
+
$.extend( true, oLanguage, oInit.oLanguage );
|
495
438
|
|
496
|
-
|
497
|
-
|
439
|
+
if ( oLanguage.sUrl ) {
|
440
|
+
// Get the language definitions from a file
|
441
|
+
$.ajax( {
|
442
|
+
dataType: 'json',
|
443
|
+
url: oLanguage.sUrl,
|
444
|
+
success: function ( json ) {
|
445
|
+
_fnCamelToHungarian( defaults.oLanguage, json );
|
446
|
+
$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
|
498
447
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
448
|
+
_fnCallbackFire( oSettings, null, 'i18n', [oSettings], true);
|
449
|
+
_fnInitialise( oSettings );
|
450
|
+
},
|
451
|
+
error: function () {
|
452
|
+
// Error occurred loading language file
|
453
|
+
_fnLog( oSettings, 0, 'i18n file loading error', 21 );
|
454
|
+
|
455
|
+
// Continue on as best we can
|
456
|
+
_fnInitialise( oSettings );
|
457
|
+
}
|
458
|
+
} );
|
503
459
|
}
|
504
460
|
else {
|
505
|
-
|
461
|
+
_fnCallbackFire( oSettings, null, 'i18n', [oSettings], true);
|
462
|
+
_fnInitialise( oSettings );
|
506
463
|
}
|
507
|
-
|
508
464
|
} );
|
509
465
|
_that = null;
|
510
466
|
return this;
|
@@ -1021,6 +977,15 @@
|
|
1021
977
|
info: {
|
1022
978
|
container: 'dt-info'
|
1023
979
|
},
|
980
|
+
layout: {
|
981
|
+
row: 'dt-layout-row',
|
982
|
+
cell: 'dt-layout-cell',
|
983
|
+
tableRow: 'dt-layout-table',
|
984
|
+
tableCell: '',
|
985
|
+
start: 'dt-layout-start',
|
986
|
+
end: 'dt-layout-end',
|
987
|
+
full: 'dt-layout-full'
|
988
|
+
},
|
1024
989
|
length: {
|
1025
990
|
container: 'dt-length',
|
1026
991
|
select: 'dt-input'
|
@@ -1069,7 +1034,8 @@
|
|
1069
1034
|
active: 'current',
|
1070
1035
|
button: 'dt-paging-button',
|
1071
1036
|
container: 'dt-paging',
|
1072
|
-
disabled: 'disabled'
|
1037
|
+
disabled: 'disabled',
|
1038
|
+
nav: ''
|
1073
1039
|
}
|
1074
1040
|
} );
|
1075
1041
|
|
@@ -1144,7 +1110,7 @@
|
|
1144
1110
|
};
|
1145
1111
|
|
1146
1112
|
|
1147
|
-
var _isNumber = function ( d, decimalPoint, formatted ) {
|
1113
|
+
var _isNumber = function ( d, decimalPoint, formatted, allowEmpty ) {
|
1148
1114
|
var type = typeof d;
|
1149
1115
|
var strType = type === 'string';
|
1150
1116
|
|
@@ -1155,7 +1121,7 @@
|
|
1155
1121
|
// If empty return immediately so there must be a number if it is a
|
1156
1122
|
// formatted string (this stops the string "k", or "kr", etc being detected
|
1157
1123
|
// as a formatted number for currency
|
1158
|
-
if ( _empty( d ) ) {
|
1124
|
+
if ( allowEmpty && _empty( d ) ) {
|
1159
1125
|
return true;
|
1160
1126
|
}
|
1161
1127
|
|
@@ -1177,8 +1143,8 @@
|
|
1177
1143
|
};
|
1178
1144
|
|
1179
1145
|
// Is a string a number surrounded by HTML?
|
1180
|
-
var _htmlNumeric = function ( d, decimalPoint, formatted ) {
|
1181
|
-
if ( _empty( d ) ) {
|
1146
|
+
var _htmlNumeric = function ( d, decimalPoint, formatted, allowEmpty ) {
|
1147
|
+
if ( allowEmpty && _empty( d ) ) {
|
1182
1148
|
return true;
|
1183
1149
|
}
|
1184
1150
|
|
@@ -1190,7 +1156,7 @@
|
|
1190
1156
|
var html = _isHtml( d );
|
1191
1157
|
return ! html ?
|
1192
1158
|
null :
|
1193
|
-
_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
|
1159
|
+
_isNumber( _stripHtml( d ), decimalPoint, formatted, allowEmpty ) ?
|
1194
1160
|
true :
|
1195
1161
|
null;
|
1196
1162
|
};
|
@@ -1232,7 +1198,7 @@
|
|
1232
1198
|
// is essential here
|
1233
1199
|
if ( prop2 !== undefined ) {
|
1234
1200
|
for ( ; i<ien ; i++ ) {
|
1235
|
-
if ( a[ order[i] ][ prop ] ) {
|
1201
|
+
if ( a[ order[i] ] && a[ order[i] ][ prop ] ) {
|
1236
1202
|
out.push( a[ order[i] ][ prop ][ prop2 ] );
|
1237
1203
|
}
|
1238
1204
|
}
|
@@ -1286,6 +1252,10 @@
|
|
1286
1252
|
|
1287
1253
|
// Replaceable function in api.util
|
1288
1254
|
var _stripHtml = function (input) {
|
1255
|
+
if (! input || typeof input !== 'string') {
|
1256
|
+
return input;
|
1257
|
+
}
|
1258
|
+
|
1289
1259
|
// Irrelevant check to workaround CodeQL's false positive on the regex
|
1290
1260
|
if (input.length > _max_str_len) {
|
1291
1261
|
throw new Error('Exceeded max str len');
|
@@ -1328,8 +1298,11 @@
|
|
1328
1298
|
}
|
1329
1299
|
|
1330
1300
|
// It is faster to just run `normalize` than it is to check if
|
1331
|
-
// we need to with a regex!
|
1332
|
-
|
1301
|
+
// we need to with a regex! (Check as it isn't available in old
|
1302
|
+
// Safari)
|
1303
|
+
var res = str.normalize
|
1304
|
+
? str.normalize("NFD")
|
1305
|
+
: str;
|
1333
1306
|
|
1334
1307
|
// Equally, here we check if a regex is needed or not
|
1335
1308
|
return res.length !== str.length
|
@@ -2168,6 +2141,10 @@
|
|
2168
2141
|
var width = _fnColumnsSumWidth(settings, [i], false, false);
|
2169
2142
|
|
2170
2143
|
cols[i].colEl.css('width', width);
|
2144
|
+
|
2145
|
+
if (settings.oScroll.sX) {
|
2146
|
+
cols[i].colEl.css('min-width', width);
|
2147
|
+
}
|
2171
2148
|
}
|
2172
2149
|
}
|
2173
2150
|
|
@@ -2252,6 +2229,21 @@
|
|
2252
2229
|
return a;
|
2253
2230
|
}
|
2254
2231
|
|
2232
|
+
/**
|
2233
|
+
* Allow the result from a type detection function to be `true` while
|
2234
|
+
* translating that into a string. Old type detection functions will
|
2235
|
+
* return the type name if it passes. An obect store would be better,
|
2236
|
+
* but not backwards compatible.
|
2237
|
+
*
|
2238
|
+
* @param {*} typeDetect Object or function for type detection
|
2239
|
+
* @param {*} res Result from the type detection function
|
2240
|
+
* @returns Type name or false
|
2241
|
+
*/
|
2242
|
+
function _typeResult (typeDetect, res) {
|
2243
|
+
return res === true
|
2244
|
+
? typeDetect._name
|
2245
|
+
: res;
|
2246
|
+
}
|
2255
2247
|
|
2256
2248
|
/**
|
2257
2249
|
* Calculate the 'type' of a column
|
@@ -2266,7 +2258,7 @@
|
|
2266
2258
|
var i, ien, j, jen, k, ken;
|
2267
2259
|
var col, detectedType, cache;
|
2268
2260
|
|
2269
|
-
// For each column, spin over the
|
2261
|
+
// For each column, spin over the data type detection functions, seeing if one matches
|
2270
2262
|
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
2271
2263
|
col = columns[i];
|
2272
2264
|
cache = [];
|
@@ -2275,9 +2267,34 @@
|
|
2275
2267
|
col.sType = col._sManualType;
|
2276
2268
|
}
|
2277
2269
|
else if ( ! col.sType ) {
|
2270
|
+
// With SSP type detection can be unreliable and error prone, so we provide a way
|
2271
|
+
// to turn it off.
|
2272
|
+
if (! settings.typeDetect) {
|
2273
|
+
return;
|
2274
|
+
}
|
2275
|
+
|
2278
2276
|
for ( j=0, jen=types.length ; j<jen ; j++ ) {
|
2279
|
-
|
2277
|
+
var typeDetect = types[j];
|
2280
2278
|
|
2279
|
+
// There can be either one, or three type detection functions
|
2280
|
+
var oneOf = typeDetect.oneOf;
|
2281
|
+
var allOf = typeDetect.allOf || typeDetect;
|
2282
|
+
var init = typeDetect.init;
|
2283
|
+
var one = false;
|
2284
|
+
|
2285
|
+
detectedType = null;
|
2286
|
+
|
2287
|
+
// Fast detect based on column assignment
|
2288
|
+
if (init) {
|
2289
|
+
detectedType = _typeResult(typeDetect, init(settings, col, i));
|
2290
|
+
|
2291
|
+
if (detectedType) {
|
2292
|
+
col.sType = detectedType;
|
2293
|
+
break;
|
2294
|
+
}
|
2295
|
+
}
|
2296
|
+
|
2297
|
+
for ( k=0, ken=data.length ; k<ken ; k++ ) {
|
2281
2298
|
if (! data[k]) {
|
2282
2299
|
continue;
|
2283
2300
|
}
|
@@ -2288,14 +2305,20 @@
|
|
2288
2305
|
cache[k] = _fnGetCellData( settings, k, i, 'type' );
|
2289
2306
|
}
|
2290
2307
|
|
2291
|
-
|
2308
|
+
// Only one data point in the column needs to match this function
|
2309
|
+
if (oneOf && ! one) {
|
2310
|
+
one = _typeResult(typeDetect, oneOf( cache[k], settings ));
|
2311
|
+
}
|
2312
|
+
|
2313
|
+
// All data points need to match this function
|
2314
|
+
detectedType = _typeResult(typeDetect, allOf( cache[k], settings ));
|
2292
2315
|
|
2293
2316
|
// If null, then this type can't apply to this column, so
|
2294
2317
|
// rather than testing all cells, break out. There is an
|
2295
2318
|
// exception for the last type which is `html`. We need to
|
2296
2319
|
// scan all rows since it is possible to mix string and HTML
|
2297
2320
|
// types
|
2298
|
-
if ( ! detectedType && j !== types.length-
|
2321
|
+
if ( ! detectedType && j !== types.length-3 ) {
|
2299
2322
|
break;
|
2300
2323
|
}
|
2301
2324
|
|
@@ -2309,7 +2332,7 @@
|
|
2309
2332
|
|
2310
2333
|
// Type is valid for all data points in the column - use this
|
2311
2334
|
// type
|
2312
|
-
if ( detectedType ) {
|
2335
|
+
if ( (oneOf && one && detectedType) || (!oneOf && detectedType) ) {
|
2313
2336
|
col.sType = detectedType;
|
2314
2337
|
break;
|
2315
2338
|
}
|
@@ -2331,7 +2354,7 @@
|
|
2331
2354
|
|
2332
2355
|
var renderer = _ext.type.render[col.sType];
|
2333
2356
|
|
2334
|
-
// This can only happen once! There is no way to
|
2357
|
+
// This can only happen once! There is no way to remove
|
2335
2358
|
// a renderer. After the first time the renderer has
|
2336
2359
|
// already been set so createTr will run the renderer itself.
|
2337
2360
|
if (renderer && ! col._render) {
|
@@ -3001,8 +3024,8 @@
|
|
3001
3024
|
* @returns
|
3002
3025
|
*/
|
3003
3026
|
function _fnGetRowDisplay (settings, rowIdx) {
|
3004
|
-
|
3005
|
-
|
3027
|
+
var rowModal = settings.aoData[rowIdx];
|
3028
|
+
var columns = settings.aoColumns;
|
3006
3029
|
|
3007
3030
|
if (! rowModal.displayData) {
|
3008
3031
|
// Need to render and cache
|
@@ -3087,6 +3110,9 @@
|
|
3087
3110
|
_fnWriteCell(nTd, display[i]);
|
3088
3111
|
}
|
3089
3112
|
|
3113
|
+
// column class
|
3114
|
+
_addClass(nTd, oCol.sClass);
|
3115
|
+
|
3090
3116
|
// Visibility - add or remove as required
|
3091
3117
|
if ( oCol.bVisible && create )
|
3092
3118
|
{
|
@@ -3186,9 +3212,13 @@
|
|
3186
3212
|
|
3187
3213
|
// Add the number of cells needed to make up to the number of columns
|
3188
3214
|
if (row.length === 1) {
|
3189
|
-
var
|
3215
|
+
var cellCount = 0;
|
3216
|
+
|
3217
|
+
$('td, th', row).each(function () {
|
3218
|
+
cellCount += this.colSpan;
|
3219
|
+
});
|
3190
3220
|
|
3191
|
-
for ( i=
|
3221
|
+
for ( i=cellCount, ien=columns.length ; i<ien ; i++ ) {
|
3192
3222
|
$('<th/>')
|
3193
3223
|
.html( columns[i][titleProp] || '' )
|
3194
3224
|
.appendTo( row );
|
@@ -3200,14 +3230,13 @@
|
|
3200
3230
|
|
3201
3231
|
if (side === 'header') {
|
3202
3232
|
settings.aoHeader = detected;
|
3233
|
+
$('tr', target).addClass(classes.thead.row);
|
3203
3234
|
}
|
3204
3235
|
else {
|
3205
3236
|
settings.aoFooter = detected;
|
3237
|
+
$('tr', target).addClass(classes.tfoot.row);
|
3206
3238
|
}
|
3207
3239
|
|
3208
|
-
// ARIA role for the rows
|
3209
|
-
$(target).children('tr').attr('role', 'row');
|
3210
|
-
|
3211
3240
|
// Every cell needs to be passed through the renderer
|
3212
3241
|
$(target).children('tr').children('th, td')
|
3213
3242
|
.each( function () {
|
@@ -3375,7 +3404,13 @@
|
|
3375
3404
|
oSettings.bDrawing = true;
|
3376
3405
|
|
3377
3406
|
/* Server-side processing draw intercept */
|
3378
|
-
if (
|
3407
|
+
if ( oSettings.deferLoading )
|
3408
|
+
{
|
3409
|
+
oSettings.deferLoading = false;
|
3410
|
+
oSettings.iDraw++;
|
3411
|
+
_fnProcessingDisplay( oSettings, false );
|
3412
|
+
}
|
3413
|
+
else if ( !bServerSide )
|
3379
3414
|
{
|
3380
3415
|
oSettings.iDraw++;
|
3381
3416
|
}
|
@@ -3412,7 +3447,6 @@
|
|
3412
3447
|
var td = aoData.anCells[i];
|
3413
3448
|
|
3414
3449
|
_addClass(td, _ext.type.className[col.sType]); // auto class
|
3415
|
-
_addClass(td, col.sClass); // column class
|
3416
3450
|
_addClass(td, oSettings.oClasses.tbody.cell); // all cells
|
3417
3451
|
}
|
3418
3452
|
|
@@ -3476,6 +3510,9 @@
|
|
3476
3510
|
filter = features.bFilter;
|
3477
3511
|
|
3478
3512
|
if (recompute === undefined || recompute === true) {
|
3513
|
+
// Resolve any column types that are unknown due to addition or invalidation
|
3514
|
+
_fnColumnTypes( settings );
|
3515
|
+
|
3479
3516
|
if ( sort ) {
|
3480
3517
|
_fnSort( settings );
|
3481
3518
|
}
|
@@ -3531,113 +3568,154 @@
|
|
3531
3568
|
|
3532
3569
|
|
3533
3570
|
/**
|
3534
|
-
*
|
3535
|
-
* for the renderer. This is done twice, once for above and once for below
|
3536
|
-
* the table. Ordering must also be considered.
|
3537
|
-
*
|
3538
|
-
* @param {*} settings DataTables settings object
|
3539
|
-
* @param {*} layout Layout object to convert
|
3540
|
-
* @param {string} side `top` or `bottom`
|
3541
|
-
* @returns Converted array structure - one item for each row.
|
3571
|
+
* Expand the layout items into an object for the rendering function
|
3542
3572
|
*/
|
3543
|
-
function
|
3544
|
-
|
3545
|
-
|
3546
|
-
|
3547
|
-
// Combine into like groups (e.g. `top`, `top2`, etc)
|
3548
|
-
$.each( layout, function ( pos, val ) {
|
3549
|
-
if (val === null) {
|
3550
|
-
return;
|
3573
|
+
function _layoutItems (row, align, items) {
|
3574
|
+
if ( Array.isArray(items)) {
|
3575
|
+
for (var i=0 ; i<items.length ; i++) {
|
3576
|
+
_layoutItems(row, align, items[i]);
|
3551
3577
|
}
|
3552
3578
|
|
3553
|
-
|
3579
|
+
return;
|
3580
|
+
}
|
3554
3581
|
|
3555
|
-
|
3556
|
-
groups[ splitPos[0] ] = {};
|
3557
|
-
}
|
3582
|
+
var rowCell = row[align];
|
3558
3583
|
|
3559
|
-
|
3560
|
-
|
3561
|
-
|
3562
|
-
|
3563
|
-
|
3564
|
-
|
3565
|
-
if ( $.isPlainObject( innerVal ) ) {
|
3566
|
-
Object.keys(innerVal).map(function (key) {
|
3567
|
-
contents.push( {
|
3568
|
-
feature: key,
|
3569
|
-
opts: innerVal[key]
|
3570
|
-
});
|
3571
|
-
});
|
3584
|
+
// If it is an object, then there can be multiple features contained in it
|
3585
|
+
if ( $.isPlainObject( items ) ) {
|
3586
|
+
// A feature plugin cannot be named "features" due to this check
|
3587
|
+
if (items.features) {
|
3588
|
+
if (items.rowId) {
|
3589
|
+
row.id = items.rowId;
|
3572
3590
|
}
|
3573
|
-
|
3574
|
-
|
3591
|
+
if (items.rowClass) {
|
3592
|
+
row.className = items.rowClass;
|
3575
3593
|
}
|
3576
|
-
}
|
3577
3594
|
|
3578
|
-
|
3579
|
-
|
3580
|
-
|
3595
|
+
rowCell.id = items.id;
|
3596
|
+
rowCell.className = items.className;
|
3597
|
+
|
3598
|
+
_layoutItems(row, align, items.features);
|
3581
3599
|
}
|
3600
|
+
else {
|
3601
|
+
Object.keys(items).map(function (key) {
|
3602
|
+
rowCell.contents.push( {
|
3603
|
+
feature: key,
|
3604
|
+
opts: items[key]
|
3605
|
+
});
|
3606
|
+
});
|
3607
|
+
}
|
3608
|
+
}
|
3609
|
+
else {
|
3610
|
+
rowCell.contents.push(items);
|
3611
|
+
}
|
3612
|
+
}
|
3613
|
+
|
3614
|
+
/**
|
3615
|
+
* Find, or create a layout row
|
3616
|
+
*/
|
3617
|
+
function _layoutGetRow(rows, rowNum, align) {
|
3618
|
+
var row;
|
3619
|
+
|
3620
|
+
// Find existing rows
|
3621
|
+
for (var i=0; i<rows.length; i++) {
|
3622
|
+
row = rows[i];
|
3582
3623
|
|
3583
|
-
|
3584
|
-
|
3585
|
-
|
3586
|
-
|
3624
|
+
if (row.rowNum === rowNum) {
|
3625
|
+
// full is on its own, but start and end share a row
|
3626
|
+
if (
|
3627
|
+
(align === 'full' && row.full) ||
|
3628
|
+
((align === 'start' || align === 'end') && (row.start || row.end))
|
3629
|
+
) {
|
3630
|
+
if (! row[align]) {
|
3631
|
+
row[align] = {
|
3632
|
+
contents: []
|
3633
|
+
};
|
3634
|
+
}
|
3635
|
+
|
3636
|
+
return row;
|
3587
3637
|
}
|
3588
3638
|
}
|
3589
|
-
|
3590
|
-
|
3639
|
+
}
|
3640
|
+
|
3641
|
+
// If we get this far, then there was no match, create a new row
|
3642
|
+
row = {
|
3643
|
+
rowNum: rowNum
|
3644
|
+
};
|
3645
|
+
|
3646
|
+
row[align] = {
|
3647
|
+
contents: []
|
3648
|
+
};
|
3649
|
+
|
3650
|
+
rows.push(row);
|
3651
|
+
|
3652
|
+
return row;
|
3653
|
+
}
|
3654
|
+
|
3655
|
+
/**
|
3656
|
+
* Convert a `layout` object given by a user to the object structure needed
|
3657
|
+
* for the renderer. This is done twice, once for above and once for below
|
3658
|
+
* the table. Ordering must also be considered.
|
3659
|
+
*
|
3660
|
+
* @param {*} settings DataTables settings object
|
3661
|
+
* @param {*} layout Layout object to convert
|
3662
|
+
* @param {string} side `top` or `bottom`
|
3663
|
+
* @returns Converted array structure - one item for each row.
|
3664
|
+
*/
|
3665
|
+
function _layoutArray ( settings, layout, side ) {
|
3666
|
+
var rows = [];
|
3667
|
+
|
3668
|
+
// Split out into an array
|
3669
|
+
$.each( layout, function ( pos, items ) {
|
3670
|
+
if (items === null) {
|
3671
|
+
return;
|
3591
3672
|
}
|
3592
3673
|
|
3593
|
-
|
3594
|
-
|
3595
|
-
|
3674
|
+
var parts = pos.match(/^([a-z]+)([0-9]*)([A-Za-z]*)$/);
|
3675
|
+
var rowNum = parts[2]
|
3676
|
+
? parts[2] * 1
|
3677
|
+
: 0;
|
3678
|
+
var align = parts[3]
|
3679
|
+
? parts[3].toLowerCase()
|
3680
|
+
: 'full';
|
3681
|
+
|
3682
|
+
// Filter out the side we aren't interested in
|
3683
|
+
if (parts[1] !== side) {
|
3684
|
+
return;
|
3596
3685
|
}
|
3597
|
-
} );
|
3598
3686
|
|
3599
|
-
|
3600
|
-
|
3601
|
-
// Filter to only the side we need
|
3602
|
-
if ( pos.indexOf(side) !== 0 ) {
|
3603
|
-
return null;
|
3604
|
-
}
|
3687
|
+
// Get or create the row we should attach to
|
3688
|
+
var row = _layoutGetRow(rows, rowNum, align);
|
3605
3689
|
|
3606
|
-
|
3607
|
-
|
3608
|
-
val: groups[pos]
|
3609
|
-
};
|
3610
|
-
} )
|
3611
|
-
.filter( function (item) {
|
3612
|
-
return item !== null;
|
3613
|
-
});
|
3690
|
+
_layoutItems(row, align, items);
|
3691
|
+
});
|
3614
3692
|
|
3615
3693
|
// Order by item identifier
|
3616
|
-
|
3617
|
-
var order1 = a.
|
3618
|
-
var order2 = b.
|
3694
|
+
rows.sort( function ( a, b ) {
|
3695
|
+
var order1 = a.rowNum;
|
3696
|
+
var order2 = b.rowNum;
|
3697
|
+
|
3698
|
+
// If both in the same row, then the row with `full` comes first
|
3699
|
+
if (order1 === order2) {
|
3700
|
+
var ret = a.full && ! b.full ? -1 : 1;
|
3701
|
+
|
3702
|
+
return side === 'bottom'
|
3703
|
+
? ret * -1
|
3704
|
+
: ret;
|
3705
|
+
}
|
3619
3706
|
|
3620
3707
|
return order2 - order1;
|
3621
3708
|
} );
|
3622
|
-
|
3709
|
+
|
3710
|
+
// Invert for below the table
|
3623
3711
|
if ( side === 'bottom' ) {
|
3624
|
-
|
3712
|
+
rows.reverse();
|
3625
3713
|
}
|
3626
3714
|
|
3627
|
-
|
3628
|
-
|
3629
|
-
for ( var i=0, ien=filtered.length ; i<ien ; i++ ) {
|
3630
|
-
if ( filtered[i].val.full ) {
|
3631
|
-
rows.push( { full: filtered[i].val.full } );
|
3632
|
-
_layoutResolve( settings, rows[ rows.length - 1 ] );
|
3633
|
-
|
3634
|
-
delete filtered[i].val.full;
|
3635
|
-
}
|
3715
|
+
for (var row = 0; row<rows.length; row++) {
|
3716
|
+
delete rows[row].rowNum;
|
3636
3717
|
|
3637
|
-
|
3638
|
-
rows.push( filtered[i].val );
|
3639
|
-
_layoutResolve( settings, rows[ rows.length - 1 ] );
|
3640
|
-
}
|
3718
|
+
_layoutResolve(settings, rows[row]);
|
3641
3719
|
}
|
3642
3720
|
|
3643
3721
|
return rows;
|
@@ -3661,6 +3739,10 @@
|
|
3661
3739
|
};
|
3662
3740
|
|
3663
3741
|
var resolve = function ( item ) {
|
3742
|
+
if (! row[ item ]) {
|
3743
|
+
return;
|
3744
|
+
}
|
3745
|
+
|
3664
3746
|
var line = row[ item ].contents;
|
3665
3747
|
|
3666
3748
|
for ( var i=0, ien=line.length ; i<ien ; i++ ) {
|
@@ -3688,9 +3770,9 @@
|
|
3688
3770
|
}
|
3689
3771
|
};
|
3690
3772
|
|
3691
|
-
|
3692
|
-
|
3693
|
-
|
3773
|
+
resolve('start');
|
3774
|
+
resolve('end');
|
3775
|
+
resolve('full');
|
3694
3776
|
}
|
3695
3777
|
|
3696
3778
|
|
@@ -4023,6 +4105,17 @@
|
|
4023
4105
|
_fnLog( oSettings, 0, error );
|
4024
4106
|
}
|
4025
4107
|
|
4108
|
+
// Microsoft often wrap JSON as a string in another JSON object
|
4109
|
+
// Let's handle that automatically
|
4110
|
+
if (json.d && typeof json.d === 'string') {
|
4111
|
+
try {
|
4112
|
+
json = JSON.parse(json.d);
|
4113
|
+
}
|
4114
|
+
catch (e) {
|
4115
|
+
// noop
|
4116
|
+
}
|
4117
|
+
}
|
4118
|
+
|
4026
4119
|
oSettings.json = json;
|
4027
4120
|
|
4028
4121
|
_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR], true );
|
@@ -4099,11 +4192,11 @@
|
|
4099
4192
|
else {
|
4100
4193
|
// Object to extend the base settings
|
4101
4194
|
oSettings.jqXHR = $.ajax( baseAjax );
|
4195
|
+
}
|
4102
4196
|
|
4103
|
-
|
4104
|
-
|
4105
|
-
|
4106
|
-
}
|
4197
|
+
// Restore for next time around
|
4198
|
+
if ( ajaxData ) {
|
4199
|
+
ajax.data = ajaxData;
|
4107
4200
|
}
|
4108
4201
|
}
|
4109
4202
|
|
@@ -4234,6 +4327,7 @@
|
|
4234
4327
|
}
|
4235
4328
|
settings.aiDisplay = settings.aiDisplayMaster.slice();
|
4236
4329
|
|
4330
|
+
_fnColumnTypes(settings);
|
4237
4331
|
_fnDraw( settings, true );
|
4238
4332
|
_fnInitComplete( settings );
|
4239
4333
|
_fnProcessingDisplay( settings, false );
|
@@ -4328,10 +4422,6 @@
|
|
4328
4422
|
{
|
4329
4423
|
var columnsSearch = settings.aoPreSearchCols;
|
4330
4424
|
|
4331
|
-
// Resolve any column types that are unknown due to addition or invalidation
|
4332
|
-
// @todo As per sort - can this be moved into an event handler?
|
4333
|
-
_fnColumnTypes( settings );
|
4334
|
-
|
4335
4425
|
// In server-side processing all filtering is done by the server, so no point hanging around here
|
4336
4426
|
if ( _fnDataSource( settings ) != 'ssp' )
|
4337
4427
|
{
|
@@ -4407,7 +4497,7 @@
|
|
4407
4497
|
// So the array reference doesn't break set the results into the
|
4408
4498
|
// existing array
|
4409
4499
|
displayRows.length = 0;
|
4410
|
-
|
4500
|
+
_fnArrayApply(displayRows, rows);
|
4411
4501
|
}
|
4412
4502
|
}
|
4413
4503
|
|
@@ -4636,66 +4726,90 @@
|
|
4636
4726
|
*/
|
4637
4727
|
function _fnInitialise ( settings )
|
4638
4728
|
{
|
4639
|
-
var i
|
4729
|
+
var i;
|
4730
|
+
var init = settings.oInit;
|
4731
|
+
var deferLoading = settings.deferLoading;
|
4732
|
+
var dataSrc = _fnDataSource( settings );
|
4640
4733
|
|
4641
|
-
|
4734
|
+
// Ensure that the table data is fully initialised
|
4642
4735
|
if ( ! settings.bInitialised ) {
|
4643
4736
|
setTimeout( function(){ _fnInitialise( settings ); }, 200 );
|
4644
4737
|
return;
|
4645
4738
|
}
|
4646
4739
|
|
4647
|
-
|
4740
|
+
// Build the header / footer for the table
|
4648
4741
|
_fnBuildHead( settings, 'header' );
|
4649
4742
|
_fnBuildHead( settings, 'footer' );
|
4650
|
-
_fnDrawHead( settings, settings.aoHeader );
|
4651
|
-
_fnDrawHead( settings, settings.aoFooter );
|
4652
4743
|
|
4653
|
-
//
|
4654
|
-
|
4655
|
-
|
4744
|
+
// Load the table's state (if needed) and then render around it and draw
|
4745
|
+
_fnLoadState( settings, init, function () {
|
4746
|
+
// Then draw the header / footer
|
4747
|
+
_fnDrawHead( settings, settings.aoHeader );
|
4748
|
+
_fnDrawHead( settings, settings.aoFooter );
|
4656
4749
|
|
4657
|
-
|
4750
|
+
// Cache the paging start point, as the first redraw will reset it
|
4751
|
+
var iAjaxStart = settings.iInitDisplayStart
|
4658
4752
|
|
4659
|
-
|
4660
|
-
|
4753
|
+
// Local data load
|
4754
|
+
// Check if there is data passing into the constructor
|
4755
|
+
if ( init.aaData ) {
|
4756
|
+
for ( i=0 ; i<init.aaData.length ; i++ ) {
|
4757
|
+
_fnAddData( settings, init.aaData[ i ] );
|
4758
|
+
}
|
4759
|
+
}
|
4760
|
+
else if ( deferLoading || dataSrc == 'dom' ) {
|
4761
|
+
// Grab the data from the page
|
4762
|
+
_fnAddTr( settings, $(settings.nTBody).children('tr') );
|
4763
|
+
}
|
4661
4764
|
|
4662
|
-
|
4765
|
+
// Filter not yet applied - copy the display master
|
4766
|
+
settings.aiDisplay = settings.aiDisplayMaster.slice();
|
4663
4767
|
|
4664
|
-
|
4665
|
-
|
4666
|
-
|
4667
|
-
// data (show 'loading' message possibly)
|
4668
|
-
_fnReDraw( settings );
|
4768
|
+
// Enable features
|
4769
|
+
_fnAddOptionsHtml( settings );
|
4770
|
+
_fnSortInit( settings );
|
4669
4771
|
|
4670
|
-
|
4772
|
+
_colGroup( settings );
|
4671
4773
|
|
4672
|
-
|
4673
|
-
|
4674
|
-
// if there is an ajax source load the data
|
4675
|
-
if ( dataSrc == 'ajax' ) {
|
4676
|
-
_fnBuildAjax( settings, {}, function(json) {
|
4677
|
-
var aData = _fnAjaxDataSrc( settings, json );
|
4774
|
+
/* Okay to show that something is going on now */
|
4775
|
+
_fnProcessingDisplay( settings, true );
|
4678
4776
|
|
4679
|
-
|
4680
|
-
for ( i=0 ; i<aData.length ; i++ ) {
|
4681
|
-
_fnAddData( settings, aData[i] );
|
4682
|
-
}
|
4777
|
+
_fnCallbackFire( settings, null, 'preInit', [settings], true );
|
4683
4778
|
|
4684
|
-
|
4685
|
-
|
4686
|
-
|
4687
|
-
|
4779
|
+
// If there is default sorting required - let's do it. The sort function
|
4780
|
+
// will do the drawing for us. Otherwise we draw the table regardless of the
|
4781
|
+
// Ajax source - this allows the table to look initialised for Ajax sourcing
|
4782
|
+
// data (show 'loading' message possibly)
|
4783
|
+
_fnReDraw( settings );
|
4688
4784
|
|
4689
|
-
|
4690
|
-
|
4785
|
+
// Server-side processing init complete is done by _fnAjaxUpdateDraw
|
4786
|
+
if ( dataSrc != 'ssp' || deferLoading ) {
|
4787
|
+
// if there is an ajax source load the data
|
4788
|
+
if ( dataSrc == 'ajax' ) {
|
4789
|
+
_fnBuildAjax( settings, {}, function(json) {
|
4790
|
+
var aData = _fnAjaxDataSrc( settings, json );
|
4791
|
+
|
4792
|
+
// Got the data - add it to the table
|
4793
|
+
for ( i=0 ; i<aData.length ; i++ ) {
|
4794
|
+
_fnAddData( settings, aData[i] );
|
4795
|
+
}
|
4796
|
+
|
4797
|
+
// Reset the init display for cookie saving. We've already done
|
4798
|
+
// a filter, and therefore cleared it before. So we need to make
|
4799
|
+
// it appear 'fresh'
|
4800
|
+
settings.iInitDisplayStart = iAjaxStart;
|
4801
|
+
|
4802
|
+
_fnReDraw( settings );
|
4803
|
+
_fnProcessingDisplay( settings, false );
|
4804
|
+
_fnInitComplete( settings );
|
4805
|
+
}, settings );
|
4806
|
+
}
|
4807
|
+
else {
|
4691
4808
|
_fnInitComplete( settings );
|
4692
|
-
|
4693
|
-
|
4694
|
-
else {
|
4695
|
-
_fnInitComplete( settings );
|
4696
|
-
_fnProcessingDisplay( settings, false );
|
4809
|
+
_fnProcessingDisplay( settings, false );
|
4810
|
+
}
|
4697
4811
|
}
|
4698
|
-
}
|
4812
|
+
} );
|
4699
4813
|
}
|
4700
4814
|
|
4701
4815
|
|
@@ -4850,8 +4964,37 @@
|
|
4850
4964
|
*/
|
4851
4965
|
function _fnProcessingDisplay ( settings, show )
|
4852
4966
|
{
|
4967
|
+
// Ignore cases when we are still redrawing
|
4968
|
+
if (settings.bDrawing && show === false) {
|
4969
|
+
return;
|
4970
|
+
}
|
4971
|
+
|
4853
4972
|
_fnCallbackFire( settings, null, 'processing', [settings, show] );
|
4854
4973
|
}
|
4974
|
+
|
4975
|
+
/**
|
4976
|
+
* Show the processing element if an action takes longer than a given time
|
4977
|
+
*
|
4978
|
+
* @param {*} settings DataTables settings object
|
4979
|
+
* @param {*} enable Do (true) or not (false) async processing (local feature enablement)
|
4980
|
+
* @param {*} run Function to run
|
4981
|
+
*/
|
4982
|
+
function _fnProcessingRun( settings, enable, run ) {
|
4983
|
+
if (! enable) {
|
4984
|
+
// Immediate execution, synchronous
|
4985
|
+
run();
|
4986
|
+
}
|
4987
|
+
else {
|
4988
|
+
_fnProcessingDisplay(settings, true);
|
4989
|
+
|
4990
|
+
// Allow the processing display to show if needed
|
4991
|
+
setTimeout(function () {
|
4992
|
+
run();
|
4993
|
+
|
4994
|
+
_fnProcessingDisplay(settings, false);
|
4995
|
+
}, 0);
|
4996
|
+
}
|
4997
|
+
}
|
4855
4998
|
/**
|
4856
4999
|
* Add any control elements for the table - specifically scrolling
|
4857
5000
|
* @param {object} settings dataTables settings object
|
@@ -5078,21 +5221,44 @@
|
|
5078
5221
|
// is because of Responsive which might remove `col` elements, knocking the alignment
|
5079
5222
|
// of the indexes out.
|
5080
5223
|
if (settings.aiDisplay.length) {
|
5081
|
-
// Get the column sizes from the first row in the table
|
5082
|
-
|
5083
|
-
|
5084
|
-
|
5085
|
-
|
5224
|
+
// Get the column sizes from the first row in the table. This should really be a
|
5225
|
+
// [].find, but it wasn't supported in Chrome until Sept 2015, and DT has 10 year
|
5226
|
+
// browser support
|
5227
|
+
var firstTr = null;
|
5228
|
+
var start = _fnDataSource( settings ) !== 'ssp'
|
5229
|
+
? settings._iDisplayStart
|
5230
|
+
: 0;
|
5231
|
+
|
5232
|
+
for (i=start ; i<start + settings.aiDisplay.length ; i++) {
|
5233
|
+
var idx = settings.aiDisplay[i];
|
5234
|
+
var tr = settings.aoData[idx].nTr;
|
5235
|
+
|
5236
|
+
if (tr) {
|
5237
|
+
firstTr = tr;
|
5238
|
+
break;
|
5086
5239
|
}
|
5087
|
-
}
|
5240
|
+
}
|
5241
|
+
|
5242
|
+
if (firstTr) {
|
5243
|
+
var colSizes = $(firstTr).children('th, td').map(function (vis) {
|
5244
|
+
return {
|
5245
|
+
idx: _fnVisibleToColumnIndex(settings, vis),
|
5246
|
+
width: $(this).outerWidth()
|
5247
|
+
};
|
5248
|
+
});
|
5249
|
+
|
5250
|
+
// Check against what the colgroup > col is set to and correct if needed
|
5251
|
+
for (var i=0 ; i<colSizes.length ; i++) {
|
5252
|
+
var colEl = settings.aoColumns[ colSizes[i].idx ].colEl[0];
|
5253
|
+
var colWidth = colEl.style.width.replace('px', '');
|
5088
5254
|
|
5089
|
-
|
5090
|
-
|
5091
|
-
var colEl = settings.aoColumns[ colSizes[i].idx ].colEl[0];
|
5092
|
-
var colWidth = colEl.style.width.replace('px', '');
|
5255
|
+
if (colWidth !== colSizes[i].width) {
|
5256
|
+
colEl.style.width = colSizes[i].width + 'px';
|
5093
5257
|
|
5094
|
-
|
5095
|
-
|
5258
|
+
if (scroll.sX) {
|
5259
|
+
colEl.style.minWidth = colSizes[i].width + 'px';
|
5260
|
+
}
|
5261
|
+
}
|
5096
5262
|
}
|
5097
5263
|
}
|
5098
5264
|
}
|
@@ -5182,8 +5348,25 @@
|
|
5182
5348
|
tableWidthAttr = table.getAttribute('width'), // from DOM element
|
5183
5349
|
tableContainer = table.parentNode,
|
5184
5350
|
i, column, columnIdx;
|
5351
|
+
|
5352
|
+
var styleWidth = table.style.width;
|
5353
|
+
var containerWidth = _fnWrapperWidth(settings);
|
5354
|
+
|
5355
|
+
// Don't re-run for the same width as the last time
|
5356
|
+
if (containerWidth === settings.containerWidth) {
|
5357
|
+
return false;
|
5358
|
+
}
|
5359
|
+
|
5360
|
+
settings.containerWidth = containerWidth;
|
5361
|
+
|
5362
|
+
// If there is no width applied as a CSS style or as an attribute, we assume that
|
5363
|
+
// the width is intended to be 100%, which is usually is in CSS, but it is very
|
5364
|
+
// difficult to correctly parse the rules to get the final result.
|
5365
|
+
if ( ! styleWidth && ! tableWidthAttr) {
|
5366
|
+
table.style.width = '100%';
|
5367
|
+
styleWidth = '100%';
|
5368
|
+
}
|
5185
5369
|
|
5186
|
-
var styleWidth = table.style.width;
|
5187
5370
|
if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
|
5188
5371
|
tableWidthAttr = styleWidth;
|
5189
5372
|
}
|
@@ -5232,6 +5415,8 @@
|
|
5232
5415
|
// browser will collapse it. If this width is smaller than the
|
5233
5416
|
// width the column requires, then it will have no effect
|
5234
5417
|
if ( scrollX ) {
|
5418
|
+
this.style.minWidth = width;
|
5419
|
+
|
5235
5420
|
$( this ).append( $('<div/>').css( {
|
5236
5421
|
width: width,
|
5237
5422
|
margin: 0,
|
@@ -5300,15 +5485,15 @@
|
|
5300
5485
|
|
5301
5486
|
// If there is no width attribute or style, then allow the table to
|
5302
5487
|
// collapse
|
5303
|
-
if ( tmpTable.
|
5304
|
-
tmpTable.
|
5488
|
+
if ( tmpTable.outerWidth() < tableContainer.clientWidth && tableWidthAttr ) {
|
5489
|
+
tmpTable.outerWidth( tableContainer.clientWidth );
|
5305
5490
|
}
|
5306
5491
|
}
|
5307
5492
|
else if ( scrollY ) {
|
5308
|
-
tmpTable.
|
5493
|
+
tmpTable.outerWidth( tableContainer.clientWidth );
|
5309
5494
|
}
|
5310
5495
|
else if ( tableWidthAttr ) {
|
5311
|
-
tmpTable.
|
5496
|
+
tmpTable.outerWidth( tableWidthAttr );
|
5312
5497
|
}
|
5313
5498
|
|
5314
5499
|
// Get the width of each column in the constructed table
|
@@ -5341,20 +5526,64 @@
|
|
5341
5526
|
}
|
5342
5527
|
|
5343
5528
|
if ( (tableWidthAttr || scrollX) && ! settings._reszEvt ) {
|
5344
|
-
var
|
5345
|
-
|
5346
|
-
|
5347
|
-
|
5529
|
+
var resize = DataTable.util.throttle( function () {
|
5530
|
+
var newWidth = _fnWrapperWidth(settings);
|
5531
|
+
|
5532
|
+
// Don't do it if destroying or the container width is 0
|
5533
|
+
if (! settings.bDestroying && newWidth !== 0) {
|
5534
|
+
_fnAdjustColumnSizing( settings );
|
5535
|
+
}
|
5536
|
+
} );
|
5537
|
+
|
5538
|
+
// For browsers that support it (~2020 onwards for wide support) we can watch for the
|
5539
|
+
// container changing width.
|
5540
|
+
if (window.ResizeObserver) {
|
5541
|
+
// This is a tricky beast - if the element is visible when `.observe()` is called,
|
5542
|
+
// then the callback is immediately run. Which we don't want. If the element isn't
|
5543
|
+
// visible, then it isn't run, but we want it to run when it is then made visible.
|
5544
|
+
// This flag allows the above to be satisfied.
|
5545
|
+
var first = $(settings.nTableWrapper).is(':visible');
|
5546
|
+
|
5547
|
+
// Use an empty div to attach the observer so it isn't impacted by height changes
|
5548
|
+
var resizer = $('<div>')
|
5549
|
+
.css({
|
5550
|
+
width: '100%',
|
5551
|
+
height: 0
|
5552
|
+
})
|
5553
|
+
.addClass('dt-autosize')
|
5554
|
+
.appendTo(settings.nTableWrapper);
|
5555
|
+
|
5556
|
+
settings.resizeObserver = new ResizeObserver(function (e) {
|
5557
|
+
if (first) {
|
5558
|
+
first = false;
|
5348
5559
|
}
|
5349
|
-
|
5350
|
-
|
5560
|
+
else {
|
5561
|
+
resize();
|
5562
|
+
}
|
5563
|
+
});
|
5351
5564
|
|
5352
|
-
|
5565
|
+
settings.resizeObserver.observe(resizer[0]);
|
5566
|
+
}
|
5567
|
+
else {
|
5568
|
+
// For old browsers, the best we can do is listen for a window resize
|
5569
|
+
$(window).on('resize.DT-'+settings.sInstance, resize);
|
5570
|
+
}
|
5353
5571
|
|
5354
5572
|
settings._reszEvt = true;
|
5355
5573
|
}
|
5356
5574
|
}
|
5357
5575
|
|
5576
|
+
/**
|
5577
|
+
* Get the width of the DataTables wrapper element
|
5578
|
+
*
|
5579
|
+
* @param {*} settings DataTables settings object
|
5580
|
+
* @returns Width
|
5581
|
+
*/
|
5582
|
+
function _fnWrapperWidth(settings) {
|
5583
|
+
return $(settings.nTableWrapper).is(':visible')
|
5584
|
+
? $(settings.nTableWrapper).width()
|
5585
|
+
: 0;
|
5586
|
+
}
|
5358
5587
|
|
5359
5588
|
/**
|
5360
5589
|
* Get the maximum strlen for each data column
|
@@ -5497,22 +5726,16 @@
|
|
5497
5726
|
}
|
5498
5727
|
|
5499
5728
|
if (run) {
|
5500
|
-
|
5501
|
-
|
5502
|
-
// Allow the processing display to show
|
5503
|
-
setTimeout( function () {
|
5729
|
+
_fnProcessingRun(settings, true, function () {
|
5504
5730
|
_fnSort( settings );
|
5505
5731
|
_fnSortDisplay( settings, settings.aiDisplay );
|
5506
5732
|
|
5507
|
-
// Sort processing done - redraw has its own processing display
|
5508
|
-
_fnProcessingDisplay( settings, false );
|
5509
|
-
|
5510
5733
|
_fnReDraw( settings, false, false );
|
5511
5734
|
|
5512
5735
|
if (callback) {
|
5513
5736
|
callback();
|
5514
5737
|
}
|
5515
|
-
}
|
5738
|
+
});
|
5516
5739
|
}
|
5517
5740
|
}
|
5518
5741
|
} );
|
@@ -5671,15 +5894,14 @@
|
|
5671
5894
|
displayMaster = oSettings.aiDisplayMaster,
|
5672
5895
|
aSort;
|
5673
5896
|
|
5674
|
-
//
|
5675
|
-
|
5676
|
-
// data is going to be used in the table?
|
5677
|
-
_fnColumnTypes( oSettings );
|
5897
|
+
// Make sure the columns all have types defined
|
5898
|
+
_fnColumnTypes(oSettings);
|
5678
5899
|
|
5679
5900
|
// Allow a specific column to be sorted, which will _not_ alter the display
|
5680
5901
|
// master
|
5681
5902
|
if (col !== undefined) {
|
5682
5903
|
var srcCol = oSettings.aoColumns[col];
|
5904
|
+
|
5683
5905
|
aSort = [{
|
5684
5906
|
src: col,
|
5685
5907
|
col: col,
|
@@ -5712,7 +5934,7 @@
|
|
5712
5934
|
|
5713
5935
|
// If the first sort is desc, then reverse the array to preserve original
|
5714
5936
|
// order, just in reverse
|
5715
|
-
if (aSort.length && aSort[0].dir === 'desc') {
|
5937
|
+
if (aSort.length && aSort[0].dir === 'desc' && oSettings.orderDescReverse) {
|
5716
5938
|
aiOrig.reverse();
|
5717
5939
|
}
|
5718
5940
|
|
@@ -5782,6 +6004,7 @@
|
|
5782
6004
|
if (col === undefined) {
|
5783
6005
|
// Tell the draw function that we have sorted the data
|
5784
6006
|
oSettings.bSorted = true;
|
6007
|
+
oSettings.sortDetails = aSort;
|
5785
6008
|
|
5786
6009
|
_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort] );
|
5787
6010
|
}
|
@@ -5973,15 +6196,26 @@
|
|
5973
6196
|
return;
|
5974
6197
|
}
|
5975
6198
|
|
6199
|
+
// Sort state saving uses [[idx, order]] structure.
|
6200
|
+
var sorting = [];
|
6201
|
+
_fnSortResolve(settings, sorting, settings.aaSorting );
|
6202
|
+
|
5976
6203
|
/* Store the interesting variables */
|
6204
|
+
var columns = settings.aoColumns;
|
5977
6205
|
var state = {
|
5978
6206
|
time: +new Date(),
|
5979
6207
|
start: settings._iDisplayStart,
|
5980
6208
|
length: settings._iDisplayLength,
|
5981
|
-
order:
|
6209
|
+
order: sorting.map(function (sort) {
|
6210
|
+
// If a column name is available, use it
|
6211
|
+
return columns[sort[0]] && columns[sort[0]].sName
|
6212
|
+
? [ columns[sort[0]].sName, sort[1] ]
|
6213
|
+
: sort.slice();
|
6214
|
+
} ),
|
5982
6215
|
search: $.extend({}, settings.oPreviousSearch),
|
5983
6216
|
columns: settings.aoColumns.map( function ( col, i ) {
|
5984
6217
|
return {
|
6218
|
+
name: col.sName,
|
5985
6219
|
visible: col.bVisible,
|
5986
6220
|
search: $.extend({}, settings.aoPreSearchCols[i])
|
5987
6221
|
};
|
@@ -6029,6 +6263,8 @@
|
|
6029
6263
|
function _fnImplementState ( settings, s, callback) {
|
6030
6264
|
var i, ien;
|
6031
6265
|
var columns = settings.aoColumns;
|
6266
|
+
var currentNames = _pluck(settings.aoColumns, 'sName');
|
6267
|
+
|
6032
6268
|
settings._bLoadingState = true;
|
6033
6269
|
|
6034
6270
|
// When StateRestore was introduced the state could now be implemented at any time
|
@@ -6058,13 +6294,6 @@
|
|
6058
6294
|
return;
|
6059
6295
|
}
|
6060
6296
|
|
6061
|
-
// Number of columns have changed - all bets are off, no restore of settings
|
6062
|
-
if ( s.columns && columns.length !== s.columns.length ) {
|
6063
|
-
settings._bLoadingState = false;
|
6064
|
-
callback();
|
6065
|
-
return;
|
6066
|
-
}
|
6067
|
-
|
6068
6297
|
// Store the saved state so it might be accessed at any time
|
6069
6298
|
settings.oLoadedState = $.extend( true, {}, s );
|
6070
6299
|
|
@@ -6083,8 +6312,7 @@
|
|
6083
6312
|
}
|
6084
6313
|
}
|
6085
6314
|
|
6086
|
-
// Restore key features
|
6087
|
-
// subscribed events
|
6315
|
+
// Restore key features
|
6088
6316
|
if ( s.start !== undefined ) {
|
6089
6317
|
if(api === null) {
|
6090
6318
|
settings._iDisplayStart = s.start;
|
@@ -6099,10 +6327,23 @@
|
|
6099
6327
|
if ( s.order !== undefined ) {
|
6100
6328
|
settings.aaSorting = [];
|
6101
6329
|
$.each( s.order, function ( i, col ) {
|
6102
|
-
|
6103
|
-
|
6104
|
-
|
6105
|
-
)
|
6330
|
+
var set = [ col[0], col[1] ];
|
6331
|
+
|
6332
|
+
// A column name was stored and should be used for restore
|
6333
|
+
if (typeof col[0] === 'string') {
|
6334
|
+
var idx = currentNames.indexOf(col[0]);
|
6335
|
+
|
6336
|
+
// Find the name from the current list of column names, or fallback to index 0
|
6337
|
+
set[0] = idx >= 0
|
6338
|
+
? idx
|
6339
|
+
: 0;
|
6340
|
+
}
|
6341
|
+
else if (set[0] >= columns.length) {
|
6342
|
+
// If a column name, but it is out of bounds, set to 0
|
6343
|
+
set[0] = 0;
|
6344
|
+
}
|
6345
|
+
|
6346
|
+
settings.aaSorting.push(set);
|
6106
6347
|
} );
|
6107
6348
|
}
|
6108
6349
|
|
@@ -6113,31 +6354,65 @@
|
|
6113
6354
|
|
6114
6355
|
// Columns
|
6115
6356
|
if ( s.columns ) {
|
6116
|
-
|
6117
|
-
|
6118
|
-
|
6119
|
-
|
6120
|
-
|
6121
|
-
|
6122
|
-
|
6123
|
-
|
6124
|
-
|
6357
|
+
var set = s.columns;
|
6358
|
+
var incoming = _pluck(s.columns, 'name');
|
6359
|
+
|
6360
|
+
// Check if it is a 2.2 style state object with a `name` property for the columns, and if
|
6361
|
+
// the name was defined. If so, then create a new array that will map the state object
|
6362
|
+
// given, to the current columns (don't bother if they are already matching tho).
|
6363
|
+
if (incoming.join('').length && incoming.join('') !== currentNames.join('')) {
|
6364
|
+
set = [];
|
6365
|
+
|
6366
|
+
// For each column, try to find the name in the incoming array
|
6367
|
+
for (i=0 ; i<currentNames.length ; i++) {
|
6368
|
+
if (currentNames[i] != '') {
|
6369
|
+
var idx = incoming.indexOf(currentNames[i]);
|
6370
|
+
|
6371
|
+
if (idx >= 0) {
|
6372
|
+
set.push(s.columns[idx]);
|
6373
|
+
}
|
6374
|
+
else {
|
6375
|
+
// No matching column name in the state's columns, so this might be a new
|
6376
|
+
// column and thus can't have a state already.
|
6377
|
+
set.push({});
|
6378
|
+
}
|
6125
6379
|
}
|
6126
6380
|
else {
|
6127
|
-
columns
|
6381
|
+
// If no name, but other columns did have a name, then there is no knowing
|
6382
|
+
// where this one came from originally so it can't be restored.
|
6383
|
+
set.push({});
|
6384
|
+
}
|
6385
|
+
}
|
6386
|
+
}
|
6387
|
+
|
6388
|
+
// If the number of columns to restore is different from current, then all bets are off.
|
6389
|
+
if (set.length === columns.length) {
|
6390
|
+
for ( i=0, ien=set.length ; i<ien ; i++ ) {
|
6391
|
+
var col = set[i];
|
6392
|
+
|
6393
|
+
// Visibility
|
6394
|
+
if ( col.visible !== undefined ) {
|
6395
|
+
// If the api is defined, the table has been initialised so we need to use it rather than internal settings
|
6396
|
+
if (api) {
|
6397
|
+
// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
|
6398
|
+
api.column(i).visible(col.visible, false);
|
6399
|
+
}
|
6400
|
+
else {
|
6401
|
+
columns[i].bVisible = col.visible;
|
6402
|
+
}
|
6403
|
+
}
|
6404
|
+
|
6405
|
+
// Search
|
6406
|
+
if ( col.search !== undefined ) {
|
6407
|
+
$.extend( settings.aoPreSearchCols[i], col.search );
|
6128
6408
|
}
|
6129
6409
|
}
|
6130
6410
|
|
6131
|
-
//
|
6132
|
-
if (
|
6133
|
-
|
6411
|
+
// If the api is defined then we need to adjust the columns once the visibility has been changed
|
6412
|
+
if (api) {
|
6413
|
+
api.columns.adjust();
|
6134
6414
|
}
|
6135
6415
|
}
|
6136
|
-
|
6137
|
-
// If the api is defined then we need to adjust the columns once the visibility has been changed
|
6138
|
-
if (api) {
|
6139
|
-
api.columns.adjust();
|
6140
|
-
}
|
6141
6416
|
}
|
6142
6417
|
|
6143
6418
|
settings._bLoadingState = false;
|
@@ -6454,6 +6729,30 @@
|
|
6454
6729
|
replace(/_ENTRIES-TOTAL_/g, settings.api.i18n('entries', '', vis) );
|
6455
6730
|
}
|
6456
6731
|
|
6732
|
+
/**
|
6733
|
+
* Add elements to an array as quickly as possible, but stack stafe.
|
6734
|
+
*
|
6735
|
+
* @param {*} arr Array to add the data to
|
6736
|
+
* @param {*} data Data array that is to be added
|
6737
|
+
* @returns
|
6738
|
+
*/
|
6739
|
+
function _fnArrayApply(arr, data) {
|
6740
|
+
if (! data) {
|
6741
|
+
return;
|
6742
|
+
}
|
6743
|
+
|
6744
|
+
// Chrome can throw a max stack error if apply is called with
|
6745
|
+
// too large an array, but apply is faster.
|
6746
|
+
if (data.length < 10000) {
|
6747
|
+
arr.push.apply(arr, data);
|
6748
|
+
}
|
6749
|
+
else {
|
6750
|
+
for (i=0 ; i<data.length ; i++) {
|
6751
|
+
arr.push(data[i]);
|
6752
|
+
}
|
6753
|
+
}
|
6754
|
+
}
|
6755
|
+
|
6457
6756
|
|
6458
6757
|
|
6459
6758
|
/**
|
@@ -6622,6 +6921,7 @@
|
|
6622
6921
|
return new _Api( context, data );
|
6623
6922
|
}
|
6624
6923
|
|
6924
|
+
var i;
|
6625
6925
|
var settings = [];
|
6626
6926
|
var ctxSettings = function ( o ) {
|
6627
6927
|
var a = _toSettings( o );
|
@@ -6631,7 +6931,7 @@
|
|
6631
6931
|
};
|
6632
6932
|
|
6633
6933
|
if ( Array.isArray( context ) ) {
|
6634
|
-
for (
|
6934
|
+
for ( i=0 ; i<context.length ; i++ ) {
|
6635
6935
|
ctxSettings( context[i] );
|
6636
6936
|
}
|
6637
6937
|
}
|
@@ -6645,9 +6945,7 @@
|
|
6645
6945
|
: settings;
|
6646
6946
|
|
6647
6947
|
// Initial data
|
6648
|
-
|
6649
|
-
this.push.apply(this, data);
|
6650
|
-
}
|
6948
|
+
_fnArrayApply(this, data);
|
6651
6949
|
|
6652
6950
|
// selector
|
6653
6951
|
this.selector = {
|
@@ -7028,7 +7326,7 @@
|
|
7028
7326
|
selector.forEach(function (sel) {
|
7029
7327
|
var inner = __table_selector(sel, a);
|
7030
7328
|
|
7031
|
-
|
7329
|
+
_fnArrayApply(result, inner);
|
7032
7330
|
});
|
7033
7331
|
|
7034
7332
|
return result.filter( function (item) {
|
@@ -7529,7 +7827,7 @@
|
|
7529
7827
|
// Reduce the API instance to the first item found
|
7530
7828
|
var _selector_first = function ( old )
|
7531
7829
|
{
|
7532
|
-
|
7830
|
+
var inst = new _Api(old.context[0]);
|
7533
7831
|
|
7534
7832
|
// Use a push rather than passing to the constructor, since it will
|
7535
7833
|
// merge arrays down automatically, which isn't what is wanted here
|
@@ -7882,7 +8180,7 @@
|
|
7882
8180
|
// Return an Api.rows() extended instance, so rows().nodes() etc can be used
|
7883
8181
|
var modRows = this.rows( -1 );
|
7884
8182
|
modRows.pop();
|
7885
|
-
|
8183
|
+
_fnArrayApply(modRows, newRows);
|
7886
8184
|
|
7887
8185
|
return modRows;
|
7888
8186
|
} );
|
@@ -8336,8 +8634,10 @@
|
|
8336
8634
|
switch( match[2] ) {
|
8337
8635
|
case 'visIdx':
|
8338
8636
|
case 'visible':
|
8339
|
-
|
8637
|
+
// Selector is a column index
|
8638
|
+
if (match[1] && match[1].match(/^\d+$/)) {
|
8340
8639
|
var idx = parseInt( match[1], 10 );
|
8640
|
+
|
8341
8641
|
// Visible index given, convert to column index
|
8342
8642
|
if ( idx < 0 ) {
|
8343
8643
|
// Counting from the right
|
@@ -8350,9 +8650,19 @@
|
|
8350
8650
|
return [ _fnVisibleToColumnIndex( settings, idx ) ];
|
8351
8651
|
}
|
8352
8652
|
|
8353
|
-
|
8354
|
-
|
8355
|
-
|
8653
|
+
return columns.map( function (col, idx) {
|
8654
|
+
// Not visible, can't match
|
8655
|
+
if (! col.bVisible) {
|
8656
|
+
return null;
|
8657
|
+
}
|
8658
|
+
|
8659
|
+
// Selector
|
8660
|
+
if (match[1]) {
|
8661
|
+
return $(nodes[idx]).filter(match[1]).length > 0 ? idx : null;
|
8662
|
+
}
|
8663
|
+
|
8664
|
+
// `:visible` on its own
|
8665
|
+
return idx;
|
8356
8666
|
} );
|
8357
8667
|
|
8358
8668
|
case 'name':
|
@@ -8383,7 +8693,10 @@
|
|
8383
8693
|
.map( function () {
|
8384
8694
|
return _fnColumnsFromHeader( this ); // `nodes` is column index complete and in order
|
8385
8695
|
} )
|
8386
|
-
.toArray()
|
8696
|
+
.toArray()
|
8697
|
+
.sort(function (a, b) {
|
8698
|
+
return a - b;
|
8699
|
+
});
|
8387
8700
|
|
8388
8701
|
if ( jqResult.length || ! s.nodeName ) {
|
8389
8702
|
return jqResult;
|
@@ -8637,6 +8950,10 @@
|
|
8637
8950
|
|
8638
8951
|
_api_register( 'columns.adjust()', function () {
|
8639
8952
|
return this.iterator( 'table', function ( settings ) {
|
8953
|
+
// Force a column sizing to happen with a manual call - otherwise it can skip
|
8954
|
+
// if the size hasn't changed
|
8955
|
+
settings.containerWidth = -1;
|
8956
|
+
|
8640
8957
|
_fnAdjustColumnSizing( settings );
|
8641
8958
|
}, 1 );
|
8642
8959
|
} );
|
@@ -9202,24 +9519,81 @@
|
|
9202
9519
|
} );
|
9203
9520
|
} );
|
9204
9521
|
|
9522
|
+
// Can be assigned in DateTable.use() - note luxon and moment vars are in helpers.js
|
9523
|
+
var __bootstrap;
|
9524
|
+
var __foundation;
|
9525
|
+
|
9205
9526
|
/**
|
9206
|
-
* Set the
|
9207
|
-
*
|
9208
|
-
*
|
9209
|
-
|
9210
|
-
|
9211
|
-
|
9212
|
-
|
9213
|
-
|
9527
|
+
* Set the libraries that DataTables uses, or the global objects.
|
9528
|
+
* Note that the arguments can be either way around (legacy support)
|
9529
|
+
* and the second is optional. See docs.
|
9530
|
+
*/
|
9531
|
+
DataTable.use = function (arg1, arg2) {
|
9532
|
+
// Reverse arguments for legacy support
|
9533
|
+
var module = typeof arg1 === 'string'
|
9534
|
+
? arg2
|
9535
|
+
: arg1;
|
9536
|
+
var type = typeof arg2 === 'string'
|
9537
|
+
? arg2
|
9538
|
+
: arg1;
|
9539
|
+
|
9540
|
+
// Getter
|
9541
|
+
if (module === undefined && typeof type === 'string') {
|
9542
|
+
switch (type) {
|
9543
|
+
case 'lib':
|
9544
|
+
case 'jq':
|
9545
|
+
return $;
|
9546
|
+
|
9547
|
+
case 'win':
|
9548
|
+
return window;
|
9549
|
+
|
9550
|
+
case 'datetime':
|
9551
|
+
return DataTable.DateTime;
|
9552
|
+
|
9553
|
+
case 'luxon':
|
9554
|
+
return __luxon;
|
9555
|
+
|
9556
|
+
case 'moment':
|
9557
|
+
return __moment;
|
9558
|
+
|
9559
|
+
case 'bootstrap':
|
9560
|
+
// Use local if set, otherwise try window, which could be undefined
|
9561
|
+
return __bootstrap || window.bootstrap;
|
9562
|
+
|
9563
|
+
case 'foundation':
|
9564
|
+
// Ditto
|
9565
|
+
return __foundation || window.Foundation;
|
9566
|
+
|
9567
|
+
default:
|
9568
|
+
return null;
|
9569
|
+
}
|
9570
|
+
}
|
9571
|
+
|
9572
|
+
// Setter
|
9573
|
+
if (type === 'lib' || type === 'jq' || (module && module.fn && module.fn.jquery)) {
|
9214
9574
|
$ = module;
|
9215
9575
|
}
|
9216
|
-
else if (type
|
9576
|
+
else if (type === 'win' || (module && module.document)) {
|
9217
9577
|
window = module;
|
9218
9578
|
document = module.document;
|
9219
9579
|
}
|
9220
|
-
else if (type === 'datetime' || module.type === 'DateTime') {
|
9580
|
+
else if (type === 'datetime' || (module && module.type === 'DateTime')) {
|
9221
9581
|
DataTable.DateTime = module;
|
9222
9582
|
}
|
9583
|
+
else if (type === 'luxon' || (module && module.FixedOffsetZone)) {
|
9584
|
+
__luxon = module;
|
9585
|
+
}
|
9586
|
+
else if (type === 'moment' || (module && module.isMoment)) {
|
9587
|
+
__moment = module;
|
9588
|
+
}
|
9589
|
+
else if (type === 'bootstrap' || (module && module.Modal && module.Modal.NAME === 'modal'))
|
9590
|
+
{
|
9591
|
+
// This is currently for BS5 only. BS3/4 attach to jQuery, so no need to use `.use()`
|
9592
|
+
__bootstrap = module;
|
9593
|
+
}
|
9594
|
+
else if (type === 'foundation' || (module && module.Reveal)) {
|
9595
|
+
__foundation = module;
|
9596
|
+
}
|
9223
9597
|
}
|
9224
9598
|
|
9225
9599
|
/**
|
@@ -9471,12 +9845,14 @@
|
|
9471
9845
|
// Function to run either once the table becomes ready or
|
9472
9846
|
// immediately if it is already ready.
|
9473
9847
|
return this.tables().every(function () {
|
9848
|
+
var api = this;
|
9849
|
+
|
9474
9850
|
if (this.context[0]._bInitComplete) {
|
9475
|
-
fn.call(
|
9851
|
+
fn.call(api);
|
9476
9852
|
}
|
9477
9853
|
else {
|
9478
|
-
this.on('init', function () {
|
9479
|
-
fn.call(
|
9854
|
+
this.on('init.dt.DT', function () {
|
9855
|
+
fn.call(api);
|
9480
9856
|
});
|
9481
9857
|
}
|
9482
9858
|
} );
|
@@ -9510,6 +9886,11 @@
|
|
9510
9886
|
new _Api( settings ).columns().visible( true );
|
9511
9887
|
}
|
9512
9888
|
|
9889
|
+
// Container width change listener
|
9890
|
+
if (settings.resizeObserver) {
|
9891
|
+
settings.resizeObserver.disconnect();
|
9892
|
+
}
|
9893
|
+
|
9513
9894
|
// Blitz all `DT` namespaced events (these are internal events, the
|
9514
9895
|
// lowercase, `dt` events are user subscribed and they are responsible
|
9515
9896
|
// for removing them
|
@@ -9527,20 +9908,37 @@
|
|
9527
9908
|
jqTable.append( tfoot );
|
9528
9909
|
}
|
9529
9910
|
|
9911
|
+
// Clean up the header
|
9912
|
+
$(thead).find('span.dt-column-order').remove();
|
9913
|
+
$(thead).find('span.dt-column-title').each(function () {
|
9914
|
+
var title = $(this).html();
|
9915
|
+
$(this).parent().append(title);
|
9916
|
+
$(this).remove();
|
9917
|
+
});
|
9918
|
+
|
9530
9919
|
settings.colgroup.remove();
|
9531
9920
|
|
9532
9921
|
settings.aaSorting = [];
|
9533
9922
|
settings.aaSortingFixed = [];
|
9534
9923
|
_fnSortingClasses( settings );
|
9535
9924
|
|
9925
|
+
$(jqTable).find('th, td').removeClass(
|
9926
|
+
$.map(DataTable.ext.type.className, function (v) {
|
9927
|
+
return v;
|
9928
|
+
}).join(' ')
|
9929
|
+
);
|
9930
|
+
|
9536
9931
|
$('th, td', thead)
|
9537
9932
|
.removeClass(
|
9933
|
+
orderClasses.none + ' ' +
|
9538
9934
|
orderClasses.canAsc + ' ' +
|
9539
9935
|
orderClasses.canDesc + ' ' +
|
9540
9936
|
orderClasses.isAsc + ' ' +
|
9541
9937
|
orderClasses.isDesc
|
9542
9938
|
)
|
9543
|
-
.css('width', '')
|
9939
|
+
.css('width', '')
|
9940
|
+
.removeAttr('data-dt-column')
|
9941
|
+
.removeAttr('aria-sort');
|
9544
9942
|
|
9545
9943
|
// Add the TR elements back into the table in their original order
|
9546
9944
|
jqTbody.children().detach();
|
@@ -9628,7 +10026,7 @@
|
|
9628
10026
|
* @type string
|
9629
10027
|
* @default Version number
|
9630
10028
|
*/
|
9631
|
-
DataTable.version = "2.
|
10029
|
+
DataTable.version = "2.2.2";
|
9632
10030
|
|
9633
10031
|
/**
|
9634
10032
|
* Private data store, containing all of the settings objects that are
|
@@ -10473,7 +10871,8 @@
|
|
10473
10871
|
first: 'First',
|
10474
10872
|
last: 'Last',
|
10475
10873
|
next: 'Next',
|
10476
|
-
previous: 'Previous'
|
10874
|
+
previous: 'Previous',
|
10875
|
+
number: ''
|
10477
10876
|
}
|
10478
10877
|
},
|
10479
10878
|
|
@@ -10653,6 +11052,10 @@
|
|
10653
11052
|
},
|
10654
11053
|
|
10655
11054
|
|
11055
|
+
/** The initial data order is reversed when `desc` ordering */
|
11056
|
+
orderDescReverse: true,
|
11057
|
+
|
11058
|
+
|
10656
11059
|
/**
|
10657
11060
|
* This parameter allows you to have define the global filtering state at
|
10658
11061
|
* initialisation time. As an object the `search` parameter must be
|
@@ -10701,7 +11104,7 @@
|
|
10701
11104
|
* * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
|
10702
11105
|
* * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
|
10703
11106
|
*/
|
10704
|
-
"sPaginationType": "
|
11107
|
+
"sPaginationType": "",
|
10705
11108
|
|
10706
11109
|
|
10707
11110
|
/**
|
@@ -10771,7 +11174,13 @@
|
|
10771
11174
|
/**
|
10772
11175
|
* Caption value
|
10773
11176
|
*/
|
10774
|
-
"caption": null
|
11177
|
+
"caption": null,
|
11178
|
+
|
11179
|
+
|
11180
|
+
/**
|
11181
|
+
* For server-side processing - use the data from the DOM for the first draw
|
11182
|
+
*/
|
11183
|
+
iDeferLoading: null
|
10775
11184
|
};
|
10776
11185
|
|
10777
11186
|
_fnHungarianMap( DataTable.defaults );
|
@@ -11714,7 +12123,19 @@
|
|
11714
12123
|
|
11715
12124
|
captionNode: null,
|
11716
12125
|
|
11717
|
-
colgroup: null
|
12126
|
+
colgroup: null,
|
12127
|
+
|
12128
|
+
/** Delay loading of data */
|
12129
|
+
deferLoading: null,
|
12130
|
+
|
12131
|
+
/** Allow auto type detection */
|
12132
|
+
typeDetect: true,
|
12133
|
+
|
12134
|
+
/** ResizeObserver for the container div */
|
12135
|
+
resizeObserver: null,
|
12136
|
+
|
12137
|
+
/** Keep a record of the last size of the container, so we can skip duplicates */
|
12138
|
+
containerWidth: -1
|
11718
12139
|
};
|
11719
12140
|
|
11720
12141
|
/**
|
@@ -11738,7 +12159,7 @@
|
|
11738
12159
|
},
|
11739
12160
|
|
11740
12161
|
full: function () {
|
11741
|
-
return [
|
12162
|
+
return [ 'first', 'previous', 'next', 'last' ];
|
11742
12163
|
},
|
11743
12164
|
|
11744
12165
|
numbers: function () {
|
@@ -11752,11 +12173,11 @@
|
|
11752
12173
|
full_numbers: function () {
|
11753
12174
|
return [ 'first', 'previous', 'numbers', 'next', 'last' ];
|
11754
12175
|
},
|
11755
|
-
|
12176
|
+
|
11756
12177
|
first_last: function () {
|
11757
12178
|
return ['first', 'last'];
|
11758
12179
|
},
|
11759
|
-
|
12180
|
+
|
11760
12181
|
first_last_numbers: function () {
|
11761
12182
|
return ['first', 'numbers', 'last'];
|
11762
12183
|
},
|
@@ -11838,44 +12259,62 @@
|
|
11838
12259
|
* to make working with DataTables a little bit easier.
|
11839
12260
|
*/
|
11840
12261
|
|
11841
|
-
|
11842
|
-
|
11843
|
-
|
11844
|
-
|
11845
|
-
|
11846
|
-
function __mld(
|
11847
|
-
if (
|
11848
|
-
return
|
12262
|
+
/**
|
12263
|
+
* Common logic for moment, luxon or a date action.
|
12264
|
+
*
|
12265
|
+
* Happens after __mldObj, so don't need to call `resolveWindowsLibs` again
|
12266
|
+
*/
|
12267
|
+
function __mld( dtLib, momentFn, luxonFn, dateFn, arg1 ) {
|
12268
|
+
if (__moment) {
|
12269
|
+
return dtLib[momentFn]( arg1 );
|
11849
12270
|
}
|
11850
|
-
else if (
|
11851
|
-
return
|
12271
|
+
else if (__luxon) {
|
12272
|
+
return dtLib[luxonFn]( arg1 );
|
11852
12273
|
}
|
11853
12274
|
|
11854
|
-
return dateFn ?
|
12275
|
+
return dateFn ? dtLib[dateFn]( arg1 ) : dtLib;
|
11855
12276
|
}
|
11856
12277
|
|
11857
12278
|
|
11858
12279
|
var __mlWarning = false;
|
12280
|
+
var __luxon; // Can be assigned in DateTable.use()
|
12281
|
+
var __moment; // Can be assigned in DateTable.use()
|
12282
|
+
|
12283
|
+
/**
|
12284
|
+
*
|
12285
|
+
*/
|
12286
|
+
function resolveWindowLibs() {
|
12287
|
+
if (window.luxon && ! __luxon) {
|
12288
|
+
__luxon = window.luxon;
|
12289
|
+
}
|
12290
|
+
|
12291
|
+
if (window.moment && ! __moment) {
|
12292
|
+
__moment = window.moment;
|
12293
|
+
}
|
12294
|
+
}
|
12295
|
+
|
11859
12296
|
function __mldObj (d, format, locale) {
|
11860
12297
|
var dt;
|
11861
12298
|
|
11862
|
-
|
11863
|
-
|
12299
|
+
resolveWindowLibs();
|
12300
|
+
|
12301
|
+
if (__moment) {
|
12302
|
+
dt = __moment.utc( d, format, locale, true );
|
11864
12303
|
|
11865
12304
|
if (! dt.isValid()) {
|
11866
12305
|
return null;
|
11867
12306
|
}
|
11868
12307
|
}
|
11869
|
-
else if (
|
12308
|
+
else if (__luxon) {
|
11870
12309
|
dt = format && typeof d === 'string'
|
11871
|
-
?
|
11872
|
-
:
|
12310
|
+
? __luxon.DateTime.fromFormat( d, format )
|
12311
|
+
: __luxon.DateTime.fromISO( d );
|
11873
12312
|
|
11874
12313
|
if (! dt.isValid) {
|
11875
12314
|
return null;
|
11876
12315
|
}
|
11877
12316
|
|
11878
|
-
dt.setLocale(locale);
|
12317
|
+
dt = dt.setLocale(locale);
|
11879
12318
|
}
|
11880
12319
|
else if (! format) {
|
11881
12320
|
// No format given, must be ISO
|
@@ -11914,11 +12353,11 @@
|
|
11914
12353
|
from = null;
|
11915
12354
|
}
|
11916
12355
|
|
11917
|
-
var typeName = 'datetime' + (to ? '-' +
|
12356
|
+
var typeName = 'datetime' + (to ? '-' + to : '');
|
11918
12357
|
|
11919
12358
|
// Add type detection and sorting specific to this date format - we need to be able to identify
|
11920
12359
|
// date type columns as such, rather than as numbers in extensions. Hence the need for this.
|
11921
|
-
if (! DataTable.ext.type.order[typeName]) {
|
12360
|
+
if (! DataTable.ext.type.order[typeName + '-pre']) {
|
11922
12361
|
DataTable.type(typeName, {
|
11923
12362
|
detect: function (d) {
|
11924
12363
|
// The renderer will give the value to type detect as the type!
|
@@ -12017,7 +12456,7 @@
|
|
12017
12456
|
|
12018
12457
|
// Formatted date time detection - use by declaring the formats you are going to use
|
12019
12458
|
DataTable.datetime = function ( format, locale ) {
|
12020
|
-
var typeName = 'datetime-
|
12459
|
+
var typeName = 'datetime-' + format;
|
12021
12460
|
|
12022
12461
|
if (! locale) {
|
12023
12462
|
locale = 'en';
|
@@ -12157,7 +12596,7 @@
|
|
12157
12596
|
return {
|
12158
12597
|
className: _extTypes.className[name],
|
12159
12598
|
detect: _extTypes.detect.find(function (fn) {
|
12160
|
-
return fn.
|
12599
|
+
return fn._name === name;
|
12161
12600
|
}),
|
12162
12601
|
order: {
|
12163
12602
|
pre: _extTypes.order[name + '-pre'],
|
@@ -12172,27 +12611,20 @@
|
|
12172
12611
|
var setProp = function(prop, propVal) {
|
12173
12612
|
_extTypes[prop][name] = propVal;
|
12174
12613
|
};
|
12175
|
-
var setDetect = function (
|
12176
|
-
//
|
12177
|
-
//
|
12178
|
-
|
12179
|
-
var ret = fn(d, s);
|
12180
|
-
|
12181
|
-
return ret === true
|
12182
|
-
? name
|
12183
|
-
: ret;
|
12184
|
-
};
|
12185
|
-
Object.defineProperty(cb, "name", {value: name});
|
12614
|
+
var setDetect = function (detect) {
|
12615
|
+
// `detect` can be a function or an object - we set a name
|
12616
|
+
// property for either - that is used for the detection
|
12617
|
+
Object.defineProperty(detect, "_name", {value: name});
|
12186
12618
|
|
12187
|
-
var idx = _extTypes.detect.findIndex(function (
|
12188
|
-
return
|
12619
|
+
var idx = _extTypes.detect.findIndex(function (item) {
|
12620
|
+
return item._name === name;
|
12189
12621
|
});
|
12190
12622
|
|
12191
12623
|
if (idx === -1) {
|
12192
|
-
_extTypes.detect.unshift(
|
12624
|
+
_extTypes.detect.unshift(detect);
|
12193
12625
|
}
|
12194
12626
|
else {
|
12195
|
-
_extTypes.detect.splice(idx, 1,
|
12627
|
+
_extTypes.detect.splice(idx, 1, detect);
|
12196
12628
|
}
|
12197
12629
|
};
|
12198
12630
|
var setOrder = function (obj) {
|
@@ -12248,10 +12680,30 @@
|
|
12248
12680
|
// Get a list of types
|
12249
12681
|
DataTable.types = function () {
|
12250
12682
|
return _extTypes.detect.map(function (fn) {
|
12251
|
-
return fn.
|
12683
|
+
return fn._name;
|
12252
12684
|
});
|
12253
12685
|
};
|
12254
12686
|
|
12687
|
+
var __diacriticSort = function (a, b) {
|
12688
|
+
a = a !== null && a !== undefined ? a.toString().toLowerCase() : '';
|
12689
|
+
b = b !== null && b !== undefined ? b.toString().toLowerCase() : '';
|
12690
|
+
|
12691
|
+
// Checked for `navigator.languages` support in `oneOf` so this code can't execute in old
|
12692
|
+
// Safari and thus can disable this check
|
12693
|
+
// eslint-disable-next-line compat/compat
|
12694
|
+
return a.localeCompare(b, navigator.languages[0] || navigator.language, {
|
12695
|
+
numeric: true,
|
12696
|
+
ignorePunctuation: true,
|
12697
|
+
});
|
12698
|
+
}
|
12699
|
+
|
12700
|
+
var __diacriticHtmlSort = function (a, b) {
|
12701
|
+
a = _stripHtml(a);
|
12702
|
+
b = _stripHtml(b);
|
12703
|
+
|
12704
|
+
return __diacriticSort(a, b);
|
12705
|
+
}
|
12706
|
+
|
12255
12707
|
//
|
12256
12708
|
// Built in data types
|
12257
12709
|
//
|
@@ -12264,7 +12716,7 @@
|
|
12264
12716
|
pre: function ( a ) {
|
12265
12717
|
// This is a little complex, but faster than always calling toString,
|
12266
12718
|
// http://jsperf.com/tostring-v-check
|
12267
|
-
return _empty(a) ?
|
12719
|
+
return _empty(a) && typeof a !== 'boolean' ?
|
12268
12720
|
'' :
|
12269
12721
|
typeof a === 'string' ?
|
12270
12722
|
a.toLowerCase() :
|
@@ -12276,11 +12728,38 @@
|
|
12276
12728
|
search: _filterString(false, true)
|
12277
12729
|
});
|
12278
12730
|
|
12731
|
+
DataTable.type('string-utf8', {
|
12732
|
+
detect: {
|
12733
|
+
allOf: function ( d ) {
|
12734
|
+
return true;
|
12735
|
+
},
|
12736
|
+
oneOf: function ( d ) {
|
12737
|
+
// At least one data point must contain a non-ASCII character
|
12738
|
+
// This line will also check if navigator.languages is supported or not. If not (Safari 10.0-)
|
12739
|
+
// this data type won't be supported.
|
12740
|
+
// eslint-disable-next-line compat/compat
|
12741
|
+
return ! _empty( d ) && navigator.languages && typeof d === 'string' && d.match(/[^\x00-\x7F]/);
|
12742
|
+
}
|
12743
|
+
},
|
12744
|
+
order: {
|
12745
|
+
asc: __diacriticSort,
|
12746
|
+
desc: function (a, b) {
|
12747
|
+
return __diacriticSort(a, b) * -1;
|
12748
|
+
}
|
12749
|
+
},
|
12750
|
+
search: _filterString(false, true)
|
12751
|
+
});
|
12752
|
+
|
12279
12753
|
|
12280
12754
|
DataTable.type('html', {
|
12281
|
-
detect:
|
12282
|
-
|
12283
|
-
'
|
12755
|
+
detect: {
|
12756
|
+
allOf: function ( d ) {
|
12757
|
+
return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1);
|
12758
|
+
},
|
12759
|
+
oneOf: function ( d ) {
|
12760
|
+
// At least one data point must contain a `<`
|
12761
|
+
return ! _empty( d ) && typeof d === 'string' && d.indexOf('<') !== -1;
|
12762
|
+
}
|
12284
12763
|
},
|
12285
12764
|
order: {
|
12286
12765
|
pre: function ( a ) {
|
@@ -12295,18 +12774,48 @@
|
|
12295
12774
|
});
|
12296
12775
|
|
12297
12776
|
|
12777
|
+
DataTable.type('html-utf8', {
|
12778
|
+
detect: {
|
12779
|
+
allOf: function ( d ) {
|
12780
|
+
return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1);
|
12781
|
+
},
|
12782
|
+
oneOf: function ( d ) {
|
12783
|
+
// At least one data point must contain a `<` and a non-ASCII character
|
12784
|
+
// eslint-disable-next-line compat/compat
|
12785
|
+
return navigator.languages &&
|
12786
|
+
! _empty( d ) &&
|
12787
|
+
typeof d === 'string' &&
|
12788
|
+
d.indexOf('<') !== -1 &&
|
12789
|
+
typeof d === 'string' && d.match(/[^\x00-\x7F]/);
|
12790
|
+
}
|
12791
|
+
},
|
12792
|
+
order: {
|
12793
|
+
asc: __diacriticHtmlSort,
|
12794
|
+
desc: function (a, b) {
|
12795
|
+
return __diacriticHtmlSort(a, b) * -1;
|
12796
|
+
}
|
12797
|
+
},
|
12798
|
+
search: _filterString(true, true)
|
12799
|
+
});
|
12800
|
+
|
12801
|
+
|
12298
12802
|
DataTable.type('date', {
|
12299
12803
|
className: 'dt-type-date',
|
12300
|
-
detect:
|
12301
|
-
|
12302
|
-
|
12303
|
-
|
12304
|
-
|
12305
|
-
|
12306
|
-
|
12804
|
+
detect: {
|
12805
|
+
allOf: function ( d ) {
|
12806
|
+
// V8 tries _very_ hard to make a string passed into `Date.parse()`
|
12807
|
+
// valid, so we need to use a regex to restrict date formats. Use a
|
12808
|
+
// plug-in for anything other than ISO8601 style strings
|
12809
|
+
if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
|
12810
|
+
return null;
|
12811
|
+
}
|
12812
|
+
var parsed = Date.parse(d);
|
12813
|
+
return (parsed !== null && !isNaN(parsed)) || _empty(d);
|
12814
|
+
},
|
12815
|
+
oneOf: function ( d ) {
|
12816
|
+
// At least one entry must be a date or a string with a date
|
12817
|
+
return (d instanceof Date) || (typeof d === 'string' && _re_date.test(d));
|
12307
12818
|
}
|
12308
|
-
var parsed = Date.parse(d);
|
12309
|
-
return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
|
12310
12819
|
},
|
12311
12820
|
order: {
|
12312
12821
|
pre: function ( d ) {
|
@@ -12319,10 +12828,16 @@
|
|
12319
12828
|
|
12320
12829
|
DataTable.type('html-num-fmt', {
|
12321
12830
|
className: 'dt-type-numeric',
|
12322
|
-
detect:
|
12323
|
-
|
12324
|
-
|
12325
|
-
|
12831
|
+
detect: {
|
12832
|
+
allOf: function ( d, settings ) {
|
12833
|
+
var decimal = settings.oLanguage.sDecimal;
|
12834
|
+
return _htmlNumeric( d, decimal, true, false );
|
12835
|
+
},
|
12836
|
+
oneOf: function (d, settings) {
|
12837
|
+
// At least one data point must contain a numeric value
|
12838
|
+
var decimal = settings.oLanguage.sDecimal;
|
12839
|
+
return _htmlNumeric( d, decimal, true, false );
|
12840
|
+
}
|
12326
12841
|
},
|
12327
12842
|
order: {
|
12328
12843
|
pre: function ( d, s ) {
|
@@ -12336,10 +12851,16 @@
|
|
12336
12851
|
|
12337
12852
|
DataTable.type('html-num', {
|
12338
12853
|
className: 'dt-type-numeric',
|
12339
|
-
detect:
|
12340
|
-
|
12341
|
-
|
12342
|
-
|
12854
|
+
detect: {
|
12855
|
+
allOf: function ( d, settings ) {
|
12856
|
+
var decimal = settings.oLanguage.sDecimal;
|
12857
|
+
return _htmlNumeric( d, decimal, false, true );
|
12858
|
+
},
|
12859
|
+
oneOf: function (d, settings) {
|
12860
|
+
// At least one data point must contain a numeric value
|
12861
|
+
var decimal = settings.oLanguage.sDecimal;
|
12862
|
+
return _htmlNumeric( d, decimal, false, false );
|
12863
|
+
}
|
12343
12864
|
},
|
12344
12865
|
order: {
|
12345
12866
|
pre: function ( d, s ) {
|
@@ -12353,10 +12874,16 @@
|
|
12353
12874
|
|
12354
12875
|
DataTable.type('num-fmt', {
|
12355
12876
|
className: 'dt-type-numeric',
|
12356
|
-
detect:
|
12357
|
-
|
12358
|
-
|
12359
|
-
|
12877
|
+
detect: {
|
12878
|
+
allOf: function ( d, settings ) {
|
12879
|
+
var decimal = settings.oLanguage.sDecimal;
|
12880
|
+
return _isNumber( d, decimal, true, true );
|
12881
|
+
},
|
12882
|
+
oneOf: function (d, settings) {
|
12883
|
+
// At least one data point must contain a numeric value
|
12884
|
+
var decimal = settings.oLanguage.sDecimal;
|
12885
|
+
return _isNumber( d, decimal, true, false );
|
12886
|
+
}
|
12360
12887
|
},
|
12361
12888
|
order: {
|
12362
12889
|
pre: function ( d, s ) {
|
@@ -12369,10 +12896,16 @@
|
|
12369
12896
|
|
12370
12897
|
DataTable.type('num', {
|
12371
12898
|
className: 'dt-type-numeric',
|
12372
|
-
detect:
|
12373
|
-
|
12374
|
-
|
12375
|
-
|
12899
|
+
detect: {
|
12900
|
+
allOf: function ( d, settings ) {
|
12901
|
+
var decimal = settings.oLanguage.sDecimal;
|
12902
|
+
return _isNumber( d, decimal, false, true );
|
12903
|
+
},
|
12904
|
+
oneOf: function (d, settings) {
|
12905
|
+
// At least one data point must contain a numeric value
|
12906
|
+
var decimal = settings.oLanguage.sDecimal;
|
12907
|
+
return _isNumber( d, decimal, false, false );
|
12908
|
+
}
|
12376
12909
|
},
|
12377
12910
|
order: {
|
12378
12911
|
pre: function (d, s) {
|
@@ -12456,11 +12989,18 @@
|
|
12456
12989
|
// `DT` namespace will allow the event to be removed automatically
|
12457
12990
|
// on destroy, while the `dt` namespaced event is the one we are
|
12458
12991
|
// listening for
|
12459
|
-
$(settings.nTable).on( 'order.dt.DT', function ( e, ctx
|
12992
|
+
$(settings.nTable).on( 'order.dt.DT column-visibility.dt.DT', function ( e, ctx ) {
|
12460
12993
|
if ( settings !== ctx ) { // need to check this this is the host
|
12461
12994
|
return; // table, not a nested one
|
12462
12995
|
}
|
12463
12996
|
|
12997
|
+
var sorting = ctx.sortDetails;
|
12998
|
+
|
12999
|
+
if (! sorting) {
|
13000
|
+
return;
|
13001
|
+
}
|
13002
|
+
|
13003
|
+
var i;
|
12464
13004
|
var orderClasses = classes.order;
|
12465
13005
|
var columns = ctx.api.columns( cell );
|
12466
13006
|
var col = settings.aoColumns[columns.flatten()[0]];
|
@@ -12468,9 +13008,8 @@
|
|
12468
13008
|
var ariaType = '';
|
12469
13009
|
var indexes = columns.indexes();
|
12470
13010
|
var sortDirs = columns.orderable(true).flatten();
|
12471
|
-
var orderedColumns =
|
12472
|
-
|
12473
|
-
} ).join(',') + ',';
|
13011
|
+
var orderedColumns = _pluck(sorting, 'col');
|
13012
|
+
var tabIndex = settings.iTabIndex;
|
12474
13013
|
|
12475
13014
|
cell
|
12476
13015
|
.removeClass(
|
@@ -12480,10 +13019,18 @@
|
|
12480
13019
|
.toggleClass( orderClasses.none, ! orderable )
|
12481
13020
|
.toggleClass( orderClasses.canAsc, orderable && sortDirs.includes('asc') )
|
12482
13021
|
.toggleClass( orderClasses.canDesc, orderable && sortDirs.includes('desc') );
|
13022
|
+
|
13023
|
+
// Determine if all of the columns that this cell covers are included in the
|
13024
|
+
// current ordering
|
13025
|
+
var isOrdering = true;
|
12483
13026
|
|
12484
|
-
|
13027
|
+
for (i=0; i<indexes.length; i++) {
|
13028
|
+
if (! orderedColumns.includes(indexes[i])) {
|
13029
|
+
isOrdering = false;
|
13030
|
+
}
|
13031
|
+
}
|
12485
13032
|
|
12486
|
-
if (
|
13033
|
+
if ( isOrdering ) {
|
12487
13034
|
// Get the ordering direction for the columns under this cell
|
12488
13035
|
// Note that it is possible for a cell to be asc and desc sorting
|
12489
13036
|
// (column spanning cells)
|
@@ -12495,8 +13042,19 @@
|
|
12495
13042
|
);
|
12496
13043
|
}
|
12497
13044
|
|
12498
|
-
//
|
12499
|
-
|
13045
|
+
// Find the first visible column that has ordering applied to it - it get's
|
13046
|
+
// the aria information, as the ARIA spec says that only one column should
|
13047
|
+
// be marked with aria-sort
|
13048
|
+
var firstVis = -1; // column index
|
13049
|
+
|
13050
|
+
for (i=0; i<orderedColumns.length; i++) {
|
13051
|
+
if (settings.aoColumns[orderedColumns[i]].bVisible) {
|
13052
|
+
firstVis = orderedColumns[i];
|
13053
|
+
break;
|
13054
|
+
}
|
13055
|
+
}
|
13056
|
+
|
13057
|
+
if (indexes[0] == firstVis) {
|
12500
13058
|
var firstSort = sorting[0];
|
12501
13059
|
var sortOrder = col.asSorting;
|
12502
13060
|
|
@@ -12509,14 +13067,20 @@
|
|
12509
13067
|
cell.removeAttr('aria-sort');
|
12510
13068
|
}
|
12511
13069
|
|
12512
|
-
|
12513
|
-
? col.ariaTitle + ctx.api.i18n('oAria.orderable' + ariaType)
|
12514
|
-
: col.ariaTitle
|
12515
|
-
);
|
12516
|
-
|
13070
|
+
// Make the headers tab-able for keyboard navigation
|
12517
13071
|
if (orderable) {
|
12518
|
-
cell.find('.dt-column-
|
12519
|
-
|
13072
|
+
var orderSpan = cell.find('.dt-column-order');
|
13073
|
+
|
13074
|
+
orderSpan
|
13075
|
+
.attr('role', 'button')
|
13076
|
+
.attr('aria-label', orderable
|
13077
|
+
? col.ariaTitle + ctx.api.i18n('oAria.orderable' + ariaType)
|
13078
|
+
: col.ariaTitle
|
13079
|
+
);
|
13080
|
+
|
13081
|
+
if (tabIndex !== -1) {
|
13082
|
+
orderSpan.attr('tabindex', tabIndex);
|
13083
|
+
}
|
12520
13084
|
}
|
12521
13085
|
} );
|
12522
13086
|
}
|
@@ -12524,27 +13088,68 @@
|
|
12524
13088
|
|
12525
13089
|
layout: {
|
12526
13090
|
_: function ( settings, container, items ) {
|
13091
|
+
var classes = settings.oClasses.layout;
|
12527
13092
|
var row = $('<div/>')
|
12528
|
-
.
|
13093
|
+
.attr('id', items.id || null)
|
13094
|
+
.addClass(items.className || classes.row)
|
12529
13095
|
.appendTo( container );
|
12530
13096
|
|
12531
|
-
|
12532
|
-
|
12533
|
-
|
12534
|
-
|
13097
|
+
DataTable.ext.renderer.layout._forLayoutRow(items, function (key, val) {
|
13098
|
+
if (key === 'id' || key === 'className') {
|
13099
|
+
return;
|
13100
|
+
}
|
13101
|
+
|
13102
|
+
var klass = '';
|
12535
13103
|
|
12536
13104
|
if (val.table) {
|
12537
|
-
row.addClass(
|
13105
|
+
row.addClass(classes.tableRow);
|
13106
|
+
klass += classes.tableCell + ' ';
|
13107
|
+
}
|
13108
|
+
|
13109
|
+
if (key === 'start') {
|
13110
|
+
klass += classes.start;
|
13111
|
+
}
|
13112
|
+
else if (key === 'end') {
|
13113
|
+
klass += classes.end;
|
13114
|
+
}
|
13115
|
+
else {
|
13116
|
+
klass += classes.full;
|
12538
13117
|
}
|
12539
13118
|
|
12540
13119
|
$('<div/>')
|
12541
13120
|
.attr({
|
12542
13121
|
id: val.id || null,
|
12543
|
-
"class":
|
13122
|
+
"class": val.className
|
13123
|
+
? val.className
|
13124
|
+
: classes.cell + ' ' + klass
|
12544
13125
|
})
|
12545
13126
|
.append( val.contents )
|
12546
13127
|
.appendTo( row );
|
12547
|
-
}
|
13128
|
+
});
|
13129
|
+
},
|
13130
|
+
|
13131
|
+
// Shared for use by the styling frameworks
|
13132
|
+
_forLayoutRow: function (items, fn) {
|
13133
|
+
// As we are inserting dom elements, we need start / end in a
|
13134
|
+
// specific order, this function is used for sorting the layout
|
13135
|
+
// keys.
|
13136
|
+
var layoutEnum = function (x) {
|
13137
|
+
switch (x) {
|
13138
|
+
case '': return 0;
|
13139
|
+
case 'start': return 1;
|
13140
|
+
case 'end': return 2;
|
13141
|
+
default: return 3;
|
13142
|
+
}
|
13143
|
+
};
|
13144
|
+
|
13145
|
+
Object
|
13146
|
+
.keys(items)
|
13147
|
+
.sort(function (a, b) {
|
13148
|
+
return layoutEnum(a) - layoutEnum(b);
|
13149
|
+
})
|
13150
|
+
.forEach(function (key) {
|
13151
|
+
fn(key, items[key]);
|
13152
|
+
});
|
12548
13153
|
}
|
12549
13154
|
}
|
12550
13155
|
} );
|
@@ -12564,6 +13169,25 @@
|
|
12564
13169
|
}
|
12565
13170
|
};
|
12566
13171
|
|
13172
|
+
function _divProp(el, prop, val) {
|
13173
|
+
if (val) {
|
13174
|
+
el[prop] = val;
|
13175
|
+
}
|
13176
|
+
}
|
13177
|
+
|
13178
|
+
DataTable.feature.register( 'div', function ( settings, opts ) {
|
13179
|
+
var n = $('<div>')[0];
|
13180
|
+
|
13181
|
+
if (opts) {
|
13182
|
+
_divProp(n, 'className', opts.className);
|
13183
|
+
_divProp(n, 'id', opts.id);
|
13184
|
+
_divProp(n, 'innerHTML', opts.html);
|
13185
|
+
_divProp(n, 'textContent', opts.text);
|
13186
|
+
}
|
13187
|
+
|
13188
|
+
return n;
|
13189
|
+
} );
|
13190
|
+
|
12567
13191
|
DataTable.feature.register( 'info', function ( settings, opts ) {
|
12568
13192
|
// For compatibility with the legacy `info` top level option
|
12569
13193
|
if (! settings.oFeatures.bInfo) {
|
@@ -12663,6 +13287,7 @@
|
|
12663
13287
|
|
12664
13288
|
opts = $.extend({
|
12665
13289
|
placeholder: language.sSearchPlaceholder,
|
13290
|
+
processing: false,
|
12666
13291
|
text: language.sSearch
|
12667
13292
|
}, opts);
|
12668
13293
|
|
@@ -12706,13 +13331,15 @@
|
|
12706
13331
|
|
12707
13332
|
/* Now do the filter */
|
12708
13333
|
if ( val != previousSearch.search ) {
|
12709
|
-
|
12710
|
-
|
12711
|
-
|
12712
|
-
|
12713
|
-
|
12714
|
-
|
12715
|
-
|
13334
|
+
_fnProcessingRun(settings, opts.processing, function () {
|
13335
|
+
previousSearch.search = val;
|
13336
|
+
|
13337
|
+
_fnFilterComplete( settings, previousSearch );
|
13338
|
+
|
13339
|
+
// Need to redraw, without resorting
|
13340
|
+
settings._iDisplayStart = 0;
|
13341
|
+
_fnDraw( settings );
|
13342
|
+
});
|
12716
13343
|
}
|
12717
13344
|
};
|
12718
13345
|
|
@@ -12770,17 +13397,21 @@
|
|
12770
13397
|
opts = $.extend({
|
12771
13398
|
buttons: DataTable.ext.pager.numbers_length,
|
12772
13399
|
type: settings.sPaginationType,
|
12773
|
-
boundaryNumbers: true
|
13400
|
+
boundaryNumbers: true,
|
13401
|
+
firstLast: true,
|
13402
|
+
previousNext: true,
|
13403
|
+
numbers: true
|
12774
13404
|
}, opts);
|
12775
13405
|
|
12776
|
-
|
12777
|
-
|
12778
|
-
|
12779
|
-
|
12780
|
-
|
12781
|
-
|
13406
|
+
var host = $('<div/>')
|
13407
|
+
.addClass(settings.oClasses.paging.container + (opts.type ? ' paging_' + opts.type : ''))
|
13408
|
+
.append(
|
13409
|
+
$('<nav>')
|
13410
|
+
.attr('aria-label', 'pagination')
|
13411
|
+
.addClass(settings.oClasses.paging.nav)
|
13412
|
+
);
|
12782
13413
|
var draw = function () {
|
12783
|
-
_pagingDraw(settings, host, opts);
|
13414
|
+
_pagingDraw(settings, host.children(), opts);
|
12784
13415
|
};
|
12785
13416
|
|
12786
13417
|
settings.aoDrawCallback.push(draw);
|
@@ -12791,13 +13422,39 @@
|
|
12791
13422
|
return host;
|
12792
13423
|
}, 'p' );
|
12793
13424
|
|
13425
|
+
/**
|
13426
|
+
* Dynamically create the button type array based on the configuration options.
|
13427
|
+
* This will only happen if the paging type is not defined.
|
13428
|
+
*/
|
13429
|
+
function _pagingDynamic(opts) {
|
13430
|
+
var out = [];
|
13431
|
+
|
13432
|
+
if (opts.numbers) {
|
13433
|
+
out.push('numbers');
|
13434
|
+
}
|
13435
|
+
|
13436
|
+
if (opts.previousNext) {
|
13437
|
+
out.unshift('previous');
|
13438
|
+
out.push('next');
|
13439
|
+
}
|
13440
|
+
|
13441
|
+
if (opts.firstLast) {
|
13442
|
+
out.unshift('first');
|
13443
|
+
out.push('last');
|
13444
|
+
}
|
13445
|
+
|
13446
|
+
return out;
|
13447
|
+
}
|
13448
|
+
|
12794
13449
|
function _pagingDraw(settings, host, opts) {
|
12795
13450
|
if (! settings._bInitComplete) {
|
12796
13451
|
return;
|
12797
13452
|
}
|
12798
13453
|
|
12799
13454
|
var
|
12800
|
-
plugin =
|
13455
|
+
plugin = opts.type
|
13456
|
+
? DataTable.ext.pager[ opts.type ]
|
13457
|
+
: _pagingDynamic,
|
12801
13458
|
aria = settings.oLanguage.oAria.paginate || {},
|
12802
13459
|
start = settings._iDisplayStart,
|
12803
13460
|
len = settings._iDisplayLength,
|
@@ -12805,15 +13462,17 @@
|
|
12805
13462
|
all = len === -1,
|
12806
13463
|
page = all ? 0 : Math.ceil( start / len ),
|
12807
13464
|
pages = all ? 1 : Math.ceil( visRecords / len ),
|
12808
|
-
buttons =
|
13465
|
+
buttons = [],
|
13466
|
+
buttonEls = [],
|
13467
|
+
buttonsNested = plugin(opts)
|
12809
13468
|
.map(function (val) {
|
12810
13469
|
return val === 'numbers'
|
12811
13470
|
? _pagingNumbers(page, pages, opts.buttons, opts.boundaryNumbers)
|
12812
13471
|
: val;
|
12813
|
-
})
|
12814
|
-
.flat();
|
13472
|
+
});
|
12815
13473
|
|
12816
|
-
|
13474
|
+
// .flat() would be better, but not supported in old Safari
|
13475
|
+
buttons = buttons.concat.apply(buttons, buttonsNested);
|
12817
13476
|
|
12818
13477
|
for (var i=0 ; i<buttons.length ; i++) {
|
12819
13478
|
var button = buttons[i];
|
@@ -12827,14 +13486,24 @@
|
|
12827
13486
|
btnInfo.disabled
|
12828
13487
|
);
|
12829
13488
|
|
13489
|
+
var ariaLabel = typeof button === 'string'
|
13490
|
+
? aria[ button ]
|
13491
|
+
: aria.number
|
13492
|
+
? aria.number + (button+1)
|
13493
|
+
: null;
|
13494
|
+
|
12830
13495
|
// Common attributes
|
12831
13496
|
$(btn.clicker).attr({
|
12832
13497
|
'aria-controls': settings.sTableId,
|
12833
13498
|
'aria-disabled': btnInfo.disabled ? 'true' : null,
|
12834
13499
|
'aria-current': btnInfo.active ? 'page' : null,
|
12835
|
-
'aria-label':
|
13500
|
+
'aria-label': ariaLabel,
|
12836
13501
|
'data-dt-idx': button,
|
12837
|
-
'tabIndex': btnInfo.disabled
|
13502
|
+
'tabIndex': btnInfo.disabled
|
13503
|
+
? -1
|
13504
|
+
: settings.iTabIndex && btn.clicker[0].nodeName.toLowerCase() !== 'span'
|
13505
|
+
? settings.iTabIndex
|
13506
|
+
: null, // `0` doesn't need a tabIndex since it is the default
|
12838
13507
|
});
|
12839
13508
|
|
12840
13509
|
if (typeof button !== 'number') {
|
@@ -12866,12 +13535,16 @@
|
|
12866
13535
|
|
12867
13536
|
// Responsive - check if the buttons are over two lines based on the
|
12868
13537
|
// height of the buttons and the container.
|
12869
|
-
if (
|
12870
|
-
|
12871
|
-
|
12872
|
-
|
12873
|
-
|
12874
|
-
|
13538
|
+
if (buttonEls.length) {
|
13539
|
+
var outerHeight = $(buttonEls[0]).outerHeight();
|
13540
|
+
|
13541
|
+
if (
|
13542
|
+
opts.buttons > 1 && // prevent infinite
|
13543
|
+
outerHeight > 0 && // will be 0 if hidden
|
13544
|
+
$(host).height() >= (outerHeight * 2) - 10
|
13545
|
+
) {
|
13546
|
+
_pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 }));
|
13547
|
+
}
|
12875
13548
|
}
|
12876
13549
|
}
|
12877
13550
|
|
@@ -12895,7 +13568,6 @@
|
|
12895
13568
|
switch ( button ) {
|
12896
13569
|
case 'ellipsis':
|
12897
13570
|
o.display = '…';
|
12898
|
-
o.disabled = true;
|
12899
13571
|
break;
|
12900
13572
|
|
12901
13573
|
case 'first':
|
@@ -13073,22 +13745,23 @@
|
|
13073
13745
|
}
|
13074
13746
|
|
13075
13747
|
// Wrapper element - use a span as a holder for where the select will go
|
13748
|
+
var tmpId = 'tmp-' + (+new Date())
|
13076
13749
|
var div = $('<div/>')
|
13077
13750
|
.addClass( classes.container )
|
13078
13751
|
.append(
|
13079
|
-
str.replace( '_MENU_', '<span></span>' )
|
13752
|
+
str.replace( '_MENU_', '<span id="'+tmpId+'"></span>' )
|
13080
13753
|
);
|
13081
13754
|
|
13082
13755
|
// Save text node content for macro updating
|
13083
13756
|
var textNodes = [];
|
13084
|
-
div.find('label')[0].childNodes.forEach(function (el) {
|
13757
|
+
Array.prototype.slice.call(div.find('label')[0].childNodes).forEach(function (el) {
|
13085
13758
|
if (el.nodeType === Node.TEXT_NODE) {
|
13086
13759
|
textNodes.push({
|
13087
13760
|
el: el,
|
13088
13761
|
text: el.textContent
|
13089
13762
|
});
|
13090
13763
|
}
|
13091
|
-
})
|
13764
|
+
});
|
13092
13765
|
|
13093
13766
|
// Update the label text in case it has an entries value
|
13094
13767
|
var updateEntries = function (len) {
|
@@ -13099,7 +13772,6 @@
|
|
13099
13772
|
|
13100
13773
|
// Next, the select itself, along with the options
|
13101
13774
|
var select = $('<select/>', {
|
13102
|
-
'name': tableId+'_length',
|
13103
13775
|
'aria-controls': tableId,
|
13104
13776
|
'class': classes.select
|
13105
13777
|
} );
|
@@ -13119,7 +13791,7 @@
|
|
13119
13791
|
__lengthCounter++;
|
13120
13792
|
|
13121
13793
|
// Swap in the select list
|
13122
|
-
div.find('
|
13794
|
+
div.find('#' + tmpId).replaceWith(select);
|
13123
13795
|
|
13124
13796
|
// Can't use `select` variable as user might provide their own and the
|
13125
13797
|
// reference is broken by the use of outerHTML
|