weaver 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/data/weaver/css/bootstrap.css +647 -205
  3. data/data/weaver/css/bootstrap.css.map +1 -0
  4. data/data/weaver/css/bootstrap.min.css +3 -3
  5. data/data/weaver/css/crossfade_style.css +19 -0
  6. data/data/weaver/css/patterns/1.png +0 -0
  7. data/data/weaver/css/patterns/2.png +0 -0
  8. data/data/weaver/css/patterns/3.png +0 -0
  9. data/data/weaver/css/patterns/4.png +0 -0
  10. data/data/weaver/css/patterns/5.png +0 -0
  11. data/data/weaver/css/patterns/6.png +0 -0
  12. data/data/weaver/css/patterns/7.png +0 -0
  13. data/data/weaver/css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css +251 -0
  14. data/data/weaver/css/plugins/chartist/chartist.min.css +773 -0
  15. data/data/weaver/css/plugins/clockpicker/clockpicker.css +168 -0
  16. data/data/weaver/css/plugins/dataTables/dataTables.bootstrap.css +118 -190
  17. data/data/weaver/css/plugins/dataTables/dataTables.tableTools.min.css +1 -1
  18. data/data/weaver/css/plugins/daterangepicker/daterangepicker-bs3.css +335 -0
  19. data/data/weaver/css/plugins/footable/fonts/footable.eot +0 -0
  20. data/data/weaver/css/plugins/footable/fonts/footable.svg +78 -0
  21. data/data/weaver/css/plugins/footable/fonts/footable.ttf +0 -0
  22. data/data/weaver/css/plugins/footable/fonts/footable.woff +0 -0
  23. data/data/weaver/css/plugins/footable/footable.core.css +178 -0
  24. data/data/weaver/css/plugins/select2/select2.min.css +1 -0
  25. data/data/weaver/css/plugins/slick/ajax-loader.gif +0 -0
  26. data/data/weaver/css/plugins/slick/fonts/slick.eot +0 -0
  27. data/data/weaver/css/plugins/slick/fonts/slick.svg +14 -0
  28. data/data/weaver/css/plugins/slick/fonts/slick.ttf +0 -0
  29. data/data/weaver/css/plugins/slick/fonts/slick.woff +0 -0
  30. data/data/weaver/css/plugins/slick/slick-theme.css +201 -0
  31. data/data/weaver/css/plugins/slick/slick.css +119 -0
  32. data/data/weaver/css/plugins/sweetalert/sweetalert.css +715 -0
  33. data/data/weaver/css/style.css +4352 -1310
  34. data/data/weaver/css/style.min.css +1 -1
  35. data/data/weaver/fonts/glyphicons-halflings-regular.eot +0 -0
  36. data/data/weaver/fonts/glyphicons-halflings-regular.svg +273 -214
  37. data/data/weaver/fonts/glyphicons-halflings-regular.ttf +0 -0
  38. data/data/weaver/fonts/glyphicons-halflings-regular.woff +0 -0
  39. data/data/weaver/fonts/glyphicons-halflings-regular.woff2 +0 -0
  40. data/data/weaver/js/bootstrap.js +299 -212
  41. data/data/weaver/js/bootstrap.min.js +5 -5
  42. data/data/weaver/js/inspinia.js +184 -42
  43. data/data/weaver/js/plugins/chartist/chartist.min.js +9 -0
  44. data/data/weaver/js/plugins/chartist/chartist.min.js.map +1 -0
  45. data/data/weaver/js/plugins/clockpicker/clockpicker.js +729 -0
  46. data/data/weaver/js/plugins/dataTables/dataTables.bootstrap.js +195 -234
  47. data/data/weaver/js/plugins/dataTables/dataTables.tableTools.min.js +46 -45
  48. data/data/weaver/js/plugins/dataTables/jquery.dataTables.js +628 -373
  49. data/data/weaver/js/plugins/dataTables/swf/copy_csv_xls.swf +0 -0
  50. data/data/weaver/js/plugins/dataTables/swf/copy_csv_xls_pdf.swf +0 -0
  51. data/data/weaver/js/plugins/daterangepicker/daterangepicker.js +1304 -0
  52. data/data/weaver/js/plugins/diff_match_patch/COPYING +177 -0
  53. data/data/weaver/js/plugins/diff_match_patch/README.txt +43 -0
  54. data/data/weaver/js/plugins/diff_match_patch/javascript/diff_match_patch.js +49 -0
  55. data/data/weaver/js/plugins/footable/footable.all.min.js +14 -0
  56. data/data/weaver/js/plugins/fullcalendar/moment.min.js +3 -3
  57. data/data/weaver/js/plugins/idle-timer/idle-timer.min.js +2 -0
  58. data/data/weaver/js/plugins/jvectormap/jquery-jvectormap-2.0.2.css +130 -0
  59. data/data/weaver/js/plugins/jvectormap/jquery-jvectormap-2.0.2.min.js +3328 -0
  60. data/data/weaver/js/plugins/masonary/masonry.pkgd.min.js +9 -0
  61. data/data/weaver/js/plugins/metisMenu/jquery.metisMenu.js +3 -113
  62. data/data/weaver/js/plugins/morris/morris.js +27 -23
  63. data/data/weaver/js/plugins/pace/pace.min.js +2 -2
  64. data/data/weaver/js/plugins/preetyTextDiff/jquery.pretty-text-diff.min.js +76 -0
  65. data/data/weaver/js/plugins/select2/select2.full.min.js +3 -0
  66. data/data/weaver/js/plugins/slick/slick.min.js +18 -0
  67. data/data/weaver/js/plugins/slimscroll/jquery.slimscroll.js +96 -90
  68. data/data/weaver/js/plugins/slimscroll/jquery.slimscroll.min.js +10 -10
  69. data/data/weaver/js/plugins/sweetalert/sweetalert.min.js +1 -0
  70. data/data/weaver/js/plugins/tinycon/tinycon.min.js +8 -0
  71. data/data/weaver/js/plugins/wow/wow.min.js +2 -0
  72. data/{bin → exe}/weaver +3 -2
  73. data/lib/weaver.rb +236 -53
  74. data/lib/weaver/version.rb +1 -1
  75. data/weaver.gemspec +2 -2
  76. metadata +50 -7
  77. data/data/weaver/js/plugins/jvectormap/jquery-jvectormap-1.2.2.min.js +0 -8
@@ -1,11 +1,11 @@
1
- /*! DataTables 1.10.4
1
+ /*! DataTables 1.10.8
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.4
8
+ * @version 1.10.8
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,_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*/
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,_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
 
@@ -33,10 +33,10 @@
33
33
  // Define as an AMD module if possible
34
34
  define( 'datatables', ['jquery'], factory );
35
35
  }
36
- else if ( typeof exports === 'object' ) {
37
- // Node/CommonJS
38
- factory( require( 'jquery' ) );
39
- }
36
+ else if ( typeof exports === 'object' ) {
37
+ // Node/CommonJS
38
+ module.exports = factory( require( 'jquery' ) );
39
+ }
40
40
  else if ( jQuery && !jQuery.fn.dataTable ) {
41
41
  // Define using browser globals otherwise
42
42
  // Prevent multiple instantiations if the script is loaded twice
@@ -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
 
@@ -452,6 +467,11 @@
452
467
  _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
453
468
  _fnCompatMap( init, 'searching', 'bFilter' );
454
469
 
470
+ // Boolean initialisation of x-scrolling
471
+ if ( typeof init.sScrollX === 'boolean' ) {
472
+ init.sScrollX = init.sScrollX ? '100%' : '';
473
+ }
474
+
455
475
  // Column search objects are in an array, so it needs to be converted
456
476
  // element by element
457
477
  var searchCols = init.aoSearchCols;
@@ -478,6 +498,12 @@
478
498
  _fnCompatMap( init, 'orderData', 'aDataSort' );
479
499
  _fnCompatMap( init, 'orderSequence', 'asSorting' );
480
500
  _fnCompatMap( init, 'orderDataType', 'sortDataType' );
501
+
502
+ // orderData can be given as an integer
503
+ var dataSort = init.aDataSort;
504
+ if ( dataSort && ! $.isArray( dataSort ) ) {
505
+ init.aDataSort = [ dataSort ];
506
+ }
481
507
  }
482
508
 
483
509
 
@@ -493,7 +519,7 @@
493
519
  // Scrolling feature / quirks detection
494
520
  var n = $('<div/>')
495
521
  .css( {
496
- position: 'absolute',
522
+ position: 'fixed',
497
523
  top: 0,
498
524
  left: 0,
499
525
  height: 1,
@@ -528,7 +554,10 @@
528
554
 
529
555
  // In rtl text layout, some browsers (most, but not all) will place the
530
556
  // scrollbar on the left, rather than the right.
531
- browser.bScrollbarLeft = test.offset().left !== 1;
557
+ browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
558
+
559
+ // IE8- don't provide height and width for getBoundingClientRect
560
+ browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
532
561
 
533
562
  n.remove();
534
563
  }
@@ -595,7 +624,7 @@
595
624
  searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
596
625
 
597
626
  // Use the default column options function to initialise classes etc
598
- _fnColumnOptions( oSettings, iCol, null );
627
+ _fnColumnOptions( oSettings, iCol, $(nTh).data() );
599
628
  }
600
629
 
601
630
 
@@ -658,7 +687,7 @@
658
687
  /* iDataSort to be applied (backwards compatibility), but aDataSort will take
659
688
  * priority if defined
660
689
  */
661
- if ( typeof oOptions.iDataSort === 'number' )
690
+ if ( oOptions.iDataSort !== undefined )
662
691
  {
663
692
  oCol.aDataSort = [ oOptions.iDataSort ];
664
693
  }
@@ -987,7 +1016,8 @@
987
1016
  /* Create the object for storing information about this new row */
988
1017
  var iRow = oSettings.aoData.length;
989
1018
  var oData = $.extend( true, {}, DataTable.models.oRow, {
990
- src: nTr ? 'dom' : 'data'
1019
+ src: nTr ? 'dom' : 'data',
1020
+ idx: iRow
991
1021
  } );
992
1022
 
993
1023
  oData._aData = aDataIn;
@@ -1010,6 +1040,11 @@
1010
1040
  /* Add to the display array */
1011
1041
  oSettings.aiDisplayMaster.push( iRow );
1012
1042
 
1043
+ var id = oSettings.rowIdFn( aDataIn );
1044
+ if ( id !== undefined ) {
1045
+ oSettings.aIds[ id ] = oData;
1046
+ }
1047
+
1013
1048
  /* Create the DOM information, or register it if already present */
