datatables.net 2.3.3 → 2.3.5

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.3
1
+ /*! DataTables 2.3.5
2
2
  * © SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -131,6 +131,9 @@ var DataTable = function ( selector, options )
131
131
  this.id = sId;
132
132
  }
133
133
 
134
+ // Replacing an existing colgroup with our own. Not ideal, but a merge could take a lot of code
135
+ $this.children('colgroup').remove();
136
+
134
137
  /* Create the settings object for this table and set some of the default parameters */
135
138
  var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
136
139
  "sDestroyWidth": $this[0].style.width,
@@ -2899,12 +2902,12 @@ function _fnInvalidate( settings, rowIdx, src, colIdx )
2899
2902
 
2900
2903
  // Max length string. Its a fairly cheep recalculation, so not worth
2901
2904
  // something more complicated
2902
- cols[ colIdx ].maxLenString = null;
2905
+ cols[ colIdx ].wideStrings = null;
2903
2906
  }
2904
2907
  else {
2905
2908
  for ( i=0, iLen=cols.length ; i<iLen ; i++ ) {
2906
2909
  cols[i].sType = null;
2907
- cols[i].maxLenString = null;
2910
+ cols[i].wideStrings = null;
2908
2911
  }
2909
2912
 
2910
2913
  // Update DataTables special `DT_*` attributes for the row
@@ -3445,6 +3448,14 @@ function _fnDraw( oSettings, ajaxComplete )
3445
3448
  {
3446
3449
  var iDataIndex = aiDisplay[j];
3447
3450
  var aoData = oSettings.aoData[ iDataIndex ];
3451
+
3452
+ // Row has been deleted - can't be displayed
3453
+ if (aoData === null)
3454
+ {
3455
+ continue;
3456
+ }
3457
+
3458
+ // Row node hasn't been created yet
3448
3459
  if ( aoData.nTr === null )
3449
3460
  {
3450
3461
  _fnCreateTr( oSettings, iDataIndex );
@@ -4123,24 +4134,21 @@ function _fnStart( oSettings )
4123
4134
  * DataTables - may be augmented by developer callbacks
4124
4135
  * @param {function} fn Callback function to run when data is obtained
4125
4136
  */
4126
- function _fnBuildAjax( oSettings, data, fn )
4127
- {
4137
+ function _fnBuildAjax(oSettings, data, fn) {
4128
4138
  var ajaxData;
4129
4139
  var ajax = oSettings.ajax;
4130
4140
  var instance = oSettings.oInstance;
4131
- var callback = function ( json ) {
4132
- var status = oSettings.jqXHR
4133
- ? oSettings.jqXHR.status
4134
- : null;
4141
+ var callback = function (json) {
4142
+ var status = oSettings.jqXHR ? oSettings.jqXHR.status : null;
4135
4143
 
4136
- if ( json === null || (typeof status === 'number' && status == 204 ) ) {
4144
+ if (json === null || (typeof status === 'number' && status == 204)) {
4137
4145
  json = {};
4138
- _fnAjaxDataSrc( oSettings, json, [] );
4146
+ _fnAjaxDataSrc(oSettings, json, []);
4139
4147
  }
4140
4148
 
4141
4149
  var error = json.error || json.sError;
4142
- if ( error ) {
4143
- _fnLog( oSettings, 0, error );
4150
+ if (error) {
4151
+ _fnLog(oSettings, 0, error);
4144
4152
  }
4145
4153
 
4146
4154
  // Microsoft often wrap JSON as a string in another JSON object
@@ -4148,30 +4156,27 @@ function _fnBuildAjax( oSettings, data, fn )
4148
4156
  if (json.d && typeof json.d === 'string') {
4149
4157
  try {
4150
4158
  json = JSON.parse(json.d);
4151
- }
4152
- catch (e) {
4159
+ } catch (e) {
4153
4160
  // noop
4154
4161
  }
4155
4162
  }
4156
4163
 
4157
4164
  oSettings.json = json;
4158
4165
 
4159
- _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR], true );
4160
- fn( json );
4166
+ _fnCallbackFire(oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR], true);
4167
+ fn(json);
4161
4168
  };
4162
4169
 
4163
- if ( $.isPlainObject( ajax ) && ajax.data )
4164
- {
4170
+ if ($.isPlainObject(ajax) && ajax.data) {
4165
4171
  ajaxData = ajax.data;
4166
4172
 
4167
- var newData = typeof ajaxData === 'function' ?
4168
- ajaxData( data, oSettings ) : // fn can manipulate data or return
4169
- ajaxData; // an object or array to merge
4173
+ var newData =
4174
+ typeof ajaxData === 'function'
4175
+ ? ajaxData(data, oSettings) // fn can manipulate data or return
4176
+ : ajaxData; // an object or array to merge
4170
4177
 
4171
4178
  // If the function returned something, use that alone
4172
- data = typeof ajaxData === 'function' && newData ?
4173
- newData :
4174
- $.extend( true, data, newData );
4179
+ data = typeof ajaxData === 'function' && newData ? newData : $.extend(true, data, newData);
4175
4180
 
4176
4181
  // Remove the data property as we've resolved it already and don't want
4177
4182
  // jQuery to do it again (it is restored at the end of the function)
@@ -4179,50 +4184,53 @@ function _fnBuildAjax( oSettings, data, fn )
4179
4184
  }
4180
4185
 
4181
4186
  var baseAjax = {
4182
- "url": typeof ajax === 'string' ?
4183
- ajax :
4184
- '',
4185
- "data": data,
4186
- "success": callback,
4187
- "dataType": "json",
4188
- "cache": false,
4189
- "type": oSettings.sServerMethod,
4190
- "error": function (xhr, error) {
4191
- var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR], true );
4192
-
4193
- if ( ret.indexOf(true) === -1 ) {
4194
- if ( error == "parsererror" ) {
4195
- _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
4187
+ url: typeof ajax === 'string' ? ajax : '',
4188
+ data: data,
4189
+ success: callback,
4190
+ dataType: 'json',
4191
+ cache: false,
4192
+ type: oSettings.sServerMethod,
4193
+ error: function (xhr, error) {
4194
+ var ret = _fnCallbackFire(
4195
+ oSettings,
4196
+ null,
4197
+ 'xhr',
4198
+ [oSettings, null, oSettings.jqXHR],
4199
+ true
4200
+ );
4201
+
4202
+ if (ret.indexOf(true) === -1) {
4203
+ if (error == 'parsererror') {
4204
+ _fnLog(oSettings, 0, 'Invalid JSON response', 1);
4196
4205
  }
4197
- else if ( xhr.readyState === 4 ) {
4198
- _fnLog( oSettings, 0, 'Ajax error', 7 );
4206
+ else if (xhr.readyState === 4) {
4207
+ _fnLog(oSettings, 0, 'Ajax error', 7);
4199
4208
  }
4200
4209
  }
4201
4210
 
4202
- _fnProcessingDisplay( oSettings, false );
4211
+ _fnProcessingDisplay(oSettings, false);
4203
4212
  }
4204
4213
  };
4205
4214
 
4206
4215
  // If `ajax` option is an object, extend and override our default base
4207
- if ( $.isPlainObject( ajax ) ) {
4208
- $.extend( baseAjax, ajax )
4216
+ if ($.isPlainObject(ajax)) {
4217
+ $.extend(baseAjax, ajax);
4209
4218
  }
4210
4219
 
4211
4220
  // Store the data submitted for the API
4212
4221
  oSettings.oAjaxData = data;
4213
4222
 
4214
4223
  // Allow plug-ins and external processes to modify the data
4215
- _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data, baseAjax], true );
4224
+ _fnCallbackFire(oSettings, null, 'preXhr', [oSettings, data, baseAjax], true);
4216
4225
 
4217
4226
  // Custom Ajax option to submit the parameters as a JSON string
4218
4227
  if (baseAjax.submitAs === 'json' && typeof data === 'object') {
4219
4228
  baseAjax.data = JSON.stringify(data);
4220
4229
  }
4221
4230
 
4222
- if ( typeof ajax === 'function' )
4223
- {
4231
+ if (typeof ajax === 'function') {
4224
4232
  // Is a function - let the caller define what needs to be done
4225
- oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4233
+ oSettings.jqXHR = ajax.call(instance, data, callback, oSettings);
4226
4234
  }
4227
4235
  else if (ajax.url === '') {
4228
4236
  // No url, so don't load any data. Just apply an empty data array
@@ -4234,37 +4242,30 @@ function _fnBuildAjax( oSettings, data, fn )
4234
4242
  }
4235
4243
  else {
4236
4244
  // Object to extend the base settings
4237
- oSettings.jqXHR = $.ajax( baseAjax );
4245
+ oSettings.jqXHR = $.ajax(baseAjax);
4238
4246
  }
4239
4247
 
4240
4248
  // Restore for next time around
4241
- if ( ajaxData ) {
4249
+ if (ajaxData) {
4242
4250
  ajax.data = ajaxData;
4243
4251
  }
4244
4252
  }
4245
4253
 
4246
-
4247
4254
  /**
4248
4255
  * Update the table using an Ajax call
4249
4256
  * @param {object} settings dataTables settings object
4250
4257
  * @returns {boolean} Block the table drawing or not
4251
4258
  * @memberof DataTable#oApi
4252
4259
  */
4253
- function _fnAjaxUpdate( settings )
4254
- {
4260
+ function _fnAjaxUpdate(settings) {
4255
4261
  settings.iDraw++;
4256
- _fnProcessingDisplay( settings, true );
4262
+ _fnProcessingDisplay(settings, true);
4257
4263
 
4258
- _fnBuildAjax(
4259
- settings,
4260
- _fnAjaxParameters( settings ),
4261
- function(json) {
4262
- _fnAjaxUpdateDraw( settings, json );
4263
- }
4264
- );
4264
+ _fnBuildAjax(settings, _fnAjaxParameters(settings), function (json) {
4265
+ _fnAjaxUpdateDraw(settings, json);
4266
+ });
4265
4267
  }
4266
4268
 
4267
-
4268
4269
  /**
4269
4270
  * Build up the parameters in an object needed for a server-side processing
4270
4271
  * request.
@@ -4272,22 +4273,18 @@ function _fnAjaxUpdate( settings )
4272
4273
  * @returns {bool} block the table drawing or not
4273
4274
  * @memberof DataTable#oApi
4274
4275
  */
4275
- function _fnAjaxParameters( settings )
4276
- {
4277
- var
4278
- columns = settings.aoColumns,
4276
+ function _fnAjaxParameters(settings) {
4277
+ var columns = settings.aoColumns,
4279
4278
  features = settings.oFeatures,
4280
4279
  preSearch = settings.oPreviousSearch,
4281
4280
  preColSearch = settings.aoPreSearchCols,
4282
- colData = function ( idx, prop ) {
4283
- return typeof columns[idx][prop] === 'function' ?
4284
- 'function' :
4285
- columns[idx][prop];
4281
+ colData = function (idx, prop) {
4282
+ return typeof columns[idx][prop] === 'function' ? 'function' : columns[idx][prop];
4286
4283
  };
4287
4284
 
4288
4285
  return {
4289
4286
  draw: settings.iDraw,
4290
- columns: columns.map( function ( column, i ) {
4287
+ columns: columns.map(function (column, i) {
4291
4288
  return {
4292
4289
  data: colData(i, 'mData'),
4293
4290
  name: column.sName,
@@ -4296,40 +4293,43 @@ function _fnAjaxParameters( settings )
4296
4293
  search: {
4297
4294
  value: preColSearch[i].search,
4298
4295
  regex: preColSearch[i].regex,
4299
- fixed: Object.keys(column.searchFixed).map( function(name) {
4300
- return {
4301
- name: name,
4302
- term: column.searchFixed[name].toString()
4303
- }
4304
- })
4296
+ fixed: Object.keys(column.searchFixed)
4297
+ .map(function (name) {
4298
+ return {
4299
+ name: name,
4300
+ term: typeof column.searchFixed[name] !== 'function'
4301
+ ? column.searchFixed[name].toString()
4302
+ : 'function'
4303
+ };
4304
+ })
4305
4305
  }
4306
4306
  };
4307
- } ),
4308
- order: _fnSortFlatten( settings ).map( function ( val ) {
4307
+ }),
4308
+ order: _fnSortFlatten(settings).map(function (val) {
4309
4309
  return {
4310
4310
  column: val.col,
4311
4311
  dir: val.dir,
4312
4312
  name: colData(val.col, 'sName')
4313
4313
  };
4314
- } ),
4314
+ }),
4315
4315
  start: settings._iDisplayStart,
4316
- length: features.bPaginate ?
4317
- settings._iDisplayLength :
4318
- -1,
4316
+ length: features.bPaginate ? settings._iDisplayLength : -1,
4319
4317
  search: {
4320
4318
  value: preSearch.search,
4321
4319
  regex: preSearch.regex,
4322
- fixed: Object.keys(settings.searchFixed).map( function(name) {
4323
- return {
4324
- name: name,
4325
- term: settings.searchFixed[name].toString()
4326
- }
4327
- })
4320
+ fixed: Object.keys(settings.searchFixed)
4321
+ .map(function (name) {
4322
+ return {
4323
+ name: name,
4324
+ term: typeof settings.searchFixed[name] !== 'function'
4325
+ ? settings.searchFixed[name].toString()
4326
+ : 'function'
4327
+ };
4328
+ })
4328
4329
  }
4329
4330
  };
4330
4331
  }
4331
4332
 
4332
-
4333
4333
  /**
4334
4334
  * Data the data from the server (nuking the old) and redraw the table
4335
4335
  * @param {object} oSettings dataTables settings object
@@ -4341,42 +4341,40 @@ function _fnAjaxParameters( settings )
4341
4341
  * @param {string} [json.sColumns] Column ordering (sName, comma separated)
4342
4342
  * @memberof DataTable#oApi
4343
4343
  */
4344
- function _fnAjaxUpdateDraw ( settings, json )
4345
- {
4344
+ function _fnAjaxUpdateDraw(settings, json) {
4346
4345
  var data = _fnAjaxDataSrc(settings, json);
4347
4346
  var draw = _fnAjaxDataSrcParam(settings, 'draw', json);
4348
4347
  var recordsTotal = _fnAjaxDataSrcParam(settings, 'recordsTotal', json);
4349
4348
  var recordsFiltered = _fnAjaxDataSrcParam(settings, 'recordsFiltered', json);
4350
4349
 
4351
- if ( draw !== undefined ) {
4350
+ if (draw !== undefined) {
4352
4351
  // Protect against out of sequence returns
4353
- if ( draw*1 < settings.iDraw ) {
4352
+ if (draw * 1 < settings.iDraw) {
4354
4353
  return;
4355
4354
  }
4356
4355
  settings.iDraw = draw * 1;
4357
4356
  }
4358
4357
 
4359
4358
  // No data in returned object, so rather than an array, we show an empty table
4360
- if ( ! data ) {
4359
+ if (!data) {
4361
4360
  data = [];
4362
4361
  }
4363
4362
 
4364
- _fnClearTable( settings );
4365
- settings._iRecordsTotal = parseInt(recordsTotal, 10);
4363
+ _fnClearTable(settings);
4364
+ settings._iRecordsTotal = parseInt(recordsTotal, 10);
4366
4365
  settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4367
4366
 
4368
- for ( var i=0, iLen=data.length ; i<iLen ; i++ ) {
4369
- _fnAddData( settings, data[i] );
4367
+ for (var i = 0, iLen = data.length; i < iLen; i++) {
4368
+ _fnAddData(settings, data[i]);
4370
4369
  }
4371
4370
  settings.aiDisplay = settings.aiDisplayMaster.slice();
4372
4371
 
4373
4372
  _fnColumnTypes(settings);
4374
- _fnDraw( settings, true );
4375
- _fnInitComplete( settings );
4376
- _fnProcessingDisplay( settings, false );
4373
+ _fnDraw(settings, true);
4374
+ _fnInitComplete(settings);
4375
+ _fnProcessingDisplay(settings, false);
4377
4376
  }
4378
4377
 
4379
-
4380
4378
  /**
4381
4379
  * Get the data from the JSON data source to use for drawing a table. Using
4382
4380
  * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
@@ -4385,11 +4383,10 @@ function _fnAjaxUpdateDraw ( settings, json )
4385
4383
  * @param {object} json Data source object / array from the server
4386
4384
  * @return {array} Array of data to use
4387
4385
  */
4388
- function _fnAjaxDataSrc ( settings, json, write )
4389
- {
4386
+ function _fnAjaxDataSrc(settings, json, write) {
4390
4387
  var dataProp = 'data';
4391
4388
 
4392
- if ($.isPlainObject( settings.ajax ) && settings.ajax.dataSrc !== undefined) {
4389
+ if ($.isPlainObject(settings.ajax) && settings.ajax.dataSrc !== undefined) {
4393
4390
  // Could in inside a `dataSrc` object, or not!
4394
4391
  var dataSrc = settings.ajax.dataSrc;
4395
4392
 
@@ -4402,20 +4399,18 @@ function _fnAjaxDataSrc ( settings, json, write )
4402
4399
  }
4403
4400
  }
4404
4401
 
4405
- if ( ! write ) {
4406
- if ( dataProp === 'data' ) {
4402
+ if (!write) {
4403
+ if (dataProp === 'data') {
4407
4404
  // If the default, then we still want to support the old style, and safely ignore
4408
4405
  // it if possible
4409
4406
  return json.aaData || json[dataProp];
4410
4407
  }
4411
4408
 
4412
- return dataProp !== "" ?
4413
- _fnGetObjectDataFn( dataProp )( json ) :
4414
- json;
4409
+ return dataProp !== '' ? _fnGetObjectDataFn(dataProp)(json) : json;
4415
4410
  }
4416
-
4411
+
4417
4412
  // set
4418
- _fnSetObjectDataFn( dataProp )( json, write );
4413
+ _fnSetObjectDataFn(dataProp)(json, write);
4419
4414
  }
4420
4415
 
4421
4416
  /**
@@ -4425,14 +4420,12 @@ function _fnAjaxDataSrc ( settings, json, write )
4425
4420
  * @param {*} json JSON data
4426
4421
  * @returns Resolved value
4427
4422
  */
4428
- function _fnAjaxDataSrcParam (settings, param, json) {
4429
- var dataSrc = $.isPlainObject( settings.ajax )
4430
- ? settings.ajax.dataSrc
4431
- : null;
4423
+ function _fnAjaxDataSrcParam(settings, param, json) {
4424
+ var dataSrc = $.isPlainObject(settings.ajax) ? settings.ajax.dataSrc : null;
4432
4425
 
4433
4426
  if (dataSrc && dataSrc[param]) {
4434
4427
  // Get from custom location
4435
- return _fnGetObjectDataFn( dataSrc[param] )( json );
4428
+ return _fnGetObjectDataFn(dataSrc[param])(json);
4436
4429
  }
4437
4430
 
4438
4431
  // else - Default behaviour
@@ -4449,9 +4442,7 @@ function _fnAjaxDataSrcParam (settings, param, json) {
4449
4442
  old = 'iTotalDisplayRecords';
4450
4443
  }
4451
4444
 
4452
- return json[old] !== undefined
4453
- ? json[old]
4454
- : json[param];
4445
+ return json[old] !== undefined ? json[old] : json[param];
4455
4446
  }
4456
4447
 
4457
4448
 
@@ -5390,7 +5381,7 @@ function _fnCalculateColumnWidths ( settings )
5390
5381
  visibleColumns = _fnGetColumns( settings, 'bVisible' ),
5391
5382
  tableWidthAttr = table.getAttribute('width'), // from DOM element
5392
5383
  tableContainer = table.parentNode,
5393
- i, column, columnIdx;
5384
+ i, j, column, columnIdx;
5394
5385
 
5395
5386
  var styleWidth = table.style.width;
5396
5387
  var containerWidth = _fnWrapperWidth(settings);
@@ -5424,17 +5415,16 @@ function _fnCalculateColumnWidths ( settings )
5424
5415
  false
5425
5416
  );
5426
5417
 
5427
- // Construct a single row, worst case, table with the widest
5428
- // node in the data, assign any user defined widths, then insert it into
5429
- // the DOM and allow the browser to do all the hard work of calculating
5430
- // table widths
5418
+ // Construct a worst case table with the widest, assign any user defined
5419
+ // widths, then insert it into the DOM and allow the browser to do all
5420
+ // the hard work of calculating table widths
5431
5421
  var tmpTable = $(table.cloneNode())
5432
5422
  .css( 'visibility', 'hidden' )
5423
+ .css( 'margin', 0 )
5433
5424
  .removeAttr( 'id' );
5434
5425
 
5435
5426
  // Clean up the table body
5436
5427
  tmpTable.append('<tbody/>')
5437
- var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5438
5428
 
5439
5429
  // Clone the table header and footer - we can't use the header / footer
5440
5430
  // from the cloned table, since if scrolling is active, the table's
@@ -5474,23 +5464,37 @@ function _fnCalculateColumnWidths ( settings )
5474
5464
  }
5475
5465
  } );
5476
5466
 
5477
- // Find the widest piece of data for each column and put it into the table
5467
+ // Get the widest strings for each of the visible columns and add them to
5468
+ // our table to create a "worst case"
5469
+ var longestData = [];
5470
+
5478
5471
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
5479
- columnIdx = visibleColumns[i];
5480
- column = columns[ columnIdx ];
5481
-
5482
- var longest = _fnGetMaxLenString(settings, columnIdx);
5483
- var autoClass = _ext.type.className[column.sType];
5484
- var text = longest + column.sContentPadding;
5485
- var insert = longest.indexOf('<') === -1
5486
- ? document.createTextNode(text)
5487
- : text
5488
-
5489
- $('<td/>')
5490
- .addClass(autoClass)
5491
- .addClass(column.sClass)
5492
- .append(insert)
5493
- .appendTo(tr);
5472
+ longestData.push(_fnGetWideStrings(settings, visibleColumns[i]));
5473
+ }
5474
+
5475
+ if (longestData.length) {
5476
+ for ( i=0 ; i<longestData[0].length ; i++ ) {
5477
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5478
+
5479
+ for ( j=0 ; j<visibleColumns.length ; j++ ) {
5480
+ columnIdx = visibleColumns[j];
5481
+ column = columns[ columnIdx ];
5482
+
5483
+ var longest = longestData[j][i] || '';
5484
+ var autoClass = _ext.type.className[column.sType];
5485
+ var padding = column.sContentPadding || (scrollX ? '-' : '');
5486
+ var text = longest + padding;
5487
+ var insert = longest.indexOf('<') === -1
5488
+ ? document.createTextNode(text)
5489
+ : text
5490
+
5491
+ $('<td/>')
5492
+ .addClass(autoClass)
5493
+ .addClass(column.sClass)
5494
+ .append(insert)
5495
+ .appendTo(tr);
5496
+ }
5497
+ }
5494
5498
  }
5495
5499
 
5496
5500
  // Tidy the temporary table - remove name attributes so there aren't
@@ -5629,19 +5633,31 @@ function _fnWrapperWidth(settings) {
5629
5633
  }
5630
5634
 
5631
5635
  /**
5632
- * Get the maximum strlen for each data column
5636
+ * Get the widest strings for each column.
5637
+ *
5638
+ * It is very difficult to determine what the widest string actually is due to variable character
5639
+ * width and kerning. Doing an exact calculation with the DOM or even Canvas would kill performance
5640
+ * and this is a critical point, so we use two techniques to determine a collection of the longest
5641
+ * strings from the column, which will likely contain the widest strings:
5642
+ *
5643
+ * 1) Get the top three longest strings from the column
5644
+ * 2) Get the top three widest words (i.e. an unbreakable phrase)
5645
+ *
5633
5646
  * @param {object} settings dataTables settings object
5634
5647
  * @param {int} colIdx column of interest
5635
- * @returns {string} string of the max length
5648
+ * @returns {string[]} Array of the longest strings
5636
5649
  * @memberof DataTable#oApi
5637
5650
  */
5638
- function _fnGetMaxLenString( settings, colIdx )
5651
+ function _fnGetWideStrings( settings, colIdx )
5639
5652
  {
5640
5653
  var column = settings.aoColumns[colIdx];
5641
5654
 
5642
- if (! column.maxLenString) {
5643
- var s, max='', maxLen = -1;
5644
-
5655
+ // Do we need to recalculate (i.e. was invalidated), or just use the cached data?
5656
+ if (! column.wideStrings) {
5657
+ var allStrings = [];
5658
+ var collection = [];
5659
+
5660
+ // Create an array with the string information for the column
5645
5661
  for ( var i=0, iLen=settings.aiDisplayMaster.length ; i<iLen ; i++ ) {
5646
5662
  var rowIdx = settings.aiDisplayMaster[i];
5647
5663
  var data = _fnGetRowDisplay(settings, rowIdx)[colIdx];
@@ -5656,21 +5672,49 @@ function _fnGetMaxLenString( settings, colIdx )
5656
5672
  .replace(/id=".*?"/g, '')
5657
5673
  .replace(/name=".*?"/g, '');
5658
5674
 
5659
- s = _stripHtml(cellString)
5675
+ var s = _stripHtml(cellString)
5660
5676
  .replace( /&nbsp;/g, ' ' );
5661
5677
 
5662
- if ( s.length > maxLen ) {
5663
- // We want the HTML in the string, but the length that
5664
- // is important is the stripped string
5665
- max = cellString;
5666
- maxLen = s.length;
5667
- }
5678
+ collection.push({
5679
+ str: s,
5680
+ len: s.length
5681
+ });
5682
+
5683
+ allStrings.push(s);
5684
+ }
5685
+
5686
+ // Order and then cut down to the size we need
5687
+ collection
5688
+ .sort(function (a, b) {
5689
+ return b.len - a.len;
5690
+ })
5691
+ .splice(3);
5692
+
5693
+ column.wideStrings = collection.map(function (item) {
5694
+ return item.str;
5695
+ });
5696
+
5697
+ // Longest unbroken string
5698
+ let parts = allStrings.join(' ').split(' ');
5699
+
5700
+ parts.sort(function (a, b) {
5701
+ return b.length - a.length;
5702
+ });
5703
+
5704
+ if (parts.length) {
5705
+ column.wideStrings.push(parts[0]);
5706
+ }
5707
+
5708
+ if (parts.length > 1) {
5709
+ column.wideStrings.push(parts[1]);
5668
5710
  }
5669
5711
 
5670
- column.maxLenString = max;
5712
+ if (parts.length > 2) {
5713
+ column.wideStrings.push(parts[3]);
5714
+ }
5671
5715
  }
5672
5716
 
5673
- return column.maxLenString;
5717
+ return column.wideStrings;
5674
5718
  }
5675
5719
 
5676
5720
 
@@ -6466,7 +6510,9 @@ function _fnImplementState ( settings, s, callback) {
6466
6510
 
6467
6511
  // If the api is defined then we need to adjust the columns once the visibility has been changed
6468
6512
  if (api) {
6469
- api.columns.adjust();
6513
+ api.one('draw', function () {
6514
+ api.columns.adjust();
6515
+ });
6470
6516
  }
6471
6517
  }
6472
6518
  }
@@ -9009,13 +9055,16 @@ _api_registerPlural( 'columns().titles()', 'column().title()', function (title,
9009
9055
 
9010
9056
  _api_registerPlural( 'columns().types()', 'column().type()', function () {
9011
9057
  return this.iterator( 'column', function ( settings, column ) {
9012
- var type = settings.aoColumns[column].sType;
9058
+ var colObj = settings.aoColumns[column]
9059
+ var type = colObj.sType;
9013
9060
 
9014
9061
  // If the type was invalidated, then resolve it. This actually does
9015
9062
  // all columns at the moment. Would only happen once if getting all
9016
9063
  // column's data types.
9017
9064
  if (! type) {
9018
9065
  _fnColumnTypes(settings);
9066
+
9067
+ type = colObj.sType;
9019
9068
  }
9020
9069
 
9021
9070
  return type;
@@ -10186,7 +10235,7 @@ function cleanHeader(node, className) {
10186
10235
  * @type string
10187
10236
  * @default Version number
10188
10237
  */
10189
- DataTable.version = "2.3.3";
10238
+ DataTable.version = "2.3.5";
10190
10239
 
10191
10240
  /**
10192
10241
  * Private data store, containing all of the settings objects that are
@@ -10488,8 +10537,8 @@ DataTable.models.oColumn = {
10488
10537
  */
10489
10538
  "sWidthOrig": null,
10490
10539
 
10491
- /** Cached string which is the longest in the column */
10492
- maxLenString: null,
10540
+ /** Cached longest strings from a column */
10541
+ wideStrings: null,
10493
10542
 
10494
10543
  /**
10495
10544
  * Store for named searches
@@ -12603,7 +12652,10 @@ function __mlHelper (localeString) {
12603
12652
  }
12604
12653
 
12605
12654
  var formatted = to === null
12606
- ? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
12655
+ ? __mld(dt, 'toDate', 'toJSDate', '')[localeString](
12656
+ navigator.language,
12657
+ { timeZone: "UTC" }
12658
+ )
12607
12659
  : __mld(dt, 'format', 'toFormat', 'toISOString', to);
12608
12660
 
12609
12661
  // XSS protection