datatables.net 2.1.8 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/dataTables.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! DataTables 2.1.8
1
+ /*! DataTables 2.2.1
2
2
  * © SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -376,7 +376,6 @@ var DataTable = function ( selector, options )
376
376
  thead = $('<thead/>').appendTo($this);
377
377
  }
378
378
  oSettings.nTHead = thead[0];
379
- $('tr', thead).addClass(oClasses.thead.row);
380
379
 
381
380
  var tbody = $this.children('tbody');
382
381
  if ( tbody.length === 0 ) {
@@ -391,7 +390,6 @@ var DataTable = function ( selector, options )
391
390
  tfoot = $('<tfoot/>').appendTo($this);
392
391
  }
393
392
  oSettings.nTFoot = tfoot[0];
394
- $('tr', tfoot).addClass(oClasses.tfoot.row);
395
393
 
396
394
  // Copy the data index array
397
395
  oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
@@ -2108,6 +2106,10 @@ function _fnColumnSizes ( settings )
2108
2106
  var width = _fnColumnsSumWidth(settings, [i], false, false);
2109
2107
 
2110
2108
  cols[i].colEl.css('width', width);
2109
+
2110
+ if (settings.oScroll.sX) {
2111
+ cols[i].colEl.css('min-width', width);
2112
+ }
2111
2113
  }
2112
2114
  }
2113
2115
 
@@ -3175,9 +3177,13 @@ function _fnBuildHead( settings, side )
3175
3177
 
3176
3178
  // Add the number of cells needed to make up to the number of columns
3177
3179
  if (row.length === 1) {
3178
- var cells = $('td, th', row);
3180
+ var cellCount = 0;
3181
+
3182
+ $('td, th', row).each(function () {
3183
+ cellCount += this.colSpan;
3184
+ });
3179
3185
 
3180
- for ( i=cells.length, ien=columns.length ; i<ien ; i++ ) {
3186
+ for ( i=cellCount, ien=columns.length ; i<ien ; i++ ) {
3181
3187
  $('<th/>')
3182
3188
  .html( columns[i][titleProp] || '' )
3183
3189
  .appendTo( row );
@@ -3189,9 +3195,11 @@ function _fnBuildHead( settings, side )
3189
3195
 
3190
3196
  if (side === 'header') {
3191
3197
  settings.aoHeader = detected;
3198
+ $('tr', target).addClass(classes.thead.row);
3192
3199
  }
3193
3200
  else {
3194
3201
  settings.aoFooter = detected;
3202
+ $('tr', target).addClass(classes.tfoot.row);
3195
3203
  }
3196
3204
 
3197
3205
  // Every cell needs to be passed through the renderer
@@ -4454,7 +4462,7 @@ function _fnFilterCustom( settings )
4454
4462
  // So the array reference doesn't break set the results into the
4455
4463
  // existing array
4456
4464
  displayRows.length = 0;
4457
- displayRows.push.apply(displayRows, rows);
4465
+ _fnArrayApply(displayRows, rows);
4458
4466
  }
4459
4467
  }
4460
4468
 
@@ -5182,8 +5190,11 @@ function _fnScrollDraw ( settings )
5182
5190
  // [].find, but it wasn't supported in Chrome until Sept 2015, and DT has 10 year
5183
5191
  // browser support
5184
5192
  var firstTr = null;
5193
+ var start = _fnDataSource( settings ) !== 'ssp'
5194
+ ? settings._iDisplayStart
5195
+ : 0;
5185
5196
 
5186
- for (i=settings._iDisplayStart ; i<settings.aiDisplay.length ; i++) {
5197
+ for (i=start ; i<start + settings.aiDisplay.length ; i++) {
5187
5198
  var idx = settings.aiDisplay[i];
5188
5199
  var tr = settings.aoData[idx].nTr;
5189
5200
 
@@ -5198,7 +5209,7 @@ function _fnScrollDraw ( settings )
5198
5209
  return {
5199
5210
  idx: _fnVisibleToColumnIndex(settings, vis),
5200
5211
  width: $(this).outerWidth()
5201
- }
5212
+ };
5202
5213
  });
5203
5214
 
5204
5215
  // Check against what the colgroup > col is set to and correct if needed
@@ -5208,6 +5219,10 @@ function _fnScrollDraw ( settings )
5208
5219
 
5209
5220
  if (colWidth !== colSizes[i].width) {
5210
5221
  colEl.style.width = colSizes[i].width + 'px';
5222
+
5223
+ if (scroll.sX) {
5224
+ colEl.style.minWidth = colSizes[i].width + 'px';
5225
+ }
5211
5226
  }
5212
5227
  }
5213
5228
  }
@@ -5300,6 +5315,14 @@ function _fnCalculateColumnWidths ( settings )
5300
5315
  i, column, columnIdx;
5301
5316
 
5302
5317
  var styleWidth = table.style.width;
5318
+ var containerWidth = _fnWrapperWidth(settings);
5319
+
5320
+ // Don't re-run for the same width as the last time
5321
+ if (containerWidth === settings.containerWidth) {
5322
+ return false;
5323
+ }
5324
+
5325
+ settings.containerWidth = containerWidth;
5303
5326
 
5304
5327
  // If there is no width applied as a CSS style or as an attribute, we assume that
5305
5328
  // the width is intended to be 100%, which is usually is in CSS, but it is very
@@ -5357,6 +5380,8 @@ function _fnCalculateColumnWidths ( settings )
5357
5380
  // browser will collapse it. If this width is smaller than the
5358
5381
  // width the column requires, then it will have no effect
5359
5382
  if ( scrollX ) {
5383
+ this.style.minWidth = width;
5384
+
5360
5385
  $( this ).append( $('<div/>').css( {
5361
5386
  width: width,
5362
5387
  margin: 0,
@@ -5425,15 +5450,15 @@ function _fnCalculateColumnWidths ( settings )
5425
5450
 
5426
5451
  // If there is no width attribute or style, then allow the table to
5427
5452
  // collapse
5428
- if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5429
- tmpTable.width( tableContainer.clientWidth );
5453
+ if ( tmpTable.outerWidth() < tableContainer.clientWidth && tableWidthAttr ) {
5454
+ tmpTable.outerWidth( tableContainer.clientWidth );
5430
5455
  }
5431
5456
  }
5432
5457
  else if ( scrollY ) {
5433
- tmpTable.width( tableContainer.clientWidth );
5458
+ tmpTable.outerWidth( tableContainer.clientWidth );
5434
5459
  }
5435
5460
  else if ( tableWidthAttr ) {
5436
- tmpTable.width( tableWidthAttr );
5461
+ tmpTable.outerWidth( tableWidthAttr );
5437
5462
  }
5438
5463
 
5439
5464
  // Get the width of each column in the constructed table
@@ -5466,20 +5491,55 @@ function _fnCalculateColumnWidths ( settings )
5466
5491
  }
5467
5492
 
5468
5493
  if ( (tableWidthAttr || scrollX) && ! settings._reszEvt ) {
5469
- var bindResize = function () {
5470
- $(window).on('resize.DT-'+settings.sInstance, DataTable.util.throttle( function () {
5471
- if (! settings.bDestroying) {
5472
- _fnAdjustColumnSizing( settings );
5494
+ var resize = DataTable.util.throttle( function () {
5495
+ var newWidth = _fnWrapperWidth(settings);
5496
+
5497
+ // Don't do it if destroying or the container width is 0
5498
+ if (! settings.bDestroying && newWidth !== 0) {
5499
+ _fnAdjustColumnSizing( settings );
5500
+ }
5501
+ } );
5502
+
5503
+ // For browsers that support it (~2020 onwards for wide support) we can watch for the
5504
+ // container changing width.
5505
+ if (window.ResizeObserver) {
5506
+ // This is a tricky beast - if the element is visible when `.observe()` is called,
5507
+ // then the callback is immediately run. Which we don't want. If the element isn't
5508
+ // visible, then it isn't run, but we want it to run when it is then made visible.
5509
+ // This flag allows the above to be satisfied.
5510
+ var first = $(settings.nTableWrapper).is(':visible');
5511
+
5512
+ settings.resizeObserver = new ResizeObserver(function (e) {
5513
+ if (first) {
5514
+ first = false;
5473
5515
  }
5474
- } ) );
5475
- };
5516
+ else {
5517
+ resize();
5518
+ }
5519
+ });
5476
5520
 
5477
- bindResize();
5521
+ settings.resizeObserver.observe(settings.nTableWrapper);
5522
+ }
5523
+ else {
5524
+ // For old browsers, the best we can do is listen for a window resize
5525
+ $(window).on('resize.DT-'+settings.sInstance, resize);
5526
+ }
5478
5527
 
5479
5528
  settings._reszEvt = true;
5480
5529
  }
5481
5530
  }
5482
5531
 
5532
+ /**
5533
+ * Get the width of the DataTables wrapper element
5534
+ *
5535
+ * @param {*} settings DataTables settings object
5536
+ * @returns Width
5537
+ */
5538
+ function _fnWrapperWidth(settings) {
5539
+ return $(settings.nTableWrapper).is(':visible')
5540
+ ? $(settings.nTableWrapper).width()
5541
+ : 0;
5542
+ }
5483
5543
 
