jquery-datatables-rails 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js +64 -29
  3. data/app/assets/javascripts/dataTables/extras/dataTables.autoFill.js +806 -648
  4. data/app/assets/javascripts/dataTables/extras/dataTables.buttons.js +1607 -0
  5. data/app/assets/javascripts/dataTables/extras/dataTables.colReorder.js +220 -267
  6. data/app/assets/javascripts/dataTables/extras/dataTables.fixedColumns.js +164 -69
  7. data/app/assets/javascripts/dataTables/extras/dataTables.fixedHeader.js +469 -870
  8. data/app/assets/javascripts/dataTables/extras/dataTables.keyTable.js +636 -972
  9. data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +472 -187
  10. data/app/assets/javascripts/dataTables/extras/dataTables.rowReorder.js +619 -0
  11. data/app/assets/javascripts/dataTables/extras/dataTables.scroller.js +146 -111
  12. data/app/assets/javascripts/dataTables/extras/dataTables.select.js +1038 -0
  13. data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnGetColumnData.js +0 -0
  14. data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnReloadAjax.js +0 -0
  15. data/app/assets/javascripts/dataTables/jquery.dataTables.foundation.js +37 -61
  16. data/app/assets/javascripts/dataTables/jquery.dataTables.js +720 -387
  17. data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.ipAddress.js +44 -0
  18. data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.numbersHtml.js +0 -0
  19. data/app/assets/javascripts/dataTables/jquery.dataTables.typeDetection.numbersHtml.js +0 -0
  20. data/app/assets/stylesheets/dataTables/jquery.dataTables.scss +34 -66
  21. data/app/assets/stylesheets/dataTables/src/demo_table.css +1 -1
  22. data/app/assets/stylesheets/dataTables/src/demo_table_jui.css.scss +4 -4
  23. data/lib/jquery/datatables/rails/version.rb +1 -1
  24. metadata +24 -19
@@ -1,5 +1,5 @@
1
1
  /*! DataTables Foundation integration
2
- * ©2011-2014 SpryMedia Ltd - datatables.net/license
2
+ * ©2011-2015 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
@@ -10,14 +10,39 @@
10
10
  * controls using Foundation. See http://datatables.net/manual/styling/foundation
11
11
  * for further information.
12
12
  */