1014
1049
  if ( nTr || ! oSettings.oFeatures.bDeferRender )
1015
1050
  {
@@ -1153,7 +1188,7 @@
1153
1188
  */
1154
1189
  function _fnSplitObjNotation( str )
1155
1190
  {
1156
- return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1191
+ return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
1157
1192
  return s.replace(/\\./g, '.');
1158
1193
  } );
1159
1194
  }
@@ -1519,7 +1554,7 @@
1519
1554
  }
1520
1555
 
1521
1556
  // Update DataTables special `DT_*` attributes for the row
1522
- _fnRowAttributes( row );
1557
+ _fnRowAttributes( settings, row );
1523
1558
  }
1524
1559
  }
1525
1560
 
@@ -1614,12 +1649,18 @@
1614
1649
  else {
1615
1650
  // Existing row object passed in
1616
1651
  tds = row.anCells;
1617
-
1652
+
1618
1653
  for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1619
1654
  cellProcess( tds[j] );
1620
1655
  }
1621
1656
  }
1622
1657
 
1658
+ // Read the ID from the DOM if present
1659
+ var id = row.getAttribute( 'id' );
1660
+ if ( id ) {
1661
+ _fnSetObjectDataFn( settings.rowId )( d, id );
1662
+ }
1663
+
1623
1664
  return {
1624
1665
  data: d,
1625
1666
  cells: tds
@@ -1657,7 +1698,7 @@
1657
1698
  nTr._DT_RowIndex = iRow;
1658
1699
 
1659
1700
  /* Special parameters can be given by the data source to be used on the row */
1660
- _fnRowAttributes( row );
1701
+ _fnRowAttributes( oSettings, row );
1661
1702
 
1662
1703
  /* Process each column */
1663
1704
  for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
@@ -1709,17 +1750,20 @@
1709
1750
  /**
1710
1751
  * Add attributes to a row based on the special `DT_*` parameters in a data
1711
1752
  * source object.
1753
+ * @param {object} settings DataTables settings object
1712
1754
  * @param {object} DataTables row object for the row to be modified
1713
1755
  * @memberof DataTable#oApi
1714
1756
  */
1715
- function _fnRowAttributes( row )
1757
+ function _fnRowAttributes( settings, row )
1716
1758
  {
1717
1759
  var tr = row.nTr;
1718
1760
  var data = row._aData;
1719
1761
 
1720
1762
  if ( tr ) {
1721
- if ( data.DT_RowId ) {
1722
- tr.id = data.DT_RowId;
1763
+ var id = settings.rowIdFn( data );
1764
+
1765
+ if ( id ) {
1766
+ tr.id = id;
1723
1767
  }
1724
1768
 
1725
1769
  if ( data.DT_RowClass ) {
@@ -1734,6 +1778,10 @@
1734
1778
  .addClass( data.DT_RowClass );
1735
1779
  }
1736
1780
 
1781
+ if ( data.DT_RowAttr ) {
1782
+ $(tr).attr( data.DT_RowAttr );
1783
+ }
1784
+
1737
1785
  if ( data.DT_RowData ) {
1738
1786
  $(tr).data( data.DT_RowData );
1739
1787
  }
@@ -1780,7 +1828,7 @@
1780
1828
  }
1781
1829
  }
1782
1830
 
1783
- if ( column.sTitle != cell.html() ) {
1831
+ if ( column.sTitle != cell[0].innerHTML ) {
1784
1832
  cell.html( column.sTitle );
1785
1833
  }
1786
1834
 
@@ -2252,6 +2300,7 @@
2252
2300
 
2253
2301
  /* Built our DOM structure - replace the holding div with what we want */
2254
2302
  holding.replaceWith( insert );
2303
+ oSettings.nHolding = null;
2255
2304
  }
2256
2305
 
2257
2306
 
@@ -2367,8 +2416,6 @@
2367
2416
  return aReturn;
2368
2417
  }
2369
2418
 
2370
-
2371
-
2372
2419
  /**
2373
2420
  * Create an Ajax call based on the table's settings, taking into account that
2374
2421
  * parameters can have multiple forms, and backwards compatibility.
@@ -2411,16 +2458,20 @@
2411
2458
  var ajaxData;
2412
2459
  var ajax = oSettings.ajax;
2413
2460
  var instance = oSettings.oInstance;
2461
+ var callback = function ( json ) {
2462
+ _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
2463
+ fn( json );
2464
+ };
2414
2465
 
2415
2466
  if ( $.isPlainObject( ajax ) && ajax.data )
2416
2467
  {
2417
2468
  ajaxData = ajax.data;
2418
2469
 
2419
2470
  var newData = $.isFunction( ajaxData ) ?
2420
- ajaxData( data ) : // fn can manipulate data or return an object
2421
- ajaxData; // object or array to merge
2471
+ ajaxData( data, oSettings ) : // fn can manipulate data or return
2472
+ ajaxData; // an object object or array to merge
2422
2473
 
2423
- // If the function returned an object, use that alone
2474
+ // If the function returned something, use that alone
2424
2475
  data = $.isFunction( ajaxData ) && newData ?
2425
2476
  newData :
2426
2477
  $.extend( true, data, newData );
@@ -2435,24 +2486,25 @@
2435
2486
  "success": function (json) {
2436
2487
  var error = json.error || json.sError;
2437
2488
  if ( error ) {
2438
- oSettings.oApi._fnLog( oSettings, 0, error );
2489
+ _fnLog( oSettings, 0, error );
2439
2490
  }
2440
2491
 
2441
2492
  oSettings.json = json;
2442
- _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2443
- fn( json );
2493
+ callback( json );
2444
2494
  },
2445
2495
  "dataType": "json",
2446
2496
  "cache": false,
2447
2497
  "type": oSettings.sServerMethod,
2448
2498
  "error": function (xhr, error, thrown) {
2449
- var log = oSettings.oApi._fnLog;
2499
+ var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
2450
2500
 
2451
- if ( error == "parsererror" ) {
2452
- log( oSettings, 0, 'Invalid JSON response', 1 );
2453
- }
2454
- else if ( xhr.readyState === 4 ) {
2455
- log( oSettings, 0, 'Ajax error', 7 );
2501
+ if ( $.inArray( true, ret ) === -1 ) {
2502
+ if ( error == "parsererror" ) {
2503
+ _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
2504
+ }
2505
+ else if ( xhr.readyState === 4 ) {
2506
+ _fnLog( oSettings, 0, 'Ajax error', 7 );
2507
+ }
2456
2508
  }
2457
2509
 
2458
2510
  _fnProcessingDisplay( oSettings, false );
@@ -2473,7 +2525,7 @@
2473
2525
  $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2474
2526
  return { name: key, value: val };
2475
2527
  } ),
2476
- fn,
2528
+ callback,
2477
2529
  oSettings
2478
2530
  );
2479
2531
  }
@@ -2487,7 +2539,7 @@
2487
2539
  else if ( $.isFunction( ajax ) )
2488
2540
  {
2489
2541
  // Is a function - let the caller define what needs to be done
2490
- oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2542
+ oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
2491
2543
  }
2492
2544
  else
2493
2545
  {
@@ -2653,6 +2705,7 @@
2653
2705
  return json[old] !== undefined ? json[old] : json[modern];
2654
2706
  };
2655
2707
 
2708
+ var data = _fnAjaxDataSrc( settings, json );
2656
2709
  var draw = compat( 'sEcho', 'draw' );
2657
2710
  var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
2658
2711
  var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
@@ -2669,7 +2722,6 @@
2669
2722
  settings._iRecordsTotal = parseInt(recordsTotal, 10);
2670
2723
  settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
2671
2724
 
2672
- var data = _fnAjaxDataSrc( settings, json );
2673
2725
  for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2674
2726
  _fnAddData( settings, data[i] );
2675
2727
  }
@@ -2712,7 +2764,6 @@
2712
2764
  json;
2713
2765
  }
2714
2766
 
2715
-
2716
2767
  /**
2717
2768
  * Generate the node required for filtering text
2718
2769
  * @returns {node} Filter control element
@@ -2993,7 +3044,7 @@
2993
3044
  *
2994
3045
  * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2995
3046
  */
2996
- var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
3047
+ var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
2997
3048
  if ( word.charAt(0) === '"' ) {
2998
3049
  var m = word.match( /^"(.*)"$/ );
2999
3050
  word = m ? m[1] : word;
@@ -3238,6 +3289,7 @@
3238
3289
  var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3239
3290
  var columns = settings.aoColumns, column;
3240
3291
  var features = settings.oFeatures;
3292
+ var deferLoading = settings.bDeferLoading; // value modified by the draw
3241
3293
 
3242
3294
  /* Ensure that the table data is fully initialised */
3243
3295
  if ( ! settings.bInitialised ) {
@@ -3269,6 +3321,8 @@
3269
3321
  }
3270
3322
  }
3271
3323
 
3324
+ _fnCallbackFire( settings, null, 'preInit', [settings] );
3325
+
3272
3326
  // If there is default sorting required - let's do it. The sort function
3273
3327
  // will do the drawing for us. Otherwise we draw the table regardless of the
3274
3328
  // Ajax source - this allows the table to look initialised for Ajax sourcing
@@ -3277,7 +3331,7 @@
3277
3331
 
3278
3332
  // Server-side processing init complete is done by _fnAjaxUpdateDraw
3279
3333
  var dataSrc = _fnDataSource( settings );
3280
- if ( dataSrc != 'ssp' ) {
3334
+ if ( dataSrc != 'ssp' || deferLoading ) {
3281
3335
  // if there is an ajax source load the data
3282
3336
  if ( dataSrc == 'ajax' ) {
3283
3337
  _fnBuildAjax( settings, [], function(json) {
@@ -3318,9 +3372,9 @@
3318
3372
  {
3319
3373
  settings._bInitComplete = true;
3320
3374
 
3321
- // On an Ajax load we now have data and therefore want to apply the column
3322
- // sizing
3323
- if ( json ) {
3375
+ // When data was added after the initialisation (data or Ajax) we need to
3376
+ // calculate the column sizing
3377
+ if ( json || settings.oInit.aaData ) {
3324
3378
  _fnAdjustColumnSizing( settings );
3325
3379
  }
3326
3380
 
@@ -3660,8 +3714,8 @@
3660
3714
  .append(
3661
3715
  $(_div, { 'class': classes.sScrollBody } )
3662
3716
  .css( {
3717
+ position: 'relative',
3663
3718
  overflow: 'auto',
3664
- height: size( scrollY ),
3665
3719
  width: size( scrollX )
3666
3720
  } )
3667
3721
  .append( table )
@@ -3697,7 +3751,7 @@
3697
3751
 
3698
3752
  // When the body is scrolled, then we also want to scroll the headers
3699
3753
  if ( scrollX ) {
3700
- $(scrollBody).scroll( function (e) {
3754
+ $(scrollBody).on( 'scroll.DT', function (e) {
3701
3755
  var scrollLeft = this.scrollLeft;
3702
3756
 
3703
3757
  scrollHead.scrollLeft = scrollLeft;
@@ -3708,6 +3762,11 @@
3708
3762
  } );
3709
3763
  }
3710
3764
 
3765
+ $(scrollBody).css(
3766
+ scrollY && scroll.bCollapse ? 'max-height' : 'height',
3767
+ scrollY
3768
+ );
3769
+
3711
3770
  settings.nScrollHead = scrollHead;
3712
3771
  settings.nScrollBody = scrollBody;
3713
3772
  settings.nScrollFoot = scrollFoot;
@@ -3824,13 +3883,6 @@
3824
3883
  }, footerSrcEls );
3825
3884
  }
3826
3885
 
3827
- // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3828
- // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3829
- // then hide it (end of this function), so add the header height to the body scroller.
3830
- if ( scroll.bCollapse && scrollY !== "" ) {
3831
- divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3832
- }
3833
-
3834
3886
  // Size the table as a whole
3835
3887
  sanityWidth = table.outerWidth();
3836
3888
  if ( scrollX === "" ) {
@@ -3845,32 +3897,17 @@
3845
3897
  ) {
3846
3898
  tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3847
3899
  }
3900
+
3901
+ // Recalculate the sanity width
3902
+ sanityWidth = table.outerWidth();
3848
3903
  }
3849
- else
3850
- {
3851
- // x scrolling
3852
- if ( scrollXInner !== "" ) {
3853
- // x scroll inner has been given - use it
3854
- tableStyle.width = _fnStringToCss(scrollXInner);
3855
- }
3856
- else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3857
- // There is y-scrolling - try to take account of the y scroll bar
3858
- tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3859
- if ( table.outerWidth() > sanityWidth-barWidth ) {
3860
- // Not possible to take account of it
3861
- tableStyle.width = _fnStringToCss( sanityWidth );
3862
- }
3863
- }
3864
- else {
3865
- // When all else fails
3866
- tableStyle.width = _fnStringToCss( sanityWidth );
3867
- }
3868
- }
3904
+ else if ( scrollXInner !== "" ) {
3905
+ // legacy x scroll inner has been given - use it
3906
+ tableStyle.width = _fnStringToCss(scrollXInner);
3869
3907
 
3870
- // Recalculate the sanity width - now that we've applied the required width,
3871
- // before it was a temporary variable. This is required because the column
3872
- // width calculation is done before this table DOM is created.
3873
- sanityWidth = table.outerWidth();
3908
+ // Recalculate the sanity width
3909
+ sanityWidth = table.outerWidth();
3910
+ }
3874
3911
 
3875
3912
  // Hidden header should have zero height, so remove padding and borders. Then
3876
3913
  // set the width based on the real headers
@@ -3978,18 +4015,6 @@
3978
4015
  }
3979
4016
  }
3980
4017
 
3981
- if ( scrollY && scroll.bCollapse ) {
3982
- divBodyStyle.height = _fnStringToCss( scrollY );
3983
-
3984
- var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
3985
- barWidth :
3986
- 0;
3987
-
3988
- if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
3989
- divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
3990
- }
3991
- }
3992
-
3993
4018
  /* Finally set the width's of the header and footer tables */
3994
4019
  var iOuterWidth = table.outerWidth();
3995
4020
  divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
@@ -4078,10 +4103,17 @@
4078
4103
  columnCount = columns.length,
4079
4104
  visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4080
4105
  headerCells = $('th', oSettings.nTHead),
4081
- tableWidthAttr = table.getAttribute('width'),
4106
+ tableWidthAttr = table.getAttribute('width'), // from DOM element
4082
4107
  tableContainer = table.parentNode,
4083
4108
  userInputs = false,
4084
- i, column, columnIdx, width, outerWidth;
4109
+ i, column, columnIdx, width, outerWidth,
4110
+ browser = oSettings.oBrowser,
4111
+ ie67 = browser.bScrollOversize;
4112
+
4113
+ var styleWidth = table.style.width;
4114
+ if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
4115
+ tableWidthAttr = styleWidth;
4116
+ }
4085
4117
 
4086
4118
  /* Convert any user input sizes into pixel sizes */
4087
4119
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
@@ -4099,9 +4131,9 @@
4099
4131
  * the web- browser. No custom sizes can be set in order for this to happen,
4100
4132
  * nor scrolling used
4101
4133
  */
4102
- if ( ! userInputs && ! scrollX && ! scrollY &&
4103
- columnCount == _fnVisbleColumns( oSettings ) &&
4104
- columnCount == headerCells.length
4134
+ if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
4135
+ columnCount == _fnVisbleColumns( oSettings ) &&
4136
+ columnCount == headerCells.length
4105
4137
  ) {
4106
4138
  for ( i=0 ; i<columnCount ; i++ ) {
4107
4139
  columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
@@ -4109,22 +4141,29 @@
4109
4141
  }
4110
4142
  else
4111
4143
  {
4112
- // Otherwise construct a single row table with the widest node in the
4113
- // data, assign any user defined widths, then insert it into the DOM and
4114
- // allow the browser to do all the hard work of calculating table widths
4144
+ // Otherwise construct a single row, worst case, table with the widest
4145
+ // node in the data, assign any user defined widths, then insert it into
4146
+ // the DOM and allow the browser to do all the hard work of calculating
4147
+ // table widths
4115
4148
  var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4116
- .empty()
4117
4149
  .css( 'visibility', 'hidden' )
4118
- .removeAttr( 'id' )
4119
- .append( $(oSettings.nTHead).clone( false ) )
4120
- .append( $(oSettings.nTFoot).clone( false ) )
4121
- .append( $('<tbody><tr/></tbody>') );
4150
+ .removeAttr( 'id' );
4151
+
4152
+ // Clean up the table body
4153
+ tmpTable.find('tbody tr').remove();
4154
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
4155
+
4156
+ // Clone the table header and footer - we can't use the header / footer
4157
+ // from the cloned table, since if scrolling is active, the table's
4158
+ // real header and footer are contained in different table tags
4159
+ tmpTable.find('thead, tfoot').remove();
4160
+ tmpTable
4161
+ .append( $(oSettings.nTHead).clone() )
4162
+ .append( $(oSettings.nTFoot).clone() );
4122
4163
 
4123
4164
  // Remove any assigned widths from the footer (from scrolling)
4124
4165
  tmpTable.find('tfoot th, tfoot td').css('width', '');
4125
4166
 
4126
- var tr = tmpTable.find( 'tbody tr' );
4127
-
4128
4167
  // Apply custom sizing to the cloned header
4129
4168
  headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4130
4169
 
@@ -4149,8 +4188,24 @@
4149
4188
  }
4150
4189
  }
4151
4190
 
4152
- // Table has been built, attach to the document so we can work with it
4153
- tmpTable.appendTo( tableContainer );
4191
+ // Table has been built, attach to the document so we can work with it.
4192
+ // A holding element is used, positioned at the top of the container
4193
+ // with minimal height, so it has no effect on if the container scrolls
4194
+ // or not. Otherwise it might trigger scrolling when it actually isn't
4195
+ // needed
4196
+ var holder = $('<div/>').css( scrollX || scrollY ?
4197
+ {
4198
+ position: 'absolute',
4199
+ top: 0,
4200
+ left: 0,
4201
+ height: 1,
4202
+ right: 0,
4203
+ overflow: 'hidden'
4204
+ } :
4205
+ {}
4206
+ )
4207
+ .append( tmpTable )
4208
+ .appendTo( tableContainer );
4154
4209
 
4155
4210
  // When scrolling (X or Y) we want to set the width of the table as
4156
4211
  // appropriate. However, when not scrolling leave the table width as it
@@ -4161,20 +4216,17 @@
4161
4216
  else if ( scrollX ) {
4162
4217
  tmpTable.css( 'width', 'auto' );
4163
4218
 
4164
- if ( tmpTable.width() < tableContainer.offsetWidth ) {
4165
- tmpTable.width( tableContainer.offsetWidth );
4219
+ if ( tmpTable.width() < tableContainer.clientWidth ) {
4220
+ tmpTable.width( tableContainer.clientWidth );
4166
4221
  }
4167
4222
  }
4168
4223
  else if ( scrollY ) {
4169
- tmpTable.width( tableContainer.offsetWidth );
4224
+ tmpTable.width( tableContainer.clientWidth );
4170
4225
  }
4171
4226
  else if ( tableWidthAttr ) {
4172
4227
  tmpTable.width( tableWidthAttr );
4173
4228
  }
4174
4229
 
4175
- // Take into account the y scrollbar
4176
- _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4177
-
4178
4230
  // Browsers need a bit of a hand when a width is assigned to any columns
4179
4231
  // when x-scrolling as they tend to collapse the table to the min-width,
4180
4232
  // even if we sent the column widths. So we need to keep track of what
@@ -4186,7 +4238,12 @@
4186
4238
 
4187
4239
  for ( i=0 ; i<visibleColumns.length ; i++ ) {
4188
4240
  column = columns[ visibleColumns[i] ];
4189
- outerWidth = $(headerCells[i]).outerWidth();
4241
+
4242
+ // Much prefer to use getBoundingClientRect due to its sub-pixel
4243
+ // resolution, but IE8- do not support the width property.
4244
+ outerWidth = browser.bBounding ?
4245
+ headerCells[i].getBoundingClientRect().width :
4246
+ $(headerCells[i]).outerWidth();
4190
4247
 
4191
4248
  total += column.sWidthOrig === null ?
4192
4249
  outerWidth :
@@ -4210,7 +4267,7 @@
4210
4267
  table.style.width = _fnStringToCss( tmpTable.css('width') );
4211
4268
 
4212
4269
  // Finished with the table - ditch it
4213
- tmpTable.remove();
4270
+ holder.remove();
4214
4271
  }
4215
4272
 
4216
4273
  // If there is a width attr, we want to attach an event listener which
@@ -4222,9 +4279,20 @@
4222
4279
  }
4223
4280
 
4224
4281
  if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4225
- $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4226
- _fnAdjustColumnSizing( oSettings );
4227
- } ) );
4282
+ var bindResize = function () {
4283
+ $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4284
+ _fnAdjustColumnSizing( oSettings );
4285
+ } ) );
4286
+ };
4287
+
4288
+ // IE6/7 will crash if we bind a resize event handler on page load.
4289
+ // To be removed in 1.11 which drops IE6/7 support
4290
+ if ( ie67 ) {
4291
+ setTimeout( bindResize, 1000 );
4292
+ }
4293
+ else {
4294
+ bindResize();
4295
+ }
4228
4296
 