5484
5544
  /**
5485
5545
  * Get the maximum strlen for each data column
@@ -6088,15 +6148,26 @@ function _fnSaveState ( settings )
6088
6148
  return;
6089
6149
  }
6090
6150
 
6151
+ // Sort state saving uses [[idx, order]] structure.
6152
+ var sorting = [];
6153
+ _fnSortResolve(settings, sorting, settings.aaSorting );
6154
+
6091
6155
  /* Store the interesting variables */
6156
+ var columns = settings.aoColumns;
6092
6157
  var state = {
6093
6158
  time: +new Date(),
6094
6159
  start: settings._iDisplayStart,
6095
6160
  length: settings._iDisplayLength,
6096
- order: $.extend( true, [], settings.aaSorting ),
6161
+ order: sorting.map(function (sort) {
6162
+ // If a column name is available, use it
6163
+ return columns[sort[0]] && columns[sort[0]].sName
6164
+ ? [ columns[sort[0]].sName, sort[1] ]
6165
+ : sort.slice();
6166
+ } ),
6097
6167
  search: $.extend({}, settings.oPreviousSearch),
6098
6168
  columns: settings.aoColumns.map( function ( col, i ) {
6099
6169
  return {
6170
+ name: col.sName,
6100
6171
  visible: col.bVisible,
6101
6172
  search: $.extend({}, settings.aoPreSearchCols[i])
6102
6173
  };
@@ -6144,6 +6215,8 @@ function _fnLoadState ( settings, init, callback )
6144
6215
  function _fnImplementState ( settings, s, callback) {
6145
6216
  var i, ien;
6146
6217
  var columns = settings.aoColumns;
6218
+ var currentNames = _pluck(settings.aoColumns, 'sName');
6219
+
6147
6220
  settings._bLoadingState = true;
6148
6221
 
6149
6222
  // When StateRestore was introduced the state could now be implemented at any time
@@ -6173,13 +6246,6 @@ function _fnImplementState ( settings, s, callback) {
6173
6246
  return;
6174
6247
  }
6175
6248
 
6176
- // Number of columns have changed - all bets are off, no restore of settings
6177
- if ( s.columns && columns.length !== s.columns.length ) {
6178
- settings._bLoadingState = false;
6179
- callback();
6180
- return;
6181
- }
6182
-
6183
6249
  // Store the saved state so it might be accessed at any time
6184
6250
  settings.oLoadedState = $.extend( true, {}, s );
6185
6251
 
@@ -6213,10 +6279,23 @@ function _fnImplementState ( settings, s, callback) {
6213
6279
  if ( s.order !== undefined ) {
6214
6280
  settings.aaSorting = [];
6215
6281
  $.each( s.order, function ( i, col ) {
6216
- settings.aaSorting.push( col[0] >= columns.length ?
6217
- [ 0, col[1] ] :
6218
- col
6219
- );
6282
+ var set = [ col[0], col[1] ];
6283
+
6284
+ // A column name was stored and should be used for restore
6285
+ if (typeof col[0] === 'string') {
6286
+ var idx = currentNames.indexOf(col[0]);
6287
+
6288
+ // Find the name from the current list of column names, or fallback to index 0
6289
+ set[0] = idx >= 0
6290
+ ? idx
6291
+ : 0;
6292
+ }
6293
+ else if (set[0] >= columns.length) {
6294
+ // If a column name, but it is out of bounds, set to 0
6295
+ set[0] = 0;
6296
+ }
6297
+
6298
+ settings.aaSorting.push(set);
6220
6299
  } );
6221
6300
  }
6222
6301
 
@@ -6227,31 +6306,65 @@ function _fnImplementState ( settings, s, callback) {
6227
6306
 
6228
6307
  // Columns
6229
6308
  if ( s.columns ) {
6230
- for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6231
- var col = s.columns[i];
6232
-
6233
- // Visibility
6234
- if ( col.visible !== undefined ) {
6235
- // If the api is defined, the table has been initialised so we need to use it rather than internal settings
6236
- if (api) {
6237
- // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6238
- api.column(i).visible(col.visible, false);
6309
+ var set = s.columns;
6310
+ var incoming = _pluck(s.columns, 'name');
6311
+
6312
+ // Check if it is a 2.2 style state object with a `name` property for the columns, and if
6313
+ // the name was defined. If so, then create a new array that will map the state object
6314
+ // given, to the current columns (don't bother if they are already matching tho).
6315
+ if (incoming.join('').length && incoming.join('') !== currentNames.join('')) {
6316
+ set = [];
6317
+
6318
+ // For each column, try to find the name in the incoming array
6319
+ for (i=0 ; i<currentNames.length ; i++) {
6320
+ if (currentNames[i] != '') {
6321
+ var idx = incoming.indexOf(currentNames[i]);
6322
+
6323
+ if (idx >= 0) {
6324
+ set.push(s.columns[idx]);
6325
+ }
6326
+ else {
6327
+ // No matching column name in the state's columns, so this might be a new
6328
+ // column and thus can't have a state already.
6329
+ set.push({});
6330
+ }
6239
6331
  }
6240
6332
  else {
6241
- columns[i].bVisible = col.visible;
6333
+ // If no name, but other columns did have a name, then there is no knowing
6334
+ // where this one came from originally so it can't be restored.
6335
+ set.push({});
6336
+ }
6337
+ }
6338
+ }
6339
+
6340
+ // If the number of columns to restore is different from current, then all bets are off.
6341
+ if (set.length === columns.length) {
6342
+ for ( i=0, ien=set.length ; i<ien ; i++ ) {
6343
+ var col = set[i];
6344
+
6345
+ // Visibility
6346
+ if ( col.visible !== undefined ) {
6347
+ // If the api is defined, the table has been initialised so we need to use it rather than internal settings
6348
+ if (api) {
6349
+ // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6350
+ api.column(i).visible(col.visible, false);
6351
+ }
6352
+ else {
6353
+ columns[i].bVisible = col.visible;
6354
+ }
6355
+ }
6356
+
6357
+ // Search
6358
+ if ( col.search !== undefined ) {
6359
+ $.extend( settings.aoPreSearchCols[i], col.search );
6242
6360
  }
6243
6361
  }
6244
6362
 
6245
- // Search
6246
- if ( col.search !== undefined ) {
6247
- $.extend( settings.aoPreSearchCols[i], col.search );
6363
+ // If the api is defined then we need to adjust the columns once the visibility has been changed
6364
+ if (api) {
6365
+ api.columns.adjust();
6248
6366
  }
6249
6367
  }
6250
-
6251
- // If the api is defined then we need to adjust the columns once the visibility has been changed
6252
- if (api) {
6253
- api.columns.adjust();
6254
- }
6255
6368
  }
6256
6369
 
6257
6370
  settings._bLoadingState = false;
@@ -6568,6 +6681,30 @@ function _fnMacros ( settings, str, entries )
6568
6681
  replace(/_ENTRIES-TOTAL_/g, settings.api.i18n('entries', '', vis) );
6569
6682
  }
6570
6683
 
6684
+ /**
6685
+ * Add elements to an array as quickly as possible, but stack stafe.
6686
+ *
6687
+ * @param {*} arr Array to add the data to
6688
+ * @param {*} data Data array that is to be added
6689
+ * @returns
6690
+ */
6691
+ function _fnArrayApply(arr, data) {
6692
+ if (! data) {
6693
+ return;
6694
+ }
6695
+
6696
+ // Chrome can throw a max stack error if apply is called with
6697
+ // too large an array, but apply is faster.
6698
+ if (data.length < 10000) {
6699
+ arr.push.apply(arr, data);
6700
+ }
6701
+ else {
6702
+ for (i=0 ; i<data.length ; i++) {
6703
+ arr.push(data[i]);
6704
+ }
6705
+ }
6706
+ }
6707
+
6571
6708
 
6572
6709
 
6573
6710
  /**
@@ -6760,18 +6897,7 @@ _Api = function ( context, data )
6760
6897
  : settings;
6761
6898
 
6762
6899
  // Initial data
6763
- if ( data ) {
6764
- // Chrome can throw a max stack error if apply is called with
6765
- // too large an array, but apply is faster.
6766
- if (data.length < 10000) {
6767
- this.push.apply(this, data);
6768
- }
6769
- else {
6770
- for (i=0 ; i<data.length ; i++) {
6771
- this.push(data[i]);
6772
- }
6773
- }
6774
- }
6900
+ _fnArrayApply(this, data);
6775
6901
 
6776
6902
  // selector
6777
6903
  this.selector = {
@@ -7152,7 +7278,7 @@ var __table_selector = function ( selector, a )
7152
7278
  selector.forEach(function (sel) {
7153
7279
  var inner = __table_selector(sel, a);
7154
7280
 
7155
- result.push.apply(result, inner);
7281
+ _fnArrayApply(result, inner);
7156
7282
  });
7157
7283
 
7158
7284
  return result.filter( function (item) {
@@ -8006,7 +8132,7 @@ _api_register( 'rows.add()', function ( rows ) {
8006
8132
  // Return an Api.rows() extended instance, so rows().nodes() etc can be used
8007
8133
  var modRows = this.rows( -1 );
8008
8134
  modRows.pop();
8009
- modRows.push.apply(modRows, newRows);
8135
+ _fnArrayApply(modRows, newRows);
8010
8136
 
8011
8137
  return modRows;
8012
8138
  } );
@@ -8519,7 +8645,10 @@ var __column_selector = function ( settings, selector, opts )
8519
8645
  .map( function () {
8520
8646
  return _fnColumnsFromHeader( this ); // `nodes` is column index complete and in order
8521
8647
  } )
8522
- .toArray();
8648
+ .toArray()
8649
+ .sort(function (a, b) {
8650
+ return a - b;
8651
+ });
8523
8652
 
8524
8653
  if ( jqResult.length || ! s.nodeName ) {
8525
8654
  return jqResult;
@@ -8773,6 +8902,10 @@ _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type
8773
8902
 
8774
8903
  _api_register( 'columns.adjust()', function () {
8775
8904
  return this.iterator( 'table', function ( settings ) {
8905
+ // Force a column sizing to happen with a manual call - otherwise it can skip
8906
+ // if the size hasn't changed
8907
+ settings.containerWidth = -1;
8908
+
8776
8909
  _fnAdjustColumnSizing( settings );
8777
8910
  }, 1 );
8778
8911
  } );
@@ -9338,6 +9471,10 @@ _api_register( 'state.save()', function () {
9338
9471
  } );
9339
9472
  } );
9340
9473
 
9474
+ // Can be assigned in DateTable.use() - note luxon and moment vars are in helpers.js
9475
+ var __bootstrap;
9476
+ var __foundation;
9477
+
9341
9478
  /**
9342
9479
  * Set the libraries that DataTables uses, or the global objects.
9343
9480
  * Note that the arguments can be either way around (legacy support)
@@ -9371,6 +9508,14 @@ DataTable.use = function (arg1, arg2) {
9371
9508
  case 'moment':
9372
9509
  return __moment;
9373
9510
 
9511
+ case 'bootstrap':
9512
+ // Use local if set, otherwise try window, which could be undefined
9513
+ return __bootstrap || window.bootstrap;
9514
+
9515
+ case 'foundation':
9516
+ // Ditto
9517
+ return __foundation || window.Foundation;
9518
+
9374
9519
  default:
9375
9520
  return null;
9376
9521
  }
@@ -9380,7 +9525,7 @@ DataTable.use = function (arg1, arg2) {
9380
9525
  if (type === 'lib' || type === 'jq' || (module && module.fn && module.fn.jquery)) {
9381
9526
  $ = module;
9382
9527
  }
9383
- else if (type == 'win' || (module && module.document)) {
9528
+ else if (type === 'win' || (module && module.document)) {
9384
9529
  window = module;
9385
9530
  document = module.document;
9386
9531
  }
@@ -9393,6 +9538,14 @@ DataTable.use = function (arg1, arg2) {
9393
9538
  else if (type === 'moment' || (module && module.isMoment)) {
9394
9539
  __moment = module;
9395
9540
  }
9541
+ else if (type === 'bootstrap' || (module && module.Modal && module.Modal.NAME === 'modal'))
9542
+ {
9543
+ // This is currently for BS5 only. BS3/4 attach to jQuery, so no need to use `.use()`
9544
+ __bootstrap = module;
9545
+ }
9546
+ else if (type === 'foundation' || (module && module.Reveal)) {
9547
+ __foundation = module;
9548
+ }
9396
9549
  }
9397
9550
 
9398
9551
  /**
@@ -9683,6 +9836,11 @@ _api_register( 'destroy()', function ( remove ) {
9683
9836
  new _Api( settings ).columns().visible( true );
9684
9837
  }
9685
9838
 
9839
+ // Container width change listener
9840
+ if (settings.resizeObserver) {
9841
+ settings.resizeObserver.disconnect();
9842
+ }
9843
+
9686
9844
  // Blitz all `DT` namespaced events (these are internal events, the
9687
9845
  // lowercase, `dt` events are user subscribed and they are responsible
9688
9846
  // for removing them
@@ -9801,7 +9959,7 @@ _api_register( 'i18n()', function ( token, def, plural ) {
9801
9959
  * @type string
9802
9960
  * @default Version number
9803
9961
  */
9804
- DataTable.version = "2.1.8";
9962
+ DataTable.version = "2.2.1";
9805
9963
 
9806
9964
  /**
9807
9965
  * Private data store, containing all of the settings objects that are
@@ -11904,7 +12062,13 @@ DataTable.models.oSettings = {
11904
12062
  deferLoading: null,
11905
12063
 
11906
12064
  /** Allow auto type detection */
11907
- typeDetect: true
12065
+ typeDetect: true,
12066
+
12067
+ /** ResizeObserver for the container div */
12068
+ resizeObserver: null,
12069
+
12070
+ /** Keep a record of the last size of the container, so we can skip duplicates */
12071
+ containerWidth: -1
11908
12072
  };
11909
12073
 
11910
12074
  /**
@@ -12046,8 +12210,8 @@ function __mld( dtLib, momentFn, luxonFn, dateFn, arg1 ) {
12046
12210
 
12047
12211
 
12048
12212
  var __mlWarning = false;
12049
- var __luxon; // Can be assigned in DateTeble.use()
12050
- var __moment; // Can be assigned in DateTeble.use()
12213
+ var __luxon; // Can be assigned in DateTable.use()
12214
+ var __moment; // Can be assigned in DateTable.use()
12051
12215
 
12052
12216
  /**
12053
12217
  *
@@ -12083,7 +12247,7 @@ function __mldObj (d, format, locale) {
12083
12247
  return null;
12084
12248
  }
12085
12249
 
12086
- dt.setLocale(locale);
12250
+ dt = dt.setLocale(locale);
12087
12251
  }
12088
12252
  else if (! format) {
12089
12253
  // No format given, must be ISO
@@ -12466,6 +12630,13 @@ var __diacriticSort = function (a, b) {
12466
12630
  });
12467
12631
  }
12468
12632
 
12633
+ var __diacriticHtmlSort = function (a, b) {
12634
+ a = _stripHtml(a);
12635
+ b = _stripHtml(b);
12636
+
12637
+ return __diacriticSort(a, b);
12638
+ }
12639
+
12469
12640
  //
12470
12641
  // Built in data types
12471
12642
  //
@@ -12536,6 +12707,31 @@ DataTable.type('html', {
12536
12707
  });
12537
12708
 
12538
12709
 
12710
+ DataTable.type('html-utf8', {
12711
+ detect: {
12712
+ allOf: function ( d ) {
12713
+ return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1);
12714
+ },
12715
+ oneOf: function ( d ) {
12716
+ // At least one data point must contain a `<` and a non-ASCII character
12717
+ // eslint-disable-next-line compat/compat
12718
+ return navigator.languages &&
12719
+ ! _empty( d ) &&
12720
+ typeof d === 'string' &&
12721
+ d.indexOf('<') !== -1 &&
12722
+ typeof d === 'string' && d.match(/[^\x00-\x7F]/);
12723
+ }
12724
+ },
12725
+ order: {
12726
+ asc: __diacriticHtmlSort,
12727
+ desc: function (a, b) {
12728
+ return __diacriticHtmlSort(a, b) * -1;
12729
+ }
12730
+ },
12731
+ search: _filterString(true, true)
12732
+ });
12733
+
12734
+
12539
12735
  DataTable.type('date', {
12540
12736
  className: 'dt-type-date',
12541
12737
  detect: {
@@ -12746,6 +12942,7 @@ $.extend( true, DataTable.ext.renderer, {
12746
12942
  var indexes = columns.indexes();
12747
12943
  var sortDirs = columns.orderable(true).flatten();
12748
12944
  var orderedColumns = _pluck(sorting, 'col');
12945
+ var tabIndex = settings.iTabIndex;
12749
12946
 
12750
12947
  cell
12751
12948
  .removeClass(
@@ -12810,8 +13007,13 @@ $.extend( true, DataTable.ext.renderer, {
12810
13007
 
12811
13008
  // Make the headers tab-able for keyboard navigation
12812
13009
  if (orderable) {
12813
- cell.find('.dt-column-title').attr('role', 'button');
12814
- cell.attr('tabindex', 0)
13010
+ var orderSpan = cell.find('.dt-column-order');
13011
+
13012
+ orderSpan.attr('role', 'button');
13013
+
13014
+ if (tabIndex !== -1) {
13015
+ orderSpan.attr('tabindex', tabIndex);
13016
+ }
12815
13017
  }
12816
13018
  } );
12817
13019
  }
@@ -12825,7 +13027,7 @@ $.extend( true, DataTable.ext.renderer, {
12825
13027
  .addClass(items.className || classes.row)
12826
13028
  .appendTo( container );
12827
13029
 
12828
- $.each( items, function (key, val) {
13030
+ DataTable.ext.renderer.layout._forLayoutRow(items, function (key, val) {
12829
13031
  if (key === 'id' || key === 'className') {
12830
13032
  return;
12831
13033
  }
@@ -12856,7 +13058,31 @@ $.extend( true, DataTable.ext.renderer, {
12856
13058
  })
12857
13059
  .append( val.contents )
12858
13060
  .appendTo( row );
12859
- } );
13061
+ });
13062
+ },
13063
+
13064
+ // Shared for use by the styling frameworks
13065
+ _forLayoutRow: function (items, fn) {
13066
+ // As we are inserting dom elements, we need start / end in a
13067
+ // specific order, this function is used for sorting the layout
13068
+ // keys.
13069
+ var layoutEnum = function (x) {
13070
+ switch (x) {
13071
+ case '': return 0;
13072
+ case 'start': return 1;
13073
+ case 'end': return 2;
13074
+ default: return 3;
13075
+ }
13076
+ };
13077
+
13078
+ Object
13079
+ .keys(items)
13080
+ .sort(function (a, b) {
13081
+ return layoutEnum(a) - layoutEnum(b);
13082
+ })
13083
+ .forEach(function (key) {
13084
+ fn(key, items[key]);
13085
+ });
12860
13086
  }
12861
13087
  }
12862
13088
  } );
@@ -13208,7 +13434,7 @@ function _pagingDraw(settings, host, opts) {
13208
13434
  'data-dt-idx': button,
13209
13435
  'tabIndex': btnInfo.disabled
13210
13436
  ? -1
13211
- : settings.iTabIndex
13437
+ : settings.iTabIndex && btn.clicker[0].nodeName.toLowerCase() !== 'span'
13212
13438
  ? settings.iTabIndex
13213
13439
  : null, // `0` doesn't need a tabIndex since it is the default
13214
13440
  });
@@ -13242,12 +13468,16 @@ function _pagingDraw(settings, host, opts) {
13242
13468
 
13243
13469
  // Responsive - check if the buttons are over two lines based on the
13244
13470
  // height of the buttons and the container.
13245
- if (
13246
- buttonEls.length && // any buttons
13247
- opts.buttons > 1 && // prevent infinite
13248
- $(host).height() >= ($(buttonEls[0]).outerHeight() * 2) - 10
13249
- ) {
13250
- _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 }));
13471
+ if (buttonEls.length) {
13472
+ var outerHeight = $(buttonEls[0]).outerHeight();
13473
+
13474
+ if (
13475
+ opts.buttons > 1 && // prevent infinite
13476
+ outerHeight > 0 && // will be 0 if hidden
13477
+ $(host).height() >= (outerHeight * 2) - 10
13478
+ ) {
13479
+ _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 }));
13480
+ }
13251
13481
  }
13252
13482
  }
13253
13483
 
@@ -13271,7 +13501,6 @@ function _pagingButtonInfo(settings, button, page, pages) {
13271
13501
  switch ( button ) {
13272
13502
  case 'ellipsis':
13273
13503
  o.display = '&#x2026;';
13274
- o.disabled = true;
13275
13504
  break;
13276
13505
 
13277
13506
  case 'first':
@@ -13458,7 +13687,7 @@ DataTable.feature.register( 'pageLength', function ( settings, opts ) {
13458
13687
 
13459
13688
  // Save text node content for macro updating
13460
13689
  var textNodes = [];
13461
- Array.from(div.find('label')[0].childNodes).forEach(function (el) {
13690
+ Array.prototype.slice.call(div.find('label')[0].childNodes).forEach(function (el) {
13462
13691
  if (el.nodeType === Node.TEXT_NODE) {
13463
13692
  textNodes.push({
13464
13693
  el: el,
@@ -13476,7 +13705,6 @@ DataTable.feature.register( 'pageLength', function ( settings, opts ) {
13476
13705
 
13477
13706
  // Next, the select itself, along with the options
13478
13707
  var select = $('<select/>', {
13479
- 'name': tableId+'_length',
13480
13708
  'aria-controls': tableId,
13481
13709
  'class': classes.select
13482
13710
  } );