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.js CHANGED
@@ -1,25 +1,7 @@
1
- /*! DataTables 2.1.8
1
+ /*! DataTables 2.2.1
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.1.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
 
@@ -429,7 +411,6 @@
429
411
  thead = $('<thead/>').appendTo($this);
430
412
  }
431
413
  oSettings.nTHead = thead[0];
432
- $('tr', thead).addClass(oClasses.thead.row);
433
414
 
434
415
  var tbody = $this.children('tbody');
435
416
  if ( tbody.length === 0 ) {
@@ -444,7 +425,6 @@
444
425
  tfoot = $('<tfoot/>').appendTo($this);
445
426
  }
446
427
  oSettings.nTFoot = tfoot[0];
447
- $('tr', tfoot).addClass(oClasses.tfoot.row);
448
428
 
449
429
  // Copy the data index array
450
430
  oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
@@ -2161,6 +2141,10 @@
2161
2141
  var width = _fnColumnsSumWidth(settings, [i], false, false);
2162
2142
 
2163
2143
  cols[i].colEl.css('width', width);
2144
+
2145
+ if (settings.oScroll.sX) {
2146
+ cols[i].colEl.css('min-width', width);
2147
+ }
2164
2148
  }
2165
2149
  }
2166
2150
 
@@ -3228,9 +3212,13 @@
3228
3212
 
3229
3213
  // Add the number of cells needed to make up to the number of columns
3230
3214
  if (row.length === 1) {
3231
- var cells = $('td, th', row);
3215
+ var cellCount = 0;
3216
+
3217
+ $('td, th', row).each(function () {
3218
+ cellCount += this.colSpan;
3219
+ });
3232
3220
 
3233
- for ( i=cells.length, ien=columns.length ; i<ien ; i++ ) {
3221
+ for ( i=cellCount, ien=columns.length ; i<ien ; i++ ) {
3234
3222
  $('<th/>')
3235
3223
  .html( columns[i][titleProp] || '' )
3236
3224
  .appendTo( row );
@@ -3242,9 +3230,11 @@
3242
3230
 
3243
3231
  if (side === 'header') {
3244
3232
  settings.aoHeader = detected;
3233
+ $('tr', target).addClass(classes.thead.row);
3245
3234
  }
3246
3235
  else {
3247
3236
  settings.aoFooter = detected;
3237
+ $('tr', target).addClass(classes.tfoot.row);
3248
3238
  }
3249
3239
 
3250
3240
  // Every cell needs to be passed through the renderer
@@ -4507,7 +4497,7 @@
4507
4497
  // So the array reference doesn't break set the results into the
4508
4498
  // existing array
4509
4499
  displayRows.length = 0;
4510
- displayRows.push.apply(displayRows, rows);
4500
+ _fnArrayApply(displayRows, rows);
4511
4501
  }
4512
4502
  }
4513
4503
 
@@ -5235,8 +5225,11 @@
5235
5225
  // [].find, but it wasn't supported in Chrome until Sept 2015, and DT has 10 year
5236
5226
  // browser support
5237
5227
  var firstTr = null;
5228
+ var start = _fnDataSource( settings ) !== 'ssp'
5229
+ ? settings._iDisplayStart
5230
+ : 0;
5238
5231
 
5239
- for (i=settings._iDisplayStart ; i<settings.aiDisplay.length ; i++) {
5232
+ for (i=start ; i<start + settings.aiDisplay.length ; i++) {
5240
5233
  var idx = settings.aiDisplay[i];
5241
5234
  var tr = settings.aoData[idx].nTr;
5242
5235
 
@@ -5251,7 +5244,7 @@
5251
5244
  return {
5252
5245
  idx: _fnVisibleToColumnIndex(settings, vis),
5253
5246
  width: $(this).outerWidth()
5254
- }
5247
+ };
5255
5248
  });
5256
5249
 
5257
5250
  // Check against what the colgroup > col is set to and correct if needed
@@ -5261,6 +5254,10 @@
5261
5254
 
5262
5255
  if (colWidth !== colSizes[i].width) {
5263
5256
  colEl.style.width = colSizes[i].width + 'px';
5257
+
5258
+ if (scroll.sX) {
5259
+ colEl.style.minWidth = colSizes[i].width + 'px';
5260
+ }
5264
5261
  }
5265
5262
  }
5266
5263
  }
@@ -5353,6 +5350,14 @@
5353
5350
  i, column, columnIdx;
5354
5351
 
5355
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;
5356
5361
 
5357
5362
  // If there is no width applied as a CSS style or as an attribute, we assume that
5358
5363
  // the width is intended to be 100%, which is usually is in CSS, but it is very
@@ -5410,6 +5415,8 @@
5410
5415
  // browser will collapse it. If this width is smaller than the
5411
5416
  // width the column requires, then it will have no effect
5412
5417
  if ( scrollX ) {
5418
+ this.style.minWidth = width;
5419
+
5413
5420
  $( this ).append( $('<div/>').css( {
5414
5421
  width: width,
5415
5422
  margin: 0,
@@ -5478,15 +5485,15 @@
5478
5485
 
5479
5486
  // If there is no width attribute or style, then allow the table to
5480
5487
  // collapse
5481
- if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5482
- tmpTable.width( tableContainer.clientWidth );
5488
+ if ( tmpTable.outerWidth() < tableContainer.clientWidth && tableWidthAttr ) {
5489
+ tmpTable.outerWidth( tableContainer.clientWidth );
5483
5490
  }
5484
5491
  }
5485
5492
  else if ( scrollY ) {
5486
- tmpTable.width( tableContainer.clientWidth );
5493
+ tmpTable.outerWidth( tableContainer.clientWidth );
5487
5494
  }
5488
5495
  else if ( tableWidthAttr ) {
5489
- tmpTable.width( tableWidthAttr );
5496
+ tmpTable.outerWidth( tableWidthAttr );
5490
5497
  }
5491
5498
 
5492
5499
  // Get the width of each column in the constructed table
@@ -5519,20 +5526,55 @@
5519
5526
  }
5520
5527
 
5521
5528
  if ( (tableWidthAttr || scrollX) && ! settings._reszEvt ) {
5522
- var bindResize = function () {
5523
- $(window).on('resize.DT-'+settings.sInstance, DataTable.util.throttle( function () {
5524
- if (! settings.bDestroying) {
5525
- _fnAdjustColumnSizing( settings );
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
+ settings.resizeObserver = new ResizeObserver(function (e) {
5548
+ if (first) {
5549
+ first = false;
5526
5550
  }
5527
- } ) );
5528
- };
5551
+ else {
5552
+ resize();
5553
+ }
5554
+ });
5529
5555
 
5530
- bindResize();
5556
+ settings.resizeObserver.observe(settings.nTableWrapper);
5557
+ }
5558
+ else {
5559
+ // For old browsers, the best we can do is listen for a window resize
5560
+ $(window).on('resize.DT-'+settings.sInstance, resize);
5561
+ }
5531
5562
 
5532
5563
  settings._reszEvt = true;
5533
5564
  }
5534
5565
  }
5535
5566
 
5567
+ /**
5568
+ * Get the width of the DataTables wrapper element
5569
+ *
5570
+ * @param {*} settings DataTables settings object
5571
+ * @returns Width
5572
+ */
5573
+ function _fnWrapperWidth(settings) {
5574
+ return $(settings.nTableWrapper).is(':visible')
5575
+ ? $(settings.nTableWrapper).width()
5576
+ : 0;
5577
+ }
5536
5578
 
