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.js 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
 
@@ -174,7 +174,7 @@
174
174
  "sDestroyWidth": $this[0].style.width,
175
175
  "sInstance": sId,
176
176
  "sTableId": sId,
177
- colgroup: $('<colgroup>').prependTo(this),
177
+ colgroup: $('<colgroup>'),
178
178
  fastData: function (row, column, type) {
179
179
  return _fnGetCellData(oSettings, row, column, type);
180
180
  }
@@ -247,6 +247,7 @@
247
247
  "orderHandler",
248
248
  "titleRow",
249
249
  "typeDetect",
250
+ "columnTitleTag",
250
251
  [ "iCookieDuration", "iStateDuration" ], // backwards compat
251
252
  [ "oSearch", "oPreviousSearch" ],
252
253
  [ "aoSearchCols", "aoPreSearchCols" ],
@@ -411,7 +412,7 @@
411
412
 
412
413
  if ( oSettings.caption ) {
413
414
  if ( caption.length === 0 ) {
414
- caption = $('<caption/>').appendTo( $this );
415
+ caption = $('<caption/>').prependTo( $this );
415
416
  }
416
417
 
417
418
  caption.html( oSettings.caption );
@@ -424,6 +425,14 @@
424
425
  oSettings.captionNode = caption[0];
425
426
  }
426
427
 
428
+ // Place the colgroup element in the correct location for the HTML structure
429
+ if (caption.length) {
430
+ oSettings.colgroup.insertAfter(caption);
431
+ }
432
+ else {
433
+ oSettings.colgroup.prependTo(oSettings.nTable);
434
+ }
435
+
427
436
  if ( thead.length === 0 ) {
428
437
  thead = $('<thead/>').appendTo($this);
429
438
  }
@@ -439,7 +448,7 @@
439
448
  if ( tfoot.length === 0 ) {
440
449
  // If we are a scrolling table, and no footer has been given, then we need to create
441
450
  // a tfoot element for the caption element to be appended to
442
- tfoot = $('<tfoot/>').appendTo($this);
451
+ tfoot = $('<tfoot/>').insertAfter(thead);
443
452
  }
444
453
  oSettings.nTFoot = tfoot[0];
445
454
 
@@ -1280,7 +1289,7 @@
1280
1289
  };
1281
1290
 
1282
1291
  // Replaceable function in api.util
1283
- var _stripHtml = function (input) {
1292
+ var _stripHtml = function (input, replacement) {
1284
1293
  if (! input || typeof input !== 'string') {
1285
1294
  return input;
1286
1295
  }
@@ -1292,7 +1301,7 @@
1292
1301
 
1293
1302
  var previous;
1294
1303
 
1295
- input = input.replace(_re_html, ''); // Complete tags
1304
+ input = input.replace(_re_html, replacement || ''); // Complete tags
1296
1305
 
1297
1306
  // Safety for incomplete script tag - use do / while to ensure that
1298
1307
  // we get all instances
@@ -1757,7 +1766,7 @@
1757
1766
  }
1758
1767
  },
1759
1768
 
1760
- stripHtml: function (mixed) {
1769
+ stripHtml: function (mixed, replacement) {
1761
1770
  var type = typeof mixed;
1762
1771
 
1763
1772
  if (type === 'function') {
@@ -1765,7 +1774,7 @@
1765
1774
  return;
1766
1775
  }
1767
1776
  else if (type === 'string') {
1768
- return _stripHtml(mixed);
1777
+ return _stripHtml(mixed, replacement);
1769
1778
  }
1770
1779
  return mixed;
1771
1780
  },
@@ -2937,12 +2946,12 @@
2937
2946
 
2938
2947
  // Max length string. Its a fairly cheep recalculation, so not worth
2939
2948
  // something more complicated
2940
- cols[ colIdx ].maxLenString = null;
2949
+ cols[ colIdx ].wideStrings = null;
2941
2950
  }
2942
2951
  else {
2943
2952
  for ( i=0, iLen=cols.length ; i<iLen ; i++ ) {
2944
2953
  cols[i].sType = null;
2945
- cols[i].maxLenString = null;
2954
+ cols[i].wideStrings = null;
2946
2955
  }
2947
2956
 
2948
2957
  // Update DataTables special `DT_*` attributes for the row
@@ -3367,7 +3376,7 @@
3367
3376
  colspan++;
3368
3377
  }
3369
3378
 
3370
- var titleSpan = $('span.dt-column-title', cell);
3379
+ var titleSpan = $('.dt-column-title', cell);
3371
3380
 
