jquery-datatables-rails 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js +110 -96
  3. data/app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js +6 -6
  4. data/app/assets/javascripts/dataTables/extras/dataTables.colReorder.js +28 -27
  5. data/app/assets/javascripts/dataTables/extras/dataTables.colVis.js +27 -11
  6. data/app/assets/javascripts/dataTables/extras/dataTables.fixedColumns.js +53 -29
  7. data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +110 -47
  8. data/app/assets/javascripts/dataTables/extras/dataTables.tableTools.js +90 -25
  9. data/app/assets/javascripts/dataTables/jquery.dataTables.foundation.js +133 -139
  10. data/app/assets/javascripts/dataTables/jquery.dataTables.js +483 -375
  11. data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.numbersHtml.js +37 -14
  12. data/app/assets/javascripts/dataTables/jquery.dataTables.typeDetection.numbersHtml.js +49 -33
  13. data/app/assets/media/dataTables/extras/swf/copy_csv_xls.swf +0 -0
  14. data/app/assets/media/dataTables/extras/swf/copy_csv_xls_pdf.swf +0 -0
  15. data/app/assets/stylesheets/dataTables/bootstrap/2/jquery.dataTables.bootstrap.scss +34 -9
  16. data/app/assets/stylesheets/dataTables/bootstrap/3/jquery.dataTables.bootstrap.scss +122 -31
  17. data/app/assets/stylesheets/dataTables/extras/dataTables.colvis.jqueryui.scss +18 -0
  18. data/app/assets/stylesheets/dataTables/extras/dataTables.fixedColumns.scss +1 -0
  19. data/app/assets/stylesheets/dataTables/extras/dataTables.responsive.scss +29 -12
  20. data/app/assets/stylesheets/dataTables/extras/dataTables.tableTools.scss +43 -19
  21. data/app/assets/stylesheets/dataTables/jquery.dataTables.foundation.scss +15 -4
  22. data/app/assets/stylesheets/dataTables/jquery.dataTables.scss +22 -11
  23. data/lib/jquery/datatables/rails/version.rb +1 -1
  24. metadata +18 -18
@@ -1,11 +1,11 @@
1
- /*! DataTables 1.10.3
1
+ /*! DataTables 1.10.6
2
2
  * ©2008-2014 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary DataTables
7
7
  * @description Paginate, search and order HTML tables
8
- * @version 1.10.3
8
+ * @version 1.10.6
9
9
  * @file jquery.dataTables.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  /*jslint evil: true, undef: true, browser: true */
25
- /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
25
+ /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
26
 
27
27
  (/** @lends <global> */function( window, document, undefined ) {
28
28
 
@@ -35,7 +35,7 @@
35
35
  }
36
36
  else if ( typeof exports === 'object' ) {
37
37
  // Node/CommonJS
38
- factory( require( 'jquery' ) );
38
+ module.exports = factory( require( 'jquery' ) );
39
39
  }
40
40
  else if ( jQuery && !jQuery.fn.dataTable ) {
41
41
  // Define using browser globals otherwise
@@ -111,9 +111,17 @@
111
111
  // Escape regular expression special characters
112
112
  var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
113
113
 
114
- // U+2009 is thin space and U+202F is narrow no-break space, both used in many
115
- // standards as thousands separators
116
- var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
114
+ // http://en.wikipedia.org/wiki/Foreign_exchange_market
115
+ // - \u20BD - Russian ruble.
116
+ // - \u20a9 - South Korean Won
117
+ // - \u20BA - Turkish Lira
118
+ // - \u20B9 - Indian Rupee
119
+ // - R - Brazil (R$) and South Africa
120
+ // - fr - Swiss Franc
121
+ // - kr - Swedish krona, Norwegian krone and Danish krone
122
+ // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
123
+ // standards as thousands separators.
124
+ var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
117
125
 
118
126
 
119
127
  var _empty = function ( d ) {
@@ -142,6 +150,13 @@
142
150
  var _isNumber = function ( d, decimalPoint, formatted ) {
143
151
  var strType = typeof d === 'string';
144
152
 
153
+ // If empty return immediately so there must be a number if it is a
154
+ // formatted string (this stops the string "k", or "kr", etc being detected
155
+ // as a formatted number for currency
156
+ if ( _empty( d ) ) {
157
+ return true;
158
+ }
159
+
145
160
  if ( decimalPoint && strType ) {
146
161
  d = _numToDecimal( d, decimalPoint );
147
162
  }
@@ -150,7 +165,7 @@
150
165
  d = d.replace( _re_formatted_numeric, '' );
151
166
  }
152
167
 
153
- return _empty( d ) || (!isNaN( parseFloat(d) ) && isFinite( d ));
168
+ return !isNaN( parseFloat(d) ) && isFinite( d );
154
169
  };
155
170
 
156
171
 
@@ -210,7 +225,9 @@
210
225
  // is essential here
211
226
  if ( prop2 !== undefined ) {
212
227
  for ( ; i<ien ; i++ ) {
213
- out.push( a[ order[i] ][ prop ][ prop2 ] );
228
+ if ( a[ order[i] ][ prop ] ) {
229
+ out.push( a[ order[i] ][ prop ][ prop2 ] );
230
+ }
214
231
  }
215
232
  }
216
233
  else {
@@ -245,6 +262,20 @@
245
262
  };
246
263
 
247
264
 
265
+ var _removeEmpty = function ( a )
266
+ {
267
+ var out = [];
268
+
269
+ for ( var i=0, ien=a.length ; i<ien ; i++ ) {
270
+ if ( a[i] ) { // careful - will remove all falsy values!
271
+ out.push( a[i] );
272
+ }
273
+ }
274
+
275
+ return out;
276
+ };
277
+
278
+
248
279
  var _stripHtml = function ( d ) {
249
280
  return d.replace( _re_html, '' );
250
281
  };
@@ -462,6 +493,12 @@
462
493
  _fnCompatMap( init, 'orderData', 'aDataSort' );
463
494
  _fnCompatMap( init, 'orderSequence', 'asSorting' );
464
495
  _fnCompatMap( init, 'orderDataType', 'sortDataType' );
496
+
497
+ // orderData can be given as an integer
498
+ var dataSort = init.aDataSort;
499
+ if ( dataSort && ! $.isArray( dataSort ) ) {
500
+ init.aDataSort = [ dataSort ];
501
+ }
465
502
  }
466
503
 
467
504
 
@@ -512,7 +549,7 @@
512
549
 
513
550
  // In rtl text layout, some browsers (most, but not all) will place the
514
551
  // scrollbar on the left, rather than the right.
515
- browser.bScrollbarLeft = test.offset().left !== 1;
552
+ browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
516
553
 
517
554
  n.remove();
518
555
  }
@@ -579,7 +616,7 @@
579
616
  searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
580
617
 
581
618
  // Use the default column options function to initialise classes etc
582
- _fnColumnOptions( oSettings, iCol, null );
619
+ _fnColumnOptions( oSettings, iCol, $(nTh).data() );
583
620
  }
584
621
 
585
622
 
@@ -642,7 +679,7 @@
642
679
  /* iDataSort to be applied (backwards compatibility), but aDataSort will take
643
680
  * priority if defined
644
681
  */
645
- if ( typeof oOptions.iDataSort === 'number' )
682
+ if ( oOptions.iDataSort !== undefined )
646
683
  {
647
684
  oCol.aDataSort = [ oOptions.iDataSort ];
648
685
  }
@@ -842,11 +879,18 @@
842
879
 
843
880
  detectedType = types[j]( cache[k], settings );
844
881
 
845
- // Doesn't match, so break early, since this type can't
846
- // apply to this column. Also, HTML is a special case since
847
- // it is so similar to `string`. Just a single match is
848
- // needed for a column to be html type
849
- if ( ! detectedType || detectedType === 'html' ) {
882
+ // If null, then this type can't apply to this column, so
883
+ // rather than testing all cells, break out. There is an
884
+ // exception for the last type which is `html`. We need to
885
+ // scan all rows since it is possible to mix string and HTML
886
+ // types
887
+ if ( ! detectedType && j !== types.length-1 ) {
888
+ break;
889
+ }
890
+
891
+ // Only a single match is needed for html type since it is
892
+ // bottom of the pile and very similar to string
893
+ if ( detectedType === 'html' ) {
850
894
  break;
851
895
  }
852
896
  }
@@ -1429,61 +1473,75 @@
1429
1473
  * the cached data is next requested. Also update from the data source object.
1430
1474
  *
1431
1475
  * @param {object} settings DataTables settings object