5537
5579
  /**
5538
5580
  * Get the maximum strlen for each data column
@@ -6141,15 +6183,26 @@
6141
6183
  return;
6142
6184
  }
6143
6185
 
6186
+ // Sort state saving uses [[idx, order]] structure.
6187
+ var sorting = [];
6188
+ _fnSortResolve(settings, sorting, settings.aaSorting );
6189
+
6144
6190
  /* Store the interesting variables */
6191
+ var columns = settings.aoColumns;
6145
6192
  var state = {
6146
6193
  time: +new Date(),
6147
6194
  start: settings._iDisplayStart,
6148
6195
  length: settings._iDisplayLength,
6149
- order: $.extend( true, [], settings.aaSorting ),
6196
+ order: sorting.map(function (sort) {
6197
+ // If a column name is available, use it
6198
+ return columns[sort[0]] && columns[sort[0]].sName
6199
+ ? [ columns[sort[0]].sName, sort[1] ]
6200
+ : sort.slice();
6201
+ } ),
6150
6202
  search: $.extend({}, settings.oPreviousSearch),
6151
6203
  columns: settings.aoColumns.map( function ( col, i ) {
6152
6204
  return {
6205
+ name: col.sName,
6153
6206
  visible: col.bVisible,
6154
6207
  search: $.extend({}, settings.aoPreSearchCols[i])
6155
6208
  };
@@ -6197,6 +6250,8 @@
6197
6250
  function _fnImplementState ( settings, s, callback) {
6198
6251
  var i, ien;
6199
6252
  var columns = settings.aoColumns;
6253
+ var currentNames = _pluck(settings.aoColumns, 'sName');
6254
+
6200
6255
  settings._bLoadingState = true;
6201
6256
 
6202
6257
  // When StateRestore was introduced the state could now be implemented at any time
@@ -6226,13 +6281,6 @@
6226
6281
  return;
6227
6282
  }
6228
6283
 
6229
- // Number of columns have changed - all bets are off, no restore of settings
6230
- if ( s.columns && columns.length !== s.columns.length ) {
6231
- settings._bLoadingState = false;
6232
- callback();
6233
- return;
6234
- }
6235
-
6236
6284
  // Store the saved state so it might be accessed at any time
6237
6285
  settings.oLoadedState = $.extend( true, {}, s );
6238
6286
 
@@ -6266,10 +6314,23 @@
6266
6314
  if ( s.order !== undefined ) {
6267
6315
  settings.aaSorting = [];
6268
6316
  $.each( s.order, function ( i, col ) {
6269
- settings.aaSorting.push( col[0] >= columns.length ?
6270
- [ 0, col[1] ] :
6271
- col
6272
- );
6317
+ var set = [ col[0], col[1] ];
6318
+
6319
+ // A column name was stored and should be used for restore
6320
+ if (typeof col[0] === 'string') {
6321
+ var idx = currentNames.indexOf(col[0]);
6322
+
6323
+ // Find the name from the current list of column names, or fallback to index 0
6324
+ set[0] = idx >= 0
6325
+ ? idx
6326
+ : 0;
6327
+ }
6328
+ else if (set[0] >= columns.length) {
6329
+ // If a column name, but it is out of bounds, set to 0
6330
+ set[0] = 0;
6331
+ }
6332
+
6333
+ settings.aaSorting.push(set);
6273
6334
  } );
6274
6335
  }
6275
6336
 
@@ -6280,31 +6341,65 @@
6280
6341
 
6281
6342
  // Columns
6282
6343
  if ( s.columns ) {
6283
- for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6284
- var col = s.columns[i];
6285
-
6286
- // Visibility
6287
- if ( col.visible !== undefined ) {
6288
- // If the api is defined, the table has been initialised so we need to use it rather than internal settings
6289
- if (api) {
6290
- // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6291
- api.column(i).visible(col.visible, false);
6344
+ var set = s.columns;
6345
+ var incoming = _pluck(s.columns, 'name');
6346
+
6347
+ // Check if it is a 2.2 style state object with a `name` property for the columns, and if
6348
+ // the name was defined. If so, then create a new array that will map the state object
6349
+ // given, to the current columns (don't bother if they are already matching tho).
6350
+ if (incoming.join('').length && incoming.join('') !== currentNames.join('')) {
6351
+ set = [];
6352
+
6353
+ // For each column, try to find the name in the incoming array
6354
+ for (i=0 ; i<currentNames.length ; i++) {
6355
+ if (currentNames[i] != '') {
6356
+ var idx = incoming.indexOf(currentNames[i]);
6357
+
6358
+ if (idx >= 0) {
6359
+ set.push(s.columns[idx]);
6360
+ }
6361
+ else {
6362
+ // No matching column name in the state's columns, so this might be a new
6363
+ // column and thus can't have a state already.
6364
+ set.push({});
6365
+ }
6292
6366
  }
6293
6367
  else {
6294
- columns[i].bVisible = col.visible;
6368
+ // If no name, but other columns did have a name, then there is no knowing
6369
+ // where this one came from originally so it can't be restored.
6370
+ set.push({});
6371
+ }
6372
+ }
6373
+ }
6374
+
6375
+ // If the number of columns to restore is different from current, then all bets are off.
6376
+ if (set.length === columns.length) {
6377
+ for ( i=0, ien=set.length ; i<ien ; i++ ) {
6378
+ var col = set[i];
6379
+
6380
+ // Visibility
6381
+ if ( col.visible !== undefined ) {
6382
+ // If the api is defined, the table has been initialised so we need to use it rather than internal settings
6383
+ if (api) {
6384
+ // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6385
+ api.column(i).visible(col.visible, false);
6386
+ }
6387
+ else {
6388
+ columns[i].bVisible = col.visible;
6389
+ }
6390
+ }
6391
+
6392
+ // Search
6393
+ if ( col.search !== undefined ) {
6394
+ $.extend( settings.aoPreSearchCols[i], col.search );
6295
6395
  }
6296
6396
  }
6297
6397
 
6298
- // Search
6299
- if ( col.search !== undefined ) {
6300
- $.extend( settings.aoPreSearchCols[i], col.search );
6398
+ // If the api is defined then we need to adjust the columns once the visibility has been changed
6399
+ if (api) {
6400
+ api.columns.adjust();
6301
6401
  }
6302
6402
  }
6303
-
6304
- // If the api is defined then we need to adjust the columns once the visibility has been changed
6305
- if (api) {
6306
- api.columns.adjust();
6307
- }
6308
6403
  }
6309
6404
 
6310
6405
  settings._bLoadingState = false;
@@ -6621,6 +6716,30 @@
6621
6716
  replace(/_ENTRIES-TOTAL_/g, settings.api.i18n('entries', '', vis) );
6622
6717
  }
6623
6718
 
6719
+ /**
6720
+ * Add elements to an array as quickly as possible, but stack stafe.
6721
+ *
6722
+ * @param {*} arr Array to add the data to
6723
+ * @param {*} data Data array that is to be added
6724
+ * @returns
6725
+ */
6726
+ function _fnArrayApply(arr, data) {
6727
+ if (! data) {
6728
+ return;
6729
+ }
6730
+
6731
+ // Chrome can throw a max stack error if apply is called with
6732
+ // too large an array, but apply is faster.
6733
+ if (data.length < 10000) {
6734
+ arr.push.apply(arr, data);
6735
+ }
6736
+ else {
6737
+ for (i=0 ; i<data.length ; i++) {
6738
+ arr.push(data[i]);
6739
+ }
6740
+ }
6741
+ }
6742
+
6624
6743
 
6625
6744
 
6626
6745
  /**
@@ -6813,18 +6932,7 @@
6813
6932
  : settings;
6814
6933
 
6815
6934
  // Initial data
6816
- if ( data ) {
6817
- // Chrome can throw a max stack error if apply is called with
6818
- // too large an array, but apply is faster.
6819
- if (data.length < 10000) {
6820
- this.push.apply(this, data);
6821
- }
6822
- else {
6823
- for (i=0 ; i<data.length ; i++) {
6824
- this.push(data[i]);
6825
- }
6826
- }
6827
- }
6935
+ _fnArrayApply(this, data);
6828
6936
 
6829
6937
  // selector
6830
6938
  this.selector = {
@@ -7205,7 +7313,7 @@
7205
7313
  selector.forEach(function (sel) {
7206
7314
  var inner = __table_selector(sel, a);
7207
7315
 
7208
- result.push.apply(result, inner);
7316
+ _fnArrayApply(result, inner);
7209
7317
  });
7210
7318
 
7211
7319
  return result.filter( function (item) {
@@ -8059,7 +8167,7 @@
8059
8167
  // Return an Api.rows() extended instance, so rows().nodes() etc can be used
8060
8168
  var modRows = this.rows( -1 );
8061
8169
  modRows.pop();
8062
- modRows.push.apply(modRows, newRows);
8170
+ _fnArrayApply(modRows, newRows);
8063
8171
 
8064
8172
  return modRows;
8065
8173
  } );
@@ -8572,7 +8680,10 @@
8572
8680
  .map( function () {
8573
8681
  return _fnColumnsFromHeader( this ); // `nodes` is column index complete and in order
8574
8682
  } )
8575
- .toArray();
8683
+ .toArray()
8684
+ .sort(function (a, b) {
8685
+ return a - b;
8686
+ });
8576
8687
 
8577
8688
  if ( jqResult.length || ! s.nodeName ) {
8578
8689
  return jqResult;
@@ -8826,6 +8937,10 @@
8826
8937
 
8827
8938
  _api_register( 'columns.adjust()', function () {
8828
8939
  return this.iterator( 'table', function ( settings ) {
8940
+ // Force a column sizing to happen with a manual call - otherwise it can skip
8941
+ // if the size hasn't changed
8942
+ settings.containerWidth = -1;
8943
+
8829
8944
  _fnAdjustColumnSizing( settings );
8830
8945
  }, 1 );
8831
8946
  } );
@@ -9391,6 +9506,10 @@
9391
9506
  } );
9392
9507
  } );
9393
9508
 
9509
+ // Can be assigned in DateTable.use() - note luxon and moment vars are in helpers.js
9510
+ var __bootstrap;
9511
+ var __foundation;
9512
+
9394
9513
  /**
9395
9514
  * Set the libraries that DataTables uses, or the global objects.
9396
9515
  * Note that the arguments can be either way around (legacy support)
@@ -9424,6 +9543,14 @@
9424
9543
  case 'moment':
9425
9544
  return __moment;
9426
9545
 
9546
+ case 'bootstrap':
9547
+ // Use local if set, otherwise try window, which could be undefined
9548
+ return __bootstrap || window.bootstrap;
9549
+
9550
+ case 'foundation':
9551
+ // Ditto
9552
+ return __foundation || window.Foundation;
9553
+
9427
9554
  default:
9428
9555
  return null;
9429
9556
  }
@@ -9433,7 +9560,7 @@
9433
9560
  if (type === 'lib' || type === 'jq' || (module && module.fn && module.fn.jquery)) {
9434
9561
  $ = module;
9435
9562
  }
9436
- else if (type == 'win' || (module && module.document)) {
9563
+ else if (type === 'win' || (module && module.document)) {
9437
9564
  window = module;
9438
9565
  document = module.document;
9439
9566
  }
@@ -9446,6 +9573,14 @@
9446
9573
  else if (type === 'moment' || (module && module.isMoment)) {
9447
9574
  __moment = module;
9448
9575
  }
9576
+ else if (type === 'bootstrap' || (module && module.Modal && module.Modal.NAME === 'modal'))
9577
+ {
9578
+ // This is currently for BS5 only. BS3/4 attach to jQuery, so no need to use `.use()`
9579
+ __bootstrap = module;
9580
+ }
9581
+ else if (type === 'foundation' || (module && module.Reveal)) {
9582
+ __foundation = module;
9583
+ }
9449
9584
  }
9450
9585
 
9451
9586
  /**
@@ -9736,6 +9871,11 @@
9736
9871
  new _Api( settings ).columns().visible( true );
9737
9872
  }
9738
9873
 
9874
+ // Container width change listener
9875
+ if (settings.resizeObserver) {
9876
+ settings.resizeObserver.disconnect();
9877
+ }
9878
+
9739
9879
  // Blitz all `DT` namespaced events (these are internal events, the
9740
9880
  // lowercase, `dt` events are user subscribed and they are responsible
9741
9881
  // for removing them
@@ -9854,7 +9994,7 @@
9854
9994
  * @type string
9855
9995
  * @default Version number
9856
9996
  */
9857
- DataTable.version = "2.1.8";
9997
+ DataTable.version = "2.2.1";
9858
9998
 
9859
9999
  /**
9860
10000
  * Private data store, containing all of the settings objects that are
@@ -11957,7 +12097,13 @@
11957
12097
  deferLoading: null,
11958
12098
 
11959
12099
  /** Allow auto type detection */
11960
- typeDetect: true
12100
+ typeDetect: true,
12101
+
12102
+ /** ResizeObserver for the container div */
12103
+ resizeObserver: null,
12104
+
12105
+ /** Keep a record of the last size of the container, so we can skip duplicates */
12106
+ containerWidth: -1
11961
12107
  };
11962
12108
 
11963
12109
  /**
@@ -12099,8 +12245,8 @@
12099
12245
 
12100
12246
 
12101
12247
  var __mlWarning = false;
12102
- var __luxon; // Can be assigned in DateTeble.use()
12103
- var __moment; // Can be assigned in DateTeble.use()
12248
+ var __luxon; // Can be assigned in DateTable.use()
12249
+ var __moment; // Can be assigned in DateTable.use()
12104
12250
 
12105
12251
  /**
12106
12252
  *
@@ -12136,7 +12282,7 @@
12136
12282
  return null;
12137
12283
  }
12138
12284
 
12139
- dt.setLocale(locale);
12285
+ dt = dt.setLocale(locale);
12140
12286
  }
12141
12287
  else if (! format) {
12142
12288
  // No format given, must be ISO
@@ -12519,6 +12665,13 @@
12519
12665
  });
12520
12666
  }
12521
12667
 
12668
+ var __diacriticHtmlSort = function (a, b) {
12669
+ a = _stripHtml(a);
12670
+ b = _stripHtml(b);
12671
+
12672
+ return __diacriticSort(a, b);
12673
+ }
12674
+
12522
12675
  //
12523
12676
  // Built in data types
12524
12677
  //
@@ -12589,6 +12742,31 @@
12589
12742
  });
12590
12743
 
12591
12744
 
12745
+ DataTable.type('html-utf8', {
12746
+ detect: {
12747
+ allOf: function ( d ) {
12748
+ return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1);
12749
+ },
12750
+ oneOf: function ( d ) {
12751
+ // At least one data point must contain a `<` and a non-ASCII character
12752
+ // eslint-disable-next-line compat/compat
12753
+ return navigator.languages &&
12754
+ ! _empty( d ) &&
12755
+ typeof d === 'string' &&
12756
+ d.indexOf('<') !== -1 &&
12757
+ typeof d === 'string' && d.match(/[^\x00-\x7F]/);
12758
+ }
12759
+ },
12760
+ order: {
12761
+ asc: __diacriticHtmlSort,
12762
+ desc: function (a, b) {
12763
+ return __diacriticHtmlSort(a, b) * -1;
12764
+ }
12765
+ },
12766
+ search: _filterString(true, true)
12767
+ });
12768
+
12769
+
12592
12770
  DataTable.type('date', {
12593
12771
  className: 'dt-type-date',
12594
12772
  detect: {
@@ -12799,6 +12977,7 @@
12799
12977
  var indexes = columns.indexes();
12800
12978
  var sortDirs = columns.orderable(true).flatten();
12801
12979
  var orderedColumns = _pluck(sorting, 'col');
12980
+ var tabIndex = settings.iTabIndex;
12802
12981
 
12803
12982
  cell
12804
12983
  .removeClass(
@@ -12863,8 +13042,13 @@
12863
13042
 
12864
13043
  // Make the headers tab-able for keyboard navigation
12865
13044
  if (orderable) {
12866
- cell.find('.dt-column-title').attr('role', 'button');
12867
- cell.attr('tabindex', 0)
13045
+ var orderSpan = cell.find('.dt-column-order');
13046
+
13047
+ orderSpan.attr('role', 'button');
13048
+
13049
+ if (tabIndex !== -1) {
13050
+ orderSpan.attr('tabindex', tabIndex);
13051
+ }
12868
13052
  }
12869
13053
  } );
12870
13054
  }
@@ -12878,7 +13062,7 @@
12878
13062
  .addClass(items.className || classes.row)
12879
13063
  .appendTo( container );
12880
13064
 
12881
- $.each( items, function (key, val) {
13065
+ DataTable.ext.renderer.layout._forLayoutRow(items, function (key, val) {
12882
13066
  if (key === 'id' || key === 'className') {
12883
13067
  return;
12884
13068
  }
@@ -12909,7 +13093,31 @@
12909
13093
  })
12910
13094
  .append( val.contents )
12911
13095
  .appendTo( row );
12912
- } );
13096
+ });
13097
+ },
13098
+
13099
+ // Shared for use by the styling frameworks
13100
+ _forLayoutRow: function (items, fn) {
13101
+ // As we are inserting dom elements, we need start / end in a
13102
+ // specific order, this function is used for sorting the layout
13103
+ // keys.
13104
+ var layoutEnum = function (x) {
13105
+ switch (x) {
13106
+ case '': return 0;
13107
+ case 'start': return 1;
13108
+ case 'end': return 2;
13109
+ default: return 3;
13110
+ }
13111
+ };
13112
+
13113
+ Object
13114
+ .keys(items)
13115
+ .sort(function (a, b) {
13116
+ return layoutEnum(a) - layoutEnum(b);
13117
+ })
13118
+ .forEach(function (key) {
13119
+ fn(key, items[key]);
13120
+ });
12913
13121
  }
12914
13122
  }
12915
13123
  } );
@@ -13261,7 +13469,7 @@
13261
13469
  'data-dt-idx': button,
13262
13470
  'tabIndex': btnInfo.disabled
13263
13471
  ? -1
13264
- : settings.iTabIndex
13472
+ : settings.iTabIndex && btn.clicker[0].nodeName.toLowerCase() !== 'span'
13265
13473
  ? settings.iTabIndex
13266
13474
  : null, // `0` doesn't need a tabIndex since it is the default
13267
13475
  });
@@ -13295,12 +13503,16 @@
13295
13503
 
13296
13504
  // Responsive - check if the buttons are over two lines based on the
13297
13505
  // height of the buttons and the container.
13298
- if (
13299
- buttonEls.length && // any buttons
13300
- opts.buttons > 1 && // prevent infinite
13301
- $(host).height() >= ($(buttonEls[0]).outerHeight() * 2) - 10
13302
- ) {
13303
- _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 }));
13506
+ if (buttonEls.length) {
13507
+ var outerHeight = $(buttonEls[0]).outerHeight();
13508
+
13509
+ if (
13510
+ opts.buttons > 1 && // prevent infinite
13511
+ outerHeight > 0 && // will be 0 if hidden
13512
+ $(host).height() >= (outerHeight * 2) - 10
13513
+ ) {
13514
+ _pagingDraw(settings, host, $.extend({}, opts, { buttons: opts.buttons - 2 }));
13515
+ }
13304
13516
  }
13305
13517
  }
13306
13518
 
@@ -13324,7 +13536,6 @@
13324
13536
  switch ( button ) {
13325
13537
  case 'ellipsis':
13326
13538
  o.display = '&#x2026;';
13327
- o.disabled = true;
13328
13539
  break;
13329
13540
 
13330
13541
  case 'first':
@@ -13511,7 +13722,7 @@
13511
13722
 
13512
13723
  // Save text node content for macro updating
13513
13724
  var textNodes = [];
13514
- Array.from(div.find('label')[0].childNodes).forEach(function (el) {
13725
+ Array.prototype.slice.call(div.find('label')[0].childNodes).forEach(function (el) {
13515
13726
  if (el.nodeType === Node.TEXT_NODE) {
13516
13727
  textNodes.push({
13517
13728
  el: el,
@@ -13529,7 +13740,6 @@
13529
13740
 
13530
13741
  // Next, the select itself, along with the options
13531
13742
  var select = $('<select/>', {
13532
- 'name': tableId+'_length',
13533
13743
  'aria-controls': tableId,
13534
13744
  'class': classes.select
13535
13745
  } );