jquery-datatables 1.10.12 → 1.10.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/app/assets/javascripts/datatables/dataTables.bootstrap.js +2 -2
  4. data/app/assets/javascripts/datatables/dataTables.bootstrap4.js +5 -5
  5. data/app/assets/javascripts/datatables/dataTables.foundation.js +1 -1
  6. data/app/assets/javascripts/datatables/dataTables.material.js +1 -1
  7. data/app/assets/javascripts/datatables/dataTables.semanticui.js +1 -1
  8. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +63 -31
  9. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +2 -3
  10. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.flash.js +145 -55
  11. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +224 -206
  12. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +14 -8
  13. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +54 -24
  14. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +137 -68
  15. data/app/assets/javascripts/datatables/extensions/Responsive/dataTables.responsive.js +30 -7
  16. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap.js +6 -2
  17. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap4.js +6 -2
  18. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +64 -6
  19. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +40 -15
  20. data/app/assets/javascripts/datatables/jquery.dataTables.js +246 -217
  21. data/app/assets/javascripts/datatables/plugins/api/average.js +32 -0
  22. data/app/assets/javascripts/datatables/plugins/api/sum.js +51 -0
  23. data/app/assets/javascripts/datatables/plugins/pagination/input.js +224 -0
  24. data/app/assets/javascripts/datatables/plugins/search/alphabetSearch.js +368 -0
  25. data/app/assets/javascripts/datatables/plugins/sorting/file-size.js +43 -0
  26. data/app/assets/javascripts/datatables/plugins/sorting/ip-address.js +103 -0
  27. data/app/assets/stylesheets/datatables/dataTables.bootstrap.css +0 -1
  28. data/app/assets/stylesheets/datatables/dataTables.semanticui.css +0 -1
  29. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap.css +4 -4
  30. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap4.css +4 -4
  31. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.dataTables.css +4 -4
  32. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.foundation.css +4 -4
  33. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.jqueryui.css +4 -4
  34. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.semanticui.css +4 -4
  35. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap.css +9 -4
  36. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap4.css +9 -4
  37. data/app/assets/stylesheets/datatables/extensions/Select/select.dataTables.css +9 -4
  38. data/app/assets/stylesheets/datatables/extensions/Select/select.foundation.css +9 -4
  39. data/app/assets/stylesheets/datatables/extensions/Select/select.jqueryui.css +9 -4
  40. data/app/assets/stylesheets/datatables/extensions/Select/select.semanticui.css +9 -4
  41. data/app/assets/stylesheets/datatables/plugins/search/alphabetSearch.css +43 -0
  42. data/lib/jquery-datatables/version.rb +1 -1
  43. metadata +10 -3
@@ -1,11 +1,11 @@
1
- /*! Responsive 2.1.0
1
+ /*! Responsive 2.1.1
2
2
  * 2014-2016 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary Responsive
7
7
  * @description Responsive tables plug-in for DataTables
8
- * @version 2.1.0
8
+ * @version 2.1.1
9
9
  * @file dataTables.responsive.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
@@ -166,7 +166,7 @@ $.extend( Responsive.prototype, {
166
166
  // new data is added
167
167
  dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
168
168
  if ( $.inArray( false, that.s.current ) !== -1 ) {
169
- $('td, th', tr).each( function ( i ) {
169
+ $('>td, >th', tr).each( function ( i ) {
170
170
  var idx = dt.column.index( 'toData', i );
171
171
 
172
172
  if ( that.s.current[idx] === false ) {
@@ -236,6 +236,23 @@ $.extend( Responsive.prototype, {
236
236
  that._resize();
237
237
  });
238
238
 
239
+ // On Ajax reload we want to reopen any child rows which are displayed
240
+ // by responsive
241
+ dt.on( 'preXhr.dtr', function () {
242
+ var rowIds = [];
243
+ dt.rows().every( function () {
244
+ if ( this.child.isShown() ) {
245
+ rowIds.push( this.id(true) );
246
+ }
247
+ } );
248
+
249
+ dt.one( 'draw.dtr', function () {
250
+ dt.rows( rowIds ).every( function () {
251
+ that._detailsDisplay( this, false );
252
+ } );
253
+ } );
254
+ });
255
+
239
256
  dt.on( 'init.dtr', function (e, settings, details) {
240
257
  that._resizeAuto();
241
258
  that._resize();
@@ -598,7 +615,7 @@ $.extend( Responsive.prototype, {
598
615
  }
599
616
 
600
617
  // Check that the row is actually a DataTable's controlled node
601
- if ( ! dt.row( $(this).closest('tr') ).length ) {
618
+ if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
602
619
  return;
603
620
  }
604
621
 
@@ -907,6 +924,12 @@ $.extend( Responsive.prototype, {
907
924
  ':eq('+target+')' :
908
925
  target;
909
926
 
927
+ // This is a bit of a hack - we need to limit the selected nodes to just
928
+ // those of this table
929
+ if ( selector === 'td:first-child, th:first-child' ) {
930
+ selector = '>td:first-child, >th:first-child';
931
+ }
932
+
910
933
  $( selector, dt.rows( { page: 'current' } ).nodes() )
911
934
  .attr( 'tabIndex', ctx.iTabIndex )
912
935
  .data( 'dtr-keyboard', 1 );
@@ -1062,7 +1085,7 @@ Responsive.renderer = {
1062
1085
  } ).join('');
1063
1086
 
1064
1087
  return data ?
1065
- $('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
1088
+ $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
1066
1089
  false;
1067
1090
  }
1068
1091
  },
@@ -1080,7 +1103,7 @@ Responsive.renderer = {
1080
1103
  '</tr>';
1081
1104
  } ).join('');
1082
1105
 
1083
- return $('<table class="'+options.tableClass+'" width="100%"/>').append( data );
1106
+ return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
1084
1107
  }
1085
1108
  }
1086
1109
  };
@@ -1201,7 +1224,7 @@ Api.register( 'responsive.hasHidden()', function () {
1201
1224
  * @name Responsive.version
1202
1225
  * @static
1203
1226
  */