3372
3381
  structure[row][column] = {
3373
3382
  cell: cell,
@@ -3483,6 +3492,14 @@
3483
3492
  {
3484
3493
  var iDataIndex = aiDisplay[j];
3485
3494
  var aoData = oSettings.aoData[ iDataIndex ];
3495
+
3496
+ // Row has been deleted - can't be displayed
3497
+ if (aoData === null)
3498
+ {
3499
+ continue;
3500
+ }
3501
+
3502
+ // Row node hasn't been created yet
3486
3503
  if ( aoData.nTr === null )
3487
3504
  {
3488
3505
  _fnCreateTr( oSettings, iDataIndex );
@@ -4073,8 +4090,8 @@
4073
4090
  }
4074
4091
 
4075
4092
  // Wrap the column title so we can write to it in future
4076
- if ( $('span.dt-column-title', cell).length === 0) {
4077
- $('<span>')
4093
+ if ( $('.dt-column-title', cell).length === 0) {
4094
+ $(document.createElement(settings.columnTitleTag))
4078
4095
  .addClass('dt-column-title')
4079
4096
  .append(cell.childNodes)
4080
4097
  .appendTo(cell);
@@ -4085,9 +4102,9 @@
4085
4102
  isHeader &&
4086
4103
  jqCell.filter(':not([data-dt-order=disable])').length !== 0 &&
4087
4104
  jqCell.parent(':not([data-dt-order=disable])').length !== 0 &&
4088
- $('span.dt-column-order', cell).length === 0
4105
+ $('.dt-column-order', cell).length === 0
4089
4106
  ) {
4090
- $('<span>')
4107
+ $(document.createElement(settings.columnTitleTag))
4091
4108
  .addClass('dt-column-order')
4092
4109
  .appendTo(cell);
4093
4110
  }
@@ -4096,7 +4113,7 @@
4096
4113
  // layout for those elements
4097
4114
  var headerFooter = isHeader ? 'header' : 'footer';
4098
4115
 
4099
- if ( $('span.dt-column-' + headerFooter, cell).length === 0) {
4116
+ if ( $('div.dt-column-' + headerFooter, cell).length === 0) {
4100
4117
  $('<div>')
4101
4118
  .addClass('dt-column-' + headerFooter)
4102
4119
  .append(cell.childNodes)
@@ -4253,6 +4270,10 @@
4253
4270
  // Custom Ajax option to submit the parameters as a JSON string
4254
4271
  if (baseAjax.submitAs === 'json' && typeof data === 'object') {
4255
4272
  baseAjax.data = JSON.stringify(data);
4273
+
4274
+ if (!baseAjax.contentType) {
4275
+ baseAjax.contentType = 'application/json; charset=utf-8';
4276
+ }
4256
4277
  }
4257
4278
 
4258
4279
  if (typeof ajax === 'function') {
@@ -5408,7 +5429,7 @@
5408
5429
  visibleColumns = _fnGetColumns( settings, 'bVisible' ),
5409
5430
  tableWidthAttr = table.getAttribute('width'), // from DOM element
5410
5431
  tableContainer = table.parentNode,
5411
- i, column, columnIdx;
5432
+ i, j, column, columnIdx;
5412
5433
 
5413
5434
  var styleWidth = table.style.width;
5414
5435
  var containerWidth = _fnWrapperWidth(settings);
@@ -5442,17 +5463,16 @@
5442
5463
  false
5443
5464
  );
5444
5465
 
5445
- // Construct a single row, worst case, table with the widest
5446
- // node in the data, assign any user defined widths, then insert it into
5447
- // the DOM and allow the browser to do all the hard work of calculating
5448
- // table widths
5466
+ // Construct a worst case table with the widest, assign any user defined
5467
+ // widths, then insert it into the DOM and allow the browser to do all
5468
+ // the hard work of calculating table widths
5449
5469
  var tmpTable = $(table.cloneNode())
5450
5470
  .css( 'visibility', 'hidden' )
5471
+ .css( 'margin', 0 )
5451
5472
  .removeAttr( 'id' );
5452
5473
 
5453
5474
  // Clean up the table body
5454
5475
  tmpTable.append('<tbody/>')
5455
- var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5456
5476
 
5457
5477
  // Clone the table header and footer - we can't use the header / footer
5458
5478
  // from the cloned table, since if scrolling is active, the table's
@@ -5492,23 +5512,37 @@
5492
5512
  }
5493
5513
  } );
5494
5514
 
5495
- // Find the widest piece of data for each column and put it into the table
5515
+ // Get the widest strings for each of the visible columns and add them to
5516
+ // our table to create a "worst case"
5517
+ var longestData = [];
5518
+
5496
5519
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
5497
- columnIdx = visibleColumns[i];
5498
- column = columns[ columnIdx ];
5499
-
5500
- var longest = _fnGetMaxLenString(settings, columnIdx);
5501
- var autoClass = _ext.type.className[column.sType];
5502
- var text = longest + column.sContentPadding;
5503
- var insert = longest.indexOf('<') === -1
5504
- ? document.createTextNode(text)
5505
- : text
5506
-
5507
- $('<td/>')
5508
- .addClass(autoClass)
5509
- .addClass(column.sClass)
5510
- .append(insert)
5511
- .appendTo(tr);
5520
+ longestData.push(_fnGetWideStrings(settings, visibleColumns[i]));
5521
+ }
5522
+
5523
+ if (longestData.length) {
5524
+ for ( i=0 ; i<longestData[0].length ; i++ ) {
5525
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5526
+
5527
+ for ( j=0 ; j<visibleColumns.length ; j++ ) {
5528
+ columnIdx = visibleColumns[j];
5529
+ column = columns[ columnIdx ];
5530
+
5531
+ var longest = longestData[j][i] || '';
5532
+ var autoClass = _ext.type.className[column.sType];
5533
+ var padding = column.sContentPadding || (scrollX ? '-' : '');
5534
+ var text = longest + padding;
5535
+ var insert = longest.indexOf('<') === -1 && longest.indexOf('&') === -1
5536
+ ? document.createTextNode(text)
5537
+ : text
5538
+
5539
+ $('<td/>')
5540
+ .addClass(autoClass)
5541
+ .addClass(column.sClass)
5542
+ .append(insert)
5543
+ .appendTo(tr);
5544
+ }
5545
+ }
5512
5546
  }
5513
5547
 
5514
5548
  // Tidy the temporary table - remove name attributes so there aren't
@@ -5647,19 +5681,31 @@
5647
5681
  }