4229
4297
  oSettings._reszEvt = true;
4230
4298
  }
@@ -4259,12 +4327,9 @@
4259
4327
  fn.apply( that, args );
4260
4328
  }, frequency );
4261
4329
  }
4262
- else if ( last ) {
4263
- last = now;
4264
- fn.apply( that, args );
4265
- }
4266
4330
  else {
4267
4331
  last = now;
4332
+ fn.apply( that, args );
4268
4333
  }
4269
4334
  };
4270
4335
  }
@@ -4294,27 +4359,6 @@
4294
4359
  }
4295
4360
 
4296
4361
 
4297
- /**
4298
- * Adjust a table's width to take account of vertical scroll bar
4299
- * @param {object} oSettings dataTables settings object
4300
- * @param {node} n table node
4301
- * @memberof DataTable#oApi
4302
- */
4303
-
4304
- function _fnScrollingWidthAdjust ( settings, n )
4305
- {
4306
- var scroll = settings.oScroll;
4307
-
4308
- if ( scroll.sX || scroll.sY ) {
4309
- // When y-scrolling only, we want to remove the width of the scroll bar
4310
- // so the table + scroll bar will fit into the area available, otherwise
4311
- // we fix the table at its current size with no adjustment
4312
- var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4313
- n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4314
- }
4315
- }
4316
-
4317
-
4318
4362
  /**
4319
4363
  * Get the widest node
4320
4364
  * @param {object} settings dataTables settings object
@@ -4395,41 +4439,28 @@
4395
4439
  {
4396
4440
  // On first run a static variable is set, since this is only needed once.
4397
4441
  // Subsequent runs will just use the previously calculated value
4398
- if ( ! DataTable.__scrollbarWidth ) {
4399
- var inner = $('<p/>').css( {
4400
- width: '100%',
4401
- height: 200,
4402
- padding: 0
4403
- } )[0];
4404
-
4405
- var outer = $('<div/>')
4406
- .css( {
4442
+ var width = DataTable.__scrollbarWidth;
4443
+
4444
+ if ( width === undefined ) {
4445
+ var sizer = $('<p/>').css( {
4407
4446
  position: 'absolute',
4408
4447
  top: 0,
4409
4448
  left: 0,
4410
- width: 200,
4449
+ width: '100%',
4411
4450
  height: 150,
4412
4451
  padding: 0,
4413
- overflow: 'hidden',
4452
+ overflow: 'scroll',
4414
4453
  visibility: 'hidden'
4415
4454
  } )
4416
- .append( inner )
4417
- .appendTo( 'body' );
4455
+ .appendTo('body');
4418
4456
 
4419
- var w1 = inner.offsetWidth;
4420
- outer.css( 'overflow', 'scroll' );
4421
- var w2 = inner.offsetWidth;
4457
+ width = sizer[0].offsetWidth - sizer[0].clientWidth;
4458
+ DataTable.__scrollbarWidth = width;
4422
4459
 
4423
- if ( w1 === w2 ) {
4424
- w2 = outer[0].clientWidth;
4425
- }
4426
-
4427
- outer.remove();
4428
-
4429
- DataTable.__scrollbarWidth = w1 - w2;
4460
+ sizer.remove();
4430
4461
  }
4431
4462
 
4432
- return DataTable.__scrollbarWidth;
4463
+ return width;
4433
4464
  }
4434
4465
 
4435
4466
 
@@ -4720,6 +4751,10 @@
4720
4751
  // Yes, modify the sort
4721
4752
  nextSortIdx = next( sorting[sortIdx], true );
4722
4753
 
4754
+ if ( nextSortIdx === null && sorting.length === 1 ) {
4755
+ nextSortIdx = 0; // can't remove sorting completely
4756
+ }
4757
+
4723
4758
  if ( nextSortIdx === null ) {
4724
4759
  sorting.splice( sortIdx, 1 );
4725
4760
  }
@@ -4954,31 +4989,43 @@
4954
4989
 
4955
4990
  // Restore key features - todo - for 1.11 this needs to be done by
4956
4991
  // subscribed events
4957
- settings._iDisplayStart = state.start;
4958
- settings.iInitDisplayStart = state.start;
4959
- settings._iDisplayLength = state.length;
4960
- settings.aaSorting = [];
4992
+ if ( state.start !== undefined ) {
4993
+ settings._iDisplayStart = state.start;
4994
+ settings.iInitDisplayStart = state.start;
4995
+ }
4996
+ if ( state.length !== undefined ) {
4997
+ settings._iDisplayLength = state.length;
4998
+ }
4961
4999
 
4962
5000
  // Order
4963
- $.each( state.order, function ( i, col ) {
4964
- settings.aaSorting.push( col[0] >= columns.length ?
4965
- [ 0, col[1] ] :
4966
- col
4967
- );
4968
- } );
5001
+ if ( state.order !== undefined ) {
5002
+ settings.aaSorting = [];
5003
+ $.each( state.order, function ( i, col ) {
5004
+ settings.aaSorting.push( col[0] >= columns.length ?
5005
+ [ 0, col[1] ] :
5006
+ col
5007
+ );
5008
+ } );
5009
+ }
4969
5010
 
4970
5011
  // Search
4971
- $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
5012
+ if ( state.search !== undefined ) {
5013
+ $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
5014
+ }
4972
5015
 
4973
5016
  // Columns
4974
5017
  for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
4975
5018
  var col = state.columns[i];
4976
5019
 
4977
5020
  // Visibility
4978
- columns[i].bVisible = col.visible;
5021
+ if ( col.visible !== undefined ) {
5022
+ columns[i].bVisible = col.visible;
5023
+ }
4979
5024
 
4980
5025
  // Search
4981
- $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5026
+ if ( col.search !== undefined ) {
5027
+ $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5028
+ }
4982
5029
  }
4983
5030
 
4984
5031
  _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
@@ -5013,7 +5060,7 @@
5013
5060
  function _fnLog( settings, level, msg, tn )
5014
5061
  {
5015
5062
  msg = 'DataTables warning: '+
5016
- (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
5063
+ (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
5017
5064
 
5018
5065
  if ( tn ) {
5019
5066
  msg += '. For more information about this error, please see '+
@@ -5025,12 +5072,19 @@
5025
5072
  var ext = DataTable.ext;
5026
5073
  var type = ext.sErrMode || ext.errMode;
5027
5074
 
5075
+ if ( settings ) {
5076
+ _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5077
+ }
5078
+
5028
5079
  if ( type == 'alert' ) {
5029
5080
  alert( msg );
5030
5081
  }
5031
- else {
5082
+ else if ( type == 'throw' ) {
5032
5083
  throw new Error(msg);
5033
5084
  }
5085
+ else if ( typeof type == 'function' ) {
5086
+ type( settings, tn, msg );
5087
+ }
5034
5088
  }
5035
5089
  else if ( window.console && console.log ) {
5036
5090
  console.log( msg );
@@ -5173,13 +5227,13 @@
5173
5227
  * @param {object} settings dataTables settings object
5174
5228
  * @param {string} callbackArr Name of the array storage for the callbacks in
5175
5229
  * oSettings
5176
- * @param {string} event Name of the jQuery custom event to trigger. If null no
5177
- * trigger is fired
5230
+ * @param {string} eventName Name of the jQuery custom event to trigger. If
5231
+ * null no trigger is fired
5178
5232
  * @param {array} args Array of arguments to pass to the callback function /
5179
5233
  * trigger
5180
5234
  * @memberof DataTable#oApi
5181
5235
  */