1432
- * @param {int} rowIdx Row index to invalidate
1476
+ * @param {int} rowIdx Row index to invalidate
1477
+ * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
1478
+ * or 'data'
1479
+ * @param {int} [colIdx] Column index to invalidate. If undefined the whole
1480
+ * row will be invalidated
1433
1481
  * @memberof DataTable#oApi
1434
1482
  *
1435
1483
  * @todo For the modularisation of v1.11 this will need to become a callback, so
1436
1484
  * the sort and filter methods can subscribe to it. That will required
1437
1485
  * initialisation options for sorting, which is why it is not already baked in
1438
1486
  */
1439
- function _fnInvalidateRow( settings, rowIdx, src, column )
1487
+ function _fnInvalidate( settings, rowIdx, src, colIdx )
1440
1488
  {
1441
1489
  var row = settings.aoData[ rowIdx ];
1442
1490
  var i, ien;
1491
+ var cellWrite = function ( cell, col ) {
1492
+ // This is very frustrating, but in IE if you just write directly
1493
+ // to innerHTML, and elements that are overwritten are GC'ed,
1494
+ // even if there is a reference to them elsewhere
1495
+ while ( cell.childNodes.length ) {
1496
+ cell.removeChild( cell.firstChild );
1497
+ }
1498
+
1499
+ cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
1500
+ };
1443
1501
 
1444
1502
  // Are we reading last data from DOM or the data object?
1445
1503
  if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1446
1504
  // Read the data from the DOM
1447
- row._aData = _fnGetRowElements( settings, row ).data;
1505
+ row._aData = _fnGetRowElements(
1506
+ settings, row, colIdx, colIdx === undefined ? undefined : row._aData
1507
+ )
1508
+ .data;
1448
1509
  }
1449
1510
  else {
1450
1511
  // Reading from data object, update the DOM
1451
1512
  var cells = row.anCells;
1452
- var cell;
1453
1513
 
1454
1514
  if ( cells ) {
1455
- for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1456
- cell = cells[i];
1457
-
1458
- // This is very frustrating, but in IE if you just write directly
1459
- // to innerHTML, and elements that are overwritten are GC'ed,
1460
- // even if there is a reference to them elsewhere
1461
- while ( cell.childNodes.length ) {
1462
- cell.removeChild( cell.firstChild );
1515
+ if ( colIdx !== undefined ) {
1516
+ cellWrite( cells[colIdx], colIdx );
1517
+ }
1518
+ else {
1519
+ for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1520
+ cellWrite( cells[i], i );
1463
1521
  }
1464
-
1465
- cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );
1466
1522
  }
1467
1523
  }
1468
1524
  }
1469
1525
 
1526
+ // For both row and cell invalidation, the cached data for sorting and
1527
+ // filtering is nulled out
1470
1528
  row._aSortData = null;
1471
1529
  row._aFilterData = null;
1472
1530
 
1473
1531
  // Invalidate the type for a specific column (if given) or all columns since
1474
1532
  // the data might have changed
1475
1533
  var cols = settings.aoColumns;
1476
- if ( column !== undefined ) {
1477
- cols[ column ].sType = null;
1534
+ if ( colIdx !== undefined ) {
1535
+ cols[ colIdx ].sType = null;
1478
1536
  }
1479
1537
  else {
1480
1538
  for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1481
1539
  cols[i].sType = null;
1482
1540
  }
1483
- }
1484
1541
 
1485
- // Update DataTables special `DT_*` attributes for the row
1486
- _fnRowAttributes( row );
1542
+ // Update DataTables special `DT_*` attributes for the row
1543
+ _fnRowAttributes( row );
1544
+ }
1487
1545
  }
1488
1546
 
1489
1547
 
@@ -1494,13 +1552,17 @@
1494
1552
  * @param {object} settings DataTables settings object
1495
1553
  * @param {node|object} TR element from which to read data or existing row
1496
1554
  * object from which to re-read the data from the cells
1555
+ * @param {int} [colIdx] Optional column index
1556
+ * @param {array|object} [d] Data source object. If `colIdx` is given then this
1557
+ * parameter should also be given and will be used to write the data into.
1558
+ * Only the column in question will be written
1497
1559
  * @returns {object} Object with two parameters: `data` the data read, in
1498
1560
  * document order, and `cells` and array of nodes (they can be useful to the
1499
1561
  * caller, so rather than needing a second traversal to get them, just return
1500
1562
  * them from here).
1501
1563
  * @memberof DataTable#oApi
1502
1564
  */