13
- (function(window, document, undefined){
13
+ (function( factory ){
14
+ if ( typeof define === 'function' && define.amd ) {
15
+ // AMD
16
+ define( ['jquery', 'datatables.net'], function ( $ ) {
17
+ return factory( $, window, document );
18
+ } );
19
+ }
20
+ else if ( typeof exports === 'object' ) {
21
+ // CommonJS
22
+ module.exports = function (root, $) {
23
+ if ( ! root ) {
24
+ root = window;
25
+ }
26
+
27
+ if ( ! $ || ! $.fn.dataTable ) {
28
+ $ = require('datatables.net')(root, $).$;
29
+ }
14
30
 
15
- var factory = function( $, DataTable ) {
16
- "use strict";
31
+ return factory( $, root, root.document );
32
+ };
33
+ }
34
+ else {
35
+ // Browser
36
+ factory( jQuery, window, document );
37
+ }
38
+ }(function( $, window, document, undefined ) {
39
+ 'use strict';
40
+ var DataTable = $.fn.dataTable;
17
41
 
18
42
 
19
43
  $.extend( DataTable.ext.classes, {
20
- sWrapper: "dataTables_wrapper dt-foundation"
44
+ sWrapper: "dataTables_wrapper dt-foundation",
45
+ sProcessing: "dataTables_processing panel"
21
46
  } );
22
47
 
23
48
 
@@ -36,14 +61,15 @@ DataTable.ext.renderer.pageButton.foundation = function ( settings, host, idx, b
36
61
  var api = new DataTable.Api( settings );
37
62
  var classes = settings.oClasses;
38
63
  var lang = settings.oLanguage.oPaginate;
64
+ var aria = settings.oLanguage.oAria.paginate || {};
39
65
  var btnDisplay, btnClass;
40
66
 
41
67
  var attach = function( container, buttons ) {
42
68
  var i, ien, node, button;
43
69
  var clickHandler = function ( e ) {
44
70
  e.preventDefault();
45
- if ( e.data.action !== 'ellipsis' ) {
46
- api.page( e.data.action ).draw( false );
71
+ if ( !$(e.currentTarget).hasClass('unavailable') && api.page() != e.data.action ) {
72
+ api.page( e.data.action ).draw( 'page' );
47
73
  }
48
74
  };
49
75
 
@@ -59,7 +85,7 @@ DataTable.ext.renderer.pageButton.foundation = function ( settings, host, idx, b
59
85
 
60
86
  switch ( button ) {
61
87
  case 'ellipsis':
62
- btnDisplay = '…';
88
+ btnDisplay = '…';
63
89
  btnClass = 'unavailable';
64
90
  break;
65
91
 
@@ -98,6 +124,7 @@ DataTable.ext.renderer.pageButton.foundation = function ( settings, host, idx, b
98
124
  node = $('<li>', {
99
125
  'class': classes.sPageButton+' '+btnClass,
100
126
  'aria-controls': settings.sTableId,
127
+ 'aria-label': aria[ button ],
101
128
  'tabindex': settings.iTabIndex,
102
129
  'id': idx === 0 && typeof button === 'string' ?
103
130
  settings.sTableId +'_'+ button :
@@ -125,56 +152,5 @@ DataTable.ext.renderer.pageButton.foundation = function ( settings, host, idx, b
125
152
  };
126
153
 
127
154
 
128
- /*
129
- * TableTools Foundation compatibility
130
- * Required TableTools 2.1+
131
- */
132
- if ( DataTable.TableTools ) {
133
- // Set the classes that TableTools uses to something suitable for Foundation
134
- $.extend( true, DataTable.TableTools.classes, {
135
- "container": "DTTT button-group",
136
- "buttons": {
137
- "normal": "button small",
138
- "disabled": "disabled"
139
- },
140
- "collection": {
141
- "container": "DTTT_dropdown dropdown-menu",
142
- "buttons": {
143
- "normal": "",
144
- "disabled": "disabled"
145
- }
146
- },
147
- "select": {
148
- "row": "active"
149
- }
150
- } );
151
-
152
- // Have the collection use a bootstrap compatible dropdown
153
- $.extend( true, DataTable.TableTools.DEFAULTS.oTags, {
154
- "collection": {
155
- "container": "ul",
156
- "button": "li",
157
- "liner": "a"
158
- }
159
- } );
160
- }
161
-
162
- }; // /factory
163
-
164
-
165
- // Define as an AMD module if possible
166
- if ( typeof define === 'function' && define.amd ) {
167
- define( ['jquery', 'datatables'], factory );
168
- }
169
- else if ( typeof exports === 'object' ) {
170
- // Node/CommonJS
171
- factory( require('jquery'), require('datatables') );
172
- }
173
- else if ( jQuery ) {
174
- // Otherwise simply initialise as normal, stopping multiple evaluation
175
- factory( jQuery, jQuery.fn.dataTable );
176
- }
177
-
178
-
179
- })(window, document);
180
-
155
+ return DataTable;
156
+ }));
@@ -1,15 +1,15 @@
1
- /*! DataTables 1.10.6
2
- * ©2008-2014 SpryMedia Ltd - datatables.net/license
1
+ /*! DataTables 1.10.10
2
+ * ©2008-2015 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.6
8
+ * @version 1.10.10
9
9
  * @file jquery.dataTables.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
12
- * @copyright Copyright 2008-2014 SpryMedia Ltd.
12
+ * @copyright Copyright 2008-2015 SpryMedia Ltd.
13
13
  *
14
14
  * This source file is free software, available under the following license:
15
15
  * MIT license - http://datatables.net/license
@@ -22,28 +22,41 @@
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*/
26
-
27
- (/** @lends <global> */function( window, document, undefined ) {
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,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
28
26
 
29
27
  (function( factory ) {
30
28
  "use strict";
31
29
 
32
30
  if ( typeof define === 'function' && define.amd ) {
33
- // Define as an AMD module if possible
34
- define( 'datatables', ['jquery'], factory );
31
+ // AMD
32
+ define( ['jquery'], function ( $ ) {
33
+ return factory( $, window, document );
34
+ } );
35
35
  }
36
- else if ( typeof exports === 'object' ) {
37
- // Node/CommonJS
38
- module.exports = factory( require( 'jquery' ) );
39
- }
40
- else if ( jQuery && !jQuery.fn.dataTable ) {
41
- // Define using browser globals otherwise
42
- // Prevent multiple instantiations if the script is loaded twice
43
- factory( jQuery );
36
+ else if ( typeof exports === 'object' ) {
37
+ // CommonJS
38
+ module.exports = function (root, $) {
39
+ if ( ! root ) {
40
+ // CommonJS environments without a window global must pass a
41
+ // root. This will give an error otherwise
42
+ root = window;
43
+ }
44
+
45
+ if ( ! $ ) {
46
+ $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
47
+ require('jquery') :
48
+ require('jquery')( root );
49
+ }
50
+
51
+ return factory( $, root, root.document );
52
+ };
53
+ }
54
+ else {
55
+ // Browser
56
+ factory( jQuery, window, document );
44
57
  }
45
58
  }
46
- (/** @lends <global> */function( $ ) {
59
+ (function( $, window, document, undefined ) {
47
60
  "use strict";
48
61
 
49
62
  /**
@@ -467,6 +480,14 @@
467
480
  _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
468
481
  _fnCompatMap( init, 'searching', 'bFilter' );
469
482
 
483
+ // Boolean initialisation of x-scrolling
484
+ if ( typeof init.sScrollX === 'boolean' ) {
485
+ init.sScrollX = init.sScrollX ? '100%' : '';
486
+ }
487
+ if ( typeof init.scrollX === 'boolean' ) {
488
+ init.scrollX = init.scrollX ? '100%' : '';
489
+ }
490
+
470
491
  // Column search objects are in an array, so it needs to be converted
471
492
  // element by element
472
493
  var searchCols = init.aoSearchCols;
@@ -509,49 +530,75 @@
509
530
  */
510
531
  function _fnBrowserDetect( settings )
511
532
  {
512
- var browser = settings.oBrowser;
533
+ // We don't need to do this every time DataTables is constructed, the values
534
+ // calculated are specific to the browser and OS configuration which we
535
+ // don't expect to change between initialisations
536
+ if ( ! DataTable.__browser ) {
537
+ var browser = {};
538
+ DataTable.__browser = browser;
539
+
540
+ // Scrolling feature / quirks detection
541
+ var n = $('<div/>')
542
+ .css( {
543
+ position: 'fixed',
544
+ top: 0,
545
+ left: 0,
546
+ height: 1,
547
+ width: 1,
548
+ overflow: 'hidden'
549
+ } )
550
+ .append(
551
+ $('<div/>')
552
+ .css( {
553
+ position: 'absolute',
554
+ top: 1,
555
+ left: 1,
556
+ width: 100,
557
+ overflow: 'scroll'
558
+ } )
559
+ .append(
560
+ $('<div/>')
561
+ .css( {
562
+ width: '100%',
563
+ height: 10
564
+ } )
565
+ )
566
+ )
567
+ .appendTo( 'body' );
513
568
 
514
- // Scrolling feature / quirks detection
515
- var n = $('<div/>')
516
- .css( {
517
- position: 'absolute',
518
- top: 0,
519
- left: 0,
520
- height: 1,
521
- width: 1,
522
- overflow: 'hidden'
523
- } )
524
- .append(
525
- $('<div/>')
526
- .css( {
527
- position: 'absolute',
528
- top: 1,
529
- left: 1,
530
- width: 100,
531
- overflow: 'scroll'
532
- } )
533
- .append(
534
- $('<div class="test"/>')
535
- .css( {
536
- width: '100%',
537
- height: 10
538
- } )
539
- )
540
- )
541
- .appendTo( 'body' );
569
+ var outer = n.children();
570
+ var inner = outer.children();
542
571
 
543
- var test = n.find('.test');
572
+ // Numbers below, in order, are:
573
+ // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
574
+ //
575
+ // IE6 XP: 100 100 100 83
576
+ // IE7 Vista: 100 100 100 83
577
+ // IE 8+ Windows: 83 83 100 83
578
+ // Evergreen Windows: 83 83 100 83
579
+ // Evergreen Mac with scrollbars: 85 85 100 85
580
+ // Evergreen Mac without scrollbars: 100 100 100 100
544
581
 
545
- // IE6/7 will oversize a width 100% element inside a scrolling element, to
546
- // include the width of the scrollbar, while other browsers ensure the inner
547
- // element is contained without forcing scrolling
548
- browser.bScrollOversize = test[0].offsetWidth === 100;
582
+ // Get scrollbar width
583
+ browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
549
584
 
550
- // In rtl text layout, some browsers (most, but not all) will place the
551
- // scrollbar on the left, rather than the right.
552
- browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
585
+ // IE6/7 will oversize a width 100% element inside a scrolling element, to
586
+ // include the width of the scrollbar, while other browsers ensure the inner
587
+ // element is contained without forcing scrolling
588
+ browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
553
589
 
554
- n.remove();
590
+ // In rtl text layout, some browsers (most, but not all) will place the
591
+ // scrollbar on the left, rather than the right.
592
+ browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
593
+
594
+ // IE8- don't provide height and width for getBoundingClientRect
595
+ browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
596
+
597
+ n.remove();
598
+ }
599
+
600
+ $.extend( settings.oBrowser, DataTable.__browser );
601
+ settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
555
602
  }
556
603
 
557
604
 
@@ -1008,7 +1055,8 @@
1008
1055
  /* Create the object for storing information about this new row */
1009
1056
  var iRow = oSettings.aoData.length;
1010
1057
  var oData = $.extend( true, {}, DataTable.models.oRow, {
1011
- src: nTr ? 'dom' : 'data'
1058
+ src: nTr ? 'dom' : 'data',
1059
+ idx: iRow
1012
1060
  } );
1013
1061
 
1014
1062
  oData._aData = aDataIn;
@@ -1017,20 +1065,21 @@
1017
1065
  /* Create the cells */
1018
1066
  var nTd, sThisType;
1019
1067
  var columns = oSettings.aoColumns;
1068
+
1069
+ // Invalidate the column types as the new data needs to be revalidated
1020
1070
  for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
1021
1071
  {
1022
- // When working with a row, the data source object must be populated. In
1023
- // all other cases, the data source object is already populated, so we
1024
- // don't overwrite it, which might break bindings etc
1025
- if ( nTr ) {
1026
- _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
1027
- }
1028
1072
  columns[i].sType = null;
1029
1073
  }
1030
1074
 
1031
1075
  /* Add to the display array */
1032
1076
  oSettings.aiDisplayMaster.push( iRow );
1033
1077
 
1078
+ var id = oSettings.rowIdFn( aDataIn );
1079
+ if ( id !== undefined ) {
1080
+ oSettings.aIds[ id ] = oData;
1081
+ }
1082
+
1034
1083
  /* Create the DOM information, or register it if already present */
1035
1084
  if ( nTr || ! oSettings.oFeatures.bDeferRender )
1036
1085
  {
@@ -1119,7 +1168,7 @@
1119
1168
  if ( settings.iDrawError != draw && defaultContent === null ) {
1120
1169
  _fnLog( settings, 0, "Requested unknown parameter "+
1121
1170
  (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1122
- " for row "+rowIdx, 4 );
1171
+ " for row "+rowIdx+", column "+colIdx, 4 );
1123
1172
  settings.iDrawError = draw;
1124
1173
  }
1125
1174
  return defaultContent;
@@ -1174,7 +1223,7 @@
1174
1223
  */
1175
1224
  function _fnSplitObjNotation( str )
1176
1225
  {
1177
- return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1226
+ return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
1178
1227
  return s.replace(/\\./g, '.');
1179
1228
  } );
1180
1229
  }
@@ -1257,8 +1306,10 @@
1257
1306
  innerSrc = a.join('.');
1258
1307
 
1259
1308
  // Traverse each entry in the array getting the properties requested
1260
- for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1261
- out.push( fetchData( data[j], type, innerSrc ) );
1309
+ if ( $.isArray( data ) ) {
1310
+ for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1311
+ out.push( fetchData( data[j], type, innerSrc ) );
1312
+ }
1262
1313
  }
1263
1314
 
1264
1315
  // If a string is given in between the array notation indicators, that
@@ -1358,11 +1409,21 @@
1358
1409
  innerSrc = b.join('.');
1359
1410
 
1360
1411
  // Traverse each entry in the array setting the properties requested
1361
- for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1412
+ if ( $.isArray( val ) )
1362
1413
  {
1363
- o = {};
1364
- setData( o, val[j], innerSrc );
1365
- data[ a[i] ].push( o );
1414
+ for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1415
+ {
1416
+ o = {};
1417
+ setData( o, val[j], innerSrc );
1418
+ data[ a[i] ].push( o );
1419
+ }
1420
+ }
1421
+ else
1422
+ {
1423
+ // We've been asked to save data to an array, but it
1424
+ // isn't array data to be saved. Best that can be done
1425
+ // is to just save the value.
1426
+ data[ a[i] ] = val;
1366
1427
  }
1367
1428
 
1368
1429
  // The inner call to setData has already traversed through the remainder
@@ -1435,6 +1496,7 @@
1435
1496
  settings.aoData.length = 0;
1436
1497
  settings.aiDisplayMaster.length = 0;
1437
1498
  settings.aiDisplay.length = 0;
1499
+ settings.aIds = {};
1438
1500
  }
1439
1501
 
1440
1502
 
@@ -1540,7 +1602,7 @@
1540
1602
  }
1541
1603
 
1542
1604
  // Update DataTables special `DT_*` attributes for the row
1543
- _fnRowAttributes( row );
1605
+ _fnRowAttributes( settings, row );
1544
1606
  }
1545
1607
  }
1546
1608
 
@@ -1572,7 +1634,11 @@
1572
1634
  objectRead = settings._rowReadObject;
1573
1635
 
1574
1636
  // Allow the data object to be passed in, or construct
1575
- d = d || objectRead ? {} : [];
1637
+ d = d !== undefined ?
1638
+ d :
1639
+ objectRead ?
1640
+ {} :
1641
+ [];
1576
1642
 
1577
1643
  var attr = function ( str, td ) {
1578
1644
  if ( typeof str === 'string' ) {
@@ -1635,12 +1701,23 @@
1635
1701
  else {
1636
1702
  // Existing row object passed in
1637
1703
  tds = row.anCells;
1638
-
1704
+
1639
1705
  for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1640
1706
  cellProcess( tds[j] );
1641
1707
  }
1642
1708
  }
1643
1709
 
1710
+ // Read the ID from the DOM if present
1711
+ var rowNode = row.firstChild ? row : row.nTr;
1712
+
1713
+ if ( rowNode ) {
1714
+ var id = rowNode.getAttribute( 'id' );
1715
+
1716
+ if ( id ) {
1717
+ _fnSetObjectDataFn( settings.rowId )( d, id );
1718
+ }
1719
+ }
1720
+
1644
1721
  return {
1645
1722
  data: d,
1646
1723
  cells: tds
@@ -1678,7 +1755,7 @@
1678
1755
  nTr._DT_RowIndex = iRow;
1679
1756
 
1680
1757
  /* Special parameters can be given by the data source to be used on the row */
1681
- _fnRowAttributes( row );
1758
+ _fnRowAttributes( oSettings, row );
1682
1759
 
1683
1760
  /* Process each column */
1684
1761
  for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
@@ -1686,6 +1763,11 @@
1686
1763
  oCol = oSettings.aoColumns[i];
1687
1764
 
1688
1765
  nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1766
+ nTd._DT_CellIndex = {
1767
+ row: iRow,
1768
+ column: i
1769
+ };
1770
+
1689
1771
  cells.push( nTd );
1690
1772
 
1691
1773
  // Need to create the HTML if new, or if a rendering function is defined
@@ -1730,17 +1812,20 @@
1730
1812
  /**
1731
1813
  * Add attributes to a row based on the special `DT_*` parameters in a data
1732
1814
  * source object.
1815
+ * @param {object} settings DataTables settings object
1733
1816
  * @param {object} DataTables row object for the row to be modified
1734
1817
  * @memberof DataTable#oApi
1735
1818
  */
1736
- function _fnRowAttributes( row )
1819
+ function _fnRowAttributes( settings, row )
1737
1820
  {
1738
1821
  var tr = row.nTr;
1739
1822
  var data = row._aData;
1740
1823
 
1741
1824
  if ( tr ) {
1742
- if ( data.DT_RowId ) {
1743
- tr.id = data.DT_RowId;
1825
+ var id = settings.rowIdFn( data );
1826
+
1827
+ if ( id ) {
1828
+ tr.id = id;
1744
1829
  }
1745
1830
 
1746
1831
  if ( data.DT_RowClass ) {
@@ -1805,7 +1890,7 @@
1805
1890
  }
1806
1891
  }
1807
1892
 
1808
- if ( column.sTitle != cell.html() ) {
1893
+ if ( column.sTitle != cell[0].innerHTML ) {
1809
1894
  cell.html( column.sTitle );
1810
1895
  }
1811
1896
 
@@ -2277,6 +2362,7 @@
2277
2362
 
2278
2363
  /* Built our DOM structure - replace the holding div with what we want */
2279
2364
  holding.replaceWith( insert );
2365
+ oSettings.nHolding = null;
2280
2366
  }
2281
2367
 
2282
2368
 
@@ -2435,7 +2521,7 @@
2435
2521
  var ajax = oSettings.ajax;
2436
2522
  var instance = oSettings.oInstance;
2437
2523
  var callback = function ( json ) {
2438
- _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2524
+ _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
2439
2525
  fn( json );
2440
2526
  };
2441
2527
 
@@ -2462,7 +2548,7 @@
2462
2548
  "success": function (json) {
2463
2549
  var error = json.error || json.sError;
2464
2550
  if ( error ) {
2465
- oSettings.oApi._fnLog( oSettings, 0, error );
2551
+ _fnLog( oSettings, 0, error );
2466
2552
  }
2467
2553
 
2468
2554
  oSettings.json = json;
@@ -2472,13 +2558,15 @@
2472
2558
  "cache": false,
2473
2559
  "type": oSettings.sServerMethod,
2474
2560
  "error": function (xhr, error, thrown) {
2475
- var log = oSettings.oApi._fnLog;
2561
+ var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
2476
2562
 
2477
- if ( error == "parsererror" ) {
2478
- log( oSettings, 0, 'Invalid JSON response', 1 );
2479
- }
2480
- else if ( xhr.readyState === 4 ) {
2481
- log( oSettings, 0, 'Ajax error', 7 );
2563
+ if ( $.inArray( true, ret ) === -1 ) {
2564
+ if ( error == "parsererror" ) {
2565
+ _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
2566
+ }
2567
+ else if ( xhr.readyState === 4 ) {
2568
+ _fnLog( oSettings, 0, 'Ajax error', 7 );
2569
+ }
2482
2570
  }
2483
2571
 
2484
2572
  _fnProcessingDisplay( oSettings, false );
@@ -2907,7 +2995,7 @@
2907
2995
  // So the array reference doesn't break set the results into the
2908
2996
  // existing array
2909
2997
  displayRows.length = 0;
2910
- displayRows.push.apply( displayRows, rows );
2998
+ $.merge( displayRows, rows );
2911
2999
  }
2912
3000
  }
2913
3001
 
@@ -3018,7 +3106,7 @@
3018
3106
  *
3019
3107
  * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
3020
3108
  */
3021
- var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
3109
+ var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
3022
3110
  if ( word.charAt(0) === '"' ) {
3023
3111
  var m = word.match( /^"(.*)"$/ );
3024
3112
  word = m ? m[1] : word;
@@ -3263,6 +3351,7 @@
3263
3351
  var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3264
3352
  var columns = settings.aoColumns, column;
3265
3353
  var features = settings.oFeatures;
3354
+ var deferLoading = settings.bDeferLoading; // value modified by the draw
3266
3355
 
3267
3356
  /* Ensure that the table data is fully initialised */
3268
3357
  if ( ! settings.bInitialised ) {
@@ -3294,6 +3383,8 @@
3294
3383
  }
3295
3384
  }
3296
3385
 
3386
+ _fnCallbackFire( settings, null, 'preInit', [settings] );
3387
+
3297
3388
  // If there is default sorting required - let's do it. The sort function
3298
3389
  // will do the drawing for us. Otherwise we draw the table regardless of the
3299
3390
  // Ajax source - this allows the table to look initialised for Ajax sourcing
@@ -3302,7 +3393,7 @@
3302
3393
 
3303
3394
  // Server-side processing init complete is done by _fnAjaxUpdateDraw
3304
3395
  var dataSrc = _fnDataSource( settings );
3305
- if ( dataSrc != 'ssp' ) {
3396
+ if ( dataSrc != 'ssp' || deferLoading ) {
3306
3397
  // if there is an ajax source load the data
3307
3398
  if ( dataSrc == 'ajax' ) {
3308
3399
  _fnBuildAjax( settings, [], function(json) {
@@ -3343,12 +3434,13 @@
3343
3434
  {
3344
3435
  settings._bInitComplete = true;
3345
3436
 
3346
- // On an Ajax load we now have data and therefore want to apply the column
3347
- // sizing
3348
- if ( json ) {
3437
+ // When data was added after the initialisation (data or Ajax) we need to
3438
+ // calculate the column sizing
3439
+ if ( json || settings.oInit.aaData ) {
3349
3440
  _fnAdjustColumnSizing( settings );
3350
3441
  }
3351
3442
 
3443
+ _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
3352
3444
  _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3353
3445
  }
3354
3446
 
@@ -3625,17 +3717,6 @@
3625
3717
  return !s ? null : _fnStringToCss( s );
3626
3718
  };
3627
3719
 
3628
- // This is fairly messy, but with x scrolling enabled, if the table has a
3629
- // width attribute, regardless of any width applied using the column width
3630
- // options, the browser will shrink or grow the table as needed to fit into
3631
- // that 100%. That would make the width options useless. So we remove it.
3632
- // This is okay, under the assumption that width:100% is applied to the
3633
- // table in CSS (it is in the default stylesheet) which will set the table
3634
- // width as appropriate (the attribute and css behave differently...)
3635
- if ( scroll.sX && table.attr('width') === '100%' ) {
3636
- table.removeAttr('width');
3637
- }
3638
-
3639
3720
  if ( ! footer.length ) {
3640
3721
  footer = null;
3641
3722
  }
@@ -3685,8 +3766,8 @@
3685
3766
  .append(
3686
3767
  $(_div, { 'class': classes.sScrollBody } )
3687
3768
  .css( {
3769
+ position: 'relative',
3688
3770
  overflow: 'auto',
3689
- height: size( scrollY ),
3690
3771
  width: size( scrollX )
3691
3772
  } )
3692
3773
  .append( table )
@@ -3733,6 +3814,11 @@
3733
3814
  } );
3734
3815
  }
3735
3816
 
3817
+ $(scrollBody).css(
3818
+ scrollY && scroll.bCollapse ? 'max-height' : 'height',
3819
+ scrollY
3820
+ );
3821
+
3736
3822
  settings.nScrollHead = scrollHead;
3737
3823
  settings.nScrollBody = scrollBody;
3738
3824
  settings.nScrollFoot = scrollFoot;
@@ -3805,6 +3891,20 @@
3805
3891
  style.height = 0;
3806
3892
  };
3807
3893
 
3894
+ // If the scrollbar visibility has changed from the last draw, we need to
3895
+ // adjust the column sizes as the table width will have changed to account
3896
+ // for the scrollbar
3897
+ var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
3898
+
3899
+ if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
3900
+ settings.scrollBarVis = scrollBarVis;
3901
+ _fnAdjustColumnSizing( settings );
3902
+ return; // adjust column sizing will call this function again
3903
+ }
3904
+ else {
3905
+ settings.scrollBarVis = scrollBarVis;
3906
+ }
3907
+
3808
3908
  /*
3809
3909
  * 1. Re-create the table inside the scrolling div
3810
3910
  */
@@ -3849,13 +3949,6 @@
3849
3949
  }, footerSrcEls );
3850
3950
  }
3851
3951
 
3852
- // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3853
- // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3854
- // then hide it (end of this function), so add the header height to the body scroller.
3855
- if ( scroll.bCollapse && scrollY !== "" ) {
3856
- divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3857
- }
3858
-
3859
3952
  // Size the table as a whole
3860
3953
  sanityWidth = table.outerWidth();
3861
3954
  if ( scrollX === "" ) {
@@ -3870,32 +3963,17 @@
3870
3963
  ) {
3871
3964
  tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3872
3965
  }
3966
+
3967
+ // Recalculate the sanity width
3968
+ sanityWidth = table.outerWidth();
3873
3969
  }
3874
- else
3875
- {
3876
- // x scrolling
3877
- if ( scrollXInner !== "" ) {
3878
- // x scroll inner has been given - use it
3879
- tableStyle.width = _fnStringToCss(scrollXInner);
3880
- }
3881
- else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3882
- // There is y-scrolling - try to take account of the y scroll bar
3883
- tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3884
- if ( table.outerWidth() > sanityWidth-barWidth ) {
3885
- // Not possible to take account of it
3886
- tableStyle.width = _fnStringToCss( sanityWidth );
3887
- }
3888
- }
3889
- else {
3890
- // When all else fails
3891
- tableStyle.width = _fnStringToCss( sanityWidth );
3892
- }
3893
- }
3970
+ else if ( scrollXInner !== "" ) {
3971
+ // legacy x scroll inner has been given - use it
3972
+ tableStyle.width = _fnStringToCss(scrollXInner);
3894
3973
 
3895
- // Recalculate the sanity width - now that we've applied the required width,
3896
- // before it was a temporary variable. This is required because the column
3897
- // width calculation is done before this table DOM is created.
3898
- sanityWidth = table.outerWidth();
3974
+ // Recalculate the sanity width
3975
+ sanityWidth = table.outerWidth();
3976
+ }
3899
3977
 
3900
3978
  // Hidden header should have zero height, so remove padding and borders. Then
3901
3979
  // set the width based on the real headers
@@ -4003,18 +4081,6 @@
4003
4081
  }
4004
4082
  }
4005
4083
 
4006
- if ( scrollY && scroll.bCollapse ) {
4007
- divBodyStyle.height = _fnStringToCss( scrollY );
4008
-
4009
- var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
4010
- barWidth :
4011
- 0;
4012
-
4013
- if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
4014
- divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
4015
- }
4016
- }
4017
-
4018
4084
  /* Finally set the width's of the header and footer tables */
4019
4085
  var iOuterWidth = table.outerWidth();
4020
4086
  divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
@@ -4106,7 +4172,9 @@
4106
4172
  tableWidthAttr = table.getAttribute('width'), // from DOM element
4107
4173
  tableContainer = table.parentNode,
4108
4174
  userInputs = false,
4109
- i, column, columnIdx, width, outerWidth;
4175
+ i, column, columnIdx, width, outerWidth,
4176
+ browser = oSettings.oBrowser,
4177
+ ie67 = browser.bScrollOversize;
4110
4178
 
4111
4179
  var styleWidth = table.style.width;
4112
4180
  if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
@@ -4129,32 +4197,43 @@
4129
4197
  * the web- browser. No custom sizes can be set in order for this to happen,
4130
4198
  * nor scrolling used
4131
4199
  */
4132
- if ( ! userInputs && ! scrollX && ! scrollY &&
4133
- columnCount == _fnVisbleColumns( oSettings ) &&
4134
- columnCount == headerCells.length
4200
+ if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
4201
+ columnCount == _fnVisbleColumns( oSettings ) &&
4202
+ columnCount == headerCells.length
4135
4203
  ) {
4136
4204
  for ( i=0 ; i<columnCount ; i++ ) {
4137
- columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4205
+ var colIdx = _fnVisibleToColumnIndex( oSettings, i );
4206
+
4207
+ if ( colIdx !== null ) {
4208
+ columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4209
+ }
4138
4210
  }
4139
4211
  }
4140
4212
  else
4141
4213
  {
4142
- // Otherwise construct a single row table with the widest node in the
4143
- // data, assign any user defined widths, then insert it into the DOM and
4144
- // allow the browser to do all the hard work of calculating table widths
4214
+ // Otherwise construct a single row, worst case, table with the widest
4215
+ // node in the data, assign any user defined widths, then insert it into
4216
+ // the DOM and allow the browser to do all the hard work of calculating
4217
+ // table widths
4145
4218
  var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4146
- .empty()
4147
4219
  .css( 'visibility', 'hidden' )
4148
- .removeAttr( 'id' )
4149
- .append( $(oSettings.nTHead).clone( false ) )
4150
- .append( $(oSettings.nTFoot).clone( false ) )
4151
- .append( $('<tbody><tr/></tbody>') );
4220
+ .removeAttr( 'id' );
4221
+
4222
+ // Clean up the table body
4223
+ tmpTable.find('tbody tr').remove();
4224
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
4225
+
4226
+ // Clone the table header and footer - we can't use the header / footer
4227
+ // from the cloned table, since if scrolling is active, the table's
4228
+ // real header and footer are contained in different table tags
4229
+ tmpTable.find('thead, tfoot').remove();
4230
+ tmpTable
4231
+ .append( $(oSettings.nTHead).clone() )
4232
+ .append( $(oSettings.nTFoot).clone() );
4152
4233
 
4153
4234
  // Remove any assigned widths from the footer (from scrolling)
4154
4235
  tmpTable.find('tfoot th, tfoot td').css('width', '');
4155
4236
 
4156
- var tr = tmpTable.find( 'tbody tr' );
4157
-
4158
4237
  // Apply custom sizing to the cloned header
4159
4238
  headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4160
4239
 
@@ -4164,6 +4243,19 @@
4164
4243
  headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4165
4244
  _fnStringToCss( column.sWidthOrig ) :
4166
4245
  '';
4246
+
4247
+ // For scrollX we need to force the column width otherwise the
4248
+ // browser will collapse it. If this width is smaller than the
4249
+ // width the column requires, then it will have no effect
4250
+ if ( column.sWidthOrig && scrollX ) {
4251
+ $( headerCells[i] ).append( $('<div/>').css( {
4252
+ width: column.sWidthOrig,
4253
+ margin: 0,
4254
+ padding: 0,
4255
+ border: 0,
4256
+ height: 1
4257
+ } ) );
4258
+ }
4167
4259
  }
4168
4260
 
4169
4261
  // Find the widest cell for each column and put it into the table
@@ -4179,8 +4271,24 @@
4179
4271
  }
4180
4272
  }
4181
4273
 
4182
- // Table has been built, attach to the document so we can work with it
4183
- tmpTable.appendTo( tableContainer );
4274
+ // Table has been built, attach to the document so we can work with it.
4275
+ // A holding element is used, positioned at the top of the container
4276
+ // with minimal height, so it has no effect on if the container scrolls
4277
+ // or not. Otherwise it might trigger scrolling when it actually isn't
4278
+ // needed
4279
+ var holder = $('<div/>').css( scrollX || scrollY ?
4280
+ {
4281
+ position: 'absolute',
4282
+ top: 0,
4283
+ left: 0,
4284
+ height: 1,
4285
+ right: 0,
4286
+ overflow: 'hidden'
4287
+ } :
4288
+ {}
4289
+ )
4290
+ .append( tmpTable )
4291
+ .appendTo( tableContainer );
4184
4292
 
4185
4293
  // When scrolling (X or Y) we want to set the width of the table as
4186
4294
  // appropriate. However, when not scrolling leave the table width as it
@@ -4190,57 +4298,50 @@
4190
4298
  }
4191
4299
  else if ( scrollX ) {
4192
4300
  tmpTable.css( 'width', 'auto' );
4301
+ tmpTable.removeAttr('width');
4193
4302
 
4194
- if ( tmpTable.width() < tableContainer.offsetWidth ) {
4195
- tmpTable.width( tableContainer.offsetWidth );
4303
+ // If there is no width attribute or style, then allow the table to
4304
+ // collapse
4305
+ if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
4306
+ tmpTable.width( tableContainer.clientWidth );
4196
4307
  }
4197
4308
  }
4198
4309
  else if ( scrollY ) {
4199
- tmpTable.width( tableContainer.offsetWidth );
4310
+ tmpTable.width( tableContainer.clientWidth );
4200
4311
  }
4201
4312
  else if ( tableWidthAttr ) {
4202
4313
  tmpTable.width( tableWidthAttr );
4203
4314
  }
4204
4315
 
4205
- // Take into account the y scrollbar
4206
- _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4207
-
4208
- // Browsers need a bit of a hand when a width is assigned to any columns
4209
- // when x-scrolling as they tend to collapse the table to the min-width,
4210
- // even if we sent the column widths. So we need to keep track of what
4211
- // the table width should be by summing the user given values, and the
4212
- // automatic values
4213
- if ( scrollX )
4214
- {
4215
- var total = 0;
4216
-
4217
- for ( i=0 ; i<visibleColumns.length ; i++ ) {
4218
- column = columns[ visibleColumns[i] ];
4219
- outerWidth = $(headerCells[i]).outerWidth();
4220
-
4221
- total += column.sWidthOrig === null ?
4222
- outerWidth :
4223
- parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4224
- }
4316
+ // Get the width of each column in the constructed table - we need to
4317
+ // know the inner width (so it can be assigned to the other table's
4318
+ // cells) and the outer width so we can calculate the full width of the
4319
+ // table. This is safe since DataTables requires a unique cell for each
4320
+ // column, but if ever a header can span multiple columns, this will
4321
+ // need to be modified.
4322
+ var total = 0;
4323
+ for ( i=0 ; i<visibleColumns.length ; i++ ) {
4324
+ var cell = $(headerCells[i]);
4325
+ var border = cell.outerWidth() - cell.width();
4225
4326
 
4226
- tmpTable.width( _fnStringToCss( total ) );
4227
- table.style.width = _fnStringToCss( total );
4228
- }
4327
+ // Use getBounding... where possible (not IE8-) because it can give
4328
+ // sub-pixel accuracy, which we then want to round up!
4329
+ var bounding = browser.bBounding ?
4330
+ Math.ceil( headerCells[i].getBoundingClientRect().width ) :
4331
+ cell.outerWidth();
4229
4332
 
4230
- // Get the width of each column in the constructed table
4231
- for ( i=0 ; i<visibleColumns.length ; i++ ) {
4232
- column = columns[ visibleColumns[i] ];
4233
- width = $(headerCells[i]).width();
4333
+ // Total is tracked to remove any sub-pixel errors as the outerWidth
4334
+ // of the table might not equal the total given here (IE!).
4335
+ total += bounding;
4234
4336
 
4235
- if ( width ) {
4236
- column.sWidth = _fnStringToCss( width );
4237
- }
4337
+ // Width for each column to use
4338
+ columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
4238
4339
  }
4239
4340
 
4240
- table.style.width = _fnStringToCss( tmpTable.css('width') );
4341
+ table.style.width = _fnStringToCss( total );
4241
4342
 
4242
4343
  // Finished with the table - ditch it
4243
- tmpTable.remove();
4344
+ holder.remove();
4244
4345
  }
4245
4346
 
4246
4347
  // If there is a width attr, we want to attach an event listener which
@@ -4252,9 +4353,20 @@
4252
4353
  }
4253
4354
 
4254
4355
  if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4255
- $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4256
- _fnAdjustColumnSizing( oSettings );
4257
- } ) );
4356
+ var bindResize = function () {
4357
+ $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4358
+ _fnAdjustColumnSizing( oSettings );
4359
+ } ) );
4360
+ };
4361
+
4362
+ // IE6/7 will crash if we bind a resize event handler on page load.
4363
+ // To be removed in 1.11 which drops IE6/7 support
4364
+ if ( ie67 ) {
4365
+ setTimeout( bindResize, 1000 );
4366
+ }
4367
+ else {
4368
+ bindResize();
4369
+ }
4258
4370
 