5182
- function _fnCallbackFire( settings, callbackArr, e, args )
5236
+ function _fnCallbackFire( settings, callbackArr, eventName, args )
5183
5237
  {
5184
5238
  var ret = [];
5185
5239
 
@@ -5189,8 +5243,12 @@
5189
5243
  } );
5190
5244
  }
5191
5245
 
5192
- if ( e !== null ) {
5193
- $(settings.nTable).trigger( e+'.dt', args );
5246
+ if ( eventName !== null ) {
5247
+ var e = $.Event( eventName+'.dt' );
5248
+
5249
+ $(settings.nTable).trigger( e, args );
5250
+
5251
+ ret.push( e.result );
5194
5252
  }
5195
5253
 
5196
5254
  return ret;
@@ -5602,8 +5660,8 @@
5602
5660
  this.fnDraw = function( complete )
5603
5661
  {
5604
5662
  // Note that this isn't an exact match to the old call to _fnDraw - it takes
5605
- // into account the new data, but can old position.
5606
- this.api( true ).draw( ! complete );
5663
+ // into account the new data, but can hold position.
5664
+ this.api( true ).draw( complete );
5607
5665
  };
5608
5666
 
5609
5667
 
@@ -6051,6 +6109,7 @@
6051
6109
  var sId = this.getAttribute( 'id' );
6052
6110
  var bInitHandedOff = false;
6053
6111
  var defaults = DataTable.defaults;
6112
+ var $this = $(this);
6054
6113
 
6055
6114
 
6056
6115
  /* Sanity check */
@@ -6069,30 +6128,34 @@
6069
6128
  _fnCamelToHungarian( defaults.column, defaults.column, true );
6070
6129
 
6071
6130
  /* Setting up the initialisation object */
6072
- _fnCamelToHungarian( defaults, oInit );
6131
+ _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
6132
+
6133
+
6073
6134
 
6074
6135
  /* Check to see if we are re-initialising a table */
6075
6136
  var allSettings = DataTable.settings;
6076
6137
  for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6077
6138
  {
6139
+ var s = allSettings[i];
6140
+
6078
6141
  /* Base check on table node */
6079
- if ( allSettings[i].nTable == this )
6142
+ if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
6080
6143
  {
6081
6144
  var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6082
6145
  var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6083
6146
 
6084
6147
  if ( emptyInit || bRetrieve )
6085
6148
  {
6086
- return allSettings[i].oInstance;
6149
+ return s.oInstance;
6087
6150
  }
6088
6151
  else if ( bDestroy )
6089
6152
  {
6090
- allSettings[i].oInstance.fnDestroy();
6153
+ s.oInstance.fnDestroy();
6091
6154
  break;
6092
6155
  }
6093
6156
  else
6094
6157
  {
6095
- _fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
6158
+ _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
6096
6159
  return;
6097
6160
  }
6098
6161
  }
@@ -6102,7 +6165,7 @@
6102
6165
  * instance by simply deleting it. This is under the assumption that the table has been
6103
6166
  * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6104
6167
  */
6105
- if ( allSettings[i].sTableId == this.id )
6168
+ if ( s.sTableId == this.id )
6106
6169
  {
6107
6170
  allSettings.splice( i, 1 );
6108
6171
  break;
@@ -6118,18 +6181,19 @@
6118
6181
 
6119
6182
  /* Create the settings object for this table and set some of the default parameters */
6120
6183
  var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6121
- "nTable": this,
6122
- "oApi": _that.internal,
6123
- "oInit": oInit,
6124
- "sDestroyWidth": $(this)[0].style.width,
6184
+ "sDestroyWidth": $this[0].style.width,
6125
6185
  "sInstance": sId,
6126
6186
  "sTableId": sId
6127
6187
  } );
6188
+ oSettings.nTable = this;
6189
+ oSettings.oApi = _that.internal;
6190
+ oSettings.oInit = oInit;
6191
+
6128
6192
  allSettings.push( oSettings );
6129
6193
 
6130
6194
  // Need to add the instance after the instance after the settings object has been added
6131
6195
  // to the settings array, so we can self reference the table instance if more than one
6132
- oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
6196
+ oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
6133
6197
 
6134
6198
  // Backwards compatibility, before we apply all the defaults
6135
6199
  _fnCompatOpts( oInit );
@@ -6185,6 +6249,7 @@
6185
6249
  "fnStateSaveCallback",
6186
6250
  "renderer",
6187
6251
  "searchDelay",
6252
+ "rowId",
6188
6253
  [ "iCookieDuration", "iStateDuration" ], // backwards compat
6189
6254
  [ "oSearch", "oPreviousSearch" ],
6190
6255
  [ "aoSearchCols", "aoPreSearchCols" ],
@@ -6212,6 +6277,8 @@
6212
6277
  _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
6213
6278
  _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
6214
6279
 
6280
+ oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
6281
+
6215
6282
  var oClasses = oSettings.oClasses;
6216
6283
 
6217
6284
  // @todo Remove in 1.11
@@ -6239,16 +6306,13 @@
6239
6306
  {
6240
6307
  $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6241
6308
  }
6242
- $(this).addClass( oClasses.sTable );
6309
+ $this.addClass( oClasses.sTable );
6243
6310
 
6244
6311
  /* Calculate the scroll bar width and cache it for use later on */
6245
6312
  if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6246
6313
  {
6247
6314
  oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6248
6315
  }
6249
- if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6250
- oSettings.oScroll.sX = '100%';
6251
- }
6252
6316
 