1503
- function _fnGetRowElements( settings, row )
1565
+ function _fnGetRowElements( settings, row, colIdx, d )
1504
1566
  {
1505
1567
  var
1506
1568
  tds = [],
@@ -1509,7 +1571,8 @@
1509
1571
  columns = settings.aoColumns,
1510
1572
  objectRead = settings._rowReadObject;
1511
1573
 
1512
- var d = objectRead ? {} : [];
1574
+ // Allow the data object to be passed in, or construct
1575
+ d = d || objectRead ? {} : [];
1513
1576
 
1514
1577
  var attr = function ( str, td ) {
1515
1578
  if ( typeof str === 'string' ) {
@@ -1523,30 +1586,33 @@
1523
1586
  }
1524
1587
  };
1525
1588
 
1589
+ // Read data from a cell and store into the data object
1526
1590
  var cellProcess = function ( cell ) {
1527
- col = columns[i];
1528
- contents = $.trim(cell.innerHTML);
1591
+ if ( colIdx === undefined || colIdx === i ) {
1592
+ col = columns[i];
1593
+ contents = $.trim(cell.innerHTML);
1529
1594
 
1530
- if ( col && col._bAttrSrc ) {
1531
- var setter = _fnSetObjectDataFn( col.mData._ );
1532
- setter( d, contents );
1595
+ if ( col && col._bAttrSrc ) {
1596
+ var setter = _fnSetObjectDataFn( col.mData._ );
1597
+ setter( d, contents );
1533
1598
 
1534
- attr( col.mData.sort, cell );
1535
- attr( col.mData.type, cell );
1536
- attr( col.mData.filter, cell );
1537
- }
1538
- else {
1539
- // Depending on the `data` option for the columns the data can be
1540
- // read to either an object or an array.
1541
- if ( objectRead ) {
1542
- if ( ! col._setter ) {
1543
- // Cache the setter function
1544
- col._setter = _fnSetObjectDataFn( col.mData );
1545
- }
1546
- col._setter( d, contents );
1599
+ attr( col.mData.sort, cell );
1600
+ attr( col.mData.type, cell );
1601
+ attr( col.mData.filter, cell );
1547
1602
  }
1548
1603
  else {
1549
- d.push( contents );
1604
+ // Depending on the `data` option for the columns the data can
1605
+ // be read to either an object or an array.
1606
+ if ( objectRead ) {
1607
+ if ( ! col._setter ) {
1608
+ // Cache the setter function
1609
+ col._setter = _fnSetObjectDataFn( col.mData );
1610
+ }
1611
+ col._setter( d, contents );
1612
+ }
1613
+ else {
1614
+ d[i] = contents;
1615
+ }
1550
1616
  }
1551
1617
  }
1552
1618
 
@@ -1554,7 +1620,7 @@
1554
1620
  };
1555
1621
 
1556
1622
  if ( td ) {
1557
- // `tr` element passed in
1623
+ // `tr` element was passed in
1558
1624
  while ( td ) {
1559
1625
  name = td.nodeName.toUpperCase();
1560
1626
 
@@ -1689,6 +1755,10 @@
1689
1755
  .addClass( data.DT_RowClass );
1690
1756
  }
1691
1757
 
1758
+ if ( data.DT_RowAttr ) {
1759
+ $(tr).attr( data.DT_RowAttr );
1760
+ }
1761
+
1692
1762
  if ( data.DT_RowData ) {
1693
1763
  $(tr).data( data.DT_RowData );
1694
1764
  }
@@ -2322,8 +2392,6 @@
2322
2392
  return aReturn;
2323
2393
  }
2324
2394
 
2325
-
2326
-
2327
2395
  /**
2328
2396
  * Create an Ajax call based on the table's settings, taking into account that
2329
2397
  * parameters can have multiple forms, and backwards compatibility.
@@ -2366,16 +2434,20 @@
2366
2434
  var ajaxData;
2367
2435
  var ajax = oSettings.ajax;
2368
2436
  var instance = oSettings.oInstance;
2437
+ var callback = function ( json ) {
2438
+ _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2439
+ fn( json );
2440
+ };
2369
2441
 
2370
2442
  if ( $.isPlainObject( ajax ) && ajax.data )
2371
2443
  {
2372
2444
  ajaxData = ajax.data;
2373
2445
 
2374
2446
  var newData = $.isFunction( ajaxData ) ?
2375
- ajaxData( data ) : // fn can manipulate data or return an object
2376
- ajaxData; // object or array to merge
2447
+ ajaxData( data, oSettings ) : // fn can manipulate data or return
2448
+ ajaxData; // an object object or array to merge
2377
2449
 
2378
- // If the function returned an object, use that alone
2450
+ // If the function returned something, use that alone
2379
2451
  data = $.isFunction( ajaxData ) && newData ?
2380
2452
  newData :
2381
2453
  $.extend( true, data, newData );
@@ -2394,8 +2466,7 @@
2394
2466
  }
2395
2467
 
2396
2468
  oSettings.json = json;
2397
- _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2398
- fn( json );
2469
+ callback( json );
2399
2470
  },
2400
2471
  "dataType": "json",
2401
2472
  "cache": false,
@@ -2428,7 +2499,7 @@
2428
2499
  $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2429
2500
  return { name: key, value: val };
2430
2501
  } ),
2431
- fn,
2502
+ callback,
2432
2503
  oSettings
2433
2504
  );
2434
2505
  }
@@ -2442,7 +2513,7 @@
2442
2513
  else if ( $.isFunction( ajax ) )
2443
2514
  {
2444
2515
  // Is a function - let the caller define what needs to be done
2445
- oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2516
+ oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
2446
2517
  }
2447
2518
  else
2448
2519
  {
@@ -2608,9 +2679,10 @@
2608
2679
  return json[old] !== undefined ? json[old] : json[modern];
2609
2680
  };
2610
2681
 
2682
+ var data = _fnAjaxDataSrc( settings, json );
2611
2683
  var draw = compat( 'sEcho', 'draw' );
2612
2684
  var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
2613
- var rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2685
+ var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2614
2686
 
2615
2687
  if ( draw ) {
2616
2688
  // Protect against out of sequence returns
@@ -2622,9 +2694,8 @@
2622
2694
 
2623
2695
  _fnClearTable( settings );
2624
2696
  settings._iRecordsTotal = parseInt(recordsTotal, 10);
2625
- settings._iRecordsDisplay = parseInt(rocordsFiltered, 10);
2697
+ settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
2626
2698
 
2627
- var data = _fnAjaxDataSrc( settings, json );
2628
2699
  for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2629
2700
  _fnAddData( settings, data[i] );
2630
2701
  }
@@ -2667,7 +2738,6 @@
2667
2738
  json;
2668
2739
  }
2669
2740
 
2670
-
2671
2741
  /**
2672
2742
  * Generate the node required for filtering text
2673
2743
  * @returns {node} Filter control element
@@ -2965,7 +3035,7 @@
2965
3035
 
2966
3036
 
2967
3037
  /**
2968
- * scape a string such that it can be used in a regular expression
3038
+ * Escape a string such that it can be used in a regular expression
2969
3039
  * @param {string} sVal string to escape
2970
3040
  * @returns {string} escaped string
2971
3041
  * @memberof DataTable#oApi
@@ -3605,12 +3675,12 @@
3605
3675
  headerClone
3606
3676
  .removeAttr('id')
3607
3677
  .css( 'margin-left', 0 )
3678
+ .append( captionSide === 'top' ? caption : null )
3608
3679
  .append(
3609
3680
  table.children('thead')
3610
3681
  )
3611
3682
  )
3612
3683
  )
3613
- .append( captionSide === 'top' ? caption : null )
3614
3684
  )
3615
3685
  .append(
3616
3686
  $(_div, { 'class': classes.sScrollBody } )
@@ -3636,12 +3706,12 @@
3636
3706
  footerClone
3637
3707
  .removeAttr('id')
3638
3708
  .css( 'margin-left', 0 )
3709
+ .append( captionSide === 'bottom' ? caption : null )
3639
3710
  .append(
3640
3711
  table.children('tfoot')
3641
3712
  )
3642
3713
  )
3643
3714
  )
3644
- .append( captionSide === 'bottom' ? caption : null )
3645
3715
  );
3646
3716
  }
3647
3717
 
@@ -3652,7 +3722,7 @@
3652
3722
 
3653
3723
  // When the body is scrolled, then we also want to scroll the headers
3654
3724
  if ( scrollX ) {
3655
- $(scrollBody).scroll( function (e) {
3725
+ $(scrollBody).on( 'scroll.DT', function (e) {
3656
3726
  var scrollLeft = this.scrollLeft;
3657
3727
 
3658
3728
  scrollHead.scrollLeft = scrollLeft;
@@ -4033,11 +4103,16 @@
4033
4103
  columnCount = columns.length,
4034
4104
  visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4035
4105
  headerCells = $('th', oSettings.nTHead),
4036
- tableWidthAttr = table.getAttribute('width'),
4106
+ tableWidthAttr = table.getAttribute('width'), // from DOM element
4037
4107
  tableContainer = table.parentNode,
4038
4108
  userInputs = false,
4039
4109
  i, column, columnIdx, width, outerWidth;
4040
4110
 
4111
+ var styleWidth = table.style.width;
4112
+ if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
4113
+ tableWidthAttr = styleWidth;
4114
+ }
4115
+
4041
4116
  /* Convert any user input sizes into pixel sizes */
4042
4117
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
4043
4118
  column = columns[ visibleColumns[i] ];
@@ -4214,12 +4289,9 @@
4214
4289
  fn.apply( that, args );
4215
4290
  }, frequency );
4216
4291
  }
4217
- else if ( last ) {
4218
- last = now;
4219
- fn.apply( that, args );
4220
- }
4221
4292
  else {
4222
4293
  last = now;
4294
+ fn.apply( that, args );
4223
4295
  }
4224
4296
  };
4225
4297
  }