4259
4371
  oSettings._reszEvt = true;
4260
4372
  }
@@ -4321,27 +4433,6 @@
4321
4433
  }
4322
4434
 
4323
4435
 
4324
- /**
4325
- * Adjust a table's width to take account of vertical scroll bar
4326
- * @param {object} oSettings dataTables settings object
4327
- * @param {node} n table node
4328
- * @memberof DataTable#oApi
4329
- */
4330
-
4331
- function _fnScrollingWidthAdjust ( settings, n )
4332
- {
4333
- var scroll = settings.oScroll;
4334
-
4335
- if ( scroll.sX || scroll.sY ) {
4336
- // When y-scrolling only, we want to remove the width of the scroll bar
4337
- // so the table + scroll bar will fit into the area available, otherwise
4338
- // we fix the table at its current size with no adjustment
4339
- var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4340
- n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4341
- }
4342
- }
4343
-
4344
-
4345
4436
  /**
4346
4437
  * Get the widest node
4347
4438
  * @param {object} settings dataTables settings object
@@ -4377,6 +4468,7 @@
4377
4468
  for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4378
4469
  s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4379
4470
  s = s.replace( __re_html_remove, '' );
4471
+ s = s.replace( /&nbsp;/g, ' ' );
4380
4472
 
4381
4473
  if ( s.length > max ) {
4382
4474
  max = s.length;
@@ -4413,40 +4505,6 @@
4413
4505
  }
4414
4506
 
4415
4507
 
4416
- /**
4417
- * Get the width of a scroll bar in this browser being used
4418
- * @returns {int} width in pixels
4419
- * @memberof DataTable#oApi
4420
- */
4421
- function _fnScrollBarWidth ()
4422
- {
4423
- // On first run a static variable is set, since this is only needed once.
4424
- // Subsequent runs will just use the previously calculated value
4425
- var width = DataTable.__scrollbarWidth;
4426
-
4427
- if ( width === undefined ) {
4428
- var sizer = $('<p/>').css( {
4429
- position: 'absolute',
4430
- top: 0,
4431
- left: 0,
4432
- width: '100%',
4433
- height: 150,
4434
- padding: 0,
4435
- overflow: 'scroll',
4436
- visibility: 'hidden'
4437
- } )
4438
- .appendTo('body');
4439
-
4440
- width = sizer[0].offsetWidth - sizer[0].clientWidth;
4441
- DataTable.__scrollbarWidth = width;
4442
-
4443
- sizer.remove();
4444
- }
4445
-
4446
- return width;
4447
- }
4448
-
4449
-
4450
4508
 
