jquery-datatables-rails 3.2.0 → 3.3.0

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.
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,