@@ -4350,41 +4422,28 @@
4350
4422
  {
4351
4423
  // On first run a static variable is set, since this is only needed once.
4352
4424
  // Subsequent runs will just use the previously calculated value
4353
- if ( ! DataTable.__scrollbarWidth ) {
4354
- var inner = $('<p/>').css( {
4355
- width: '100%',
4356
- height: 200,
4357
- padding: 0
4358
- } )[0];
4359
-
4360
- var outer = $('<div/>')
4361
- .css( {
4425
+ var width = DataTable.__scrollbarWidth;
4426
+
4427
+ if ( width === undefined ) {
4428
+ var sizer = $('<p/>').css( {
4362
4429
  position: 'absolute',
4363
4430
  top: 0,
4364
4431
  left: 0,
4365
- width: 200,
4432
+ width: '100%',
4366
4433
  height: 150,
4367
4434
  padding: 0,
4368
- overflow: 'hidden',
4435
+ overflow: 'scroll',
4369
4436
  visibility: 'hidden'
4370
4437
  } )
4371
- .append( inner )
4372
- .appendTo( 'body' );
4373
-
4374
- var w1 = inner.offsetWidth;
4375
- outer.css( 'overflow', 'scroll' );
4376
- var w2 = inner.offsetWidth;
4377
-
4378
- if ( w1 === w2 ) {
4379
- w2 = outer[0].clientWidth;
4380
- }
4438
+ .appendTo('body');
4381
4439
 
4382
- outer.remove();
4440
+ width = sizer[0].offsetWidth - sizer[0].clientWidth;
4441
+ DataTable.__scrollbarWidth = width;
4383
4442
 
4384
- DataTable.__scrollbarWidth = w1 - w2;
4443
+ sizer.remove();
4385
4444
  }
4386
4445
 
4387
- return DataTable.__scrollbarWidth;
4446
+ return width;
4388
4447
  }
4389
4448
 
4390
4449
 
@@ -4675,6 +4734,10 @@
4675
4734
  // Yes, modify the sort
4676
4735
  nextSortIdx = next( sorting[sortIdx], true );
4677
4736
 
4737
+ if ( nextSortIdx === null && sorting.length === 1 ) {
4738
+ nextSortIdx = 0; // can't remove sorting completely
4739
+ }
4740
+
4678
4741
  if ( nextSortIdx === null ) {
4679
4742
  sorting.splice( sortIdx, 1 );
4680
4743
  }
@@ -4909,31 +4972,43 @@
4909
4972
 
4910
4973
  // Restore key features - todo - for 1.11 this needs to be done by
4911
4974
  // subscribed events
4912
- settings._iDisplayStart = state.start;
4913
- settings.iInitDisplayStart = state.start;
4914
- settings._iDisplayLength = state.length;
4915
- settings.aaSorting = [];
4975
+ if ( state.start !== undefined ) {
4976
+ settings._iDisplayStart = state.start;
4977
+ settings.iInitDisplayStart = state.start;
4978
+ }
4979
+ if ( state.length !== undefined ) {
4980
+ settings._iDisplayLength = state.length;
4981
+ }
4916
4982
 
4917
4983
  // Order
4918
- $.each( state.order, function ( i, col ) {
4919
- settings.aaSorting.push( col[0] >= columns.length ?
4920
- [ 0, col[1] ] :
4921
- col
4922
- );
4923
- } );
4984
+ if ( state.order !== undefined ) {
4985
+ settings.aaSorting = [];
4986
+ $.each( state.order, function ( i, col ) {
4987
+ settings.aaSorting.push( col[0] >= columns.length ?
4988
+ [ 0, col[1] ] :
4989
+ col
4990
+ );
4991
+ } );
4992
+ }
4924
4993
 
4925
4994
  // Search
4926
- $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
4995
+ if ( state.search !== undefined ) {
4996
+ $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
4997
+ }
4927
4998
 
4928
4999
  // Columns
4929
5000
  for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
4930
5001
  var col = state.columns[i];
4931
5002
 
4932
5003
  // Visibility
4933
- columns[i].bVisible = col.visible;
5004
+ if ( col.visible !== undefined ) {
5005
+ columns[i].bVisible = col.visible;
5006
+ }
4934
5007
 
4935
5008
  // Search
4936
- $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5009
+ if ( col.search !== undefined ) {
5010
+ $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5011
+ }
4937
5012
  }
4938
5013
 
4939
5014
  _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
@@ -4980,12 +5055,17 @@
4980
5055
  var ext = DataTable.ext;
4981
5056
  var type = ext.sErrMode || ext.errMode;
4982
5057
 
5058
+ _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5059
+
4983
5060
  if ( type == 'alert' ) {
4984
5061
  alert( msg );
4985
5062
  }
4986
- else {
5063
+ else if ( type == 'throw' ) {
4987
5064
  throw new Error(msg);
4988
5065
  }
5066
+ else if ( typeof type == 'function' ) {
5067
+ type( settings, tn, msg );
5068
+ }
4989
5069
  }
4990
5070
  else if ( window.console && console.log ) {
4991
5071
  console.log( msg );
@@ -5160,11 +5240,14 @@
5160
5240
  len = settings._iDisplayLength;
5161
5241
 
5162
5242
  /* If we have space to show extra rows (backing up from the end point - then do so */
5163
- if (start >= end)
5243
+ if ( start >= end )
5164
5244
  {
5165
5245
  start = end - len;
5166
5246
  }
5167
5247
 
5248
+ // Keep the start record on the current page
5249
+ start -= (start % len);
5250
+
5168
5251
  if ( len === -1 || start < 0 )
5169
5252
  {
5170
5253
  start = 0;
@@ -5554,8 +5637,8 @@
5554
5637
  this.fnDraw = function( complete )
5555
5638
  {
5556
5639
  // Note that this isn't an exact match to the old call to _fnDraw - it takes
5557
- // into account the new data, but can old position.
5558
- this.api( true ).draw( ! complete );
5640
+ // into account the new data, but can hold position.
5641
+ this.api( true ).draw( complete );
5559
5642
  };
5560
5643
 
5561
5644
 
@@ -6003,6 +6086,7 @@
6003
6086
  var sId = this.getAttribute( 'id' );
6004
6087
  var bInitHandedOff = false;
6005
6088
  var defaults = DataTable.defaults;
6089
+ var $this = $(this);
6006
6090
 
6007
6091
 
6008
6092
  /* Sanity check */
@@ -6021,30 +6105,34 @@
6021
6105
  _fnCamelToHungarian( defaults.column, defaults.column, true );
6022
6106
 
6023
6107
  /* Setting up the initialisation object */
6024
- _fnCamelToHungarian( defaults, oInit );
6108
+ _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
6109
+
6110
+
6025
6111
 
6026
6112
  /* Check to see if we are re-initialising a table */
6027
6113
  var allSettings = DataTable.settings;
6028
6114
  for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6029
6115
  {
6116
+ var s = allSettings[i];
6117
+
6030
6118
  /* Base check on table node */
6031
- if ( allSettings[i].nTable == this )
6119
+ if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
6032
6120
  {
6033
6121
  var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6034
6122
  var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6035
6123
 
6036
6124
  if ( emptyInit || bRetrieve )
6037
6125
  {
6038
- return allSettings[i].oInstance;
6126
+ return s.oInstance;
6039
6127
  }
6040
6128
  else if ( bDestroy )
6041
6129
  {
6042
- allSettings[i].oInstance.fnDestroy();
6130
+ s.oInstance.fnDestroy();
6043
6131
  break;
6044
6132
  }
6045
6133
  else
6046
6134
  {
6047
- _fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
6135
+ _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
6048
6136
  return;
6049
6137
  }
6050
6138
  }
@@ -6054,7 +6142,7 @@
6054
6142
  * instance by simply deleting it. This is under the assumption that the table has been
6055
6143
  * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6056
6144
  */
6057
- if ( allSettings[i].sTableId == this.id )
6145
+ if ( s.sTableId == this.id )
6058
6146
  {
6059
6147
  allSettings.splice( i, 1 );
6060
6148
  break;
@@ -6070,18 +6158,19 @@
6070
6158
 
6071
6159
  /* Create the settings object for this table and set some of the default parameters */
6072
6160
  var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6073
- "nTable": this,
6074
- "oApi": _that.internal,
6075
- "oInit": oInit,
6076
- "sDestroyWidth": $(this)[0].style.width,
6161
+ "sDestroyWidth": $this[0].style.width,
6077
6162
  "sInstance": sId,
6078
6163
  "sTableId": sId
6079
6164
  } );
6165
+ oSettings.nTable = this;
6166
+ oSettings.oApi = _that.internal;
6167
+ oSettings.oInit = oInit;
6168
+
6080
6169
  allSettings.push( oSettings );
6081
6170
 
6082
6171
  // Need to add the instance after the instance after the settings object has been added
6083
6172
  // to the settings array, so we can self reference the table instance if more than one
6084
- oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
6173
+ oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
6085
6174
 
6086
6175
  // Backwards compatibility, before we apply all the defaults
6087
6176
  _fnCompatOpts( oInit );
@@ -6191,7 +6280,7 @@
6191
6280
  {
6192
6281
  $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6193
6282
  }
6194
- $(this).addClass( oClasses.sTable );
6283
+ $this.addClass( oClasses.sTable );
6195
6284
 
6196
6285
  /* Calculate the scroll bar width and cache it for use later on */
6197
6286
  if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
@@ -6218,26 +6307,31 @@
6218
6307
  }
6219
6308
 
6220
6309
  /* Language definitions */
6221
- if ( oInit.oLanguage.sUrl !== "" )
6310
+ var oLanguage = oSettings.oLanguage;
6311
+ $.extend( true, oLanguage, oInit.oLanguage );
6312
+
6313
+ if ( oLanguage.sUrl !== "" )
6222
6314
  {
6223
6315
  /* Get the language definitions from a file - because this Ajax call makes the language
6224
6316
  * get async to the remainder of this function we use bInitHandedOff to indicate that
6225
6317
  * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6226
6318
  */
6227
- oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6228
- $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6229
- _fnLanguageCompat( json );
6230
- _fnCamelToHungarian( defaults.oLanguage, json );
6231
- $.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
6232
- _fnInitialise( oSettings );
6319
+ $.ajax( {
6320
+ dataType: 'json',
6321
+ url: oLanguage.sUrl,
6322
+ success: function ( json ) {
6323
+ _fnLanguageCompat( json );
6324
+ _fnCamelToHungarian( defaults.oLanguage, json );
6325
+ $.extend( true, oLanguage, json );
6326
+ _fnInitialise( oSettings );
6327
+ },
6328
+ error: function () {
6329
+ // Error occurred loading language file, continue on as best we can
6330
+ _fnInitialise( oSettings );
6331
+ }
6233
6332
  } );
6234
6333
  bInitHandedOff = true;
6235
6334
  }
6236
- else
6237
- {
6238
- $.extend( true, oSettings.oLanguage, oInit.oLanguage );
6239
- }
6240
-
6241
6335
 
6242
6336
  /*
6243
6337
  * Stripes
@@ -6252,7 +6346,7 @@
6252
6346
 
6253
6347
  /* Remove row stripe classes if they are already on the table row */
6254
6348
  var stripeClasses = oSettings.asStripeClasses;
6255
- var rowOne = $('tbody tr:eq(0)', this);
6349
+ var rowOne = $this.children('tbody').find('tr').eq(0);
6256
6350
  if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6257
6351
  return rowOne.hasClass(el);
6258
6352
  } ) ) !== -1 ) {
@@ -6303,7 +6397,7 @@
6303
6397
  */
6304
6398
  if ( rowOne.length ) {
6305
6399
  var a = function ( cell, name ) {
6306
- return cell.getAttribute( 'data-'+name ) ? name : null;
6400
+ return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6307
6401
  };
6308
6402
 
6309
6403
  $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
@@ -6392,25 +6486,25 @@
6392
6486
  _fnBrowserDetect( oSettings );
6393
6487
 
6394
6488
  // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6395
- var captions = $(this).children('caption').each( function () {
6396
- this._captionSide = $(this).css('caption-side');
6489
+ var captions = $this.children('caption').each( function () {
6490
+ this._captionSide = $this.css('caption-side');
6397
6491
  } );
6398
6492
 
6399
- var thead = $(this).children('thead');
6493
+ var thead = $this.children('thead');
6400
6494
  if ( thead.length === 0 )
6401
6495
  {
6402
6496
  thead = $('<thead/>').appendTo(this);
6403
6497
  }
6404
6498
  oSettings.nTHead = thead[0];
6405
6499
 
6406
- var tbody = $(this).children('tbody');
6500
+ var tbody = $this.children('tbody');
6407
6501
  if ( tbody.length === 0 )
6408
6502
  {
6409
6503
  tbody = $('<tbody/>').appendTo(this);
6410
6504
  }
6411
6505
  oSettings.nTBody = tbody[0];
6412
6506
 
6413
- var tfoot = $(this).children('tfoot');
6507
+ var tfoot = $this.children('tfoot');
6414
6508
  if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6415
6509
  {
6416
6510
  // If we are a scrolling table, and no footer has been given, then we need to create
@@ -6419,7 +6513,7 @@
6419
6513
  }
6420
6514
 
6421
6515
  if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6422
- $(this).addClass( oClasses.sNoFooter );
6516
+ $this.addClass( oClasses.sNoFooter );
6423
6517
  }
6424
6518
  else if ( tfoot.length > 0 ) {
6425
6519
  oSettings.nTFoot = tfoot[0];
@@ -6750,8 +6844,8 @@
6750
6844
  return -1;
6751
6845
  },
6752
6846
 
6753
- // Internal only at the moment - relax?
6754
- iterator: function ( flatten, type, fn ) {
6847
+ // Note that `alwaysNew` is internal - use iteratorNew externally
6848
+ iterator: function ( flatten, type, fn, alwaysNew ) {
6755
6849
  var
6756
6850
  a = [], ret,
6757
6851
  i, ien, j, jen,
@@ -6761,6 +6855,7 @@
6761
6855
 
6762
6856
  // Argument shifting
6763
6857
  if ( typeof flatten === 'string' ) {
6858
+ alwaysNew = fn;
6764
6859
  fn = type;
6765
6860
  type = flatten;
6766
6861
  flatten = false;
@@ -6810,7 +6905,7 @@
6810
6905
  }
6811
6906
  }
6812
6907
 
6813
- if ( a.length ) {
6908
+ if ( a.length || alwaysNew ) {
6814
6909
  var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6815
6910
  var apiSelector = api.selector;
6816
6911
  apiSelector.rows = selector.rows;
@@ -6923,7 +7018,7 @@
6923
7018
  _Api.extend = function ( scope, obj, ext )
6924
7019
  {
6925
7020
  // Only extend API instances and static properties of the API
6926
- if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7021
+ if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6927
7022
  return;
6928
7023
  }
6929
7024
 
@@ -7137,35 +7232,35 @@
7137
7232
  _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7138
7233
  return this.iterator( 'table', function ( ctx ) {
7139
7234
  return ctx.nTable;
7140
- } );
7235
+ }, 1 );
7141
7236
  } );
7142
7237
 
7143
7238
 
7144
7239
  _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7145
7240
  return this.iterator( 'table', function ( ctx ) {
7146
7241
  return ctx.nTBody;
7147
- } );
7242
+ }, 1 );
7148
7243
  } );