4451
4509
  function _fnSortFlatten ( settings )
4452
4510
  {
@@ -4466,7 +4524,7 @@
4466
4524
  }
4467
4525
  else {
4468
4526
  // 2D array
4469
- nestedSort.push.apply( nestedSort, a );
4527
+ $.merge( nestedSort, a );
4470
4528
  }
4471
4529
  };
4472
4530
 
@@ -5043,7 +5101,7 @@
5043
5101
  function _fnLog( settings, level, msg, tn )
5044
5102
  {
5045
5103
  msg = 'DataTables warning: '+
5046
- (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
5104
+ (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
5047
5105
 
5048
5106
  if ( tn ) {
5049
5107
  msg += '. For more information about this error, please see '+
@@ -5055,7 +5113,9 @@
5055
5113
  var ext = DataTable.ext;
5056
5114
  var type = ext.sErrMode || ext.errMode;
5057
5115
 
5058
- _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5116
+ if ( settings ) {
5117
+ _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5118
+ }
5059
5119
 
5060
5120
  if ( type == 'alert' ) {
5061
5121
  alert( msg );
@@ -5208,13 +5268,13 @@
5208
5268
  * @param {object} settings dataTables settings object
5209
5269
  * @param {string} callbackArr Name of the array storage for the callbacks in
5210
5270
  * oSettings
5211
- * @param {string} event Name of the jQuery custom event to trigger. If null no
5212
- * trigger is fired
5271
+ * @param {string} eventName Name of the jQuery custom event to trigger. If
5272
+ * null no trigger is fired
5213
5273
  * @param {array} args Array of arguments to pass to the callback function /
5214
5274
  * trigger
5215
5275
  * @memberof DataTable#oApi
5216
5276
  */
5217
- function _fnCallbackFire( settings, callbackArr, e, args )
5277
+ function _fnCallbackFire( settings, callbackArr, eventName, args )
5218
5278
  {
5219
5279
  var ret = [];
5220
5280
 
@@ -5224,8 +5284,12 @@
5224
5284
  } );
5225
5285
  }
5226
5286
 
5227
- if ( e !== null ) {
5228
- $(settings.nTable).trigger( e+'.dt', args );
5287
+ if ( eventName !== null ) {
5288
+ var e = $.Event( eventName+'.dt' );
5289
+
5290
+ $(settings.nTable).trigger( e, args );
5291
+
5292
+ ret.push( e.result );
5229
5293
  }
5230
5294
 
5231
5295
  return ret;
@@ -6226,6 +6290,7 @@
6226
6290
  "fnStateSaveCallback",
6227
6291
  "renderer",
6228
6292
  "searchDelay",
6293
+ "rowId",
6229
6294
  [ "iCookieDuration", "iStateDuration" ], // backwards compat
6230
6295
  [ "oSearch", "oPreviousSearch" ],
6231
6296
  [ "aoSearchCols", "aoPreSearchCols" ],
@@ -6253,6 +6318,11 @@
6253
6318
  _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
6254
6319
  _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
6255
6320
 
6321
+ oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
6322
+
6323
+ /* Browser support detection */
6324
+ _fnBrowserDetect( oSettings );
6325
+
6256
6326
  var oClasses = oSettings.oClasses;
6257
6327
 
6258
6328
  // @todo Remove in 1.11
@@ -6282,14 +6352,6 @@
6282
6352
  }
6283
6353
  $this.addClass( oClasses.sTable );
6284
6354
 
6285
- /* Calculate the scroll bar width and cache it for use later on */
6286
- if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6287
- {
6288
- oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6289
- }
6290
- if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6291
- oSettings.oScroll.sX = '100%';
6292
- }
6293
6355
 
6294
6356
  if ( oSettings.iInitDisplayStart === undefined )
6295
6357
  {
@@ -6400,7 +6462,7 @@
6400
6462
  return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6401
6463
  };
6402
6464
 
6403
- $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6465
+ $( rowOne[0] ).children('th, td').each( function (i, cell) {
6404
6466
  var col = oSettings.aoColumns[i];
6405
6467
 
6406
6468
  if ( col.mData === i ) {
@@ -6482,9 +6544,6 @@
6482
6544
  * Cache the header, body and footer as required, creating them if needed
6483
6545
  */
6484
6546
 
6485
- /* Browser support detection */
6486
- _fnBrowserDetect( oSettings );
6487
-
6488
6547
  // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6489
6548
  var captions = $this.children('caption').each( function () {
6490
6549
  this._captionSide = $this.css('caption-side');
@@ -6722,17 +6781,15 @@
6722
6781
  */
6723
6782
  _Api = function ( context, data )
6724
6783
  {
6725
- if ( ! this instanceof _Api ) {
6726
- throw 'DT API must be constructed as a new object';
6727
- // or should it do the 'new' for the caller?
6728
- // return new _Api.apply( this, arguments );
6784
+ if ( ! (this instanceof _Api) ) {
6785
+ return new _Api( context, data );
6729
6786
  }
6730
6787
 
6731
6788
  var settings = [];
6732
6789
  var ctxSettings = function ( o ) {
6733
6790
  var a = _toSettings( o );
6734
6791
  if ( a ) {
6735
- settings.push.apply( settings, a );
6792
+ settings = settings.concat( a );
6736
6793
  }
6737
6794
  };
6738
6795
 
@@ -6750,7 +6807,7 @@
6750
6807
 
6751
6808
  // Initial data
6752
6809
  if ( data ) {
6753
- this.push.apply( this, data.toArray ? data.toArray() : data );
6810
+ $.merge( this, data );
6754
6811
  }
6755
6812
 
6756
6813
  // selector
@@ -6765,25 +6822,27 @@
6765
6822
 
6766
6823
  DataTable.Api = _Api;
6767
6824
 
6768
- _Api.prototype = /** @lends DataTables.Api */{
6769
- /**
6770
- * Return a new Api instance, comprised of the data held in the current
6771
- * instance, join with the other array(s) and/or value(s).
6772
- *
6773
- * An alias for `Array.prototype.concat`.
6774
- *
6775
- * @type method
6776
- * @param {*} value1 Arrays and/or values to concatenate.
6777
- * @param {*} [...] Additional arrays and/or values to concatenate.
6778
- * @returns {DataTables.Api} New API instance, comprising of the combined
6779
- * array.
6780
- */
6825
+ // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6826
+ // isPlainObject.
6827
+ $.extend( _Api.prototype, {
6828
+ any: function ()
6829
+ {
6830
+ return this.count() !== 0;
6831
+ },
6832
+
6833
+
6781
6834
  concat: __arrayProto.concat,
6782
6835
 
6783
6836
 
6784
6837
  context: [], // array of table settings objects
6785
6838
 
6786
6839
 
6840
+ count: function ()
6841
+ {
6842
+ return this.flatten().length;
6843
+ },
6844
+
6845
+
6787
6846
  each: function ( fn )
6788
6847
  {
6789
6848
  for ( var i=0, ien=this.length ; i<ien; i++ ) {
@@ -6844,7 +6903,6 @@
6844
6903
  return -1;
6845
6904
  },
6846
6905
 
6847
- // Note that `alwaysNew` is internal - use iteratorNew externally
6848
6906
  iterator: function ( flatten, type, fn, alwaysNew ) {
6849
6907
  var
6850
6908
  a = [], ret,
@@ -7012,7 +7070,7 @@
7012
7070
 
7013
7071
 
7014
7072
  unshift: __arrayProto.unshift
7015
- };
7073
+ } );
7016
7074
 
7017
7075
 
7018
7076
  _Api.extend = function ( scope, obj, ext )
@@ -7267,15 +7325,21 @@
7267
7325
 
7268
7326
  /**
7269
7327
  * Redraw the tables in the current context.
7270
- *
7271
- * @param {boolean} [reset=true] Reset (default) or hold the current paging
7272
- * position. A full re-sort and re-filter is performed when this method is
7273
- * called, which is why the pagination reset is the default action.
7274
- * @returns {DataTables.Api} this
7275
7328
  */
7276
- _api_register( 'draw()', function ( resetPaging ) {
7329
+ _api_register( 'draw()', function ( paging ) {
7277
7330
  return this.iterator( 'table', function ( settings ) {
7278
- _fnReDraw( settings, resetPaging===false );
7331
+ if ( paging === 'page' ) {
7332
+ _fnDraw( settings );
7333
+ }
7334
+ else {
7335
+ if ( typeof paging === 'string' ) {
7336
+ paging = paging === 'full-hold' ?
7337
+ false :
7338
+ true;
7339
+ }
7340
+
7341
+ _fnReDraw( settings, paging===false );
7342
+ }
7279
7343
  } );
7280
7344
  } );
7281
7345
 
@@ -7338,7 +7402,7 @@
7338
7402
  var
7339
7403
  settings = this.context[0],
7340
7404
  start = settings._iDisplayStart,
7341
- len = settings._iDisplayLength,
7405
+ len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7342
7406
  visRecords = settings.fnRecordsDisplay(),
7343
7407
  all = len === -1;
7344
7408
 
@@ -7349,7 +7413,8 @@
7349
7413
  "end": settings.fnDisplayEnd(),
7350
7414
  "length": len,
7351
7415
  "recordsTotal": settings.fnRecordsTotal(),
7352
- "recordsDisplay": visRecords
7416
+ "recordsDisplay": visRecords,
7417
+ "serverSide": _fnDataSource( settings ) === 'ssp'
7353
7418
  };
7354
7419
  } );
7355
7420
 
@@ -7397,9 +7462,15 @@
7397
7462
  _fnReDraw( settings, holdPosition );
7398
7463
  }
7399
7464
  else {
7400
- // Trigger xhr
7401
7465
  _fnProcessingDisplay( settings, true );
7402
7466
 
7467
+ // Cancel an existing request
7468
+ var xhr = settings.jqXHR;
7469
+ if ( xhr && xhr.readyState !== 4 ) {
7470
+ xhr.abort();
7471
+ }
7472
+
7473
+ // Trigger xhr
7403
7474
  _fnBuildAjax( settings, [], function( json ) {
7404
7475
  _fnClearTable( settings );
7405
7476
 
@@ -7527,7 +7598,7 @@
7527
7598
 
7528
7599
 
7529
7600
 
7530
- var _selector_run = function ( selector, select )
7601
+ var _selector_run = function ( type, selector, selectFn, settings, opts )
7531
7602
  {
7532
7603
  var
7533
7604
  out = [], res,
@@ -7546,15 +7617,23 @@
7546
7617
  [ selector[i] ];
7547
7618
 
7548
7619
  for ( j=0, jen=a.length ; j<jen ; j++ ) {
7549
- res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7620
+ res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7550
7621
 
7551
7622
  if ( res && res.length ) {
7552
- out.push.apply( out, res );
7623
+ out = out.concat( res );
7553
7624
  }
7554
7625
  }
7555
7626
  }
7556
7627
 
7557
- return out;
7628
+ // selector extensions
7629
+ var ext = _ext.selector[ type ];
7630
+ if ( ext.length ) {
7631
+ for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7632
+ out = ext[i]( settings, opts, out );
7633
+ }
7634
+ }
7635
+
7636
+ return _unique( out );
7558
7637
  };
7559
7638
 
7560
7639
 
@@ -7566,15 +7645,15 @@
7566
7645
 
7567
7646
  // Backwards compatibility for 1.9- which used the terminology filter rather
7568
7647
  // than search
7569
- if ( opts.filter && ! opts.search ) {
7648
+ if ( opts.filter && opts.search === undefined ) {
7570
7649
  opts.search = opts.filter;
7571
7650
  }
7572
7651
 
7573
- return {
7574
- search: opts.search || 'none',
7575
- order: opts.order || 'current',
7576
- page: opts.page || 'all'
7577
- };
7652
+ return $.extend( {
7653
+ search: 'none',
7654
+ order: 'current',
7655
+ page: 'all'
7656
+ }, opts );
7578
7657
  };
7579
7658
 
7580
7659
 
@@ -7586,6 +7665,7 @@
7586
7665
  // Assign the first element to the first item in the instance
7587
7666
  // and truncate the instance and context
7588
7667
  inst[0] = inst[i];
7668
+ inst[0].length = 1;
7589
7669
  inst.length = 1;
7590
7670
  inst.context = [ inst.context[i] ];
7591
7671
 
@@ -7672,7 +7752,7 @@
7672
7752
 
7673
7753
  var __row_selector = function ( settings, selector, opts )
7674
7754
  {
7675
- return _selector_run( selector, function ( sel ) {
7755
+ var run = function ( sel ) {
7676
7756
  var selInt = _intVal( sel );
7677
7757
  var i, ien;
7678
7758
 
@@ -7715,6 +7795,26 @@
7715
7795
  }
7716
7796
  }
7717
7797
 
7798
+ // ID selector. Want to always be able to select rows by id, regardless
7799
+ // of if the tr element has been created or not, so can't rely upon
7800
+ // jQuery here - hence a custom implementation. This does not match
7801
+ // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7802
+ // but to select it using a CSS selector engine (like Sizzle or
7803
+ // querySelect) it would need to need to be escaped for some characters.
7804
+ // DataTables simplifies this for row selectors since you can select
7805
+ // only a row. A # indicates an id any anything that follows is the id -
7806
+ // unescaped.
7807
+ if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7808
+ // get row index from id
7809
+ var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7810
+ if ( rowObj !== undefined ) {
7811
+ return [ rowObj.idx ];
7812
+ }
7813
+
7814
+ // need to fall through to jQuery in case there is DOM id that
7815
+ // matches
7816
+ }
7817
+
7718
7818
  // Selector - jQuery selector string, array of nodes or jQuery object/
7719
7819
  // As jQuery's .filter() allows jQuery objects to be passed in filter,
7720
7820
  // it also allows arrays, so this will cope with all three options
@@ -7724,7 +7824,9 @@
7724
7824
  return this._DT_RowIndex;
7725
7825
  } )
7726
7826
  .toArray();
7727
- } );
7827
+ };
7828
+
7829
+ return _selector_run( 'row', selector, run, settings, opts );
7728
7830
  };
7729
7831
 
7730
7832
 
@@ -7782,23 +7884,49 @@
7782
7884
  }, 1 );
7783
7885
  } );
7784
7886
 
7887
+ _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7888
+ var a = [];
7889
+ var context = this.context;
7890
+
7891
+ // `iterator` will drop undefined values, but in this case we want them
7892
+ for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7893
+ for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7894
+ var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7895
+ a.push( (hash === true ? '#' : '' )+ id );
7896
+ }
7897
+ }
7898
+
7899
+ return new _Api( context, a );
7900
+ } );
7901
+
7785
7902
  _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7786
