datatables.net 2.3.4 → 2.3.6

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.3.4
1
+ /*! DataTables 2.3.6
2
2
  * © SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -139,7 +139,7 @@ var DataTable = function ( selector, options )
139
139
  "sDestroyWidth": $this[0].style.width,
140
140
  "sInstance": sId,
141
141
  "sTableId": sId,
142
- colgroup: $('<colgroup>').prependTo(this),
142
+ colgroup: $('<colgroup>'),
143
143
  fastData: function (row, column, type) {
144
144
  return _fnGetCellData(oSettings, row, column, type);
145
145
  }
@@ -212,6 +212,7 @@ var DataTable = function ( selector, options )
212
212
  "orderHandler",
213
213
  "titleRow",
214
214
  "typeDetect",
215
+ "columnTitleTag",
215
216
  [ "iCookieDuration", "iStateDuration" ], // backwards compat
216
217
  [ "oSearch", "oPreviousSearch" ],
217
218
  [ "aoSearchCols", "aoPreSearchCols" ],
@@ -376,7 +377,7 @@ var DataTable = function ( selector, options )
376
377
 
377
378
  if ( oSettings.caption ) {
378
379
  if ( caption.length === 0 ) {
379
- caption = $('<caption/>').appendTo( $this );
380
+ caption = $('<caption/>').prependTo( $this );
380
381
  }
381
382
 
382
383
  caption.html( oSettings.caption );
@@ -389,6 +390,14 @@ var DataTable = function ( selector, options )
389
390
  oSettings.captionNode = caption[0];
390
391
  }
391
392
 
393
+ // Place the colgroup element in the correct location for the HTML structure
394
+ if (caption.length) {
395
+ oSettings.colgroup.insertAfter(caption);
396
+ }
397
+ else {
398
+ oSettings.colgroup.prependTo(oSettings.nTable);
399
+ }
400
+
392
401
  if ( thead.length === 0 ) {
393
402
  thead = $('<thead/>').appendTo($this);
394
403
  }
@@ -404,7 +413,7 @@ var DataTable = function ( selector, options )
404
413
  if ( tfoot.length === 0 ) {
405
414
  // If we are a scrolling table, and no footer has been given, then we need to create
406
415
  // a tfoot element for the caption element to be appended to
407
- tfoot = $('<tfoot/>').appendTo($this);
416
+ tfoot = $('<tfoot/>').insertAfter(thead);
408
417
  }
409
418
  oSettings.nTFoot = tfoot[0];
410
419
 
@@ -1245,7 +1254,7 @@ var _removeEmpty = function ( a )
1245
1254
  };
1246
1255
 
1247
1256
  // Replaceable function in api.util
1248
- var _stripHtml = function (input) {
1257
+ var _stripHtml = function (input, replacement) {
1249
1258
  if (! input || typeof input !== 'string') {
1250
1259
  return input;
1251
1260
  }
@@ -1257,7 +1266,7 @@ var _stripHtml = function (input) {
1257
1266
 
1258
1267
  var previous;
1259
1268
 
1260
- input = input.replace(_re_html, ''); // Complete tags
1269
+ input = input.replace(_re_html, replacement || ''); // Complete tags
1261
1270
 
1262
1271
  // Safety for incomplete script tag - use do / while to ensure that
1263
1272
  // we get all instances
@@ -1722,7 +1731,7 @@ DataTable.util = {
1722
1731
  }
1723
1732
  },
1724
1733
 
1725
- stripHtml: function (mixed) {
1734
+ stripHtml: function (mixed, replacement) {
1726
1735
  var type = typeof mixed;
1727
1736
 
1728
1737
  if (type === 'function') {
@@ -1730,7 +1739,7 @@ DataTable.util = {
1730
1739
  return;
1731
1740
  }
1732
1741
  else if (type === 'string') {
1733
- return _stripHtml(mixed);
1742
+ return _stripHtml(mixed, replacement);
1734
1743
  }
1735
1744
  return mixed;
1736
1745
  },
@@ -2902,12 +2911,12 @@ function _fnInvalidate( settings, rowIdx, src, colIdx )
2902
2911
 
2903
2912
  // Max length string. Its a fairly cheep recalculation, so not worth
2904
2913
  // something more complicated
2905
- cols[ colIdx ].maxLenString = null;
2914
+ cols[ colIdx ].wideStrings = null;
2906
2915
  }
2907
2916
  else {
2908
2917
  for ( i=0, iLen=cols.length ; i<iLen ; i++ ) {
2909
2918
  cols[i].sType = null;
2910
- cols[i].maxLenString = null;
2919
+ cols[i].wideStrings = null;
2911
2920
  }
2912
2921
 
2913
2922
  // Update DataTables special `DT_*` attributes for the row
@@ -3332,7 +3341,7 @@ function _fnHeaderLayout( settings, source, incColumns )
3332
3341
  colspan++;
3333
3342
  }
3334
3343
 
3335
- var titleSpan = $('span.dt-column-title', cell);
3344
+ var titleSpan = $('.dt-column-title', cell);
3336
3345
 
3337
3346
  structure[row][column] = {
3338
3347
  cell: cell,
@@ -3448,6 +3457,14 @@ function _fnDraw( oSettings, ajaxComplete )
3448
3457
  {
3449
3458
  var iDataIndex = aiDisplay[j];
3450
3459
  var aoData = oSettings.aoData[ iDataIndex ];
3460
+
3461
+ // Row has been deleted - can't be displayed
3462
+ if (aoData === null)
3463
+ {
3464
+ continue;
3465
+ }
3466
+
3467
+ // Row node hasn't been created yet
3451
3468
  if ( aoData.nTr === null )
3452
3469
  {
3453
3470
  _fnCreateTr( oSettings, iDataIndex );
@@ -4038,8 +4055,8 @@ function _fnDetectHeader ( settings, thead, write )
4038
4055
  }
4039
4056
 
4040
4057
  // Wrap the column title so we can write to it in future
4041
- if ( $('span.dt-column-title', cell).length === 0) {
4042
- $('<span>')
4058
+ if ( $('.dt-column-title', cell).length === 0) {
4059
+ $(document.createElement(settings.columnTitleTag))
4043
4060
  .addClass('dt-column-title')
4044
4061
  .append(cell.childNodes)
4045
4062
  .appendTo(cell);
@@ -4050,9 +4067,9 @@ function _fnDetectHeader ( settings, thead, write )
4050
4067
  isHeader &&
4051
4068
  jqCell.filter(':not([data-dt-order=disable])').length !== 0 &&
4052
4069
  jqCell.parent(':not([data-dt-order=disable])').length !== 0 &&
4053
- $('span.dt-column-order', cell).length === 0
4070
+ $('.dt-column-order', cell).length === 0
4054
4071
  ) {
4055
- $('<span>')
4072
+ $(document.createElement(settings.columnTitleTag))
4056
4073
  .addClass('dt-column-order')
4057
4074
  .appendTo(cell);
4058
4075
  }
@@ -4061,7 +4078,7 @@ function _fnDetectHeader ( settings, thead, write )
4061
4078
  // layout for those elements
4062
4079
  var headerFooter = isHeader ? 'header' : 'footer';
4063
4080
 
4064
- if ( $('span.dt-column-' + headerFooter, cell).length === 0) {
4081
+ if ( $('div.dt-column-' + headerFooter, cell).length === 0) {
4065
4082
  $('<div>')
4066
4083
  .addClass('dt-column-' + headerFooter)
4067
4084
  .append(cell.childNodes)
@@ -4218,6 +4235,10 @@ function _fnBuildAjax(oSettings, data, fn) {
4218
4235
  // Custom Ajax option to submit the parameters as a JSON string
4219
4236
  if (baseAjax.submitAs === 'json' && typeof data === 'object') {
4220
4237
  baseAjax.data = JSON.stringify(data);
4238
+
4239
+ if (!baseAjax.contentType) {
4240
+ baseAjax.contentType = 'application/json; charset=utf-8';
4241
+ }
4221
4242
  }
4222
4243
 
4223
4244
  if (typeof ajax === 'function') {
@@ -5373,7 +5394,7 @@ function _fnCalculateColumnWidths ( settings )
5373
5394
  visibleColumns = _fnGetColumns( settings, 'bVisible' ),
5374
5395
  tableWidthAttr = table.getAttribute('width'), // from DOM element
5375
5396
  tableContainer = table.parentNode,
5376
- i, column, columnIdx;
5397
+ i, j, column, columnIdx;
5377
5398
 
5378
5399
  var styleWidth = table.style.width;
5379
5400
  var containerWidth = _fnWrapperWidth(settings);
@@ -5407,17 +5428,16 @@ function _fnCalculateColumnWidths ( settings )
5407
5428
  false
5408
5429
  );
5409
5430
 
5410
- // Construct a single row, worst case, table with the widest
5411
- // node in the data, assign any user defined widths, then insert it into
5412
- // the DOM and allow the browser to do all the hard work of calculating
5413
- // table widths
5431
+ // Construct a worst case table with the widest, assign any user defined
5432
+ // widths, then insert it into the DOM and allow the browser to do all
5433
+ // the hard work of calculating table widths
5414
5434
  var tmpTable = $(table.cloneNode())
5415
5435
  .css( 'visibility', 'hidden' )
5436
+ .css( 'margin', 0 )
5416
5437
  .removeAttr( 'id' );
5417
5438
 
5418
5439
  // Clean up the table body
5419
5440
  tmpTable.append('<tbody/>')
5420
- var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5421
5441
 
5422
5442
  // Clone the table header and footer - we can't use the header / footer
5423
5443
  // from the cloned table, since if scrolling is active, the table's
@@ -5457,23 +5477,37 @@ function _fnCalculateColumnWidths ( settings )
5457
5477
  }
5458
5478
  } );
5459
5479
 
5460
- // Find the widest piece of data for each column and put it into the table
5480
+ // Get the widest strings for each of the visible columns and add them to
5481
+ // our table to create a "worst case"
5482
+ var longestData = [];
5483
+
5461
5484
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
5462
- columnIdx = visibleColumns[i];
5463
- column = columns[ columnIdx ];
5464
-
5465
- var longest = _fnGetMaxLenString(settings, columnIdx);
5466
- var autoClass = _ext.type.className[column.sType];
5467
- var text = longest + column.sContentPadding;
5468
- var insert = longest.indexOf('<') === -1
5469
- ? document.createTextNode(text)
5470
- : text
5471
-
5472
- $('<td/>')
5473
- .addClass(autoClass)
5474
- .addClass(column.sClass)
5475
- .append(insert)
5476
- .appendTo(tr);
5485
+ longestData.push(_fnGetWideStrings(settings, visibleColumns[i]));
5486
+ }
5487
+
5488
+ if (longestData.length) {
5489
+ for ( i=0 ; i<longestData[0].length ; i++ ) {
5490
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5491
+
5492
+ for ( j=0 ; j<visibleColumns.length ; j++ ) {
5493
+ columnIdx = visibleColumns[j];
5494
+ column = columns[ columnIdx ];
5495
+
5496
+ var longest = longestData[j][i] || '';
5497
+ var autoClass = _ext.type.className[column.sType];
5498
+ var padding = column.sContentPadding || (scrollX ? '-' : '');
5499
+ var text = longest + padding;
5500
+ var insert = longest.indexOf('<') === -1 && longest.indexOf('&') === -1
5501
+ ? document.createTextNode(text)
5502
+ : text
5503
+
5504
+ $('<td/>')
5505
+ .addClass(autoClass)
5506
+ .addClass(column.sClass)
5507
+ .append(insert)
5508
+ .appendTo(tr);
5509
+ }
5510
+ }
5477
5511
  }
5478
5512
 
5479
5513
  // Tidy the temporary table - remove name attributes so there aren't
@@ -5612,19 +5646,31 @@ function _fnWrapperWidth(settings) {
5612
5646
  }
5613
5647
 
5614
5648
  /**
5615
- * Get the maximum strlen for each data column
5649
+ * Get the widest strings for each column.
5650
+ *
5651
+ * It is very difficult to determine what the widest string actually is due to variable character
5652
+ * width and kerning. Doing an exact calculation with the DOM or even Canvas would kill performance
5653
+ * and this is a critical point, so we use two techniques to determine a collection of the longest
5654
+ * strings from the column, which will likely contain the widest strings:
5655
+ *
5656
+ * 1) Get the top three longest strings from the column
5657
+ * 2) Get the top three widest words (i.e. an unbreakable phrase)
5658
+ *
5616
5659
  * @param {object} settings dataTables settings object
5617
5660
  * @param {int} colIdx column of interest
5618
- * @returns {string} string of the max length
5661
+ * @returns {string[]} Array of the longest strings
5619
5662
  * @memberof DataTable#oApi
5620
5663
  */