7149
7244
 
7150
7245
 
7151
7246
  _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7152
7247
  return this.iterator( 'table', function ( ctx ) {
7153
7248
  return ctx.nTHead;
7154
- } );
7249
+ }, 1 );
7155
7250
  } );
7156
7251
 
7157
7252
 
7158
7253
  _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7159
7254
  return this.iterator( 'table', function ( ctx ) {
7160
7255
  return ctx.nTFoot;
7161
- } );
7256
+ }, 1 );
7162
7257
  } );
7163
7258
 
7164
7259
 
7165
7260
  _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7166
7261
  return this.iterator( 'table', function ( ctx ) {
7167
7262
  return ctx.nTableWrapper;
7168
- } );
7263
+ }, 1 );
7169
7264
  } );
7170
7265
 
7171
7266
 
@@ -7289,6 +7384,15 @@
7289
7384
 
7290
7385
 
7291
7386
  var __reload = function ( settings, holdPosition, callback ) {
7387
+ // Use the draw event to trigger a callback
7388
+ if ( callback ) {
7389
+ var api = new _Api( settings );
7390
+
7391
+ api.one( 'draw', function () {
7392
+ callback( api.ajax.json() );
7393
+ } );
7394
+ }
7395
+
7292
7396
  if ( _fnDataSource( settings ) == 'ssp' ) {
7293
7397
  _fnReDraw( settings, holdPosition );
7294
7398
  }
@@ -7308,16 +7412,6 @@
7308
7412
  _fnProcessingDisplay( settings, false );
7309
7413
  } );
7310
7414
  }
7311
-
7312
- // Use the draw event to trigger a callback, regardless of if it is an async
7313
- // or sync draw
7314
- if ( callback ) {
7315
- var api = new _Api( settings );
7316
-
7317
- api.one( 'draw', function () {
7318
- callback( api.ajax.json() );
7319
- } );
7320
- }
7321
7415
  };
7322
7416
 
7323
7417
 
@@ -7600,9 +7694,6 @@
7600
7694
  return rows;
7601
7695
  }
7602
7696
 
7603
- // Get nodes in the order from the `rows` array
7604
- var nodes = _pluck_order( settings.aoData, rows, 'nTr' );
7605
-
7606
7697
  // Selector - function
7607
7698
  if ( typeof sel === 'function' ) {
7608
7699
  return $.map( rows, function (idx) {
@@ -7611,11 +7702,16 @@
7611
7702
  } );
7612
7703
  }
7613
7704
 
7705
+ // Get nodes in the order from the `rows` array with null values removed
7706
+ var nodes = _removeEmpty(
7707
+ _pluck_order( settings.aoData, rows, 'nTr' )
7708
+ );
7709
+
7614
7710
  // Selector - node
7615
7711
  if ( sel.nodeName ) {
7616
7712
  if ( $.inArray( sel, nodes ) !== -1 ) {
7617
- return [ sel._DT_RowIndex ];// sel is a TR node that is in the table
7618
- // and DataTables adds a prop for fast lookup
7713
+ return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
7714
+ // and DataTables adds a prop for fast lookup
7619
7715
  }
7620
7716
  }
7621
7717
 
@@ -7632,9 +7728,6 @@
7632
7728
  };
7633
7729
 
7634
7730
 
7635
- /**
7636
- *
7637
- */
7638
7731
  _api_register( 'rows()', function ( selector, opts ) {
7639
7732
  // argument shifting
7640
7733
  if ( selector === undefined ) {
@@ -7649,7 +7742,7 @@
7649
7742
 
7650
7743
  var inst = this.iterator( 'table', function ( settings ) {
7651
7744
  return __row_selector( settings, selector, opts );
7652
- } );
7745
+ }, 1 );
7653
7746
 
7654
7747
  // Want argument shifting here and in __row_selector?
7655
7748
  inst.selector.rows = selector;
@@ -7658,36 +7751,35 @@
7658
7751
  return inst;
7659
7752
  } );
7660
7753
 
7661
-
7662
7754
  _api_register( 'rows().nodes()', function () {
7663
7755
  return this.iterator( 'row', function ( settings, row ) {
7664
7756
  return settings.aoData[ row ].nTr || undefined;
7665
- } );
7757
+ }, 1 );
7666
7758
  } );
7667
7759
 
7668
7760
  _api_register( 'rows().data()', function () {
7669
7761
  return this.iterator( true, 'rows', function ( settings, rows ) {
7670
7762
  return _pluck_order( settings.aoData, rows, '_aData' );
7671
- } );
7763
+ }, 1 );
7672
7764
  } );