6253
6317
  if ( oSettings.iInitDisplayStart === undefined )
6254
6318
  {
@@ -6305,7 +6369,7 @@
6305
6369
 
6306
6370
  /* Remove row stripe classes if they are already on the table row */
6307
6371
  var stripeClasses = oSettings.asStripeClasses;
6308
- var rowOne = $('tbody tr:eq(0)', this);
6372
+ var rowOne = $this.children('tbody').find('tr').eq(0);
6309
6373
  if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6310
6374
  return rowOne.hasClass(el);
6311
6375
  } ) ) !== -1 ) {
@@ -6356,7 +6420,7 @@
6356
6420
  */
6357
6421
  if ( rowOne.length ) {
6358
6422
  var a = function ( cell, name ) {
6359
- return cell.getAttribute( 'data-'+name ) ? name : null;
6423
+ return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6360
6424
  };
6361
6425
 
6362
6426
  $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
@@ -6445,25 +6509,25 @@
6445
6509
  _fnBrowserDetect( oSettings );
6446
6510
 
6447
6511
  // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6448
- var captions = $(this).children('caption').each( function () {
6449
- this._captionSide = $(this).css('caption-side');
6512
+ var captions = $this.children('caption').each( function () {
6513
+ this._captionSide = $this.css('caption-side');
6450
6514
  } );
6451
6515
 
6452
- var thead = $(this).children('thead');
6516
+ var thead = $this.children('thead');
6453
6517
  if ( thead.length === 0 )
6454
6518
  {
6455
6519
  thead = $('<thead/>').appendTo(this);
6456
6520
  }
6457
6521
  oSettings.nTHead = thead[0];
6458
6522
 
6459
- var tbody = $(this).children('tbody');
6523
+ var tbody = $this.children('tbody');
6460
6524
  if ( tbody.length === 0 )
6461
6525
  {
6462
6526
  tbody = $('<tbody/>').appendTo(this);
6463
6527
  }
6464
6528
  oSettings.nTBody = tbody[0];
6465
6529
 
6466
- var tfoot = $(this).children('tfoot');
6530
+ var tfoot = $this.children('tfoot');
6467
6531
  if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6468
6532
  {
6469
6533
  // If we are a scrolling table, and no footer has been given, then we need to create
@@ -6472,7 +6536,7 @@
6472
6536
  }
6473
6537
 
6474
6538
  if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6475
- $(this).addClass( oClasses.sNoFooter );
6539
+ $this.addClass( oClasses.sNoFooter );
6476
6540
  }
6477
6541
  else if ( tfoot.length > 0 ) {
6478
6542
  oSettings.nTFoot = tfoot[0];
@@ -6681,10 +6745,8 @@
6681
6745
  */
6682
6746
  _Api = function ( context, data )
6683
6747
  {
6684
- if ( ! this instanceof _Api ) {
6685
- throw 'DT API must be constructed as a new object';
6686
- // or should it do the 'new' for the caller?
6687
- // return new _Api.apply( this, arguments );
6748
+ if ( ! (this instanceof _Api) ) {
6749
+ return new _Api( context, data );
6688
6750
  }
6689
6751
 
6690
6752
  var settings = [];
@@ -6725,24 +6787,24 @@
6725
6787
  DataTable.Api = _Api;
6726
6788
 
6727
6789
  _Api.prototype = /** @lends DataTables.Api */{
6728
- /**
6729
- * Return a new Api instance, comprised of the data held in the current
6730
- * instance, join with the other array(s) and/or value(s).
6731
- *
6732
- * An alias for `Array.prototype.concat`.
6733
- *
6734
- * @type method
6735
- * @param {*} value1 Arrays and/or values to concatenate.
6736
- * @param {*} [...] Additional arrays and/or values to concatenate.
6737
- * @returns {DataTables.Api} New API instance, comprising of the combined
6738
- * array.
6739
- */
6790
+ any: function ()
6791
+ {
6792
+ return this.count() !== 0;
6793
+ },
6794
+
6795
+
6740
6796
  concat: __arrayProto.concat,
6741
6797
 
6742
6798
 
6743
6799
  context: [], // array of table settings objects
6744
6800
 
6745
6801
 
6802
+ count: function ()
6803
+ {
6804
+ return this.flatten().length;
6805
+ },
6806
+
6807
+
6746
6808
  each: function ( fn )
6747
6809
  {
6748
6810
  for ( var i=0, ien=this.length ; i<ien; i++ ) {
@@ -6803,7 +6865,6 @@
6803
6865
  return -1;
6804
6866
  },
6805
6867
 
6806
- // Note that `alwaysNew` is internal - use iteratorNew externally
6807
6868
  iterator: function ( flatten, type, fn, alwaysNew ) {
6808
6869
  var
6809
6870
  a = [], ret,
@@ -6977,7 +7038,7 @@
6977
7038
  _Api.extend = function ( scope, obj, ext )
6978
7039
  {
6979
7040
  // Only extend API instances and static properties of the API
6980
- if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7041
+ if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6981
7042
  return;
6982
7043
  }
6983
7044
 
@@ -7226,15 +7287,21 @@
7226
7287
 
7227
7288
  /**
7228
7289
  * Redraw the tables in the current context.
7229
- *
7230
- * @param {boolean} [reset=true] Reset (default) or hold the current paging
7231
- * position. A full re-sort and re-filter is performed when this method is
7232
- * called, which is why the pagination reset is the default action.
7233
- * @returns {DataTables.Api} this
7234
7290
  */
7235
- _api_register( 'draw()', function ( resetPaging ) {
7291
+ _api_register( 'draw()', function ( paging ) {
7236
7292
  return this.iterator( 'table', function ( settings ) {
7237
- _fnReDraw( settings, resetPaging===false );
7293
+ if ( paging === 'page' ) {
7294
+ _fnDraw( settings );
7295
+ }
7296
+ else {
7297
+ if ( typeof paging === 'string' ) {
7298
+ paging = paging === 'full-hold' ?
7299
+ false :
7300
+ true;
7301
+ }
7302
+
7303
+ _fnReDraw( settings, paging===false );
7304
+ }
7238
7305
  } );
7239
7306
  } );
7240
7307
 
@@ -7308,7 +7375,8 @@
7308
7375
  "end": settings.fnDisplayEnd(),
7309
7376
  "length": len,
7310
7377
  "recordsTotal": settings.fnRecordsTotal(),
7311
- "recordsDisplay": visRecords
7378
+ "recordsDisplay": visRecords,
7379
+ "serverSide": _fnDataSource( settings ) === 'ssp'
7312
7380
  };
7313
7381
  } );
7314
7382
 
@@ -7343,13 +7411,28 @@
7343
7411
 
7344
7412
 
7345
7413
  var __reload = function ( settings, holdPosition, callback ) {
7414
+ // Use the draw event to trigger a callback
7415
+ if ( callback ) {
7416
+ var api = new _Api( settings );
7417
+
7418
+ api.one( 'draw', function () {
7419
+ callback( api.ajax.json() );
7420
+ } );
7421
+ }
7422
+
7346
7423
  if ( _fnDataSource( settings ) == 'ssp' ) {
7347
7424
  _fnReDraw( settings, holdPosition );
7348
7425
  }
7349
7426
  else {
7350
- // Trigger xhr
7351
7427
  _fnProcessingDisplay( settings, true );
7352
7428
 
7429
+ // Cancel an existing request
7430
+ var xhr = settings.jqXHR;
7431
+ if ( xhr && xhr.readyState !== 4 ) {
7432
+ xhr.abort();
7433
+ }
7434
+
7435
+ // Trigger xhr
7353
7436
  _fnBuildAjax( settings, [], function( json ) {
7354
7437
  _fnClearTable( settings );
7355
7438
 
@@ -7362,16 +7445,6 @@
7362
7445
  _fnProcessingDisplay( settings, false );
7363
7446
  } );
7364
7447
  }
7365
-
7366
- // Use the draw event to trigger a callback, regardless of if it is an async
7367
- // or sync draw
7368
- if ( callback ) {
7369
- var api = new _Api( settings );
7370
-
7371
- api.one( 'draw', function () {
7372
- callback( api.ajax.json() );
7373
- } );
7374
- }
7375
7448
  };
7376
7449
 
7377
7450
 
@@ -7487,7 +7560,7 @@
7487
7560
 
7488
7561
 
7489
7562
 
7490
- var _selector_run = function ( selector, select )
7563
+ var _selector_run = function ( type, selector, selectFn, settings, opts )
7491
7564
  {
7492
7565
  var
7493
7566
  out = [], res,
@@ -7506,7 +7579,7 @@
7506
7579
  [ selector[i] ];
7507
7580
 
7508
7581
  for ( j=0, jen=a.length ; j<jen ; j++ ) {
7509
- res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7582
+ res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7510
7583
 
7511
7584
  if ( res && res.length ) {
7512
7585
  out.push.apply( out, res );
@@ -7514,6 +7587,14 @@
7514
7587
  }
7515
7588
  }
7516
7589
 
7590
+ // selector extensions
7591
+ var ext = _ext.selector[ type ];
7592
+ if ( ext.length ) {
7593
+ for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7594
+ out = ext[i]( settings, opts, out );
7595
+ }
7596
+ }
7597
+
7517
7598
  return out;
7518
7599
  };
7519
7600
 
@@ -7526,15 +7607,15 @@
7526
7607
 
7527
7608
  // Backwards compatibility for 1.9- which used the terminology filter rather
7528
7609
  // than search
7529
- if ( opts.filter && ! opts.search ) {
7610
+ if ( opts.filter && opts.search === undefined ) {
7530
7611
  opts.search = opts.filter;
7531
7612
  }
7532
7613
 
7533
- return {
7534
- search: opts.search || 'none',
7535
- order: opts.order || 'current',
7536
- page: opts.page || 'all'
7537
- };
7614
+ return $.extend( {
7615
+ search: 'none',
7616
+ order: 'current',
7617
+ page: 'all'
7618
+ }, opts );
7538
7619
  };
7539
7620
 
7540
7621
 
@@ -7546,6 +7627,7 @@
7546
7627
  // Assign the first element to the first item in the instance
7547
7628
  // and truncate the instance and context
7548
7629
  inst[0] = inst[i];
7630
+ inst[0].length = 1;
7549
7631
  inst.length = 1;
7550
7632
  inst.context = [ inst.context[i] ];
7551
7633
 
@@ -7632,7 +7714,7 @@
7632
7714
 
7633
7715
  var __row_selector = function ( settings, selector, opts )
7634
7716
  {
7635
- return _selector_run( selector, function ( sel ) {
7717
+ var run = function ( sel ) {
7636
7718
  var selInt = _intVal( sel );
7637
7719
  var i, ien;
7638
7720
 
@@ -7675,6 +7757,26 @@
7675
7757
  }
7676
7758
  }
7677
7759
 
7760
+ // ID selector. Want to always be able to select rows by id, regardless
7761
+ // of if the tr element has been created or not, so can't rely upon
7762
+ // jQuery here - hence a custom implementation. This does not match
7763
+ // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7764
+ // but to select it using a CSS selector engine (like Sizzle or
7765
+ // querySelect) it would need to need to be escaped for some characters.
7766
+ // DataTables simplifies this for row selectors since you can select
7767
+ // only a row. A # indicates an id any anything that follows is the id -
7768
+ // unescaped.
7769
+ if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7770
+ // get row index from id
7771
+ var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7772
+ if ( rowObj !== undefined ) {
7773
+ return [ rowObj.idx ];
7774
+ }
7775
+
7776
+ // need to fall through to jQuery in case there is DOM id that
7777
+ // matches
7778
+ }
7779
+
7678
7780
  // Selector - jQuery selector string, array of nodes or jQuery object/
7679
7781
  // As jQuery's .filter() allows jQuery objects to be passed in filter,
7680
7782
  // it also allows arrays, so this will cope with all three options
@@ -7684,13 +7786,12 @@
7684
7786
  return this._DT_RowIndex;
7685
7787
  } )
7686
7788
  .toArray();
7687
- } );
7789
+ };
7790
+
7791
+ return _selector_run( 'row', selector, run, settings, opts );
7688
7792
  };
7689
7793
 
7690
7794
 
7691
- /**
7692
- *
7693
- */
7694
7795
  _api_register( 'rows()', function ( selector, opts ) {
7695
7796
  // argument shifting
7696
7797
  if ( selector === undefined ) {
@@ -7714,7 +7815,6 @@
7714
7815
  return inst;
7715
7816
  } );
7716
7817
 
7717
-
7718
7818
  _api_register( 'rows().nodes()', function () {
7719
7819
  return this.iterator( 'row', function ( settings, row ) {
7720
7820
  return settings.aoData[ row ].nTr || undefined;
@@ -7746,10 +7846,25 @@
7746
7846
  }, 1 );
7747
7847
  } );
7748
7848
 
7849
+ _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7850
+ var a = [];
7851
+ var context = this.context;
7852
+
7853
+ // `iterator` will drop undefined values, but in this case we want them
7854
+ for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7855
+ for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7856
+ var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7857
+ a.push( (hash === true ? '#' : '' )+ id );
7858
+ }
7859
+ }
7860
+
7861
+ return new _Api( context, a );
7862
+ } );
7863
+
7749
7864
  _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7750