7903
  var that = this;
7787
7904
 
7788
- return this.iterator( 'row', function ( settings, row, thatIdx ) {
7905
+ this.iterator( 'row', function ( settings, row, thatIdx ) {
7789
7906
  var data = settings.aoData;
7907
+ var rowData = data[ row ];
7908
+ var i, ien, j, jen;
7909
+ var loopRow, loopCells;
7790
7910
 
7791
7911
  data.splice( row, 1 );
7792
7912
 
7793
- // Update the _DT_RowIndex parameter on all rows in the table
7794
- for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7795
- if ( data[i].nTr !== null ) {
7796
- data[i].nTr._DT_RowIndex = i;
7913
+ // Update the cached indexes
7914
+ for ( i=0, ien=data.length ; i<ien ; i++ ) {
7915
+ loopRow = data[i];
7916
+ loopCells = loopRow.anCells;
7917
+
7918
+ // Rows
7919
+ if ( loopRow.nTr !== null ) {
7920
+ loopRow.nTr._DT_RowIndex = i;
7797
7921
  }
7798
- }
7799
7922
 
7800
- // Remove the target row from the search array
7801
- var displayIndex = $.inArray( row, settings.aiDisplay );
7923
+ // Cells
7924
+ if ( loopCells !== null ) {
7925
+ for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
7926
+ loopCells[j]._DT_CellIndex.row = i;
7927
+ }
7928
+ }
7929
+ }
7802
7930
 
7803
7931
  // Delete from the display arrays
7804
7932
  _fnDeleteIndex( settings.aiDisplayMaster, row );
@@ -7807,7 +7935,21 @@
7807
7935
 
7808
7936
  // Check for an 'overflow' they case for displaying the table
7809
7937
  _fnLengthOverflow( settings );
7938
+
7939
+ // Remove the row's ID reference if there is one
7940
+ var id = settings.rowIdFn( rowData._aData );
7941
+ if ( id !== undefined ) {
7942
+ delete settings.aIds[ id ];
7943
+ }
7810
7944
  } );
7945
+
7946
+ this.iterator( 'table', function ( settings ) {
7947
+ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7948
+ settings.aoData[i].idx = i;
7949
+ }
7950
+ } );
7951
+
7952
+ return this;
7811
7953
  } );