7673
7765
 
7674
7766
  _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7675
7767
  return this.iterator( 'row', function ( settings, row ) {
7676
7768
  var r = settings.aoData[ row ];
7677
7769
  return type === 'search' ? r._aFilterData : r._aSortData;
7678
- } );
7770
+ }, 1 );
7679
7771
  } );
7680
7772
 
7681
7773
  _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7682
7774
  return this.iterator( 'row', function ( settings, row ) {
7683
- _fnInvalidateRow( settings, row, src );
7775
+ _fnInvalidate( settings, row, src );
7684
7776
  } );
7685
7777
  } );
7686
7778
 
7687
7779
  _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7688
7780
  return this.iterator( 'row', function ( settings, row ) {
7689
7781
  return row;
7690
- } );
7782
+ }, 1 );
7691
7783
  } );
7692
7784
 
7693
7785
  _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
@@ -7736,7 +7828,7 @@
7736
7828
  }
7737
7829
 
7738
7830
  return out;
7739
- } );
7831
+ }, 1 );
7740
7832
 
7741
7833
  // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7742
7834
  var modRows = this.rows( -1 );
@@ -7772,7 +7864,7 @@
7772
7864
  ctx[0].aoData[ this[0] ]._aData = data;
7773
7865
 
7774
7866
  // Automatically invalidate
7775
- _fnInvalidateRow( ctx[0], this[0], 'data' );
7867
+ _fnInvalidate( ctx[0], this[0], 'data' );
7776
7868
 
7777
7869
  return this;
7778
7870
  } );
@@ -7812,6 +7904,14 @@
7812
7904
  // Convert to array of TR elements
7813
7905
  var rows = [];
7814
7906
  var addRow = function ( r, k ) {
7907
+ // Recursion to allow for arrays of jQuery objects
7908
+ if ( $.isArray( r ) || r instanceof $ ) {
7909
+ for ( var i=0, ien=r.length ; i<ien ; i++ ) {
7910
+ addRow( r[i], k );
7911
+ }
7912
+ return;
7913
+ }
7914
+
7815
7915
  // If we get a TR element, then just add it directly - up to the dev
7816
7916
  // to add the correct number of columns etc
7817
7917
  if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
@@ -7829,14 +7929,7 @@
7829
7929
  }
7830
7930
  };
7831
7931
 
7832
- if ( $.isArray( data ) || data instanceof $ ) {
7833
- for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7834
- addRow( data[i], klass );
7835
- }
7836
- }
7837
- else {
7838
- addRow( data, klass );
7839
- }
7932
+ addRow( data, klass );
7840
7933
 
7841
7934
  if ( row._details ) {
7842
7935
  row._details.remove();
@@ -8190,9 +8283,6 @@
8190
8283
  };
8191
8284
 
8192
8285
 
8193
- /**
8194
- *
8195
- */
8196
8286
  _api_register( 'columns()', function ( selector, opts ) {
8197
8287
  // argument shifting
8198
8288
  if ( selector === undefined ) {
@@ -8207,7 +8297,7 @@
8207
8297
 
8208
8298
  var inst = this.iterator( 'table', function ( settings ) {
8209
8299
  return __column_selector( settings, selector, opts );
8210
- } );
8300
+ }, 1 );
8211
8301
 
8212
8302
  // Want argument shifting here and in _row_selector?
8213
8303
  inst.selector.cols = selector;
@@ -8216,99 +8306,65 @@
8216
8306
  return inst;
8217
8307
  } );
8218
8308
 
8219
-
8220
- /**
8221
- *
8222
- */
8223
8309
  _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8224
8310
  return this.iterator( 'column', function ( settings, column ) {
8225
8311
  return settings.aoColumns[column].nTh;
8226
- } );
8312
+ }, 1 );
8227
8313
  } );
8228
8314
 
8229
-
8230
- /**
8231
- *
8232
- */
8233
8315
  _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8234
8316
  return this.iterator( 'column', function ( settings, column ) {
8235
8317
  return settings.aoColumns[column].nTf;
8236
- } );
8318
+ }, 1 );
8237
8319
  } );
8238
8320
 
8239
-
8240
- /**
8241
- *
8242
- */
8243
8321
  _api_registerPlural( 'columns().data()', 'column().data()', function () {
8244
- return this.iterator( 'column-rows', __columnData );
8322
+ return this.iterator( 'column-rows', __columnData, 1 );
8245
8323
  } );
8246
8324
 
8247
-
8248
8325
  _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8249
8326
  return this.iterator( 'column', function ( settings, column ) {
8250
8327
  return settings.aoColumns[column].mData;
8251
- } );
8328
+ }, 1 );
8252
8329
  } );
8253
8330
 
8254
-
8255
8331
  _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8256
8332
  return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8257
8333
  return _pluck_order( settings.aoData, rows,
8258
8334
  type === 'search' ? '_aFilterData' : '_aSortData', column
8259
8335
  );
8260
- } );
8336
+ }, 1 );
8261
8337
  } );
8262
8338
 
8263
-
8264
8339
  _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8265
8340
  return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8266
8341
  return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8267
- } );
8342
+ }, 1 );
8268
8343
  } );
8269
8344
 
8270
-
8271
-
8272
8345
  _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8273
8346
  return this.iterator( 'column', function ( settings, column ) {
8274
- return vis === undefined ?
8275
- settings.aoColumns[ column ].bVisible :
8276
- __setColumnVis( settings, column, vis, calc );
8347
+ if ( vis === undefined ) {
8348
+ return settings.aoColumns[ column ].bVisible;
8349
+ } // else
8350
+ __setColumnVis( settings, column, vis, calc );
8277
8351
  } );
8278
8352
  } );
8279
8353
 
8280
-
8281
-
8282
8354
  _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8283
8355
  return this.iterator( 'column', function ( settings, column ) {
8284
8356
  return type === 'visible' ?
8285
8357
  _fnColumnIndexToVisible( settings, column ) :
8286
8358
  column;
8287
- } );
8359
+ }, 1 );
8288
8360
  } );
8289
8361
 
8290
-
8291
- // _api_register( 'columns().show()', function () {
8292
- // var selector = this.selector;
8293
- // return this.columns( selector.cols, selector.opts ).visible( true );
8294
- // } );
8295
-
8296
-
8297
- // _api_register( 'columns().hide()', function () {
8298
- // var selector = this.selector;
8299
- // return this.columns( selector.cols, selector.opts ).visible( false );
8300
- // } );
8301
-
8302
-
8303
-
8304
8362
  _api_register( 'columns.adjust()', function () {
8305
8363
  return this.iterator( 'table', function ( settings ) {
8306
8364
  _fnAdjustColumnSizing( settings );
8307
- } );
8365
+ }, 1 );
8308
8366
  } );
8309
8367
 
8310
-
8311
- // Convert from one column index type, to another type
8312
8368
  _api_register( 'column.index()', function ( type, idx ) {
8313
8369
  if ( this.context.length !== 0 ) {
8314
8370
  var ctx = this.context[0];
@@ -8322,7 +8378,6 @@
8322
8378
  }
8323
8379
  } );
8324
8380
 
8325
-
8326
8381
  _api_register( 'column()', function ( selector, opts ) {
8327
8382
  return _selector_first( this.columns( selector, opts ) );
8328
8383
  } );
@@ -8334,7 +8389,7 @@
8334
8389
  {
8335
8390
  var data = settings.aoData;
8336
8391
  var rows = _selector_row_indexes( settings, opts );
8337
- var cells = _pluck_order( data, rows, 'anCells' );
8392
+ var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8338
8393
  var allCells = $( [].concat.apply([], cells) );
8339
8394
  var row;
8340
8395
  var columns = settings.aoColumns.length;
@@ -8401,14 +8456,16 @@
8401
8456
  // Argument shifting
8402
8457
  if ( $.isPlainObject( rowSelector ) ) {
8403
8458
  // Indexes
8404
- if ( typeof rowSelector.row !== undefined ) {
8405
- opts = columnSelector;
8406
- columnSelector = null;
8407
- }
8408
- else {
8459
+ if ( rowSelector.row === undefined ) {
8460
+ // Selector options in first parameter
8409
8461
  opts = rowSelector;
8410
8462
  rowSelector = null;
8411
8463
  }
8464
+ else {
8465
+ // Cell index objects in first parameter
8466
+ opts = columnSelector;
8467
+ columnSelector = null;
8468
+ }
8412
8469
  }
8413
8470
  if ( $.isPlainObject( columnSelector ) ) {
8414
8471
  opts = columnSelector;
@@ -8440,7 +8497,7 @@
8440
8497
  }
8441
8498
 
8442
8499
  return a;
8443
- } );
8500
+ }, 1 );
8444
8501
 