7865
  var that = this;
7751
7866
 
7752
- return this.iterator( 'row', function ( settings, row, thatIdx ) {
7867
+ this.iterator( 'row', function ( settings, row, thatIdx ) {
7753
7868
  var data = settings.aoData;
7754
7869
 
7755
7870
  data.splice( row, 1 );
@@ -7761,9 +7876,6 @@
7761
7876
  }
7762
7877
  }
7763
7878
 
7764
- // Remove the target row from the search array
7765
- var displayIndex = $.inArray( row, settings.aiDisplay );
7766
-
7767
7879
  // Delete from the display arrays
7768
7880
  _fnDeleteIndex( settings.aiDisplayMaster, row );
7769
7881
  _fnDeleteIndex( settings.aiDisplay, row );
@@ -7772,6 +7884,14 @@
7772
7884
  // Check for an 'overflow' they case for displaying the table
7773
7885
  _fnLengthOverflow( settings );
7774
7886
  } );
7887
+
7888
+ this.iterator( 'table', function ( settings ) {
7889
+ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7890
+ settings.aoData[i].idx = i;
7891
+ }
7892
+ } );
7893
+
7894
+ return this;
7775
7895
  } );
7776
7896
 
7777
7897
 
@@ -7868,6 +7988,14 @@
7868
7988
  // Convert to array of TR elements
7869
7989
  var rows = [];
7870
7990
  var addRow = function ( r, k ) {
7991
+ // Recursion to allow for arrays of jQuery objects
7992
+ if ( $.isArray( r ) || r instanceof $ ) {
7993
+ for ( var i=0, ien=r.length ; i<ien ; i++ ) {
7994
+ addRow( r[i], k );
7995
+ }
7996
+ return;
7997
+ }
7998
+
7871
7999
  // If we get a TR element, then just add it directly - up to the dev
7872
8000
  // to add the correct number of columns etc
7873
8001
  if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
@@ -7885,14 +8013,7 @@
7885
8013
  }
7886
8014
  };
7887
8015
 
7888
- if ( $.isArray( data ) || data instanceof $ ) {
7889
- for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7890
- addRow( data[i], klass );
7891
- }
7892
- }
7893
- else {
7894
- addRow( data, klass );
7895
- }
8016
+ addRow( data, klass );
7896
8017
 
7897
8018
  if ( row._details ) {
7898
8019
  row._details.remove();
@@ -7914,7 +8035,7 @@
7914
8035
  if ( ctx.length ) {
7915
8036
  var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
7916
8037
 
7917
- if ( row._details ) {
8038
+ if ( row && row._details ) {
7918
8039
  row._details.remove();
7919
8040
 
7920
8041
  row._detailsShow = undefined;
@@ -8117,7 +8238,7 @@
8117
8238
  names = _pluck( columns, 'sName' ),
8118
8239
  nodes = _pluck( columns, 'nTh' );
8119
8240
 
8120
- return _selector_run( selector, function ( s ) {
8241
+ var run = function ( s ) {
8121
8242
  var selInt = _intVal( s );
8122
8243
 
8123
8244
  // Selector - all
@@ -8183,7 +8304,9 @@
8183
8304
  } )
8184
8305
  .toArray();
8185
8306
  }
8186
- } );
8307
+ };
8308
+
8309
+ return _selector_run( 'column', selector, run, settings, opts );
8187
8310
  };
8188
8311
 
8189
8312
 
@@ -8246,9 +8369,6 @@
8246
8369
  };
8247
8370
 
8248
8371
 
8249
- /**
8250
- *
8251
- */
8252
8372
  _api_register( 'columns()', function ( selector, opts ) {
8253
8373
  // argument shifting
8254
8374
  if ( selector === undefined ) {
@@ -8272,42 +8392,28 @@
8272
8392
  return inst;
8273
8393
  } );
8274
8394
 
8275
-
8276
- /**
8277
- *
8278
- */
8279
8395
  _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8280
8396
  return this.iterator( 'column', function ( settings, column ) {
8281
8397
  return settings.aoColumns[column].nTh;
8282
8398
  }, 1 );
8283
8399
  } );
8284
8400
 
8285
-
8286
- /**
8287
- *
8288
- */
8289
8401
  _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8290
8402
  return this.iterator( 'column', function ( settings, column ) {
8291
8403
  return settings.aoColumns[column].nTf;
8292
8404
  }, 1 );
8293
8405
  } );
8294
8406
 
8295
-
8296
- /**
8297
- *
8298
- */
8299
8407
  _api_registerPlural( 'columns().data()', 'column().data()', function () {
8300
8408
  return this.iterator( 'column-rows', __columnData, 1 );
8301
8409
  } );
8302
8410
 
8303
-
8304
8411
  _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8305
8412
  return this.iterator( 'column', function ( settings, column ) {
8306
8413
  return settings.aoColumns[column].mData;
8307
8414
  }, 1 );
8308
8415
  } );
8309
8416
 
8310
-
8311
8417
  _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8312
8418
  return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8313