7812
7954
 
7813
7955
 
@@ -7833,7 +7975,7 @@
7833
7975
  // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7834
7976
  var modRows = this.rows( -1 );
7835
7977
  modRows.pop();
7836
- modRows.push.apply( modRows, newRows.toArray() );
7978
+ $.merge( modRows, newRows );
7837
7979
 
7838
7980
  return modRows;
7839
7981
  } );
@@ -7951,7 +8093,7 @@
7951
8093
  if ( ctx.length ) {
7952
8094
  var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
7953
8095
 
7954
- if ( row._details ) {
8096
+ if ( row && row._details ) {
7955
8097
  row._details.remove();
7956
8098
 
7957
8099
  row._detailsShow = undefined;
@@ -8154,7 +8296,7 @@
8154
8296
  names = _pluck( columns, 'sName' ),
8155
8297
  nodes = _pluck( columns, 'nTh' );
8156
8298
 
8157
- return _selector_run( selector, function ( s ) {
8299
+ var run = function ( s ) {
8158
8300
  var selInt = _intVal( s );
8159
8301
 
8160
8302
  // Selector - all
@@ -8220,7 +8362,9 @@
8220
8362
  } )
8221
8363
  .toArray();
8222
8364
  }
8223
- } );
8365
+ };
8366
+
8367
+ return _selector_run( 'column', selector, run, settings, opts );
8224
8368
  };