8445
8502
  $.extend( cells.selector, {
8446
8503
  cols: columnSelector,
@@ -8454,15 +8511,18 @@
8454
8511
 
8455
8512
  _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8456
8513
  return this.iterator( 'cell', function ( settings, row, column ) {
8457
- return settings.aoData[ row ].anCells[ column ];
8458
- } );
8514
+ var cells = settings.aoData[ row ].anCells;
8515
+ return cells ?
8516
+ cells[ column ] :
8517
+ undefined;
8518
+ }, 1 );
8459
8519
  } );
8460
8520
 
8461
8521
 
8462
8522
  _api_register( 'cells().data()', function () {
8463
8523
  return this.iterator( 'cell', function ( settings, row, column ) {
8464
8524
  return _fnGetCellData( settings, row, column );
8465
- } );
8525
+ }, 1 );
8466
8526
  } );
8467
8527
 
8468
8528
 
@@ -8471,14 +8531,14 @@
8471
8531
 
8472
8532
  return this.iterator( 'cell', function ( settings, row, column ) {
8473
8533
  return settings.aoData[ row ][ type ][ column ];
8474
- } );
8534
+ }, 1 );
8475
8535
  } );
8476
8536
 
8477
8537
 
8478
8538
  _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8479
8539
  return this.iterator( 'cell', function ( settings, row, column ) {
8480
8540
  return _fnGetCellData( settings, row, column, type );
8481
- } );
8541
+ }, 1 );
8482
8542
  } );
8483
8543
 
8484
8544
 
@@ -8489,33 +8549,23 @@
8489
8549
  column: column,
8490
8550
  columnVisible: _fnColumnIndexToVisible( settings, column )
8491
8551
  };
8492
- } );
8552
+ }, 1 );
8493
8553
  } );
8494
8554
 
8495
8555
 
8496
- _api_register( [
8497
- 'cells().invalidate()',
8498
- 'cell().invalidate()'
8499
- ], function ( src ) {
8500
- var selector = this.selector;
8501
-
8502
- // Use the rows method of the instance to perform the invalidation, rather
8503
- // than doing it here. This avoids needing to handle duplicate rows from
8504
- // the cells.
8505
- this.rows( selector.rows, selector.opts ).invalidate( src );
8506
-
8507
- return this;
8556
+ _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8557
+ return this.iterator( 'cell', function ( settings, row, column ) {
8558
+ _fnInvalidate( settings, row, src, column );
8559
+ } );
8508
8560
  } );
8509
8561
 
8510
8562
 
8511
8563
 
8512
-
8513
8564
  _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8514
8565
  return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8515
8566
  } );
8516
8567
 
8517
8568
 
8518
-
8519
8569
  _api_register( 'cell().data()', function ( data ) {
8520
8570
  var ctx = this.context;
8521
8571
  var cell = this[0];
@@ -8529,7 +8579,7 @@
8529
8579
 
8530
8580
  // Set
8531
8581
  _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8532
- _fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );
8582
+ _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8533
8583
 
8534
8584
  return this;
8535
8585
  } );
@@ -8776,7 +8826,10 @@
8776
8826
  var is = false;
8777
8827
 
8778
8828
  $.each( DataTable.settings, function (i, o) {
8779
- if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8829
+ var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
8830
+ var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
8831
+
8832
+ if ( o.nTable === t || head === t || foot === t ) {
8780
8833
  is = true;
8781
8834
  }
8782
8835
  } );
@@ -8803,7 +8856,7 @@
8803
8856
  */
8804
8857
  DataTable.tables = DataTable.fnTables = function ( visible )
8805
8858
  {
8806
- return jQuery.map( DataTable.settings, function (o) {
8859
+ return $.map( DataTable.settings, function (o) {
8807
8860
  if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8808
8861
  return o.nTable;
8809
8862
  }
@@ -8830,7 +8883,16 @@
8830
8883
  * @param {integer} freq Call frequency in mS
8831
8884
  * @return {function} Wrapped function
8832
8885
  */
8833
- throttle: _fnThrottle
8886
+ throttle: _fnThrottle,
8887
+
8888
+
8889
+ /**
8890
+ * Escape a string such that it can be used in a regular expression
8891
+ *
8892
+ * @param {string} sVal string to escape
8893
+ * @returns {string} escaped string
8894
+ */
8895
+ escapeRegex: _fnEscapeRegex
8834
8896
  };
8835
8897
 
8836
8898
 
@@ -8895,6 +8957,12 @@
8895
8957
  } );
8896
8958
 
8897
8959
 
8960
+ _api_register( 'init()', function () {
8961
+ var ctx = this.context;
8962
+ return ctx.length ? ctx[0].oInit : null;
8963
+ } );
8964
+
8965
+
8898
8966
  _api_register( 'data()', function () {
8899
8967
  return this.iterator( 'table', function ( settings ) {
8900
8968
  return _pluck( settings.aoData, '_aData' );
@@ -9004,6 +9072,17 @@
9004
9072
  } );
9005
9073
  } );
9006
9074
 
9075
+
9076
+ // Add the `every()` method for rows, columns and cells in a compact form
9077
+ $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9078
+ _api_register( type+'s().every()', function ( fn ) {
9079
+ return this.iterator( type, function ( settings, idx, idx2 ) {
9080
+ // idx2 is undefined for rows and columns.
9081
+ fn.call( new _Api( settings )[ type ]( idx, idx2 ) );
9082
+ } );
9083
+ } );
9084
+ } );
9085
+
9007
9086
 
9008
9087
  /**
9009
9088
  * Version string for plug-ins to check compatibility. Allowed format is
@@ -9013,7 +9092,7 @@
9013
9092
  * @type string
9014
9093
  * @default Version number
9015
9094
  */
9016
- DataTable.version = "1.10.3";
9095
+ DataTable.version = "1.10.6";
9017
9096
 
9018
9097
  /**
9019
9098
  * Private data store, containing all of the settings objects that are
@@ -13387,6 +13466,17 @@
13387
13466
  * @namespace
13388
13467
  */
13389
13468
  DataTable.ext = _ext = {
13469
+ /**
13470
+ * Buttons. For use with the Buttons extension for DataTables. This is
13471
+ * defined here so other extensions can define buttons regardless of load
13472
+ * order. It is _not_ used by DataTables core.
13473
+ *
13474
+ * @type object
13475
+ * @default {}
13476
+ */
13477
+ buttons: {},
13478
+
13479
+
13390
13480
  /**
13391
13481
  * Element class names
13392
13482
  *
@@ -13399,10 +13489,10 @@
13399
13489
  /**
13400
13490
  * Error reporting.
13401
13491
  *
13402
- * How should DataTables report an error. Can take the value 'alert' or
13403
- * 'throw'
13492
+ * How should DataTables report an error. Can take the value 'alert',
13493
+ * 'throw', 'none' or a function.
13404
13494
  *
13405
- * @type string
13495
+ * @type string|function
13406
13496
  * @default alert
13407
13497
  */
13408
13498
  errMode: "alert",
@@ -14002,7 +14092,7 @@
14002
14092
  numbers.splice( 0, 0, 0 );
14003
14093
  }
14004
14094
  else {
14005
- numbers = _range( page-1, page+2 );
14095
+ numbers = _range( page-half+2, page+half-1 );
14006
14096
  numbers.push( 'ellipsis' );
14007
14097
  numbers.push( pages-1 );
14008
14098
  numbers.splice( 0, 0, 'ellipsis' );
@@ -14033,6 +14123,8 @@
14033
14123
 
14034
14124
  // For testing and plug-ins to use
14035
14125
  _numbers: _numbers,
14126
+
14127
+ // Number of number buttons (including ellipsis) to show. _Must be odd!_
14036
14128
  numbers_length: 7
14037
14129
  } );
14038
14130
 
@@ -14064,7 +14156,7 @@
14064
14156
 