8419
  return _pluck_order( settings.aoData, rows,
@@ -8316,15 +8422,12 @@
8316
8422
  }, 1 );
8317
8423
  } );
8318
8424
 
8319
-
8320
8425
  _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8321
8426
  return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8322
8427
  return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8323
8428
  }, 1 );
8324
8429
  } );
8325
8430
 
8326
-
8327
-
8328
8431
  _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8329
8432
  return this.iterator( 'column', function ( settings, column ) {
8330
8433
  if ( vis === undefined ) {
@@ -8334,8 +8437,6 @@
8334
8437
  } );
8335
8438
  } );
8336
8439
 
8337
-
8338
-
8339
8440
  _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8340
8441
  return this.iterator( 'column', function ( settings, column ) {
8341
8442
  return type === 'visible' ?
@@ -8344,28 +8445,12 @@
8344
8445
  }, 1 );
8345
8446
  } );
8346
8447
 
8347
-
8348
- // _api_register( 'columns().show()', function () {
8349
- // var selector = this.selector;
8350
- // return this.columns( selector.cols, selector.opts ).visible( true );
8351
- // } );
8352
-
8353
-
8354
- // _api_register( 'columns().hide()', function () {
8355
- // var selector = this.selector;
8356
- // return this.columns( selector.cols, selector.opts ).visible( false );
8357
- // } );
8358
-
8359
-
8360
-
8361
8448
  _api_register( 'columns.adjust()', function () {
8362
8449
  return this.iterator( 'table', function ( settings ) {
8363
8450
  _fnAdjustColumnSizing( settings );
8364
8451
  }, 1 );
8365
8452
  } );
8366
8453
 
8367
-
8368
- // Convert from one column index type, to another type
8369
8454
  _api_register( 'column.index()', function ( type, idx ) {
8370
8455
  if ( this.context.length !== 0 ) {
8371
8456
  var ctx = this.context[0];
@@ -8379,7 +8464,6 @@
8379
8464
  }
8380
8465
  } );
8381
8466
 
8382
-
8383
8467
  _api_register( 'column()', function ( selector, opts ) {
8384
8468
  return _selector_first( this.columns( selector, opts ) );
8385
8469
  } );
@@ -8397,7 +8481,7 @@
8397
8481
  var columns = settings.aoColumns.length;
8398
8482
  var a, i, ien, j, o, host;
8399
8483
 
8400
- return _selector_run( selector, function ( s ) {
8484
+ var run = function ( s ) {
8401
8485
  var fnSelector = typeof s === 'function';
8402
8486
 
8403
8487
  if ( s === null || s === undefined || fnSelector ) {
@@ -8417,7 +8501,7 @@
8417
8501
  // Selector - function
8418
8502
  host = settings.aoData[ row ];
8419
8503
 
8420
- if ( s( o, _fnGetCellData(settings, row, j), host.anCells[j] ) ) {
8504
+ if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8421
8505
  a.push( o );
8422
8506
  }
8423
8507
  }
@@ -8448,7 +8532,9 @@
8448
8532
  };
8449
8533
  } )
8450
8534
  .toArray();
8451
- } );
8535
+ };
8536
+
8537
+ return _selector_run( 'cell', selector, run, settings, opts );
8452
8538
  };
8453
8539
 
8454
8540
 
@@ -8458,14 +8544,16 @@
8458
8544
  // Argument shifting
8459
8545
  if ( $.isPlainObject( rowSelector ) ) {
8460
8546
  // Indexes
8461
- if ( typeof rowSelector.row !== undefined ) {
8462
- opts = columnSelector;
8463
- columnSelector = null;
8464
- }
8465
- else {
8547
+ if ( rowSelector.row === undefined ) {
8548
+ // Selector options in first parameter
8466
8549
  opts = rowSelector;
8467
8550
  rowSelector = null;
8468
8551
  }
8552
+ else {
8553
+ // Cell index objects in first parameter
8554
+ opts = columnSelector;
8555
+ columnSelector = null;
8556
+ }
8469
8557
  }
8470
8558
  if ( $.isPlainObject( columnSelector ) ) {
8471
8559
  opts = columnSelector;
@@ -8826,7 +8914,10 @@
8826
8914
  var is = false;
8827
8915
 
8828
8916
  $.each( DataTable.settings, function (i, o) {
8829
- if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8917
+ var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
8918
+ var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
8919
+
8920
+ if ( o.nTable === t || head === t || foot === t ) {
8830
8921
  is = true;
8831
8922
  }
8832
8923
  } );
@@ -8853,11 +8944,22 @@
8853
8944
  */
8854
8945
  DataTable.tables = DataTable.fnTables = function ( visible )
8855
8946
  {
8856
- return $.map( DataTable.settings, function (o) {
8947
+ var api = false;
8948
+
8949
+ if ( $.isPlainObject( visible ) ) {
8950
+ api = visible.api;
8951
+ visible = visible.visible;
8952
+ }
8953
+
8954
+ var a = $.map( DataTable.settings, function (o) {
8857
8955
  if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8858
8956
  return o.nTable;
8859
8957
  }
8860
8958
  } );
8959
+
8960
+ return api ?
8961
+ new _Api( a ) :
8962
+ a;
8861
8963
  };
8862
8964
 
8863
8965
 
@@ -8954,6 +9056,12 @@
8954
9056
  } );
8955
9057
 
8956
9058
 
9059
+ _api_register( 'init()', function () {
9060
+ var ctx = this.context;
9061
+ return ctx.length ? ctx[0].oInit : null;
9062
+ } );
9063
+
9064
+
8957
9065
  _api_register( 'data()', function () {
8958
9066
  return this.iterator( 'table', function ( settings ) {
8959
9067
  return _pluck( settings.aoData, '_aData' );
@@ -9006,10 +9114,6 @@
9006
9114
  jqTable.append( tfoot );
9007
9115
  }
9008
9116
 
9009
- // Remove the DataTables generated nodes, events and classes
9010
- jqTable.detach();
9011
- jqWrapper.detach();
9012
-
9013
9117
  settings.aaSorting = [];
9014
9118
  settings.aaSortingFixed = [];
9015
9119
  _fnSortingClasses( settings );
@@ -9029,30 +9133,36 @@
9029
9133
  } );
9030
9134
  }
9031
9135
 
9032
- if ( ! remove && orig ) {
9033
- // insertBefore acts like appendChild if !arg[1]
9034
- orig.insertBefore( table, settings.nTableReinsertBefore );
9035
- }
9036
-
9037
9136
  // Add the TR elements back into the table in their original order
9038
9137
  jqTbody.children().detach();
9039
9138
  jqTbody.append( rows );
9040
9139
 
9041
- // Restore the width of the original table - was read from the style property,
9042
- // so we can restore directly to that
9043
- jqTable
9044
- .css( 'width', settings.sDestroyWidth )
9045
- .removeClass( classes.sTable );
9140
+ // Remove the DataTables generated nodes, events and classes
9141
+ var removedMethod = remove ? 'remove' : 'detach';
9142
+ jqTable[ removedMethod ]();
9143
+ jqWrapper[ removedMethod ]();
9046
9144
 
9047
- // If the were originally stripe classes - then we add them back here.
9048
- // Note this is not fool proof (for example if not all rows had stripe
9049
- // classes - but it's a good effort without getting carried away
9050
- ien = settings.asDestroyStripes.length;
9145
+ // If we need to reattach the table to the document
9146
+ if ( ! remove && orig ) {
9147
+ // insertBefore acts like appendChild if !arg[1]
9148
+ orig.insertBefore( table, settings.nTableReinsertBefore );
9051
9149
 
9052
- if ( ien ) {
9053
- jqTbody.children().each( function (i) {
9054
- $(this).addClass( settings.asDestroyStripes[i % ien] );
9055
- } );
9150
+ // Restore the width of the original table - was read from the style property,
9151
+ // so we can restore directly to that
9152
+ jqTable
9153
+ .css( 'width', settings.sDestroyWidth )
9154
+ .removeClass( classes.sTable );
9155
+
9156
+ // If the were originally stripe classes - then we add them back here.
9157
+ // Note this is not fool proof (for example if not all rows had stripe
9158
+ // classes - but it's a good effort without getting carried away
9159
+ ien = settings.asDestroyStripes.length;
9160
+
9161
+ if ( ien ) {
9162
+ jqTbody.children().each( function (i) {
9163
+ $(this).addClass( settings.asDestroyStripes[i % ien] );
9164
+ } );
9165
+ }
9056
9166
  }
9057
9167
 
9058
9168
  /* Remove the settings object from the settings array */
@@ -9063,6 +9173,48 @@
9063
9173
  } );
9064
9174
  } );
9065
9175
 
9176
+
9177
+ // Add the `every()` method for rows, columns and cells in a compact form
9178
+ $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9179
+ _api_register( type+'s().every()', function ( fn ) {
9180
+ return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9181
+ // Rows and columns:
9182
+ // arg1 - index
9183
+ // arg2 - table counter
9184
+ // arg3 - loop counter
9185
+ // arg4 - undefined
9186
+ // Cells:
9187
+ // arg1 - row index
9188
+ // arg2 - column index
9189
+ // arg3 - table counter
9190
+ // arg4 - loop counter
9191
+ fn.call(
9192
+ new _Api( settings )[ type ]( arg1, type==='cell' ? arg2 : undefined ),
9193
+ arg1, arg2, arg3, arg4
9194
+ );
9195
+ } );
9196
+ } );
9197
+ } );
9198
+
9199
+
9200
+ // i18n method for extensions to be able to use the language object from the
9201
+ // DataTable
9202
+ _api_register( 'i18n()', function ( token, def, plural ) {
9203
+ var ctx = this.context[0];
9204
+ var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9205
+
9206
+ if ( resolved === undefined ) {
9207
+ resolved = def;
9208
+ }
9209
+
9210
+ if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9211
+ resolved = resolved[ plural ] !== undefined ?
9212
+ resolved[ plural ] :
9213
+ resolved._;
9214
+ }
9215
+
9216
+ return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9217
+ } );
9066
9218
 
9067
9219
  /**
9068
9220
  * Version string for plug-ins to check compatibility. Allowed format is
@@ -9072,7 +9224,7 @@
9072
9224
  * @type string
9073
9225
  * @default Version number
9074
9226
  */
9075
- DataTable.version = "1.10.4";
9227
+ DataTable.version = "1.10.8";
9076
9228
 
9077
9229
  /**
9078
9230
  * Private data store, containing all of the settings objects that are
@@ -9224,7 +9376,16 @@
9224
9376
  * @default null
9225
9377
  * @private
9226
9378
  */