8225
8369
 
8226
8370
 
@@ -8277,7 +8421,7 @@
8277
8421
  }
8278
8422
  }
8279
8423
 
8280
- _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8424
+ _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, recalc] );
8281
8425
 
8282
8426
  _fnSaveState( settings );
8283
8427
  };
@@ -8395,7 +8539,7 @@
8395
8539
  var columns = settings.aoColumns.length;
8396
8540
  var a, i, ien, j, o, host;
8397
8541
 
8398
- return _selector_run( selector, function ( s ) {
8542
+ var run = function ( s ) {
8399
8543
  var fnSelector = typeof s === 'function';
8400
8544
 
8401
8545
  if ( s === null || s === undefined || fnSelector ) {
@@ -8413,9 +8557,9 @@
8413
8557
 
8414
8558
  if ( fnSelector ) {
8415
8559
  // Selector - function
8416
- host = settings.aoData[ row ];
8560
+ host = data[ row ];
8417
8561
 
8418
- if ( s( o, _fnGetCellData(settings, row, j), host.anCells[j] ) ) {
8562
+ if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8419
8563
  a.push( o );
8420
8564
  }
8421
8565
  }
@@ -8438,15 +8582,15 @@
8438
8582
  return allCells
8439
8583
  .filter( s )
8440
8584
  .map( function (i, el) {
8441
- row = el.parentNode._DT_RowIndex;
8442
-
8443
- return {
8444
- row: row,
8445
- column: $.inArray( el, data[ row ].anCells )
8446
- };
8585
+ return { // use a new object, in case someone changes the values
8586
+ row: el._DT_CellIndex.row,
8587
+ column: el._DT_CellIndex.column
8588
+ };
8447
8589
  } )
8448
8590
  .toArray();
8449
- } );
8591
+ };
8592
+
8593
+ return _selector_run( 'cell', selector, run, settings, opts );
8450
8594
  };
8451
8595
 
8452
8596
 
@@ -8658,6 +8802,24 @@
8658
8802
  } );
8659
8803
 
8660
8804
 
8805
+ _api_register( 'order.fixed()', function ( set ) {
8806
+ if ( ! set ) {
8807
+ var ctx = this.context;
8808
+ var fixed = ctx.length ?
8809
+ ctx[0].aaSortingFixed :
8810
+ undefined;
8811
+
8812
+ return $.isArray( fixed ) ?
8813
+ { pre: fixed } :
8814
+ fixed;
8815
+ }
8816
+
8817
+ return this.iterator( 'table', function ( settings ) {
8818
+ settings.aaSortingFixed = $.extend( true, {}, set );
8819
+ } );
8820
+ } );
8821
+
8822
+
8661
8823
  // Order by the selected column(s)
8662
8824
  _api_register( [
8663
8825
  'columns().order()',
@@ -8856,11 +9018,22 @@
8856
9018
  */
8857
9019
  DataTable.tables = DataTable.fnTables = function ( visible )
8858
9020
  {
8859
- return $.map( DataTable.settings, function (o) {
9021
+ var api = false;
9022
+
9023
+ if ( $.isPlainObject( visible ) ) {
9024
+ api = visible.api;
9025
+ visible = visible.visible;
9026
+ }
9027
+
9028
+ var a = $.map( DataTable.settings, function (o) {
8860
9029
  if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8861
9030
  return o.nTable;
8862
9031
  }
8863
9032
  } );
9033
+
9034
+ return api ?
9035
+ new _Api( a ) :
9036
+ a;
8864
9037
  };
8865
9038
 
8866
9039
 
@@ -9015,10 +9188,6 @@
9015
9188
  jqTable.append( tfoot );
9016
9189
  }
9017
9190
 
9018
- // Remove the DataTables generated nodes, events and classes
9019
- jqTable.detach();
9020
- jqWrapper.detach();
9021
-
9022
9191
  settings.aaSorting = [];
9023
9192
  settings.aaSortingFixed = [];
9024
9193
  _fnSortingClasses( settings );
@@ -9038,30 +9207,36 @@
9038
9207
  } );
9039
9208
  }
9040
9209
 
9041
- if ( ! remove && orig ) {
9042
- // insertBefore acts like appendChild if !arg[1]
9043
- orig.insertBefore( table, settings.nTableReinsertBefore );
9044
- }
9045
-
9046
9210
  // Add the TR elements back into the table in their original order
9047
9211
  jqTbody.children().detach();
9048
9212
  jqTbody.append( rows );
9049
9213
 
9050
- // Restore the width of the original table - was read from the style property,
9051
- // so we can restore directly to that
9052
- jqTable
9053
- .css( 'width', settings.sDestroyWidth )
9054
- .removeClass( classes.sTable );
9214
+ // Remove the DataTables generated nodes, events and classes
9215
+ var removedMethod = remove ? 'remove' : 'detach';
9216
+ jqTable[ removedMethod ]();
9217
+ jqWrapper[ removedMethod ]();
9218
+
9219
+ // If we need to reattach the table to the document
9220
+ if ( ! remove && orig ) {
9221
+ // insertBefore acts like appendChild if !arg[1]
9222
+ orig.insertBefore( table, settings.nTableReinsertBefore );
9055
9223
 
9056
- // If the were originally stripe classes - then we add them back here.
9057
- // Note this is not fool proof (for example if not all rows had stripe
9058
- // classes - but it's a good effort without getting carried away
9059
- ien = settings.asDestroyStripes.length;
9224
+ // Restore the width of the original table - was read from the style property,
9225
+ // so we can restore directly to that
9226
+ jqTable
9227
+ .css( 'width', settings.sDestroyWidth )
9228
+ .removeClass( classes.sTable );
9060
9229
 
9061
- if ( ien ) {
9062
- jqTbody.children().each( function (i) {
9063
- $(this).addClass( settings.asDestroyStripes[i % ien] );
9064
- } );
9230
+ // If the were originally stripe classes - then we add them back here.
9231
+ // Note this is not fool proof (for example if not all rows had stripe
9232
+ // classes - but it's a good effort without getting carried away
9233
+ ien = settings.asDestroyStripes.length;
9234
+
9235
+ if ( ien ) {
9236
+ jqTbody.children().each( function (i) {
9237
+ $(this).addClass( settings.asDestroyStripes[i % ien] );
9238
+ } );
9239
+ }
9065
9240
  }
9066
9241
 
9067
9242
  /* Remove the settings object from the settings array */
@@ -9076,13 +9251,51 @@
9076
9251
  // Add the `every()` method for rows, columns and cells in a compact form
9077
9252
  $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9078
9253
  _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 ) );
9254
+ var opts = this.selector.opts;
9255
+ var api = this;
9256
+
9257
+ return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9258
+ // Rows and columns:
9259
+ // arg1 - index
9260
+ // arg2 - table counter
9261
+ // arg3 - loop counter
9262
+ // arg4 - undefined
9263
+ // Cells:
9264
+ // arg1 - row index
9265
+ // arg2 - column index
9266
+ // arg3 - table counter
9267
+ // arg4 - loop counter
9268
+ fn.call(
9269
+ api[ type ](
9270
+ arg1,
9271
+ type==='cell' ? arg2 : opts,
9272
+ type==='cell' ? opts : undefined
9273
+ ),
9274
+ arg1, arg2, arg3, arg4
9275
+ );
9082
9276
  } );
9083
9277
  } );
9084
9278
  } );
9085
9279
 
9280
+
9281
+ // i18n method for extensions to be able to use the language object from the
9282
+ // DataTable
9283
+ _api_register( 'i18n()', function ( token, def, plural ) {
9284
+ var ctx = this.context[0];
9285
+ var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9286
+
9287
+ if ( resolved === undefined ) {
9288
+ resolved = def;
9289
+ }
9290
+
9291
+ if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9292
+ resolved = resolved[ plural ] !== undefined ?
9293
+ resolved[ plural ] :
9294
+ resolved._;
9295
+ }
9296
+
9297
+ return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9298
+ } );
9086
9299
 
9087
9300
  /**
9088
9301
  * Version string for plug-ins to check compatibility. Allowed format is
@@ -9092,7 +9305,7 @@
9092
9305
  * @type string
9093
9306
  * @default Version number
9094
9307
  */
9095
- DataTable.version = "1.10.6";
9308
+ DataTable.version = "1.10.10";
9096
9309
 
9097
9310
  /**
9098
9311
  * Private data store, containing all of the settings objects that are
@@ -9244,7 +9457,16 @@
9244
9457
  * @default null
9245
9458
  * @private
9246
9459
  */
9247
- "src": null
9460
+ "src": null,
9461
+
9462
+ /**
9463
+ * Index in the aoData array. This saves an indexOf lookup when we have the
9464
+ * object, but want to know the index
9465
+ * @type integer
9466
+ * @default -1
9467
+ * @private
9468
+ */
9469
+ "idx": -1
9248
9470
  };
9249
9471
 
9250
9472
 
@@ -11685,7 +11907,18 @@
11685
11907
  * @name DataTable.defaults.renderer