14065
14157
  switch ( button ) {
14066
14158
  case 'ellipsis':
14067
- container.append('<span>&hellip;</span>');
14159
+ container.append('<span class="ellipsis">&#x2026;</span>');
14068
14160
  break;
14069
14161
 
14070
14162
  case 'first':
@@ -14124,26 +14216,113 @@
14124
14216
  // IE9 throws an 'unknown error' if document.activeElement is used
14125
14217
  // inside an iframe or frame. Try / catch the error. Not good for
14126
14218
  // accessibility, but neither are frames.
14219
+ var activeEl;
14220
+
14127
14221
  try {
14128
14222
  // Because this approach is destroying and recreating the paging
14129
14223
  // elements, focus is lost on the select button which is bad for
14130
14224
  // accessibility. So we want to restore focus once the draw has
14131
14225
  // completed
14132
- var activeEl = $(document.activeElement).data('dt-idx');
14226
+ activeEl = $(document.activeElement).data('dt-idx');
14227
+ }
14228
+ catch (e) {}
14133
14229
 
14134
- attach( $(host).empty(), buttons );
14230
+ attach( $(host).empty(), buttons );
14135
14231
 
14136
- if ( activeEl !== null ) {
14137
- $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14138
- }
14232
+ if ( activeEl ) {
14233
+ $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14139
14234
  }
14140
- catch (e) {}
14141
14235
  }
14142
14236
  }
14143
14237
  } );
14144
14238
 
14145
14239
 
14146
14240
 
14241
+ // Built in type detection. See model.ext.aTypes for information about
14242
+ // what is required from this methods.
14243
+ $.extend( DataTable.ext.type.detect, [
14244
+ // Plain numbers - first since V8 detects some plain numbers as dates
14245
+ // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14246
+ function ( d, settings )
14247
+ {
14248
+ var decimal = settings.oLanguage.sDecimal;
14249
+ return _isNumber( d, decimal ) ? 'num'+decimal : null;
14250
+ },
14251
+
14252
+ // Dates (only those recognised by the browser's Date.parse)
14253
+ function ( d, settings )
14254
+ {
14255
+ // V8 will remove any unknown characters at the start and end of the
14256
+ // expression, leading to false matches such as `$245.12` or `10%` being
14257
+ // a valid date. See forum thread 18941 for detail.
14258
+ if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14259
+ return null;
14260
+ }
14261
+ var parsed = Date.parse(d);
14262
+ return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14263
+ },
14264
+
14265
+ // Formatted numbers
14266
+ function ( d, settings )
14267
+ {
14268
+ var decimal = settings.oLanguage.sDecimal;
14269
+ return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14270
+ },
14271
+
14272
+ // HTML numeric
14273
+ function ( d, settings )
14274
+ {
14275
+ var decimal = settings.oLanguage.sDecimal;
14276
+ return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14277
+ },
14278
+
14279
+ // HTML numeric, formatted
14280
+ function ( d, settings )
14281
+ {
14282
+ var decimal = settings.oLanguage.sDecimal;
14283
+ return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14284
+ },
14285
+
14286
+ // HTML (this is strict checking - there must be html)
14287
+ function ( d, settings )
14288
+ {
14289
+ return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14290
+ 'html' : null;
14291
+ }
14292
+ ] );
14293
+
14294
+
14295
+
14296
+ // Filter formatting functions. See model.ext.ofnSearch for information about
14297
+ // what is required from these methods.
14298
+ //
14299
+ // Note that additional search methods are added for the html numbers and
14300
+ // html formatted numbers by `_addNumericSort()` when we know what the decimal
14301
+ // place is
14302
+
14303
+
14304
+ $.extend( DataTable.ext.type.search, {
14305
+ html: function ( data ) {
14306
+ return _empty(data) ?
14307
+ data :
14308
+ typeof data === 'string' ?
14309
+ data
14310
+ .replace( _re_new_lines, " " )
14311
+ .replace( _re_html, "" ) :
14312
+ '';
14313
+ },
14314
+
14315
+ string: function ( data ) {
14316
+ return _empty(data) ?
14317
+ data :
14318
+ typeof data === 'string' ?
14319
+ data.replace( _re_new_lines, " " ) :
14320
+ data;
14321
+ }
14322
+ } );
14323
+
14324
+
14325
+
14147
14326
  var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14148
14327
  if ( d !== 0 && (!d || d === '-') ) {
14149
14328
  return -Infinity;
@@ -14170,8 +14349,8 @@
14170
14349
  };
14171
14350
 
14172
14351
 
14173
- // Add the numeric 'deformatting' functions for sorting. This is done in a
14174
- // function to provide an easy ability for the language options to add
14352
+ // Add the numeric 'deformatting' functions for sorting and search. This is done
14353
+ // in a function to provide an easy ability for the language options to add
14175
14354
  // additional methods if a non-period decimal place is used.
14176
14355
  function _addNumericSort ( decimalPlace ) {
14177
14356
  $.each(
@@ -14197,7 +14376,13 @@
14197
14376
  }
14198
14377
  },
14199
14378
  function ( key, fn ) {
14379
+ // Add the ordering method
14200
14380
  _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14381
+
14382
+ // For HTML types add a search formatter that will strip the HTML
14383
+ if ( key.match(/^html\-/) ) {
14384
+ _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14385
+ }
14201
14386
  }
14202
14387
  );
14203
14388
  }
@@ -14248,87 +14433,6 @@
14248
14433
  _addNumericSort( '' );
14249
14434
 
14250
14435
 
14251
- // Built in type detection. See model.ext.aTypes for information about
14252
- // what is required from this methods.
14253
- $.extend( DataTable.ext.type.detect, [
14254
- // Plain numbers - first since V8 detects some plain numbers as dates
14255
- // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14256
- function ( d, settings )
14257
- {
14258
- var decimal = settings.oLanguage.sDecimal;
14259
- return _isNumber( d, decimal ) ? 'num'+decimal : null;
14260
- },
14261
-
14262
- // Dates (only those recognised by the browser's Date.parse)
14263
- function ( d, settings )
14264
- {
14265
- // V8 will remove any unknown characters at the start and end of the
14266
- // expression, leading to false matches such as `$245.12` or `10%` being
14267
- // a valid date. See forum thread 18941 for detail.
14268
- if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14269
- return null;
14270
- }
14271
- var parsed = Date.parse(d);
14272
- return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14273
- },
14274
-
14275
- // Formatted numbers
14276
- function ( d, settings )
14277
- {
14278
- var decimal = settings.oLanguage.sDecimal;
14279
- return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14280
- },
14281
-
14282
- // HTML numeric
14283
- function ( d, settings )
14284
- {
14285
- var decimal = settings.oLanguage.sDecimal;
14286
- return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14287
- },
14288
-
14289
- // HTML numeric, formatted
14290
- function ( d, settings )
14291
- {
14292
- var decimal = settings.oLanguage.sDecimal;
14293
- return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14294
- },
14295
-
14296
- // HTML (this is strict checking - there must be html)
14297
- function ( d, settings )
14298
- {
14299
- return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14300
- 'html' : null;
14301
- }
14302
- ] );
14303
-
14304
-
14305
-
14306
- // Filter formatting functions. See model.ext.ofnSearch for information about
14307
- // what is required from these methods.
14308
-
14309
-
14310
- $.extend( DataTable.ext.type.search, {
14311
- html: function ( data ) {
14312
- return _empty(data) ?
14313
- data :
14314
- typeof data === 'string' ?
14315
- data
14316
- .replace( _re_new_lines, " " )
14317
- .replace( _re_html, "" ) :
14318
- '';
14319
- },
14320
-
14321
- string: function ( data ) {
14322
- return _empty(data) ?
14323
- data :
14324
- typeof data === 'string' ?
14325
- data.replace( _re_new_lines, " " ) :
14326
- data;
14327
- }
14328
- } );
14329
-
14330
-
14331
-
14332
14436
  $.extend( true, DataTable.ext.renderer, {
14333
14437
  header: {
14334
14438
  _: function ( settings, cell, column, classes ) {
@@ -14436,6 +14540,10 @@
14436
14540
  number: function ( thousands, decimal, precision, prefix ) {
14437
14541
  return {
14438
14542
  display: function ( d ) {
14543
+ if ( typeof d !== 'number' && typeof d !== 'string' ) {
14544
+ return d;
14545
+ }
14546
+
14439
14547
  var negative = d < 0 ? '-' : '';
14440
14548
  d = Math.abs( parseFloat( d ) );
14441
14549
 
@@ -14517,7 +14625,7 @@
14517
14625
  _fnGetDataMaster: _fnGetDataMaster,
14518
14626
  _fnClearTable: _fnClearTable,
14519
14627
  _fnDeleteIndex: _fnDeleteIndex,
14520
- _fnInvalidateRow: _fnInvalidateRow,
14628
+ _fnInvalidate: _fnInvalidate,
14521
14629
  _fnGetRowElements: _fnGetRowElements,
14522
14630
  _fnCreateTr: _fnCreateTr,
14523
14631
  _fnBuildHead: _fnBuildHead,