5621
- function _fnGetMaxLenString( settings, colIdx )
5664
+ function _fnGetWideStrings( settings, colIdx )
5622
5665
  {
5623
5666
  var column = settings.aoColumns[colIdx];
5624
5667
 
5625
- if (! column.maxLenString) {
5626
- var s, max='', maxLen = -1;
5627
-
5668
+ // Do we need to recalculate (i.e. was invalidated), or just use the cached data?
5669
+ if (! column.wideStrings) {
5670
+ var allStrings = [];
5671
+ var collection = [];
5672
+
5673
+ // Create an array with the string information for the column
5628
5674
  for ( var i=0, iLen=settings.aiDisplayMaster.length ; i<iLen ; i++ ) {
5629
5675
  var rowIdx = settings.aiDisplayMaster[i];
5630
5676
  var data = _fnGetRowDisplay(settings, rowIdx)[colIdx];
@@ -5639,21 +5685,54 @@ function _fnGetMaxLenString( settings, colIdx )
5639
5685
  .replace(/id=".*?"/g, '')
5640
5686
  .replace(/name=".*?"/g, '');
5641
5687
 
5642
- s = _stripHtml(cellString)
5688
+ // Don't want Javascript at all in these calculation cells.
5689
+ cellString = cellString.replace(/<script.*?<\/script>/gi, ' ');
5690
+
5691
+ var noHtml = _stripHtml(cellString, ' ')
5643
5692
  .replace( /&nbsp;/g, ' ' );
5644
5693
 
5645
- if ( s.length > maxLen ) {
5646
- // We want the HTML in the string, but the length that
5647
- // is important is the stripped string
5648
- max = cellString;
5649
- maxLen = s.length;
5650
- }
5694
+ // The length is calculated on the text only, but we keep the HTML
5695
+ // in the string so it can be used in the calculation table
5696
+ collection.push({
5697
+ str: cellString,
5698
+ len: noHtml.length
5699
+ });
5700
+
5701
+ allStrings.push(noHtml);
5651
5702
  }
5652
5703
 
5653
- column.maxLenString = max;
5704
+ // Order and then cut down to the size we need
5705
+ collection
5706
+ .sort(function (a, b) {
5707
+ return b.len - a.len;
5708
+ })
5709
+ .splice(3);
5710
+
5711
+ column.wideStrings = collection.map(function (item) {
5712
+ return item.str;
5713
+ });
5714
+
5715
+ // Longest unbroken string
5716
+ let parts = allStrings.join(' ').split(' ');
5717
+
5718
+ parts.sort(function (a, b) {
5719
+ return b.length - a.length;
5720
+ });
5721
+
5722
+ if (parts.length) {
5723
+ column.wideStrings.push(parts[0]);
5724
+ }
5725
+
5726
+ if (parts.length > 1) {
5727
+ column.wideStrings.push(parts[1]);
5728
+ }
5729
+
5730
+ if (parts.length > 2) {
5731
+ column.wideStrings.push(parts[3]);
5732
+ }
5654
5733
  }
5655
5734
 
5656
- return column.maxLenString;
5735
+ return column.wideStrings;
5657
5736
  }
5658
5737
 
5659
5738
 
@@ -8674,7 +8753,7 @@ var __column_header = function ( settings, column, row ) {
8674
8753
  // Automatic - find the _last_ unique cell from the top that is not empty (last for
8675
8754
  // backwards compatibility)
8676
8755
  for (var i=0 ; i<header.length ; i++) {
8677
- if (header[i][column].unique && $('span.dt-column-title', header[i][column].cell).text()) {
8756
+ if (header[i][column].unique && $('.dt-column-title', header[i][column].cell).text()) {
8678
8757
  target = i;
8679
8758
  }
8680
8759
  }
@@ -8981,7 +9060,7 @@ _api_registerPlural( 'columns().titles()', 'column().title()', function (title,
8981
9060
  title = undefined;
8982
9061
  }
8983
9062
 
8984
- var span = $('span.dt-column-title', this.column(column).header(row));
9063
+ var span = $('.dt-column-title', this.column(column).header(row));
8985
9064
 
8986
9065
  if (title !== undefined) {
8987
9066
  span.html(title);
@@ -8994,13 +9073,16 @@ _api_registerPlural( 'columns().titles()', 'column().title()', function (title,
8994
9073
 
8995
9074
  _api_registerPlural( 'columns().types()', 'column().type()', function () {
8996
9075
  return this.iterator( 'column', function ( settings, column ) {
8997
- var type = settings.aoColumns[column].sType;
9076
+ var colObj = settings.aoColumns[column]
9077
+ var type = colObj.sType;
8998
9078
 
8999
9079
  // If the type was invalidated, then resolve it. This actually does
9000
9080
  // all columns at the moment. Would only happen once if getting all
9001
9081
  // column's data types.
9002
9082
  if (! type) {
9003
9083
  _fnColumnTypes(settings);
9084
+
9085
+ type = colObj.sType;
9004
9086
  }
9005
9087
 
9006
9088
  return type;
@@ -10152,8 +10234,8 @@ _api_register( 'i18n()', function ( token, def, plural ) {
10152
10234
 
10153
10235
  // Needed for header and footer, so pulled into its own function
10154
10236
  function cleanHeader(node, className) {
10155
- $(node).find('span.dt-column-order').remove();
10156
- $(node).find('span.dt-column-title').each(function () {
10237
+ $(node).find('.dt-column-order').remove();
10238
+ $(node).find('.dt-column-title').each(function () {
10157
10239
  var title = $(this).html();
10158
10240
  $(this).parent().parent().append(title);
10159
10241
  $(this).remove();
@@ -10171,7 +10253,7 @@ function cleanHeader(node, className) {
10171
10253
  * @type string
10172
10254
  * @default Version number
10173
10255
  */
10174
- DataTable.version = "2.3.4";
10256
+ DataTable.version = "2.3.6";
10175
10257
 
10176
10258
  /**
10177
10259
  * Private data store, containing all of the settings objects that are
@@ -10473,8 +10555,8 @@ DataTable.models.oColumn = {
10473
10555
  */
10474
10556
  "sWidthOrig": null,
10475
10557
 
10476
- /** Cached string which is the longest in the column */
10477
- maxLenString: null,
10558
+ /** Cached longest strings from a column */
10559
+ wideStrings: null,
10478
10560
 
10479
10561
  /**
10480
10562
  * Store for named searches
@@ -11339,7 +11421,10 @@ DataTable.defaults = {
11339
11421
  iDeferLoading: null,
11340
11422
 
11341
11423
  /** Event listeners */
11342
- on: null
11424
+ on: null,
11425
+
11426
+ /** Title wrapper element type */
11427
+ columnTitleTag: 'span'
11343
11428
  };
11344
11429
 
11345
11430
  _fnHungarianMap( DataTable.defaults );
@@ -12303,7 +12388,10 @@ DataTable.models.oSettings = {
12303
12388
  orderHandler: true,
12304
12389
 
12305
12390
  /** Title row indicator */
12306
- titleRow: null
12391
+ titleRow: null,
12392
+
12393
+ /** Title wrapper element type */
12394
+ columnTitleTag: 'span'
12307
12395
  };
12308
12396
 
12309
12397
  /**
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "main": "js/dataTables.js",
5
5
  "module": "js/dataTables.mjs",
6
6
  "types": "./types/types.d.ts",
7
- "version": "2.3.4",
7
+ "version": "2.3.6",
8
8
  "files": [
9
9
  "js/**/*.js",
10
10
  "js/**/*.mjs",
package/types/types.d.ts CHANGED
@@ -338,6 +338,11 @@ export interface Config {
338
338
  */
339
339
  columnDefs?: ConfigColumnDefs[];
340
340
 
341
+ /**
342
+ * HTML element to use for the title elements (including order indicator)
343
+ */
344
+ columnTitleTag?: string;
345
+
341
346
  /**
342
347
  * Data to use as the display data for the table.
343
348
  */