11686
11908
  *
11687
11909
  */
11688
- "renderer": null
11910
+ "renderer": null,
11911
+
11912
+
11913
+ /**
11914
+ * Set the data property name that DataTables should use to get a row's id
11915
+ * to set as the `id` property in the node.
11916
+ * @type string
11917
+ * @default DT_RowId
11918
+ *
11919
+ * @name DataTable.defaults.rowId
11920
+ */
11921
+ "rowId": "DT_RowId"
11689
11922
  };
11690
11923
 
11691
11924
  _fnHungarianMap( DataTable.defaults );
@@ -12784,7 +13017,21 @@
12784
13017
  * @type boolean
12785
13018
  * @default false
12786
13019
  */
12787
- "bScrollbarLeft": false
13020
+ "bScrollbarLeft": false,
13021
+
13022
+ /**
13023
+ * Flag for if `getBoundingClientRect` is fully supported or not
13024
+ * @type boolean
13025
+ * @default false
13026
+ */
13027
+ "bBounding": false,
13028
+
13029
+ /**
13030
+ * Browser scrollbar width
13031
+ * @type integer
13032
+ * @default 0
13033
+ */
13034
+ "barWidth": 0
12788
13035
  },
12789
13036
 
12790
13037
 
@@ -12829,6 +13076,13 @@
12829
13076
  */
12830
13077
  "aiDisplayMaster": [],
12831
13078
 
13079
+ /**
13080
+ * Map of row ids to data indexes
13081
+ * @type object
13082
+ * @default {}
13083
+ */
13084
+ "aIds": {},
13085
+
12832
13086
  /**
12833
13087
  * Store information about each column that is in use
12834
13088
  * @type array
@@ -13437,7 +13691,21 @@
13437
13691
  * @type object
13438
13692
  * @default {}
13439
13693
  */
13440
- "oPlugins": {}
13694
+ "oPlugins": {},
13695
+
13696
+ /**
13697
+ * Function used to get a row's id from the row's data
13698
+ * @type function
13699
+ * @default null
13700
+ */
13701
+ "rowIdFn": null,
13702
+
13703
+ /**
13704
+ * Data location where to store a row's id
13705
+ * @type string
13706
+ * @default null
13707
+ */
13708
+ "rowId": null
13441
13709
  };
13442
13710
 
13443
13711
  /**
@@ -13486,6 +13754,14 @@
13486
13754
  classes: {},
13487
13755
 
13488
13756
 
13757
+ /**
13758
+ * DataTables build type (expanded by the download builder)
13759
+ *
13760
+ * @type string
13761
+ */
13762
+ builder: "-source-",
13763
+
13764
+
13489
13765
  /**
13490
13766
  * Error reporting.
13491
13767
  *
@@ -13599,6 +13875,37 @@
13599
13875
  search: [],
13600
13876
 
13601
13877
 
13878
+ /**
13879
+ * Selector extensions
13880
+ *
13881
+ * The `selector` option can be used to extend the options available for the
13882
+ * selector modifier options (`selector-modifier` object data type) that
13883
+ * each of the three built in selector types offer (row, column and cell +
13884
+ * their plural counterparts). For example the Select extension uses this
13885
+ * mechanism to provide an option to select only rows, columns and cells
13886
+ * that have been marked as selected by the end user (`{selected: true}`),
13887
+ * which can be used in conjunction with the existing built in selector
13888
+ * options.
13889
+ *
13890
+ * Each property is an array to which functions can be pushed. The functions
13891
+ * take three attributes:
13892
+ *
13893
+ * * Settings object for the host table
13894
+ * * Options object (`selector-modifier` object type)
13895
+ * * Array of selected item indexes
13896
+ *
13897
+ * The return is an array of the resulting item indexes after the custom
13898
+ * selector has been applied.
13899
+ *
13900
+ * @type object
13901
+ */
13902
+ selector: {
13903
+ cell: [],
13904
+ column: [],
13905
+ row: []
13906
+ },
13907
+
13908
+
13602
13909
  /**
13603
13910
  * Internal functions, exposed for used in plug-ins.
13604
13911
  *
@@ -14113,6 +14420,10 @@
14113
14420
  return [ 'first', 'previous', 'next', 'last' ];
14114
14421
  },
14115
14422
 
14423
+ numbers: function ( page, pages ) {
14424
+ return [ _numbers(page, pages) ];
14425
+ },
14426
+
14116
14427
  simple_numbers: function ( page, pages ) {
14117
14428
  return [ 'previous', _numbers(page, pages), 'next' ];
14118
14429
  },
@@ -14134,6 +14445,7 @@
14134
14445
  _: function ( settings, host, idx, buttons, page, pages ) {
14135
14446
  var classes = settings.oClasses;
14136
14447
  var lang = settings.oLanguage.oPaginate;
14448
+ var aria = settings.oLanguage.oAria.paginate || {};
14137
14449
  var btnDisplay, btnClass, counter=0;
14138
14450
 
14139
14451
  var attach = function( container, buttons ) {
@@ -14151,7 +14463,7 @@
14151
14463
  attach( inner, button );
14152
14464
  }
14153
14465
  else {
14154
- btnDisplay = '';
14466
+ btnDisplay = null;
14155
14467
  btnClass = '';
14156
14468
 
14157
14469
  switch ( button ) {
@@ -14190,10 +14502,11 @@
14190
14502
  break;
14191
14503
  }
14192
14504
 
14193
- if ( btnDisplay ) {
14505
+ if ( btnDisplay !== null ) {
14194
14506
  node = $('<a>', {
14195
14507
  'class': classes.sPageButton+' '+btnClass,
14196
14508
  'aria-controls': settings.sTableId,
14509
+ 'aria-label': aria[ button ],
14197
14510
  'data-dt-idx': counter,
14198
14511
  'tabindex': settings.iTabIndex,
14199
14512
  'id': idx === 0 && typeof button === 'string' ?
@@ -14223,7 +14536,7 @@
14223
14536
  // elements, focus is lost on the select button which is bad for
14224
14537
  // accessibility. So we want to restore focus once the draw has
14225
14538
  // completed
14226
- activeEl = $(document.activeElement).data('dt-idx');
14539
+ activeEl = $(host).find(document.activeElement).data('dt-idx');
14227
14540
  }
14228
14541
  catch (e) {}
14229
14542
 
@@ -14521,11 +14834,14 @@
14521
14834
  *
14522
14835
  * * `number` - Will format numeric data (defined by `columns.data`) for
14523
14836
  * display, retaining the original unformatted data for sorting and filtering.
14524
- * It takes 4 parameters:
14837
+ * It takes 5 parameters:
14525
14838
  * * `string` - Thousands grouping separator
14526
14839
  * * `string` - Decimal point indicator
14527
14840
  * * `integer` - Number of decimal points to show
14528
14841
  * * `string` (optional) - Prefix.
14842
+ * * `string` (optional) - Postfix (/suffix).
14843
+ * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14844
+ * parameters.
14529
14845
  *
14530
14846
  * @example
14531
14847
  * // Column definition using the number renderer
@@ -14537,7 +14853,7 @@
14537
14853
  * @namespace
14538
14854
  */
14539
14855
  DataTable.render = {
14540
- number: function ( thousands, decimal, precision, prefix ) {
14856
+ number: function ( thousands, decimal, precision, prefix, postfix ) {
14541
14857
  return {
14542
14858
  display: function ( d ) {
14543
14859
  if ( typeof d !== 'number' && typeof d !== 'string' ) {
@@ -14545,7 +14861,15 @@
14545
14861
  }
14546
14862
 
14547
14863
  var negative = d < 0 ? '-' : '';
14548
- d = Math.abs( parseFloat( d ) );
14864
+ var flo = parseFloat( d );
14865
+
14866
+ // If NaN then there isn't much formatting that we can do - just
14867
+ // return immediately
14868
+ if ( isNaN( flo ) ) {
14869
+ return d;
14870
+ }
14871
+
14872
+ d = Math.abs( flo );
14549
14873
 
14550
14874
  var intPart = parseInt( d, 10 );
14551
14875
  var floatPart = precision ?
@@ -14556,7 +14880,18 @@
14556
14880
  intPart.toString().replace(
14557
14881
  /\B(?=(\d{3})+(?!\d))/g, thousands
14558
14882
  ) +
14559
- floatPart;
14883
+ floatPart +
14884
+ (postfix||'');
14885
+ }
14886
+ };
14887
+ },
14888
+
14889
+ text: function () {
14890
+ return {
14891
+ display: function ( d ) {
14892
+ return typeof d === 'string' ?
14893
+ d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14894
+ d;
14560
14895
  }
14561
14896
  };
14562
14897
  }
@@ -14660,11 +14995,9 @@
14660
14995
  _fnCalculateColumnWidths: _fnCalculateColumnWidths,
14661
14996
  _fnThrottle: _fnThrottle,
14662
14997
  _fnConvertToWidth: _fnConvertToWidth,
14663
- _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14664
14998
  _fnGetWidestNode: _fnGetWidestNode,
14665
14999
  _fnGetMaxLenString: _fnGetMaxLenString,
14666
15000
  _fnStringToCss: _fnStringToCss,
14667
- _fnScrollBarWidth: _fnScrollBarWidth,
14668
15001
  _fnSortFlatten: _fnSortFlatten,
14669
15002
  _fnSort: _fnSort,
14670
15003
  _fnSortAria: _fnSortAria,
@@ -14693,6 +15026,9 @@
14693
15026
  // jQuery access
14694
15027
  $.fn.dataTable = DataTable;
14695
15028
 
15029
+ // Provide access to the host jQuery object (circular reference)
15030
+ DataTable.$ = $;
15031
+
14696
15032
  // Legacy aliases
14697
15033
  $.fn.dataTableSettings = DataTable.settings;
14698
15034
  $.fn.dataTableExt = DataTable.ext;
@@ -14874,6 +15210,3 @@
14874
15210
 
14875
15211
  return $.fn.dataTable;
14876
15212
  }));
14877
-
14878
- }(window, document));
14879
-