1204
- Responsive.version = '2.1.0';
1227
+ Responsive.version = '2.1.1';
1205
1228
 
1206
1229
 
1207
1230
  $.fn.dataTable.Responsive = Responsive;
@@ -59,9 +59,13 @@ _display.modal = function ( options ) {
59
59
  else {
60
60
  if ( ! update ) {
61
61
  if ( options && options.header ) {
62
- _modal.find('div.modal-header')
62
+ var header = _modal.find('div.modal-header');
63
+ var button = header.find('button').detach();
64
+
65
+ header
63
66
  .empty()
64
- .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' );
67
+ .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' )
68
+ .prepend( button );
65
69
  }
66
70
 
67
71
  _modal.find( 'div.modal-body' )
@@ -59,9 +59,13 @@ _display.modal = function ( options ) {
59
59
  else {
60
60
  if ( ! update ) {
61
61
  if ( options && options.header ) {
62
- _modal.find('div.modal-header')
62
+ var header = _modal.find('div.modal-header');
63
+ var button = header.find('button').detach();
64
+
65
+ header
63
66
  .empty()
64
- .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' );
67
+ .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' )
68
+ .prepend( button );
65
69
  }
66
70
 
67
71
  _modal.find( 'div.modal-body' )
@@ -1,11 +1,11 @@
1
- /*! RowReorder 1.1.2
1
+ /*! RowReorder 1.2.0
2
2
  * 2015-2016 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary RowReorder
7
7
  * @description Row reordering extension for DataTables
8
- * @version 1.1.2
8
+ * @version 1.2.0
9
9
  * @file dataTables.rowReorder.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
@@ -170,6 +170,10 @@ $.extend( RowReorder.prototype, {
170
170
  // Use `table().container()` rather than just the table node for IE8 -
171
171
  // otherwise it only works once...
172
172
  $(dt.table().container()).on( 'mousedown.rowReorder touchstart.rowReorder', this.c.selector, function (e) {
173
+ if ( ! that.c.enabled ) {
174
+ return;
175
+ }
176
+
173
177
  var tr = $(this).closest('tr');
174
178
 
175
179
  // Double check that it is a DataTable row
@@ -447,6 +451,7 @@ $.extend( RowReorder.prototype, {
447
451
  */
448
452
  _mouseUp: function ( e )
449
453
  {
454
+ var that = this;
450
455
  var dt = this.s.dt;
451
456
  var i, ien;
452
457
  var dataSrc = this.c.dataSrc;
@@ -507,11 +512,19 @@ $.extend( RowReorder.prototype, {
507
512
 
508
513
  // Editor interface
509
514
  if ( this.c.editor ) {
515
+ // Disable user interaction while Editor is submitting
516
+ this.c.enabled = false;
517
+
510
518
  this.c.editor
511
- .edit( diffNodes, false, {
512
- submit: 'changed'
513
- } )
519
+ .edit(
520
+ diffNodes,
521
+ false,
522
+ $.extend( {submit: 'changed'}, this.c.formOptions )
523
+ )
514
524
  .multiSet( dataSrc, idDiff )
525
+ .one( 'submitComplete', function () {
526
+ that.c.enabled = true;
527
+ } )
515
528
  .submit();
516
529
  }
517
530
 
@@ -647,6 +660,20 @@ RowReorder.defaults = {
647
660
  */
648
661
  editor: null,
649
662
 
663
+ /**
664
+ * Enable / disable RowReorder's user interaction
665
+ * @type {Boolean}
666
+ */
667
+ enabled: true,
668
+
669
+ /**
670
+ * Form options to pass to Editor when submitting a change in the row order.
671
+ * See the Editor `from-options` object for details of the options
672
+ * available.
673
+ * @type {Object}
674
+ */
675
+ formOptions: {},
676
+
650
677
  /**
651
678
  * Drag handle selector. This defines the element that when dragged will
652
679
  * reorder a row.
@@ -673,13 +700,44 @@ RowReorder.defaults = {
673
700
  };
674
701
 
675
702
 
703
+ /*
704
+ * API
705
+ */
706
+ var Api = $.fn.dataTable.Api;
707
+
708
+ // Doesn't do anything - work around for a bug in DT... Not documented
709
+ Api.register( 'rowReorder()', function () {
710
+ return this;
711
+ } );
712
+
713
+ Api.register( 'rowReorder.enable()', function ( toggle ) {
714
+ if ( toggle === undefined ) {
715
+ toggle = true;
716
+ }
717
+
718
+ return this.iterator( 'table', function ( ctx ) {
719
+ if ( ctx.rowreorder ) {
720
+ ctx.rowreorder.c.enabled = toggle;
721
+ }
722
+ } );
723
+ } );
724
+
725
+ Api.register( 'rowReorder.disable()', function () {
726
+ return this.iterator( 'table', function ( ctx ) {
727
+ if ( ctx.rowreorder ) {
728
+ ctx.rowreorder.c.enabled = false;
729
+ }
730
+ } );
731
+ } );
732
+
733
+
676
734
  /**
677
735
  * Version information
678
736
  *
679
737
  * @name RowReorder.version
680
738
  * @static
681
739
  */
682
- RowReorder.version = '1.1.2';
740
+ RowReorder.version = '1.2.0';
683
741
 
684
742
 
685
743
  $.fn.dataTable.RowReorder = RowReorder;
@@ -1,4 +1,4 @@
1
- /*! Select for DataTables 1.2.0
1
+ /*! Select for DataTables 1.2.1
2
2
  * 2015-2016 SpryMedia Ltd - datatables.net/license/mit
3
3
  */
4
4
 
@@ -6,7 +6,7 @@
6
6
  * @summary Select for DataTables
7
7
  * @description A collection of API methods, events and buttons for DataTables
8
8
  * that provides selection options of the items in a DataTable
9
- * @version 1.2.0
9
+ * @version 1.2.1
10
10
  * @file dataTables.select.js
11
11
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
12
12
  * @contact datatables.net/forums
@@ -54,7 +54,7 @@ var DataTable = $.fn.dataTable;
54
54
  // Version information for debugger
55
55
  DataTable.select = {};
56
56
 
57
- DataTable.select.version = '1.2.0';
57
+ DataTable.select.version = '1.2.1';
58
58
 
59
59
  DataTable.select.init = function ( dt ) {
60
60
  var ctx = dt.settings()[0];
@@ -71,15 +71,18 @@ DataTable.select.init = function ( dt ) {
71
71
  var info = true;
72
72
  var selector = 'td, th';
73
73
  var className = 'selected';
74
+ var setStyle = false;
74
75
 
75
76
  ctx._select = {};
76
77
 
77
78
  // Initialisation customisations
78
79
  if ( opts === true ) {
79
80
  style = 'os';
81
+ setStyle = true;
80
82
  }
81
83
  else if ( typeof opts === 'string' ) {
82
84
  style = opts;
85
+ setStyle = true;
83
86
  }
84
87
  else if ( $.isPlainObject( opts ) ) {
85
88
  if ( opts.blurable !== undefined ) {
@@ -96,6 +99,7 @@ DataTable.select.init = function ( dt ) {
96
99
 
97
100
  if ( opts.style !== undefined ) {
98
101
  style = opts.style;
102
+ setStyle = true;
99
103
  }
100
104
 
101
105
  if ( opts.selector !== undefined ) {
@@ -129,7 +133,7 @@ DataTable.select.init = function ( dt ) {
129
133
 
130
134
  // If the init options haven't enabled select, but there is a selectable
131
135
  // class name, then enable
132
- if ( $( dt.table().node() ).hasClass( 'selectable' ) ) {
136
+ if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
133
137
  dt.select.style( 'os' );
134
138
  }
135
139
  };
@@ -301,7 +305,7 @@ function disableMouseSelection( dt )
301
305
  var ctx = dt.settings()[0];
302
306
  var selector = ctx._select.selector;
303
307
 
304
- $( dt.table().body() )
308
+ $( dt.table().container() )
305
309
  .off( 'mousedown.dtSelect', selector )
306
310
  .off( 'mouseup.dtSelect', selector )
307
311
  .off( 'click.dtSelect', selector );
@@ -317,16 +321,16 @@ function disableMouseSelection( dt )
317
321
  */
318
322
  function enableMouseSelection ( dt )
319
323
  {
320
- var body = $( dt.table().body() );
324
+ var container = $( dt.table().container() );
321
325
  var ctx = dt.settings()[0];
322
326
  var selector = ctx._select.selector;
323
327
 
324
- body
328
+ container
325
329
  .on( 'mousedown.dtSelect', selector, function(e) {
326
330
  // Disallow text selection for shift clicking on the table so multi
327
331
  // element selection doesn't look terrible!
328
332
  if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
329
- body
333
+ container
330
334
  .css( '-moz-user-select', 'none' )
331
335
  .one('selectstart.dtSelect', selector, function () {
332
336
  return false;
@@ -336,7 +340,7 @@ function enableMouseSelection ( dt )
336
340
  .on( 'mouseup.dtSelect', selector, function() {
337
341
  // Allow text selection to occur again, Mozilla style (tested in FF
338
342
  // 35.0.1 - still required)
339
- body.css( '-moz-user-select', '' );
343
+ container.css( '-moz-user-select', '' );
340
344
  } )
341
345
  .on( 'click.dtSelect', selector, function ( e ) {
342
346
  var items = dt.select.items();
@@ -1000,16 +1004,26 @@ function i18n( label, def ) {
1000
1004
  };
1001
1005
  }
1002
1006
 
1007
+ // Common events with suitable namespaces
1008
+ function namespacedEvents ( config ) {
1009
+ var unique = config._eventNamespace;
1010
+
1011
+ return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
1012
+ }
1013
+
1014
+ var _buttonNamespace = 0;
1015
+
1003
1016
  $.extend( DataTable.ext.buttons, {
1004
1017
  selected: {
1005
1018
  text: i18n( 'selected', 'Selected' ),
1006
1019
  className: 'buttons-selected',
1007
- init: function ( dt ) {
1020
+ init: function ( dt, node, config ) {
1008
1021
  var that = this;
1022
+ config._eventNamespace = '.select'+(_buttonNamespace++);
1009
1023
 
1010
1024
  // .DT namespace listeners are removed by DataTables automatically
1011
1025
  // on table destroy
1012
- dt.on( 'draw.dt.DT select.dt.DT deselect.dt.DT', function () {
1026
+ dt.on( namespacedEvents(config), function () {
1013
1027
  var enable = that.rows( { selected: true } ).any() ||
1014
1028
  that.columns( { selected: true } ).any() ||
1015
1029
  that.cells( { selected: true } ).any();
@@ -1018,15 +1032,19 @@ $.extend( DataTable.ext.buttons, {
1018
1032
  } );
1019
1033
 
1020
1034
  this.disable();
1035
+ },
1036
+ destroy: function ( dt, node, config ) {
1037
+ dt.off( config._eventNamespace );
1021
1038
  }
1022
1039
  },
1023
1040
  selectedSingle: {
1024
1041
  text: i18n( 'selectedSingle', 'Selected single' ),
1025
1042
  className: 'buttons-selected-single',
1026
- init: function ( dt ) {
1043
+ init: function ( dt, node, config ) {
1027
1044
  var that = this;
1045
+ config._eventNamespace = '.select'+(_buttonNamespace++);
1028
1046
 
1029
- dt.on( 'draw.dt.DT select.dt.DT deselect.dt.DT', function () {
1047
+ dt.on( namespacedEvents(config), function () {
1030
1048
  var count = dt.rows( { selected: true } ).flatten().length +
1031
1049
  dt.columns( { selected: true } ).flatten().length +
1032
1050
  dt.cells( { selected: true } ).flatten().length;
@@ -1035,6 +1053,9 @@ $.extend( DataTable.ext.buttons, {
1035
1053
  } );
1036
1054
 
1037
1055
  this.disable();
1056
+ },
1057
+ destroy: function ( dt, node, config ) {
1058
+ dt.off( config._eventNamespace );
1038
1059
  }
1039
1060
  },
1040
1061
  selectAll: {
@@ -1051,10 +1072,11 @@ $.extend( DataTable.ext.buttons, {
1051
1072
  action: function () {
1052
1073
  clear( this.settings()[0], true );
1053
1074
  },
1054
- init: function ( dt ) {
1075
+ init: function ( dt, node, config ) {
1055
1076
  var that = this;
1077
+ config._eventNamespace = '.select'+(_buttonNamespace++);
1056
1078
 
1057
- dt.on( 'draw.dt.DT select.dt.DT deselect.dt.DT', function () {
1079
+ dt.on( namespacedEvents(config), function () {
1058
1080
  var count = dt.rows( { selected: true } ).flatten().length +
1059
1081
  dt.columns( { selected: true } ).flatten().length +
1060
1082
  dt.cells( { selected: true } ).flatten().length;
@@ -1063,6 +1085,9 @@ $.extend( DataTable.ext.buttons, {
1063
1085
  } );
1064
1086
 
1065
1087
  this.disable();
1088
+ },
1089
+ destroy: function ( dt, node, config ) {
1090
+ dt.off( config._eventNamespace );
1066
1091
  }
1067
1092
  }
1068
1093
  } );
@@ -1,15 +1,15 @@
1
- /*! DataTables 1.10.12
2
- * ©2008-2015 SpryMedia Ltd - datatables.net/license
1
+ /*! DataTables 1.10.13
2
+ * ©2008-2016 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.12
8
+ * @version 1.10.13
9
9
  * @file jquery.dataTables.js
10
- * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
- * @contact www.sprymedia.co.uk/contact
12
- * @copyright Copyright 2008-2015 SpryMedia Ltd.
10
+ * @author SpryMedia Ltd
11
+ * @contact www.datatables.net
12
+ * @copyright Copyright 2008-2016 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
@@ -279,7 +279,7 @@
279
279
  * "bPaginate": false
280
280
  * } );
281
281
  *
282
- * $(window).bind('resize', function () {
282
+ * $(window).on('resize', function () {
283
283
  * oTable.fnAdjustColumnSizing();
284
284
  * } );
285
285
  * } );
@@ -1101,7 +1101,7 @@
1101
1101
  var oLanguage = oSettings.oLanguage;
1102
1102
  $.extend( true, oLanguage, oInit.oLanguage );
1103
1103
 
1104
- if ( oLanguage.sUrl !== "" )
1104
+ if ( oLanguage.sUrl )
1105
1105
  {
1106
1106
  /* Get the language definitions from a file - because this Ajax call makes the language
1107
1107
  * get async to the remainder of this function we use bInitHandedOff to indicate that
@@ -1213,131 +1213,125 @@
1213
1213
  }
1214
1214
 
1215
1215
  var features = oSettings.oFeatures;
1216
+ var loadedInit = function () {
1217
+ /*
1218
+ * Sorting
1219
+ * @todo For modularisation (1.11) this needs to do into a sort start up handler
1220
+ */
1216
1221
 
1217
- /* Must be done after everything which can be overridden by the state saving! */
1218
- if ( oInit.bStateSave )
1219
- {
1220
- features.bStateSave = true;
1221
- _fnLoadState( oSettings, oInit );
1222
- _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1223
- }
1222
+ // If aaSorting is not defined, then we use the first indicator in asSorting
1223
+ // in case that has been altered, so the default sort reflects that option
1224
+ if ( oInit.aaSorting === undefined ) {
1225
+ var sorting = oSettings.aaSorting;
1226
+ for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1227
+ sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1228
+ }
1229
+ }
1224
1230
 
1231
+ /* Do a first pass on the sorting classes (allows any size changes to be taken into
1232
+ * account, and also will apply sorting disabled classes if disabled
1233
+ */
1234
+ _fnSortingClasses( oSettings );
1225
1235
 
1226
- /*
1227
- * Sorting
1228
- * @todo For modularisation (1.11) this needs to do into a sort start up handler
1229
- */
1236
+ if ( features.bSort ) {
1237
+ _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1238
+ if ( oSettings.bSorted ) {
1239
+ var aSort = _fnSortFlatten( oSettings );
1240
+ var sortedColumns = {};
1230
1241
 
1231
- // If aaSorting is not defined, then we use the first indicator in asSorting
1232
- // in case that has been altered, so the default sort reflects that option
1233
- if ( oInit.aaSorting === undefined )
1234
- {
1235
- var sorting = oSettings.aaSorting;
1236
- for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
1237
- {
1238
- sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1239
- }
1240
- }
1242
+ $.each( aSort, function (i, val) {
1243
+ sortedColumns[ val.src ] = val.dir;
1244
+ } );
1241
1245
 
1242
- /* Do a first pass on the sorting classes (allows any size changes to be taken into
1243
- * account, and also will apply sorting disabled classes if disabled
1244
- */
1245
- _fnSortingClasses( oSettings );
1246
+ _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1247
+ _fnSortAria( oSettings );
1248
+ }
1249
+ } );
1250
+ }
1246
1251
 
1247
- if ( features.bSort )
1248
- {
1249
1252
  _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1250
- if ( oSettings.bSorted ) {
1251
- var aSort = _fnSortFlatten( oSettings );
1252
- var sortedColumns = {};
1253
+ if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1254
+ _fnSortingClasses( oSettings );
1255
+ }
1256
+ }, 'sc' );
1253
1257
 
1254
- $.each( aSort, function (i, val) {
1255
- sortedColumns[ val.src ] = val.dir;
1256
- } );
1257
1258
 
1258
- _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1259
- _fnSortAria( oSettings );
1260
- }
1259
+ /*
1260
+ * Final init
1261
+ * Cache the header, body and footer as required, creating them if needed
1262
+ */
1263
+
1264
+ // Work around for Webkit bug 83867 - store the caption-side before removing from doc
1265
+ var captions = $this.children('caption').each( function () {
1266
+ this._captionSide = $(this).css('caption-side');
1261
1267
  } );
1262
- }
1263
1268
 
1264
- _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1265
- if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1266
- _fnSortingClasses( oSettings );
1269
+ var thead = $this.children('thead');
1270
+ if ( thead.length === 0 ) {
1271
+ thead = $('<thead/>').appendTo($this);
1267
1272
  }
1268
- }, 'sc' );
1273
+ oSettings.nTHead = thead[0];
1269
1274
 
1275
+ var tbody = $this.children('tbody');
1276
+ if ( tbody.length === 0 ) {
1277
+ tbody = $('<tbody/>').appendTo($this);
1278
+ }
1279
+ oSettings.nTBody = tbody[0];
1270
1280
 
1271
- /*
1272
- * Final init
1273
- * Cache the header, body and footer as required, creating them if needed
1274
- */
1281
+ var tfoot = $this.children('tfoot');
1282
+ if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1283
+ // If we are a scrolling table, and no footer has been given, then we need to create
1284
+ // a tfoot element for the caption element to be appended to
1285
+ tfoot = $('<tfoot/>').appendTo($this);
1286
+ }
1275
1287
 
1276
- // Work around for Webkit bug 83867 - store the caption-side before removing from doc
1277
- var captions = $this.children('caption').each( function () {
1278
- this._captionSide = $this.css('caption-side');
1279
- } );
1288
+ if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1289
+ $this.addClass( oClasses.sNoFooter );
1290
+ }
1291
+ else if ( tfoot.length > 0 ) {
1292
+ oSettings.nTFoot = tfoot[0];
1293
+ _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1294
+ }
1280
1295
 
1281
- var thead = $this.children('thead');
1282
- if ( thead.length === 0 )
1283
- {
1284
- thead = $('<thead/>').appendTo(this);
1285
- }
1286
- oSettings.nTHead = thead[0];
1296
+ /* Check if there is data passing into the constructor */
1297
+ if ( oInit.aaData ) {
1298
+ for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1299
+ _fnAddData( oSettings, oInit.aaData[ i ] );
1300
+ }
1301
+ }
1302
+ else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1303
+ /* Grab the data from the page - only do this when deferred loading or no Ajax
1304
+ * source since there is no point in reading the DOM data if we are then going
1305
+ * to replace it with Ajax data
1306
+ */
1307
+ _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1308
+ }
1287
1309
 
1288
- var tbody = $this.children('tbody');
1289
- if ( tbody.length === 0 )
1290
- {
1291
- tbody = $('<tbody/>').appendTo(this);
1292
- }
1293
- oSettings.nTBody = tbody[0];
1310
+ /* Copy the data index array */
1311
+ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1294
1312
 
1295
- var tfoot = $this.children('tfoot');
1296
- if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
1297
- {
1298
- // If we are a scrolling table, and no footer has been given, then we need to create
1299
- // a tfoot element for the caption element to be appended to
1300
- tfoot = $('<tfoot/>').appendTo(this);
1301
- }
1313
+ /* Initialisation complete - table can be drawn */
1314
+ oSettings.bInitialised = true;
1302
1315
 
1303
- if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1304
- $this.addClass( oClasses.sNoFooter );
1305
- }
1306
- else if ( tfoot.length > 0 ) {
1307
- oSettings.nTFoot = tfoot[0];
1308
- _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1309
- }
1316
+ /* Check if we need to initialise the table (it might not have been handed off to the
1317
+ * language processor)
1318
+ */
1319
+ if ( bInitHandedOff === false ) {
1320
+ _fnInitialise( oSettings );
1321
+ }
1322
+ };
1310
1323
 
1311
- /* Check if there is data passing into the constructor */
1312
- if ( oInit.aaData )
1324
+ /* Must be done after everything which can be overridden by the state saving! */
1325
+ if ( oInit.bStateSave )
1313
1326
  {
1314
- for ( i=0 ; i<oInit.aaData.length ; i++ )
1315
- {
1316
- _fnAddData( oSettings, oInit.aaData[ i ] );
1317
- }
1327
+ features.bStateSave = true;
1328
+ _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1329
+ _fnLoadState( oSettings, oInit, loadedInit );
1318
1330
  }
1319
- else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
1320
- {
1321
- /* Grab the data from the page - only do this when deferred loading or no Ajax
1322
- * source since there is no point in reading the DOM data if we are then going
1323
- * to replace it with Ajax data
1324
- */
1325
- _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1331
+ else {
1332
+ loadedInit();
1326
1333
  }
1327
1334
 
1328
- /* Copy the data index array */
1329
- oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1330
-
1331
- /* Initialisation complete - table can be drawn */
1332
- oSettings.bInitialised = true;
1333
-
1334
- /* Check if we need to initialise the table (it might not have been handed off to the
1335
- * language processor)
1336
- */
1337
- if ( bInitHandedOff === false )
1338
- {
1339
- _fnInitialise( oSettings );
1340
- }
1341
1335
  } );
1342
1336
  _that = null;
1343
1337
  return this;
@@ -1368,8 +1362,10 @@
1368
1362
  var _re_dic = {};
1369
1363
  var _re_new_lines = /[\r\n]/g;
1370
1364
  var _re_html = /<.*?>/g;
1371
- var _re_date_start = /^[\w\+\-]/;
1372
- var _re_date_end = /[\w\+\-]$/;
1365
+
1366
+ // This is not strict ISO8601 - Date.parse() is quite lax, although
1367
+ // implementations differ between browsers.
1368
+ var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1373
1369
 
1374
1370
  // Escape regular expression special characters
1375
1371
  var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
@@ -1851,7 +1847,7 @@
1851
1847
  .css( {
1852
1848
  position: 'fixed',
1853
1849
  top: 0,
1854
- left: 0,
1850
+ left: $(window).scrollLeft()*-1, // allow for scrolling
1855
1851
  height: 1,
1856
1852
  width: 1,
1857
1853
  overflow: 'hidden'
@@ -2544,7 +2540,7 @@
2544
2540
  function _fnSplitObjNotation( str )
2545
2541
  {
2546
2542
  return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2547
- return s.replace(/\\./g, '.');
2543
+ return s.replace(/\\\./g, '.');
2548
2544
  } );
2549
2545
  }
2550
2546
 
@@ -4202,13 +4198,13 @@
4202
4198
  var jqFilter = $('input', filter)
4203
4199
  .val( previousSearch.sSearch )
4204
4200
  .attr( 'placeholder', language.sSearchPlaceholder )
4205
- .bind(
4201
+ .on(
4206
4202
  'keyup.DT search.DT input.DT paste.DT cut.DT',
4207
4203
  searchDelay ?
4208
4204
  _fnThrottle( searchFn, searchDelay ) :
4209
4205
  searchFn
4210
4206
  )
4211
- .bind( 'keypress.DT', function(e) {
4207
+ .on( 'keypress.DT', function(e) {
4212
4208
  /* Prevent form submission */
4213
4209
  if ( e.keyCode == 13 ) {
4214
4210
  return false;
@@ -4338,16 +4334,19 @@
4338
4334
  }
4339
4335
 
4340
4336
  var data;
4337
+ var out = [];
4341
4338
  var display = settings.aiDisplay;
4342
4339
  var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4343
4340
 
4344
- for ( var i=display.length-1 ; i>=0 ; i-- ) {
4341
+ for ( var i=0 ; i<display.length ; i++ ) {
4345
4342
  data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4346
4343
 
4347
- if ( ! rpSearch.test( data ) ) {
4348
- display.splice( i, 1 );
4344
+ if ( rpSearch.test( data ) ) {
4345
+ out.push( display[i] );
4349
4346
  }
4350
4347
  }
4348
+
4349
+ settings.aiDisplay = out;
4351
4350
  }
4352
4351
 
4353
4352
 
@@ -4367,6 +4366,7 @@
4367
4366
  var prevSearch = settings.oPreviousSearch.sSearch;
4368
4367
  var displayMaster = settings.aiDisplayMaster;
4369
4368
  var display, invalidated, i;
4369
+ var filtered = [];
4370
4370
 
4371
4371
  // Need to take account of custom filtering functions - always filter
4372
4372
  if ( DataTable.ext.search.length !== 0 ) {
@@ -4395,11 +4395,13 @@
4395
4395
  // Search the display array
4396
4396
  display = settings.aiDisplay;
4397
4397
 
4398
- for ( i=display.length-1 ; i>=0 ; i-- ) {
4399
- if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4400
- display.splice( i, 1 );
4398
+ for ( i=0 ; i<display.length ; i++ ) {
4399
+ if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4400
+ filtered.push( display[i] );
4401
4401
  }
4402
4402
  }
4403
+
4404
+ settings.aiDisplay = filtered;
4403
4405
  }
4404
4406
  }
4405
4407
 
@@ -4812,13 +4814,13 @@
4812
4814
  // reference is broken by the use of outerHTML
4813
4815
  $('select', div)
4814
4816
  .val( settings._iDisplayLength )
4815
- .bind( 'change.DT', function(e) {
4817
+ .on( 'change.DT', function(e) {
4816
4818
  _fnLengthChange( settings, $(this).val() );
4817
4819
  _fnDraw( settings );
4818
4820
  } );
4819
4821
 
4820
4822
  // Update node value whenever anything changes the table's length
4821
- $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
4823
+ $(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4822
4824
  if ( settings === s ) {
4823
4825
  $('select', div).val( len );
4824
4826
  }
@@ -5683,7 +5685,7 @@
5683
5685
 
5684
5686
  if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5685
5687
  var bindResize = function () {
5686
- $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5688
+ $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5687
5689
  _fnAdjustColumnSizing( oSettings );
5688
5690
  } ) );
5689
5691
  };
@@ -6294,86 +6296,102 @@
6294
6296
  * Attempt to load a saved table state
6295
6297
  * @param {object} oSettings dataTables settings object
6296
6298
  * @param {object} oInit DataTables init object so we can override settings
6299
+ * @param {function} callback Callback to execute when the state has been loaded
6297
6300
  * @memberof DataTable#oApi
6298
6301
  */
6299
- function _fnLoadState ( settings, oInit )
6302
+ function _fnLoadState ( settings, oInit, callback )
6300
6303
  {
6301
6304
  var i, ien;
6302
6305
  var columns = settings.aoColumns;
6306
+ var loaded = function ( s ) {
6307
+ if ( ! s || ! s.time ) {
6308
+ callback();
6309
+ return;
6310
+ }
6303
6311
 
6304
- if ( ! settings.oFeatures.bStateSave ) {
6305
- return;
6306
- }
6307
-
6308
- var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
6309
- if ( ! state || ! state.time ) {
6310
- return;
6311
- }
6312
+ // Allow custom and plug-in manipulation functions to alter the saved data set and
6313
+ // cancelling of loading by returning false
6314
+ var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
6315
+ if ( $.inArray( false, abStateLoad ) !== -1 ) {
6316
+ callback();
6317
+ return;
6318
+ }
6312
6319
 
6313
- /* Allow custom and plug-in manipulation functions to alter the saved data set and
6314
- * cancelling of loading by returning false
6315
- */
6316
- var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
6317
- if ( $.inArray( false, abStateLoad ) !== -1 ) {
6318
- return;
6319
- }
6320
+ // Reject old data
6321
+ var duration = settings.iStateDuration;
6322
+ if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6323
+ callback();
6324
+ return;
6325
+ }
6320
6326
 
6321
- /* Reject old data */
6322
- var duration = settings.iStateDuration;
6323
- if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
6324
- return;
6325
- }
6327
+ // Number of columns have changed - all bets are off, no restore of settings
6328
+ if ( s.columns && columns.length !== s.columns.length ) {
6329
+ callback();
6330
+ return;
6331
+ }
6326
6332
 
6327
- // Number of columns have changed - all bets are off, no restore of settings
6328
- if ( columns.length !== state.columns.length ) {
6329
- return;
6330
- }
6333
+ // Store the saved state so it might be accessed at any time
6334
+ settings.oLoadedState = $.extend( true, {}, state );
6331
6335
 
6332
- // Store the saved state so it might be accessed at any time
6333
- settings.oLoadedState = $.extend( true, {}, state );
6336
+ // Restore key features - todo - for 1.11 this needs to be done by
6337
+ // subscribed events
6338
+ if ( s.start !== undefined ) {
6339
+ settings._iDisplayStart = s.start;
6340
+ settings.iInitDisplayStart = s.start;
6341
+ }
6342
+ if ( s.length !== undefined ) {
6343
+ settings._iDisplayLength = s.length;
6344
+ }
6334
6345
 
6335
- // Restore key features - todo - for 1.11 this needs to be done by
6336
- // subscribed events
6337
- if ( state.start !== undefined ) {
6338
- settings._iDisplayStart = state.start;
6339
- settings.iInitDisplayStart = state.start;
6340
- }
6341
- if ( state.length !== undefined ) {
6342
- settings._iDisplayLength = state.length;
6343
- }
6346
+ // Order
6347
+ if ( s.order !== undefined ) {
6348
+ settings.aaSorting = [];
6349
+ $.each( s.order, function ( i, col ) {
6350
+ settings.aaSorting.push( col[0] >= columns.length ?
6351
+ [ 0, col[1] ] :
6352
+ col
6353
+ );
6354
+ } );
6355
+ }
6344
6356
 
6345
- // Order
6346
- if ( state.order !== undefined ) {
6347
- settings.aaSorting = [];
6348
- $.each( state.order, function ( i, col ) {
6349
- settings.aaSorting.push( col[0] >= columns.length ?
6350
- [ 0, col[1] ] :
6351
- col
6352
- );
6353
- } );
6354
- }
6357
+ // Search
6358
+ if ( s.search !== undefined ) {
6359
+ $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6360
+ }
6355
6361
 
6356
- // Search
6357
- if ( state.search !== undefined ) {
6358
- $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
6359
- }
6362
+ // Columns
6363
+ //
6364
+ if ( s.columns ) {
6365
+ for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6366
+ var col = s.columns[i];
6360
6367
 
6361
- // Columns
6362
- for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
6363
- var col = state.columns[i];
6368
+ // Visibility
6369
+ if ( col.visible !== undefined ) {
6370
+ columns[i].bVisible = col.visible;
6371
+ }
6364
6372
 
6365
- // Visibility
6366
- if ( col.visible !== undefined ) {
6367
- columns[i].bVisible = col.visible;
6373
+ // Search
6374
+ if ( col.search !== undefined ) {
6375
+ $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6376
+ }
6377
+ }
6368
6378
  }
6369
6379
 
6370
- // Search
6371
- if ( col.search !== undefined ) {
6372
- $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6373
- }
6380
+ _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
6381
+ callback();
6382
+ }
6383
+
6384
+ if ( ! settings.oFeatures.bStateSave ) {
6385
+ callback();
6386
+ return;
6374
6387
  }
6375
6388
 
6376
- _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
6389
+ var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6390
+
6391
+ if ( state !== undefined ) {
6392
+ loaded( state );
6393
+ }
6394
+ // otherwise, wait for the loaded callback to be executed
6377
6395
  }
6378
6396
 
6379
6397
 
@@ -6526,17 +6544,17 @@
6526
6544
  function _fnBindAction( n, oData, fn )
6527
6545
  {
6528
6546
  $(n)
6529
- .bind( 'click.DT', oData, function (e) {
6547
+ .on( 'click.DT', oData, function (e) {
6530
6548
  n.blur(); // Remove focus outline for mouse users
6531
6549
  fn(e);
6532
6550
  } )
6533
- .bind( 'keypress.DT', oData, function (e){
6551
+ .on( 'keypress.DT', oData, function (e){
6534
6552
  if ( e.which === 13 ) {
6535
6553
  e.preventDefault();
6536
6554
  fn(e);
6537
6555
  }
6538
6556
  } )
6539
- .bind( 'selectstart.DT', function () {
6557
+ .on( 'selectstart.DT', function () {
6540
6558
  /* Take the brutal approach to cancelling text selection */
6541
6559
  return false;
6542
6560
  } );
@@ -7664,7 +7682,8 @@
7664
7682
  }
7665
7683
 
7666
7684
  for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7667
- a = selector[i] && selector[i].split ?
7685
+ // Only split on simple strings - complex expressions will be jQuery selectors
7686
+ a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7668
7687
  selector[i].split(',') :
7669
7688
  [ selector[i] ];
7670
7689
 
@@ -7804,6 +7823,7 @@
7804
7823
 
7805
7824
  var __row_selector = function ( settings, selector, opts )
7806
7825
  {
7826
+ var rows;
7807
7827
  var run = function ( sel ) {
7808
7828
  var selInt = _intVal( sel );
7809
7829
  var i, ien;
@@ -7815,13 +7835,15 @@
7815
7835
  return [ selInt ];
7816
7836
  }
7817
7837
 
7818
- var rows = _selector_row_indexes( settings, opts );
7838
+ if ( ! rows ) {
7839
+ rows = _selector_row_indexes( settings, opts );
7840
+ }
7819
7841
 
7820
7842
  if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7821
7843
  // Selector - integer
7822
7844
  return [ selInt ];
7823
7845
  }
7824
- else if ( ! sel ) {
7846
+ else if ( sel === null || sel === undefined || sel === '' ) {
7825
7847
  // Selector - none
7826
7848
  return rows;
7827
7849
  }
@@ -8134,7 +8156,7 @@
8134
8156
  addRow( data, klass );
8135
8157
 
8136
8158
  if ( row._details ) {
8137
- row._details.remove();
8159
+ row._details.detach();
8138
8160
  }
8139
8161
 
8140
8162
  row._details = $(rows);
@@ -8335,7 +8357,7 @@
8335
8357
  // can be an array of these items, comma separated list, or an array of comma
8336
8358
  // separated lists
8337
8359
 
8338
- var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8360
+ var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8339
8361
 
8340
8362
 
8341
8363
  // r1 and r2 are redundant - but it means that the parameters match for the
@@ -9082,6 +9104,10 @@
9082
9104
  var t = $(table).get(0);
9083
9105
  var is = false;
9084
9106
 
9107
+ if ( table instanceof DataTable.Api ) {
9108
+ return true;
9109
+ }
9110
+
9085
9111
  $.each( DataTable.settings, function (i, o) {
9086
9112
  var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9087
9113
  var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
@@ -9170,9 +9196,11 @@
9170
9196
  var args = Array.prototype.slice.call(arguments);
9171
9197
 
9172
9198
  // Add the `dt` namespace automatically if it isn't already present
9173
- if ( ! args[0].match(/\.dt\b/) ) {
9174
- args[0] += '.dt';
9175
- }
9199
+ args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9200
+ return ! e.match(/\.dt\b/) ?
9201
+ e+'.dt' :
9202
+ e;
9203
+ } ).join( ' ' );
9176
9204
 
9177
9205
  var inst = $( this.tables().nodes() );
9178
9206
  inst[key].apply( inst, args );
@@ -9237,8 +9265,8 @@
9237
9265
  // Blitz all `DT` namespaced events (these are internal events, the
9238
9266
  // lowercase, `dt` events are user subscribed and they are responsible
9239
9267
  // for removing them
9240
- jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9241
- $(window).unbind('.DT-'+settings.sInstance);
9268
+ jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9269
+ $(window).off('.DT-'+settings.sInstance);
9242
9270
 
9243
9271
  // When scrolling we had to break the table up - restore it
9244
9272
  if ( table != thead.parentNode ) {
@@ -9368,7 +9396,7 @@
9368
9396
  * @type string
9369
9397
  * @default Version number
9370
9398
  */
9371
- DataTable.version = "1.10.12";
9399
+ DataTable.version = "1.10.13";
9372
9400
 
9373
9401
  /**
9374
9402
  * Private data store, containing all of the settings objects that are
@@ -10876,6 +10904,8 @@
10876
10904
  * @type function
10877
10905
  * @member
10878
10906
  * @param {object} settings DataTables settings object
10907
+ * @param {object} callback Callback that can be executed when done. It
10908
+ * should be passed the loaded state object.
10879
10909
  * @return {object} The DataTables state object to be loaded
10880
10910
  *
10881
10911
  * @dtopt Callbacks
@@ -10885,21 +10915,14 @@
10885
10915
  * $(document).ready( function() {
10886
10916
  * $('#example').dataTable( {
10887
10917
  * "stateSave": true,
10888
- * "stateLoadCallback": function (settings) {
10889
- * var o;
10890
- *
10891
- * // Send an Ajax request to the server to get the data. Note that
10892
- * // this is a synchronous request.
10918
+ * "stateLoadCallback": function (settings, callback) {
10893
10919
  * $.ajax( {
10894
10920
  * "url": "/state_load",
10895
- * "async": false,
10896
10921
  * "dataType": "json",
10897
10922
  * "success": function (json) {
10898
- * o = json;
10923
+ * callback( json );
10899
10924
  * }
10900
10925
  * } );
10901
- *
10902
- * return o;
10903
10926
  * }
10904
10927
  * } );
10905
10928
  * } );
@@ -11838,14 +11861,15 @@
11838
11861
 
11839
11862
 
11840
11863
  /**
11841
- * DataTables features four different built-in options for the buttons to
11864
+ * DataTables features six different built-in options for the buttons to
11842
11865
  * display for pagination control:
11843
11866
  *
11867
+ * * `numbers` - Page number buttons only
11844
11868
  * * `simple` - 'Previous' and 'Next' buttons only
11845
11869
  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11846
11870
  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11847
- * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11848
- * page numbers
11871
+ * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11872
+ * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11849
11873
  *
11850
11874
  * Further methods can be added using {@link DataTable.ext.oPagination}.
11851
11875
  * @type string
@@ -14494,6 +14518,10 @@
14494
14518
  full_numbers: function ( page, pages ) {
14495
14519
  return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14496
14520
  },
14521
+
14522
+ first_last_numbers: function (page, pages) {
14523
+ return ['first', _numbers(page, pages), 'last'];
14524
+ },
14497
14525
 
14498
14526
  // For testing and plug-ins to use
14499
14527
  _numbers: _numbers,
@@ -14605,7 +14633,7 @@
14605
14633
 
14606
14634
  attach( $(host).empty(), buttons );
14607
14635
 
14608
- if ( activeEl ) {
14636
+ if ( activeEl !== undefined ) {
14609
14637
  $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14610
14638
  }
14611
14639
  }
@@ -14628,10 +14656,10 @@
14628
14656
  // Dates (only those recognised by the browser's Date.parse)
14629
14657
  function ( d, settings )
14630
14658
  {
14631
- // V8 will remove any unknown characters at the start and end of the
14632
- // expression, leading to false matches such as `$245.12` or `10%` being
14633
- // a valid date. See forum thread 18941 for detail.
14634
- if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14659
+ // V8 tries _very_ hard to make a string passed into `Date.parse()`
14660
+ // valid, so we need to use a regex to restrict date formats. Use a
14661
+ // plug-in for anything other than ISO8601 style strings
14662
+ if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14635
14663
  return null;
14636
14664
  }
14637
14665
  var parsed = Date.parse(d);
@@ -14768,7 +14796,7 @@
14768
14796
  $.extend( _ext.type.order, {
14769
14797
  // Dates
14770
14798
  "date-pre": function ( d ) {
14771
- return Date.parse( d ) || 0;
14799
+ return Date.parse( d ) || -Infinity;
14772
14800
  },
14773
14801
 
14774
14802
  // html
@@ -14939,6 +14967,7 @@
14939
14967
  return __htmlEscapeEntities( d );
14940
14968
  }
14941
14969
 
14970
+ flo = flo.toFixed( precision );
14942
14971
  d = Math.abs( flo );
14943
14972
 
14944
14973
  var intPart = parseInt( d, 10 );