9227
- "src": null
9379
+ "src": null,
9380
+
9381
+ /**
9382
+ * Index in the aoData array. This saves an indexOf lookup when we have the
9383
+ * object, but want to know the index
9384
+ * @type integer
9385
+ * @default -1
9386
+ * @private
9387
+ */
9388
+ "idx": -1
9228
9389
  };
9229
9390
 
9230
9391
 
@@ -11665,7 +11826,18 @@
11665
11826
  * @name DataTable.defaults.renderer
11666
11827
  *
11667
11828
  */
11668
- "renderer": null
11829
+ "renderer": null,
11830
+
11831
+
11832
+ /**
11833
+ * Set the data property name that DataTables should use to get a row's id
11834
+ * to set as the `id` property in the node.
11835
+ * @type string
11836
+ * @default DT_RowId
11837
+ *
11838
+ * @name DataTable.defaults.rowId
11839
+ */
11840
+ "rowId": "DT_RowId"
11669
11841
  };
11670
11842
 
11671
11843
  _fnHungarianMap( DataTable.defaults );
@@ -12764,7 +12936,14 @@
12764
12936
  * @type boolean
12765
12937
  * @default false
12766
12938
  */
12767
- "bScrollbarLeft": false
12939
+ "bScrollbarLeft": false,
12940
+
12941
+ /**
12942
+ * Flag for if `getBoundingClientRect` is fully supported or not
12943
+ * @type boolean
12944
+ * @default false
12945
+ */
12946
+ "bBounding": false
12768
12947
  },
12769
12948
 
12770
12949
 
@@ -12809,6 +12988,13 @@
12809
12988
  */
12810
12989
  "aiDisplayMaster": [],
12811
12990
 
12991
+ /**
12992
+ * Map of row ids to data indexes
12993
+ * @type object
12994
+ * @default {}
12995
+ */
12996
+ "aIds": {},
12997
+
12812
12998
  /**
12813
12999
  * Store information about each column that is in use
12814
13000
  * @type array
@@ -13417,7 +13603,21 @@
13417
13603
  * @type object
13418
13604
  * @default {}
13419
13605
  */
13420
- "oPlugins": {}
13606
+ "oPlugins": {},
13607
+
13608
+ /**
13609
+ * Function used to get a row's id from the row's data
13610
+ * @type function
13611
+ * @default null
13612
+ */
13613
+ "rowIdFn": null,
13614
+
13615
+ /**
13616
+ * Data location where to store a row's id
13617
+ * @type string
13618
+ * @default null
13619
+ */
13620
+ "rowId": null
13421
13621
  };
13422
13622
 
13423
13623
  /**
@@ -13446,6 +13646,17 @@
13446
13646
  * @namespace
13447
13647
  */
13448
13648
  DataTable.ext = _ext = {
13649
+ /**
13650
+ * Buttons. For use with the Buttons extension for DataTables. This is
13651
+ * defined here so other extensions can define buttons regardless of load
13652
+ * order. It is _not_ used by DataTables core.
13653
+ *
13654
+ * @type object
13655
+ * @default {}
13656
+ */
13657
+ buttons: {},
13658
+
13659
+
13449
13660
  /**
13450
13661
  * Element class names
13451
13662
  *
@@ -13458,10 +13669,10 @@
13458
13669
  /**
13459
13670
  * Error reporting.
13460
13671
  *
13461
- * How should DataTables report an error. Can take the value 'alert' or
13462
- * 'throw'
13672
+ * How should DataTables report an error. Can take the value 'alert',
13673
+ * 'throw', 'none' or a function.
13463
13674
  *
13464
- * @type string
13675
+ * @type string|function
13465
13676
  * @default alert
13466
13677
  */
13467
13678
  errMode: "alert",
@@ -13568,6 +13779,37 @@
13568
13779
  search: [],
13569
13780
 
13570
13781
 
13782
+ /**
13783
+ * Selector extensions
13784
+ *
13785
+ * The `selector` option can be used to extend the options available for the
13786
+ * selector modifier options (`selector-modifier` object data type) that
13787
+ * each of the three built in selector types offer (row, column and cell +
13788
+ * their plural counterparts). For example the Select extension uses this
13789
+ * mechanism to provide an option to select only rows, columns and cells
13790
+ * that have been marked as selected by the end user (`{selected: true}`),
13791
+ * which can be used in conjunction with the existing built in selector
13792
+ * options.
13793
+ *
13794
+ * Each property is an array to which functions can be pushed. The functions
13795
+ * take three attributes:
13796
+ *
13797
+ * * Settings object for the host table
13798
+ * * Options object (`selector-modifier` object type)
13799
+ * * Array of selected item indexes
13800
+ *
13801
+ * The return is an array of the resulting item indexes after the custom
13802
+ * selector has been applied.
13803
+ *
13804
+ * @type object
13805
+ */
13806
+ selector: {
13807
+ cell: [],
13808
+ column: [],
13809
+ row: []
13810
+ },
13811
+
13812
+
13571
13813
  /**
13572
13814
  * Internal functions, exposed for used in plug-ins.
13573
13815
  *
@@ -14061,7 +14303,7 @@
14061
14303
  numbers.splice( 0, 0, 0 );
14062
14304
  }
14063
14305
  else {
14064
- numbers = _range( page-1, page+2 );
14306
+ numbers = _range( page-half+2, page+half-1 );
14065
14307
  numbers.push( 'ellipsis' );
14066
14308
  numbers.push( pages-1 );
14067
14309
  numbers.splice( 0, 0, 'ellipsis' );
@@ -14082,6 +14324,10 @@
14082
14324
  return [ 'first', 'previous', 'next', 'last' ];
14083
14325
  },
14084
14326
 
14327
+ numbers: function ( page, pages ) {
14328
+ return [ _numbers(page, pages) ];
14329
+ },
14330
+
14085
14331
  simple_numbers: function ( page, pages ) {
14086
14332
  return [ 'previous', _numbers(page, pages), 'next' ];
14087
14333
  },
@@ -14092,6 +14338,8 @@
14092
14338
 
14093
14339
  // For testing and plug-ins to use
14094
14340
  _numbers: _numbers,
14341
+
14342
+ // Number of number buttons (including ellipsis) to show. _Must be odd!_
14095
14343
  numbers_length: 7
14096
14344
  } );
14097
14345
 
@@ -14118,12 +14366,12 @@
14118
14366
  attach( inner, button );
14119
14367
  }
14120
14368
  else {
14121
- btnDisplay = '';
14369
+ btnDisplay = null;
14122
14370
  btnClass = '';
14123
14371
 
14124
14372
  switch ( button ) {
14125
14373
  case 'ellipsis':
14126
- container.append('<span>&hellip;</span>');
14374
+ container.append('<span class="ellipsis">&#x2026;</span>');
14127
14375
  break;
14128
14376
 
14129
14377
  case 'first':
@@ -14157,7 +14405,7 @@
14157
14405
  break;
14158
14406
  }
14159
14407
 
14160
- if ( btnDisplay ) {
14408
+ if ( btnDisplay !== null ) {
14161
14409
  node = $('<a>', {
14162
14410
  'class': classes.sPageButton+' '+btnClass,
14163
14411
  'aria-controls': settings.sTableId,
@@ -14183,20 +14431,22 @@
14183
14431
  // IE9 throws an 'unknown error' if document.activeElement is used
14184
14432
  // inside an iframe or frame. Try / catch the error. Not good for
14185
14433
  // accessibility, but neither are frames.
14434
+ var activeEl;
14435
+
14186
14436
  try {
14187
14437
  // Because this approach is destroying and recreating the paging
14188
14438
  // elements, focus is lost on the select button which is bad for
14189
14439
  // accessibility. So we want to restore focus once the draw has
14190
14440
  // completed
14191
- var activeEl = $(document.activeElement).data('dt-idx');
14441
+ activeEl = $(host).find(document.activeElement).data('dt-idx');
14442
+ }
14443
+ catch (e) {}
14192
14444
 
14193
- attach( $(host).empty(), buttons );
14445
+ attach( $(host).empty(), buttons );
14194
14446
 
14195
- if ( activeEl !== null ) {
14196
- $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14197
- }
14447
+ if ( activeEl ) {
14448
+ $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14198
14449
  }
14199
- catch (e) {}
14200
14450
  }
14201
14451
  }
14202
14452
  } );
@@ -14486,11 +14736,12 @@
14486
14736
  *
14487
14737
  * * `number` - Will format numeric data (defined by `columns.data`) for
14488
14738
  * display, retaining the original unformatted data for sorting and filtering.
14489
- * It takes 4 parameters:
14739
+ * It takes 5 parameters:
14490
14740
  * * `string` - Thousands grouping separator
14491
14741
  * * `string` - Decimal point indicator
14492
14742
  * * `integer` - Number of decimal points to show
14493
14743
  * * `string` (optional) - Prefix.
14744
+ * * `string` (optional) - Postfix (/suffix).
14494
14745
  *
14495
14746
  * @example
14496
14747
  * // Column definition using the number renderer
@@ -14502,9 +14753,13 @@
14502
14753
  * @namespace
14503
14754
  */
14504
14755
  DataTable.render = {
14505
- number: function ( thousands, decimal, precision, prefix ) {
14756
+ number: function ( thousands, decimal, precision, prefix, postfix ) {
14506
14757
  return {
14507
14758
  display: function ( d ) {
14759
+ if ( typeof d !== 'number' && typeof d !== 'string' ) {
14760
+ return d;
14761
+ }
14762
+
14508
14763
  var negative = d < 0 ? '-' : '';
14509
14764
  d = Math.abs( parseFloat( d ) );
14510
14765
 
@@ -14517,7 +14772,8 @@
14517
14772
  intPart.toString().replace(
14518
14773
  /\B(?=(\d{3})+(?!\d))/g, thousands
14519
14774
  ) +
14520
- floatPart;
14775
+ floatPart +
14776
+ (postfix||'');
14521
14777
  }
14522
14778
  };
14523
14779
  }
@@ -14621,7 +14877,6 @@
14621
14877
  _fnCalculateColumnWidths: _fnCalculateColumnWidths,
14622
14878
  _fnThrottle: _fnThrottle,
14623
14879
  _fnConvertToWidth: _fnConvertToWidth,
14624
- _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14625
14880
  _fnGetWidestNode: _fnGetWidestNode,
14626
14881
  _fnGetMaxLenString: _fnGetMaxLenString,
14627
14882
  _fnStringToCss: _fnStringToCss,