oxidized-web 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
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
|