5648
5682
 
5649
5683
  /**
5650
- * Get the maximum strlen for each data column
5684
+ * Get the widest strings for each column.
5685
+ *
5686
+ * It is very difficult to determine what the widest string actually is due to variable character
5687
+ * width and kerning. Doing an exact calculation with the DOM or even Canvas would kill performance
5688
+ * and this is a critical point, so we use two techniques to determine a collection of the longest
5689
+ * strings from the column, which will likely contain the widest strings:
5690
+ *
5691
+ * 1) Get the top three longest strings from the column
5692
+ * 2) Get the top three widest words (i.e. an unbreakable phrase)
5693
+ *
5651
5694
  * @param {object} settings dataTables settings object
5652
5695
  * @param {int} colIdx column of interest
5653
- * @returns {string} string of the max length
5696
+ * @returns {string[]} Array of the longest strings
5654
5697
  * @memberof DataTable#oApi
5655
5698
  */
5656
- function _fnGetMaxLenString( settings, colIdx )
5699
+ function _fnGetWideStrings( settings, colIdx )
5657
5700
  {
5658
5701
  var column = settings.aoColumns[colIdx];
5659
5702
 
5660
- if (! column.maxLenString) {
5661
- var s, max='', maxLen = -1;
5662
-
5703
+ // Do we need to recalculate (i.e. was invalidated), or just use the cached data?
5704
+ if (! column.wideStrings) {
5705
+ var allStrings = [];
5706
+ var collection = [];
5707
+
5708
+ // Create an array with the string information for the column
5663
5709
  for ( var i=0, iLen=settings.aiDisplayMaster.length ; i<iLen ; i++ ) {
5664
5710
  var rowIdx = settings.aiDisplayMaster[i];
5665
5711
  var data = _fnGetRowDisplay(settings, rowIdx)[colIdx];
@@ -5674,21 +5720,54 @@
5674
5720
  .replace(/id=".*?"/g, '')
5675
5721
  .replace(/name=".*?"/g, '');
5676
5722
 
5677
- s = _stripHtml(cellString)
5723
+ // Don't want Javascript at all in these calculation cells.
5724
+ cellString = cellString.replace(/<script.*?<\/script>/gi, ' ');
5725
+
5726
+ var noHtml = _stripHtml(cellString, ' ')
5678
5727
  .replace( /&nbsp;/g, ' ' );
5679
5728
 
5680
- if ( s.length > maxLen ) {
5681
- // We want the HTML in the string, but the length that
5682
- // is important is the stripped string
5683
- max = cellString;
5684
- maxLen = s.length;
5685
- }
5729
+ // The length is calculated on the text only, but we keep the HTML
5730
+ // in the string so it can be used in the calculation table
5731
+ collection.push({
5732
+ str: cellString,
5733
+ len: noHtml.length
5734
+ });
5735
+
5736
+ allStrings.push(noHtml);
5686
5737
  }
5687
5738
 
5688
- column.maxLenString = max;
5739
+ // Order and then cut down to the size we need
5740
+ collection
5741
+ .sort(function (a, b) {
5742
+ return b.len - a.len;
5743
+ })
5744
+ .splice(3);
5745
+
5746
+ column.wideStrings = collection.map(function (item) {
5747
+ return item.str;
5748
+ });
5749
+
5750
+ // Longest unbroken string
5751
+ let parts = allStrings.join(' ').split(' ');
5752
+
5753
+ parts.sort(function (a, b) {
5754
+ return b.length - a.length;
5755
+ });
5756
+
5757
+ if (parts.length) {
5758
+ column.wideStrings.push(parts[0]);
5759
+ }
5760
+
5761
+ if (parts.length > 1) {
5762
+ column.wideStrings.push(parts[1]);
5763
+ }
5764
+
5765
+ if (parts.length > 2) {
5766
+ column.wideStrings.push(parts[3]);
5767
+ }
5689
5768
  }
5690
5769
 
5691
- return column.maxLenString;
5770
+ return column.wideStrings;
5692
5771
  }
5693
5772
 
5694
5773
 
@@ -8709,7 +8788,7 @@
8709
8788
  // Automatic - find the _last_ unique cell from the top that is not empty (last for
8710
8789
  // backwards compatibility)
8711
8790
  for (var i=0 ; i<header.length ; i++) {
8712
- if (header[i][column].unique && $('span.dt-column-title', header[i][column].cell).text()) {
8791
+ if (header[i][column].unique && $('.dt-column-title', header[i][column].cell).text()) {
8713
8792
  target = i;
8714
8793
  }
8715
8794
  }
@@ -9016,7 +9095,7 @@
9016
9095
  title = undefined;
9017
9096
  }
9018
9097
 
9019
- var span = $('span.dt-column-title', this.column(column).header(row));
9098
+ var span = $('.dt-column-title', this.column(column).header(row));
9020
9099
 
9021
9100
  if (title !== undefined) {
9022
9101
  span.html(title);
@@ -9029,13 +9108,16 @@
9029
9108
 
9030
9109
  _api_registerPlural( 'columns().types()', 'column().type()', function () {
9031
9110
  return this.iterator( 'column', function ( settings, column ) {
9032
- var type = settings.aoColumns[column].sType;
9111
+ var colObj = settings.aoColumns[column]
9112
+ var type = colObj.sType;
9033
9113
 
9034
9114
  // If the type was invalidated, then resolve it. This actually does
9035
9115
  // all columns at the moment. Would only happen once if getting all
9036
9116
  // column's data types.
9037
9117
  if (! type) {
9038
9118
  _fnColumnTypes(settings);
9119
+
9120
+ type = colObj.sType;
9039
9121
  }
9040
9122
 
9041
9123
  return type;
@@ -10187,8 +10269,8 @@
10187
10269
 
10188
10270
  // Needed for header and footer, so pulled into its own function
10189
10271
  function cleanHeader(node, className) {
10190
- $(node).find('span.dt-column-order').remove();
10191
- $(node).find('span.dt-column-title').each(function () {
10272
+ $(node).find('.dt-column-order').remove();
10273
+ $(node).find('.dt-column-title').each(function () {
10192
10274
  var title = $(this).html();
10193
10275
  $(this).parent().parent().append(title);
10194
10276
  $(this).remove();
@@ -10206,7 +10288,7 @@
10206
10288
  * @type string
10207
10289
  * @default Version number
10208
10290
  */
10209
- DataTable.version = "2.3.4";
10291
+ DataTable.version = "2.3.6";
10210
10292
 
10211
10293
  /**
10212
10294
  * Private data store, containing all of the settings objects that are
@@ -10508,8 +10590,8 @@
10508
10590
  */
10509
10591
  "sWidthOrig": null,
10510
10592
 
10511
- /** Cached string which is the longest in the column */
10512
- maxLenString: null,
10593
+ /** Cached longest strings from a column */
10594
+ wideStrings: null,
10513
10595
 
10514
10596
  /**
10515
10597
  * Store for named searches
@@ -11374,7 +11456,10 @@
11374
11456
  iDeferLoading: null,
11375
11457
 
11376
11458
  /** Event listeners */
11377
- on: null
11459
+ on: null,
11460
+
11461
+ /** Title wrapper element type */
11462
+ columnTitleTag: 'span'
11378
11463
  };
11379
11464
 
11380
11465
  _fnHungarianMap( DataTable.defaults );
@@ -12338,7 +12423,10 @@
12338
12423
  orderHandler: true,
12339
12424
 
12340
12425
  /** Title row indicator */
12341
- titleRow: null
12426
+ titleRow: null,
12427
+
12428
+ /** Title wrapper element type */
12429
+ columnTitleTag: 'span'
12342
12430
  };
12343
12431
 
12344
12432
  /**