jquery-datatables 1.10.19.1 → 1.10.20

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/README.md +28 -1
  4. data/app/assets/javascripts/datatables/dataTables.uikit.js +2 -2
  5. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +42 -29
  6. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap.js +1 -1
  7. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap4.js +8 -2
  8. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +6 -3
  9. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.foundation.js +5 -4
  10. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +58 -6
  11. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +16 -5
  12. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.semanticui.js +1 -1
  13. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +267 -152
  14. data/app/assets/javascripts/datatables/extensions/ColReorder/colReorder.foundation.js +1 -1
  15. data/app/assets/javascripts/datatables/extensions/ColReorder/dataTables.colReorder.js +121 -52
  16. data/app/assets/javascripts/datatables/extensions/FixedColumns/dataTables.fixedColumns.js +32 -5
  17. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +166 -63
  18. data/app/assets/javascripts/datatables/extensions/KeyTable/keyTable.foundation.js +1 -1
  19. data/app/assets/javascripts/datatables/extensions/RowGroup/dataTables.rowGroup.js +105 -53
  20. data/app/assets/javascripts/datatables/extensions/RowGroup/rowGroup.foundation.js +1 -1
  21. data/app/assets/javascripts/datatables/extensions/RowGroup/{rowGroup.semanicui.js → rowGroup.semanticui.js} +0 -0
  22. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +10 -9
  23. data/app/assets/javascripts/datatables/extensions/RowReorder/rowReorder.foundation.js +1 -1
  24. data/app/assets/javascripts/datatables/extensions/Scroller/dataTables.scroller.js +519 -636
  25. data/app/assets/javascripts/datatables/extensions/Scroller/scroller.foundation.js +1 -1
  26. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +49 -18
  27. data/app/assets/javascripts/datatables/extensions/Select/select.foundation.js +1 -1
  28. data/app/assets/javascripts/datatables/jquery.dataTables.js +97 -60
  29. data/app/assets/javascripts/datatables/plugins/api/average.js +7 -6
  30. data/app/assets/javascripts/datatables/plugins/api/sum.js +7 -6
  31. data/app/assets/javascripts/datatables/plugins/pagination/ellipses.js +160 -0
  32. data/app/assets/javascripts/datatables/plugins/pagination/extjs.js +137 -0
  33. data/app/assets/javascripts/datatables/plugins/pagination/four_button.js +110 -0
  34. data/app/assets/javascripts/datatables/plugins/pagination/full_numbers_no_ellipses.js +59 -0
  35. data/app/assets/javascripts/datatables/plugins/pagination/input.js +22 -19
  36. data/app/assets/javascripts/datatables/plugins/pagination/scrolling.js +130 -0
  37. data/app/assets/javascripts/datatables/plugins/pagination/select.js +97 -0
  38. data/app/assets/javascripts/datatables/plugins/pagination/simple_incremental_bootstrap.js +154 -0
  39. data/app/assets/javascripts/datatables/plugins/pagination/simple_numbers_no_ellipses.js +59 -0
  40. data/app/assets/javascripts/datatables/plugins/search/dataTables.alphabetSearch.js +440 -399
  41. data/app/assets/javascripts/datatables/plugins/sorting/enum.js +51 -0
  42. data/app/assets/javascripts/datatables/plugins/type-detection/date-dd-MMM-yyyy.js +63 -0
  43. data/app/assets/javascripts/datatables/plugins/type-detection/date-de.js +125 -0
  44. data/app/assets/javascripts/datatables/plugins/type-detection/date-eu.js +64 -0
  45. data/app/assets/javascripts/datatables/plugins/type-detection/date-euro.js +48 -0
  46. data/app/assets/javascripts/datatables/plugins/type-detection/date-uk.js +35 -12
  47. data/app/assets/javascripts/datatables/plugins/type-detection/datetime-moment.js +74 -0
  48. data/app/assets/javascripts/datatables/plugins/type-detection/datetime-us.js +86 -0
  49. data/app/assets/javascripts/datatables/plugins/type-detection/file-size.js +37 -13
  50. data/app/assets/javascripts/datatables/plugins/type-detection/ip-address.js +113 -11
  51. data/app/assets/javascripts/datatables/plugins/type-detection/numString.js +63 -0
  52. data/app/assets/javascripts/datatables/plugins/type-detection/percent.js +34 -0
  53. data/app/assets/javascripts/datatables/plugins/type-detection/time-elapsed-dhms.js +42 -0
  54. data/app/assets/javascripts/datatables/plugins/type-detection/time.js +56 -0
  55. data/app/assets/javascripts/datatables/plugins/type-detection/title-numeric.js +40 -0
  56. data/app/assets/javascripts/datatables/plugins/type-detection/title-string.js +36 -0
  57. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.dataTables.scss +10 -3
  58. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap.scss +12 -3
  59. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap4.scss +13 -6
  60. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.dataTables.scss +2 -0
  61. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.foundation.scss +5 -1
  62. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.jqueryui.scss +1 -0
  63. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.semanticui.scss +2 -1
  64. data/app/assets/stylesheets/datatables/extensions/Buttons/common.scss +10 -0
  65. data/app/assets/stylesheets/datatables/extensions/Buttons/mixins.scss +42 -30
  66. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap.scss +11 -7
  67. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.foundation.scss +1 -0
  68. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.dataTables.scss +13 -5
  69. data/app/assets/stylesheets/datatables/extensions/RowGroup/rowGroup.dataTables.scss +20 -2
  70. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.dataTables.scss +15 -2
  71. data/lib/jquery-datatables/version.rb +1 -1
  72. metadata +26 -12
  73. data/app/assets/javascripts/datatables/dataTables.bootstrap2.js +0 -162
  74. data/app/assets/javascripts/datatables/extensions/ColReorder/colReorder.semanicui.js +0 -38
  75. data/app/assets/javascripts/datatables/extensions/FixedColumns/fixedColumns.semanicui.js +0 -38
  76. data/app/assets/javascripts/datatables/extensions/FixedHeader/fixedHeader.semanicui.js +0 -38
  77. data/app/assets/javascripts/datatables/extensions/KeyTable/keyTable.semanicui.js +0 -38
  78. data/app/assets/javascripts/datatables/extensions/RowReorder/rowReorder.semanicui.js +0 -38
  79. data/app/assets/stylesheets/datatables/dataTables.bootstrap2.scss +0 -178
@@ -1,4 +1,4 @@
1
- /*! Bootstrap 4 styling wrapper for KeyTable
1
+ /*! Foundation styling wrapper for KeyTable
2
2
  * ©2018 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -1,15 +1,15 @@
1
- /*! RowGroup 1.0.4
2
- * ©2017-2018 SpryMedia Ltd - datatables.net/license
1
+ /*! RowGroup 1.1.1
2
+ * ©2017-2019 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary RowGroup
7
7
  * @description RowGrouping for DataTables
8
- * @version 1.0.4
8
+ * @version 1.1.1
9
9
  * @file dataTables.rowGroup.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact datatables.net
12
- * @copyright Copyright 2017-2018 SpryMedia Ltd.
12
+ * @copyright Copyright 2017-2019 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/mit
@@ -66,9 +66,7 @@ var RowGroup = function ( dt, opts ) {
66
66
 
67
67
  // Internal settings
68
68
  this.s = {
69
- dt: new DataTable.Api( dt ),
70
-
71
- dataFn: DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc )
69
+ dt: new DataTable.Api( dt )
72
70
  };
73
71
 
74
72
  // DOM items
@@ -107,7 +105,6 @@ $.extend( RowGroup.prototype, {
107
105
  var dt = this.s.dt;
108
106
 
109
107
  this.c.dataSrc = val;
110
- this.s.dataFn = DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc );
111
108
 
112
109
  $(dt.table().node()).triggerHandler( 'rowgroup-datasrc.dt', [ dt, val ] );
113
110
 
@@ -146,17 +143,6 @@ $.extend( RowGroup.prototype, {
146
143
  {
147
144
  var that = this;
148
145
  var dt = this.s.dt;
149
- var rows = dt.rows();
150
- var groups = [];
151
-
152
- rows.every( function () {
153
- var d = this.data();
154
- var group = that.s.dataFn( d );
155
-
156
- if ( groups.indexOf(group) == -1 ) {
157
- groups.push( group );
158
- }
159
- } );
160
146
 
161
147
  dt.on( 'draw.dtrg', function () {
162
148
  if ( that.c.enable ) {
@@ -171,6 +157,10 @@ $.extend( RowGroup.prototype, {
171
157
  dt.on( 'destroy', function () {
172
158
  dt.off( '.dtrg' );
173
159
  } );
160
+
161
+ dt.on('responsive-resize.dt', function () {
162
+ that._adjustColspan();
163
+ })
174
164
  },
175
165
 
176
166
 
@@ -184,7 +174,7 @@ $.extend( RowGroup.prototype, {
184
174
  */
185
175
  _adjustColspan: function ()
186
176
  {
187
- $( 'tr.'+this.c.className, this.s.dt.table().body() )
177
+ $( 'tr.'+this.c.className, this.s.dt.table().body() ).find('td')
188
178
  .attr( 'colspan', this._colspan() );
189
179
  },
190
180
 
@@ -199,76 +189,137 @@ $.extend( RowGroup.prototype, {
199
189
  }, 0 );
200
190
  },
201
191
 
192
+
202
193
  /**
203
- * Update function that is called whenever we need to draw the grouping rows
194
+ * Update function that is called whenever we need to draw the grouping rows.
195
+ * This is basically a bootstrap for the self iterative _group and _groupDisplay
196
+ * methods
204
197
  * @private
205
198
  */
206
199
  _draw: function ()
207
200
  {
208
- var that = this;
209
201
  var dt = this.s.dt;
210
- var rows = dt.rows( { page: 'current' } );
211
- var groupedRows = [];
212
- var last, display;
202
+ var groupedRows = this._group( 0, dt.rows( { page: 'current' } ).indexes() );
203
+
204
+ this._groupDisplay( 0, groupedRows );
205
+ },
206
+
207
+ /**
208
+ * Get the grouping information from a data set (index) of rows
209
+ * @param {number} level Nesting level
210
+ * @param {DataTables.Api} rows API of the rows to consider for this group
211
+ * @returns {object[]} Nested grouping information - it is structured like this:
212
+ * {
213
+ * dataPoint: 'Edinburgh',
214
+ * rows: [ 1,2,3,4,5,6,7 ],
215
+ * children: [ {
216
+ * dataPoint: 'developer'
217
+ * rows: [ 1, 2, 3 ]
218
+ * },
219
+ * {
220
+ * dataPoint: 'support',
221
+ * rows: [ 4, 5, 6, 7 ]
222
+ * } ]
223
+ * }
224
+ * @private
225
+ */
226
+ _group: function ( level, rows ) {
227
+ var fns = $.isArray( this.c.dataSrc ) ? this.c.dataSrc : [ this.c.dataSrc ];
228
+ var fn = DataTable.ext.oApi._fnGetObjectDataFn( fns[ level ] );
229
+ var dt = this.s.dt;
230
+ var group, last;
231
+ var data = [];
232
+ var that = this;
213
233
 
214
- rows.every( function () {
215
- var d = this.data();
216
- var group = that.s.dataFn( d );
234
+ for ( var i=0, ien=rows.length ; i<ien ; i++ ) {
235
+ var rowIndex = rows[i];
236
+ var rowData = dt.row( rowIndex ).data();
237
+ var group = fn( rowData );
217
238
 
218
239
  if ( group === null || group === undefined ) {
219
240
  group = that.c.emptyDataGroup;
220
241
  }
221
242
 
222
243
  if ( last === undefined || group !== last ) {
223
- groupedRows.push( [] );
244
+ data.push( {
245
+ dataPoint: group,
246
+ rows: []
247
+ } );
248
+
224
249
  last = group;
225
250
  }
226
-
227
- groupedRows[ groupedRows.length - 1 ].push( this.index() );
228
- } );
229
251
 
230
- for ( var i=0, ien=groupedRows.length ; i<ien ; i++ ) {
231
- var group = groupedRows[i];
232
- var firstRow = dt.row(group[0]);
233
- var groupName = this.s.dataFn( firstRow.data() );
252
+ data[ data.length-1 ].rows.push( rowIndex );
253
+ }
254
+
255
+ if ( fns[ level+1 ] !== undefined ) {
256
+ for ( var i=0, ien=data.length ; i<ien ; i++ ) {
257
+ data[i].children = this._group( level+1, data[i].rows );
258
+ }
259
+ }
260
+
261
+ return data;
262
+ },
263
+
264
+ /**
265
+ * Row group display - insert the rows into the document
266
+ * @param {number} level Nesting level
267
+ * @param {object[]} groups Takes the nested array from `_group`
268
+ * @private
269
+ */
270
+ _groupDisplay: function ( level, groups )
271
+ {
272
+ var dt = this.s.dt;
273
+ var display;
274
+
275
+ for ( var i=0, ien=groups.length ; i<ien ; i++ ) {
276
+ var group = groups[i];
277
+ var groupName = group.dataPoint;
234
278
  var row;
279
+ var rows = group.rows;
235
280
 
236
281
  if ( this.c.startRender ) {
237
- display = this.c.startRender.call( this, dt.rows(group), groupName );
238
- row = this._rowWrap( display, this.c.startClassName );
282
+ display = this.c.startRender.call( this, dt.rows(rows), groupName, level );
283
+ row = this._rowWrap( display, this.c.startClassName, level );
239
284
 
240
285
  if ( row ) {
241
- row.insertBefore( firstRow.node() );
286
+ row.insertBefore( dt.row( rows[0] ).node() );
242
287
  }
243
288
  }
244
289
 
245
290
  if ( this.c.endRender ) {
246
- display = this.c.endRender.call( this, dt.rows(group), groupName );
247
- row = this._rowWrap( display, this.c.endClassName );
291
+ display = this.c.endRender.call( this, dt.rows(rows), groupName, level );
292
+ row = this._rowWrap( display, this.c.endClassName, level );
248
293
 
249
294
  if ( row ) {
250
- row.insertAfter( dt.row( group[ group.length-1 ] ).node() );
295
+ row.insertAfter( dt.row( rows[ rows.length-1 ] ).node() );
251
296
  }
252
297
  }
298
+
299
+ if ( group.children ) {
300
+ this._groupDisplay( level+1, group.children );
301
+ }
253
302
  }
254
303
  },
255
304
 
256
305
  /**
257
306
  * Take a rendered value from an end user and make it suitable for display
258
307
  * as a row, by wrapping it in a row, or detecting that it is a row.
259
- * @param [node|jQuery|string] display Display value
260
- * @param [string] className Class to add to the row
308
+ * @param {node|jQuery|string} display Display value
309
+ * @param {string} className Class to add to the row
310
+ * @param {array} group
311
+ * @param {number} group level
261
312
  * @private
262
313
  */
263
- _rowWrap: function ( display, className )
314
+ _rowWrap: function ( display, className, level )
264
315
  {
265
316
  var row;
266
317
 
267
- if ( display === null || display === undefined || display === '' ) {
318
+ if ( display === null || display === '' ) {
268
319
  display = this.c.emptyDataGroup;
269
320
  }
270
321
 
271
- if ( display === null ) {
322
+ if ( display === undefined || display === null ) {
272
323
  return null;
273
324
  }
274
325
 
@@ -289,7 +340,8 @@ $.extend( RowGroup.prototype, {
289
340
 
290
341
  return row
291
342
  .addClass( this.c.className )
292
- .addClass( className );
343
+ .addClass( className )
344
+ .addClass( 'dtrg-level-'+level );
293
345
  }
294
346
  } );
295
347
 
@@ -307,11 +359,11 @@ RowGroup.defaults = {
307
359
  * end grouping rows.
308
360
  * @type string
309
361
  */
310
- className: 'group',
362
+ className: 'dtrg-group',
311
363
 
312
364
  /**
313
365
  * Data property from which to read the grouping information
314
- * @type string|integer
366
+ * @type string|integer|array
315
367
  */
316
368
  dataSrc: 0,
317
369
 
@@ -331,7 +383,7 @@ RowGroup.defaults = {
331
383
  * Class name to give to the end grouping row
332
384
  * @type string
333
385
  */
334
- endClassName: 'group-end',
386
+ endClassName: 'dtrg-end',
335
387
 
336
388
  /**
337
389
  * End grouping label function
@@ -343,7 +395,7 @@ RowGroup.defaults = {
343
395
  * Class name to give to the start grouping row
344
396
  * @type string
345
397
  */
346
- startClassName: 'group-start',
398
+ startClassName: 'dtrg-start',
347
399
 
348
400
  /**
349
401
  * Start grouping label function
@@ -355,7 +407,7 @@ RowGroup.defaults = {
355
407
  };
356
408
 
357
409
 
358
- RowGroup.version = "1.0.4";
410
+ RowGroup.version = "1.1.1";
359
411
 
360
412
 
361
413
  $.fn.dataTable.RowGroup = RowGroup;
@@ -1,4 +1,4 @@
1
- /*! Bootstrap 4 styling wrapper for RowGroup
1
+ /*! Foundation styling wrapper for RowGroup
2
2
  * ©2018 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -1,15 +1,15 @@
1
- /*! RowReorder 1.2.5
2
- * 2015-2018 SpryMedia Ltd - datatables.net/license
1
+ /*! RowReorder 1.2.6
2
+ * 2015-2019 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.2.5
8
+ * @version 1.2.6
9
9
  * @file dataTables.rowReorder.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
12
- * @copyright Copyright 2015-2018 SpryMedia Ltd.
12
+ * @copyright Copyright 2015-2019 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/mit
@@ -528,10 +528,11 @@ $.extend( RowReorder.prototype, {
528
528
 
529
529
  // Create event args
530
530
  var eventArgs = [ fullDiff, {
531
- dataSrc: dataSrc,
532
- nodes: diffNodes,
533
- values: idDiff,
534
- triggerRow: dt.row( this.dom.target )
531
+ dataSrc: dataSrc,
532
+ nodes: diffNodes,
533
+ values: idDiff,
534
+ triggerRow: dt.row( this.dom.target ),
535
+ originalEvent: e
535
536
  } ];
536
537
 
537
538
  // Emit event
@@ -788,7 +789,7 @@ Api.register( 'rowReorder.disable()', function () {
788
789
  * @name RowReorder.version
789
790
  * @static
790
791
  */
791
- RowReorder.version = '1.2.5';
792
+ RowReorder.version = '1.2.6';
792
793
 
793
794
 
794
795
  $.fn.dataTable.RowReorder = RowReorder;
@@ -1,4 +1,4 @@
1
- /*! Bootstrap 4 styling wrapper for RowReorder
1
+ /*! Foundation styling wrapper for RowReorder
2
2
  * ©2018 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -1,15 +1,15 @@
1
- /*! Scroller 1.5.1
2
- * ©2011-2018 SpryMedia Ltd - datatables.net/license
1
+ /*! Scroller 2.0.1
2
+ * ©2011-2019 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary Scroller
7
7
  * @description Virtual rendering for DataTables
8
- * @version 1.5.1
8
+ * @version 2.0.1
9
9
  * @file dataTables.scroller.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
12
- * @copyright Copyright 2011-2018 SpryMedia Ltd.
12
+ * @copyright Copyright 2011-2019 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/mit
@@ -93,7 +93,7 @@ var DataTable = $.fn.dataTable;
93
93
  * $('#example').DataTable( {
94
94
  * "scrollY": "200px",
95
95
  * "ajax": "media/dataset/large.txt",
96
- * "dom": "frtiS",
96
+ * "scroller": true,
97
97
  * "deferRender": true
98
98
  * } );
99
99
  * } );
@@ -123,27 +123,27 @@ var Scroller = function ( dt, opts ) {
123
123
  * @type object
124
124
  * @default Passed in as first parameter to constructor
125
125
  */
126
- "dt": dtApi.settings()[0],
126
+ dt: dtApi.settings()[0],
127
127
 
128
128
  /**
129
129
  * DataTables API instance
130
130
  * @type DataTable.Api
131
131
  */
132
- "dtApi": dtApi,
132
+ dtApi: dtApi,
133
133
 
134
134
  /**
135
135
  * Pixel location of the top of the drawn table in the viewport
136
136
  * @type int
137
137
  * @default 0
138
138
  */
139
- "tableTop": 0,
139
+ tableTop: 0,
140
140
 
141
141
  /**
142
142
  * Pixel location of the bottom of the drawn table in the viewport
143
143
  * @type int
144
144
  * @default 0
145
145
  */
146
- "tableBottom": 0,
146
+ tableBottom: 0,
147
147
 
148
148
  /**
149
149
  * Pixel location of the boundary for when the next data set should be loaded and drawn
@@ -152,7 +152,7 @@ var Scroller = function ( dt, opts ) {
152
152
  * @default 0
153
153
  * @private
154
154
  */
155
- "redrawTop": 0,
155
+ redrawTop: 0,
156
156
 
157
157
  /**
158
158
  * Pixel location of the boundary for when the next data set should be loaded and drawn
@@ -162,21 +162,21 @@ var Scroller = function ( dt, opts ) {
162
162
  * @default 0
163
163
  * @private
164
164
  */
165
- "redrawBottom": 0,
165
+ redrawBottom: 0,
166
166
 
167
167
  /**
168
168
  * Auto row height or not indicator
169
169
  * @type bool
170
170
  * @default 0
171
171
  */
172
- "autoHeight": true,
172
+ autoHeight: true,
173
173
 
174
174
  /**
175
175
  * Number of rows calculated as visible in the visible viewport
176
176
  * @type int
177
177
  * @default 0
178
178
  */
179
- "viewportRows": 0,
179
+ viewportRows: 0,
180
180
 
181
181
  /**
182
182
  * setTimeout reference for state saving, used when state saving is enabled in the DataTable
@@ -185,7 +185,7 @@ var Scroller = function ( dt, opts ) {
185
185
  * @type int
186
186
  * @default 0
187
187
  */
188
- "stateTO": null,
188
+ stateTO: null,
189
189
 
190
190
  /**
191
191
  * setTimeout reference for the redraw, used when server-side processing is enabled in the
@@ -193,7 +193,7 @@ var Scroller = function ( dt, opts ) {
193
193
  * @type int
194
194
  * @default null
195
195
  */
196
- "drawTO": null,
196
+ drawTO: null,
197
197
 
198
198
  heights: {
199
199
  jump: null,
@@ -213,13 +213,18 @@ var Scroller = function ( dt, opts ) {
213
213
  * @type int
214
214
  * @default 0
215
215
  */
216
- viewport: null
216
+ viewport: null,
217
+ labelFactor: 1
217
218
  },
218
219
 
219
220
  topRowFloat: 0,
220
221
  scrollDrawDiff: null,
221
222
  loaderVisible: false,
222
- forceReposition: false
223
+ forceReposition: false,
224
+ baseRowTop: 0,
225
+ baseScrollTop: 0,
226
+ mousedown: false,
227
+ lastScrollTop: 0
223
228
  };
224
229
 
225
230
  // @todo The defaults should extend a `c` property and the internal settings
@@ -237,6 +242,7 @@ var Scroller = function ( dt, opts ) {
237
242
  */
238
243
  this.dom = {
239
244
  "force": document.createElement('div'),
245
+ "label": $('<div class="dts_label">0</div>'),
240
246
  "scroller": null,
241
247
  "table": null,
242
248
  "loader": null
@@ -251,54 +257,80 @@ var Scroller = function ( dt, opts ) {
251
257
  this.s.dt.oScroller = this;
252
258
 
253
259
  /* Let's do it */
254
- this._fnConstruct();
260
+ this.construct();
255
261
  };
256
262
 
257
263
 
258
264
 
259
265
  $.extend( Scroller.prototype, {
260
266
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
261
- * Public methods
262
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
267
+ * Public methods - to be exposed via the DataTables API
268
+ */
263
269
 
264
270
  /**
265
- * Calculate the pixel position from the top of the scrolling container for
266
- * a given row
267
- * @param {int} iRow Row number to calculate the position of
268
- * @returns {int} Pixels
269
- * @example
270
- * $(document).ready(function() {
271
- * $('#example').dataTable( {
272
- * "sScrollY": "200px",
273
- * "sAjaxSource": "media/dataset/large.txt",
274
- * "sDom": "frtiS",
275
- * "bDeferRender": true,
276
- * "fnInitComplete": function (o) {
277
- * // Find where row 25 is
278
- * alert( o.oScroller.fnRowToPixels( 25 ) );
279
- * }
280
- * } );
281
- * } );
271
+ * Calculate and store information about how many rows are to be displayed
272
+ * in the scrolling viewport, based on current dimensions in the browser's
273
+ * rendering. This can be particularly useful if the table is initially
274
+ * drawn in a hidden element - for example in a tab.
275
+ * @param {bool} [redraw=true] Redraw the table automatically after the recalculation, with
276
+ * the new dimensions forming the basis for the draw.
277
+ * @returns {void}
282
278
  */
283
- "fnRowToPixels": function ( rowIdx, intParse, virtual )
279
+ measure: function ( redraw )
284
280
  {
285
- var pixels;
286
- var diff = rowIdx - this.s.baseRowTop;
287
-
288
- if ( virtual ) {
289
- pixels = this._domain( 'virtualToPhysical', this.s.baseScrollTop );
290
- pixels += diff * this.s.heights.row;
281
+ if ( this.s.autoHeight )
282
+ {
283
+ this._calcRowHeight();
291
284
  }
292
- else {
293
- pixels = this.s.baseScrollTop;
294
- pixels += diff * this.s.heights.row;
285
+
286
+ var heights = this.s.heights;
287
+
288
+ if ( heights.row ) {
289
+ heights.viewport = $.contains(document, this.dom.scroller) ?
290
+ this.dom.scroller.clientHeight :
291
+ this._parseHeight($(this.dom.scroller).css('height'));
292
+
293
+ // If collapsed (no height) use the max-height parameter
294
+ if ( ! heights.viewport ) {
295
+ heights.viewport = this._parseHeight($(this.dom.scroller).css('max-height'));
296
+ }
297
+
298
+ this.s.viewportRows = parseInt( heights.viewport / heights.row, 10 )+1;
299
+ this.s.dt._iDisplayLength = this.s.viewportRows * this.s.displayBuffer;
295
300
  }
296
301
 
297
- return intParse || intParse === undefined ?
298
- parseInt( pixels, 10 ) :
299
- pixels;
302
+ var label = this.dom.label.outerHeight();
303
+ heights.labelFactor = (heights.viewport-label) / heights.scroll;
304
+
305
+ if ( redraw === undefined || redraw )
306
+ {
307
+ this.s.dt.oInstance.fnDraw( false );
308
+ }
300
309
  },
301
310
 
311
+ /**
312
+ * Get information about current displayed record range. This corresponds to
313
+ * the information usually displayed in the "Info" block of the table.
314
+ *
315
+ * @returns {object} info as an object:
316
+ * {
317
+ * start: {int}, // the 0-indexed record at the top of the viewport
318
+ * end: {int}, // the 0-indexed record at the bottom of the viewport
319
+ * }
320
+ */
321
+ pageInfo: function()
322
+ {
323
+ var
324
+ dt = this.s.dt,
325
+ iScrollTop = this.dom.scroller.scrollTop,
326
+ iTotal = dt.fnRecordsDisplay(),
327
+ iPossibleEnd = Math.ceil(this.pixelsToRow(iScrollTop + this.s.heights.viewport, false, this.s.ani));
328
+
329
+ return {
330
+ start: Math.floor(this.pixelsToRow(iScrollTop, false, this.s.ani)),
331
+ end: iTotal < iPossibleEnd ? iTotal-1 : iPossibleEnd-1
332
+ };
333
+ },
302
334
 
303
335
  /**
304
336
  * Calculate the row number that will be found at the given pixel position
@@ -308,25 +340,12 @@ $.extend( Scroller.prototype, {
308
340
  * pixels, Scroller switches into a non-linear mode for the scrollbar to fit
309
341
  * all of the records into a finite area, but this function returns a linear
310
342
  * value (relative to the last non-linear positioning).
311
- * @param {int} iPixels Offset from top to calculate the row number of
343
+ * @param {int} pixels Offset from top to calculate the row number of
312
344
  * @param {int} [intParse=true] If an integer value should be returned
313
345
  * @param {int} [virtual=false] Perform the calculations in the virtual domain
314
346
  * @returns {int} Row index
315
- * @example
316
- * $(document).ready(function() {
317
- * $('#example').dataTable( {
318
- * "sScrollY": "200px",
319
- * "sAjaxSource": "media/dataset/large.txt",
320
- * "sDom": "frtiS",
321
- * "bDeferRender": true,
322
- * "fnInitComplete": function (o) {
323
- * // Find what row number is at 500px
324
- * alert( o.oScroller.fnPixelsToRow( 500 ) );
325
- * }
326
- * } );
327
- * } );
328
347
  */
329
- "fnPixelsToRow": function ( pixels, intParse, virtual )
348
+ pixelsToRow: function ( pixels, intParse, virtual )
330
349
  {
331
350
  var diff = pixels - this.s.baseScrollTop;
332
351
  var row = virtual ?
@@ -338,35 +357,43 @@ $.extend( Scroller.prototype, {
338
357
  row;
339
358
  },
340
359
 
360
+ /**
361
+ * Calculate the pixel position from the top of the scrolling container for
362
+ * a given row
363
+ * @param {int} iRow Row number to calculate the position of
364
+ * @returns {int} Pixels
365
+ */
366
+ rowToPixels: function ( rowIdx, intParse, virtual )
367
+ {
368
+ var pixels;
369
+ var diff = rowIdx - this.s.baseRowTop;
370
+
371
+ if ( virtual ) {
372
+ pixels = this._domain( 'virtualToPhysical', this.s.baseScrollTop );
373
+ pixels += diff * this.s.heights.row;
374
+ }
375
+ else {
376
+ pixels = this.s.baseScrollTop;
377
+ pixels += diff * this.s.heights.row;
378
+ }
379
+
380
+ return intParse || intParse === undefined ?
381
+ parseInt( pixels, 10 ) :
382
+ pixels;
383
+ },
384
+
341
385
 
342
386
  /**
343
387
  * Calculate the row number that will be found at the given pixel position (y-scroll)
344
- * @param {int} iRow Row index to scroll to
345
- * @param {bool} [bAnimate=true] Animate the transition or not
388
+ * @param {int} row Row index to scroll to
389
+ * @param {bool} [animate=true] Animate the transition or not
346
390
  * @returns {void}
347
- * @example
348
- * $(document).ready(function() {
349
- * $('#example').dataTable( {
350
- * "sScrollY": "200px",
351
- * "sAjaxSource": "media/dataset/large.txt",
352
- * "sDom": "frtiS",
353
- * "bDeferRender": true,
354
- * "fnInitComplete": function (o) {
355
- * // Immediately scroll to row 1000
356
- * o.oScroller.fnScrollToRow( 1000 );
357
- * }
358
- * } );
359
- *
360
- * // Sometime later on use the following to scroll to row 500...
361
- * var oSettings = $('#example').dataTable().fnSettings();
362
- * oSettings.oScroller.fnScrollToRow( 500 );
363
- * } );
364
391
  */
365
- "fnScrollToRow": function ( iRow, bAnimate )
392
+ scrollToRow: function ( row, animate )
366
393
  {
367
394
  var that = this;
368
395
  var ani = false;
369
- var px = this.fnRowToPixels( iRow );
396
+ var px = this.rowToPixels( row );
370
397
 
371
398
  // We need to know if the table will redraw or not before doing the
372
399
  // scroll. If it will not redraw, then we need to use the currently
@@ -374,25 +401,25 @@ $.extend( Scroller.prototype, {
374
401
  // need to calculate the table's new position from the virtual
375
402
  // transform.
376
403
  var preRows = ((this.s.displayBuffer-1)/2) * this.s.viewportRows;
377
- var drawRow = iRow - preRows;
404
+ var drawRow = row - preRows;
378
405
  if ( drawRow < 0 ) {
379
406
  drawRow = 0;
380
407
  }
381
408
 
382
409
  if ( (px > this.s.redrawBottom || px < this.s.redrawTop) && this.s.dt._iDisplayStart !== drawRow ) {
383
410
  ani = true;
384
- px = this._domain( 'virtualToPhysical', iRow * this.s.heights.row );
411
+ px = this._domain( 'virtualToPhysical', row * this.s.heights.row );
385
412
 
386
413
  // If we need records outside the current draw region, but the new
387
414
  // scrolling position is inside that (due to the non-linear nature
388
415
  // for larger numbers of records), we need to force position update.
389
416
  if ( this.s.redrawTop < px && px < this.s.redrawBottom ) {
390
417
  this.s.forceReposition = true;
391
- bAnimate = false;
418
+ animate = false;
392
419
  }
393
420
  }
394
421
 
395
- if ( typeof bAnimate == 'undefined' || bAnimate )
422
+ if ( animate === undefined || animate )
396
423
  {
397
424
  this.s.ani = ani;
398
425
  $(this.dom.scroller).animate( {
@@ -402,7 +429,7 @@ $.extend( Scroller.prototype, {
402
429
  // the final scroll event fired
403
430
  setTimeout( function () {
404
431
  that.s.ani = false;
405
- }, 25 );
432
+ }, 250 );
406
433
  } );
407
434
  }
408
435
  else
@@ -412,100 +439,16 @@ $.extend( Scroller.prototype, {
412
439
  },
413
440
 
414
441
 
415
- /**
416
- * Calculate and store information about how many rows are to be displayed
417
- * in the scrolling viewport, based on current dimensions in the browser's
418
- * rendering. This can be particularly useful if the table is initially
419
- * drawn in a hidden element - for example in a tab.
420
- * @param {bool} [bRedraw=true] Redraw the table automatically after the recalculation, with
421
- * the new dimensions forming the basis for the draw.
422
- * @returns {void}
423
- * @example
424
- * $(document).ready(function() {
425
- * // Make the example container hidden to throw off the browser's sizing
426
- * document.getElementById('container').style.display = "none";
427
- * var oTable = $('#example').dataTable( {
428
- * "sScrollY": "200px",
429
- * "sAjaxSource": "media/dataset/large.txt",
430
- * "sDom": "frtiS",
431
- * "bDeferRender": true,
432
- * "fnInitComplete": function (o) {
433
- * // Immediately scroll to row 1000
434
- * o.oScroller.fnScrollToRow( 1000 );
435
- * }
436
- * } );
437
- *
438
- * setTimeout( function () {
439
- * // Make the example container visible and recalculate the scroller sizes
440
- * document.getElementById('container').style.display = "block";
441
- * oTable.fnSettings().oScroller.fnMeasure();
442
- * }, 3000 );
443
- */
444
- "fnMeasure": function ( bRedraw )
445
- {
446
- if ( this.s.autoHeight )
447
- {
448
- this._fnCalcRowHeight();
449
- }
450
-
451
- var heights = this.s.heights;
452
-
453
- if ( heights.row ) {
454
- heights.viewport = $.contains(document, this.dom.scroller) ?
455
- $(this.dom.scroller).height() :
456
- this._parseHeight($(this.dom.scroller).css('height'));
457
-
458
- // If collapsed (no height) use the max-height parameter
459
- if ( ! heights.viewport ) {
460
- heights.viewport = this._parseHeight($(this.dom.scroller).css('max-height'));
461
- }
462
-
463
- this.s.viewportRows = parseInt( heights.viewport / heights.row, 10 )+1;
464
- this.s.dt._iDisplayLength = this.s.viewportRows * this.s.displayBuffer;
465
- }
466
-
467
- if ( bRedraw === undefined || bRedraw )
468
- {
469
- this.s.dt.oInstance.fnDraw( false );
470
- }
471
- },
472
-
473
-
474
- /**
475
- * Get information about current displayed record range. This corresponds to
476
- * the information usually displayed in the "Info" block of the table.
477
- *
478
- * @returns {object} info as an object:
479
- * {
480
- * start: {int}, // the 0-indexed record at the top of the viewport
481
- * end: {int}, // the 0-indexed record at the bottom of the viewport
482
- * }
483
- */
484
- "fnPageInfo": function()
485
- {
486
- var
487
- dt = this.s.dt,
488
- iScrollTop = this.dom.scroller.scrollTop,
489
- iTotal = dt.fnRecordsDisplay(),
490
- iPossibleEnd = Math.ceil(this.fnPixelsToRow(iScrollTop + this.s.heights.viewport, false, this.s.ani));
491
-
492
- return {
493
- start: Math.floor(this.fnPixelsToRow(iScrollTop, false, this.s.ani)),
494
- end: iTotal < iPossibleEnd ? iTotal-1 : iPossibleEnd-1
495
- };
496
- },
497
-
498
-
499
442
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
500
- * Private methods (they are of course public in JS, but recommended as private)
501
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
443
+ * Constructor
444
+ */
502
445
 
503
446
  /**
504
447
  * Initialisation for Scroller
505
448
  * @returns {void}
506
449
  * @private
507
450
  */
508
- "_fnConstruct": function ()
451
+ construct: function ()
509
452
  {
510
453
  var that = this;
511
454
  var dt = this.s.dtApi;
@@ -534,12 +477,12 @@ $.extend( Scroller.prototype, {
534
477
  this.dom.table.style.left = "0px";
535
478
 
536
479
  // Add class to 'announce' that we are a Scroller table
537
- $(dt.table().container()).addClass('DTS');
480
+ $(dt.table().container()).addClass('dts DTS');
538
481
 
539
482
  // Add a 'loading' indicator
540
483
  if ( this.s.loadingIndicator )
541
484
  {
542
- this.dom.loader = $('<div class="dataTables_processing DTS_Loading">'+this.s.dt.oLanguage.sLoadingRecords+'</div>')
485
+ this.dom.loader = $('<div class="dataTables_processing dts_loading">'+this.s.dt.oLanguage.sLoadingRecords+'</div>')
543
486
  .css('display', 'none');
544
487
 
545
488
  $(this.dom.scroller.parentNode)
@@ -547,12 +490,14 @@ $.extend( Scroller.prototype, {
547
490
  .append( this.dom.loader );
548
491
  }
549
492
 
493
+ this.dom.label.appendTo(this.dom.scroller);
494
+
550
495
  /* Initial size calculations */
551
496
  if ( this.s.heights.row && this.s.heights.row != 'auto' )
552
497
  {
553
498
  this.s.autoHeight = false;
554
499
  }
555
- this.fnMeasure( false );
500
+ this.measure( false );
556
501
 
557
502
  // Scrolling callback to see if a page change is needed - use a throttled
558
503
  // function for the save save callback so we aren't hitting it on every
@@ -562,19 +507,28 @@ $.extend( Scroller.prototype, {
562
507
  that.s.dtApi.state.save();
563
508
  }, 500 );
564
509
  $(this.dom.scroller).on( 'scroll.dt-scroller', function (e) {
565
- that._fnScroll.call( that );
510
+ that._scroll.call( that );
566
511
  } );
567
512
 
568
513
  // In iOS we catch the touchstart event in case the user tries to scroll
569
514
  // while the display is already scrolling
570
515
  $(this.dom.scroller).on('touchstart.dt-scroller', function () {
571
- that._fnScroll.call( that );
516
+ that._scroll.call( that );
572
517
  } );
573
518
 
519
+ $(this.dom.scroller)
520
+ .on('mousedown.dt-scroller', function () {
521
+ that.s.mousedown = true;
522
+ })
523
+ .on('mouseup.dt-scroller', function () {
524
+ that.s.mouseup = false;
525
+ that.dom.label.css('display', 'none');
526
+ });
527
+
574
528
  // On resize, update the information element, since the number of rows shown might change
575
529
  $(window).on( 'resize.dt-scroller', function () {
576
- that.fnMeasure( false );
577
- that._fnInfo();
530
+ that.measure( false );
531
+ that._info();
578
532
  } );
579
533
 
580
534
  // Add a state saving parameter to the DT state saving so we can restore the exact
@@ -604,20 +558,23 @@ $.extend( Scroller.prototype, {
604
558
  }
605
559
 
606
560
  dt.on( 'init.scroller', function () {
607
- that.fnMeasure( false );
561
+ that.measure( false );
608
562
 
609
- that._fnDrawCallback();
563
+ // Setting to `jump` will instruct _draw to calculate the scroll top
564
+ // position
565
+ that.s.scrollType = 'jump';
566
+ that._draw();
610
567
 
611
568
  // Update the scroller when the DataTable is redrawn
612
569
  dt.on( 'draw.scroller', function () {
613
- that._fnDrawCallback();
570
+ that._draw();
614
571
  });
615
572
  } );
616
573
 
617
574
  // Set height before the draw happens, allowing everything else to update
618
575
  // on draw complete without worry for roder.
619
576
  dt.on( 'preDraw.dt.scroller', function () {
620
- that._fnScrollForce();
577
+ that._scrollForce();
621
578
  } );
622
579
 
623
580
  // Destructor
@@ -636,280 +593,111 @@ $.extend( Scroller.prototype, {
636
593
  },
637
594
 
638
595
 
596
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
597
+ * Private methods
598
+ */
599
+
639
600
  /**
640
- * Scrolling function - fired whenever the scrolling position is changed.
641
- * This method needs to use the stored values to see if the table should be
642
- * redrawn as we are moving towards the end of the information that is
643
- * currently drawn or not. If needed, then it will redraw the table based on
644
- * the new position.
601
+ * Automatic calculation of table row height. This is just a little tricky here as using
602
+ * initialisation DataTables has tale the table out of the document, so we need to create
603
+ * a new table and insert it into the document, calculate the row height and then whip the
604
+ * table out.
605
+ * @returns {void}
606
+ * @private
607
+ */
608
+ _calcRowHeight: function ()
609
+ {
610
+ var dt = this.s.dt;
611
+ var origTable = dt.nTable;
612
+ var nTable = origTable.cloneNode( false );
613
+ var tbody = $('<tbody/>').appendTo( nTable );
614
+ var container = $(
615
+ '<div class="'+dt.oClasses.sWrapper+' DTS">'+
616
+ '<div class="'+dt.oClasses.sScrollWrapper+'">'+
617
+ '<div class="'+dt.oClasses.sScrollBody+'"></div>'+
618
+ '</div>'+
619
+ '</div>'
620
+ );
621
+
622
+ // Want 3 rows in the sizing table so :first-child and :last-child
623
+ // CSS styles don't come into play - take the size of the middle row
624
+ $('tbody tr:lt(4)', origTable).clone().appendTo( tbody );
625
+ var rowsCount = $('tr', tbody).length;
626
+
627
+ if ( rowsCount === 1 ) {
628
+ tbody.prepend('<tr><td>&#160;</td></tr>');
629
+ tbody.append('<tr><td>&#160;</td></tr>');
630
+ }
631
+ else {
632
+ for (; rowsCount < 3; rowsCount++) {
633
+ tbody.append('<tr><td>&#160;</td></tr>');
634
+ }
635
+ }
636
+
637
+ $('div.'+dt.oClasses.sScrollBody, container).append( nTable );
638
+
639
+ // If initialised using `dom`, use the holding element as the insert point
640
+ var insertEl = this.s.dt.nHolding || origTable.parentNode;
641
+
642
+ if ( ! $(insertEl).is(':visible') ) {
643
+ insertEl = 'body';
644
+ }
645
+
646
+ container.appendTo( insertEl );
647
+ this.s.heights.row = $('tr', tbody).eq(1).outerHeight();
648
+
649
+ container.remove();
650
+ },
651
+
652
+ /**
653
+ * Draw callback function which is fired when the DataTable is redrawn. The main function of
654
+ * this method is to position the drawn table correctly the scrolling container for the rows
655
+ * that is displays as a result of the scrolling position.
645
656
  * @returns {void}
646
657
  * @private
647
658
  */
648
- "_fnScroll": function ()
659
+ _draw: function ()
649
660
  {
650
661
  var
651
662
  that = this,
652
663
  heights = this.s.heights,
653
664
  iScrollTop = this.dom.scroller.scrollTop,
654
- iTopRow;
655
-
656
- if ( this.s.skip ) {
657
- return;
658
- }
665
+ iTableHeight = $(this.s.dt.nTable).height(),
666
+ displayStart = this.s.dt._iDisplayStart,
667
+ displayLen = this.s.dt._iDisplayLength,
668
+ displayEnd = this.s.dt.fnRecordsDisplay();
659
669
 
660
- if ( this.s.ingnoreScroll ) {
661
- return;
662
- }
670
+ // Disable the scroll event listener while we are updating the DOM
671
+ this.s.skip = true;
663
672
 
664
- /* If the table has been sorted or filtered, then we use the redraw that
665
- * DataTables as done, rather than performing our own
666
- */
667
- if ( this.s.dt.bFiltered || this.s.dt.bSorted ) {
668
- this.s.lastScrollTop = 0;
669
- return;
673
+ // If paging is reset
674
+ if ( (this.s.dt.bSorted || this.s.dt.bFiltered) && displayStart === 0 && !this.s.dt._drawHold ) {
675
+ this.s.topRowFloat = 0;
670
676
  }
671
677
 
672
- /* Update the table's information display for what is now in the viewport */
673
- this._fnInfo();
678
+ iScrollTop = this.s.scrollType === 'jump' ?
679
+ this._domain( 'virtualToPhysical', this.s.topRowFloat * heights.row ) :
680
+ iScrollTop;
674
681
 
675
- /* We don't want to state save on every scroll event - that's heavy
676
- * handed, so use a timeout to update the state saving only when the
677
- * scrolling has finished
678
- */
679
- clearTimeout( this.s.stateTO );
680
- this.s.stateTO = setTimeout( function () {
681
- that.s.dtApi.state.save();
682
- }, 250 );
682
+ // Store positional information so positional calculations can be based
683
+ // upon the current table draw position
684
+ this.s.baseScrollTop = iScrollTop;
685
+ this.s.baseRowTop = this.s.topRowFloat;
683
686
 
684
- /* Check if the scroll point is outside the trigger boundary which would required
685
- * a DataTables redraw
686
- */
687
- if ( this.s.forceReposition || iScrollTop < this.s.redrawTop || iScrollTop > this.s.redrawBottom ) {
687
+ // Position the table in the virtual scroller
688
+ var tableTop = iScrollTop - ((this.s.topRowFloat - displayStart) * heights.row);
689
+ if ( displayStart === 0 ) {
690
+ tableTop = 0;
691
+ }
692
+ else if ( displayStart + displayLen >= displayEnd ) {
693
+ tableTop = heights.scroll - iTableHeight;
694
+ }
688
695
 
689
- var preRows = Math.ceil( ((this.s.displayBuffer-1)/2) * this.s.viewportRows );
696
+ this.dom.table.style.top = tableTop+'px';
690
697
 
691
- iTopRow = parseInt(this._domain( 'physicalToVirtual', iScrollTop ) / heights.row, 10) - preRows;
692
- this.s.topRowFloat = this._domain( 'physicalToVirtual', iScrollTop ) / heights.row;
693
- this.s.forceReposition = false;
694
-
695
- if ( iTopRow <= 0 ) {
696
- /* At the start of the table */
697
- iTopRow = 0;
698
- }
699
- else if ( iTopRow + this.s.dt._iDisplayLength > this.s.dt.fnRecordsDisplay() ) {
700
- /* At the end of the table */
701
- iTopRow = this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength;
702
- if ( iTopRow < 0 ) {
703
- iTopRow = 0;
704
- }
705
- }
706
- else if ( iTopRow % 2 !== 0 ) {
707
- // For the row-striping classes (odd/even) we want only to start
708
- // on evens otherwise the stripes will change between draws and
709
- // look rubbish
710
- iTopRow++;
711
- }
712
-
713
- if ( iTopRow != this.s.dt._iDisplayStart ) {
714
- /* Cache the new table position for quick lookups */
715
- this.s.tableTop = $(this.s.dt.nTable).offset().top;
716
- this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
717
-
718
- var draw = function () {
719
- if ( that.s.scrollDrawReq === null ) {
720
- that.s.scrollDrawReq = iScrollTop;
721
- }
722
-
723
- that.s.dt._iDisplayStart = iTopRow;
724
- that.s.dt.oApi._fnDraw( that.s.dt );
725
- };
726
-
727
- /* Do the DataTables redraw based on the calculated start point - note that when
728
- * using server-side processing we introduce a small delay to not DoS the server...
729
- */
730
- if ( this.s.dt.oFeatures.bServerSide ) {
731
- clearTimeout( this.s.drawTO );
732
- this.s.drawTO = setTimeout( draw, this.s.serverWait );
733
- }
734
- else {
735
- draw();
736
- }
737
-
738
- if ( this.dom.loader && ! this.s.loaderVisible ) {
739
- this.dom.loader.css( 'display', 'block' );
740
- this.s.loaderVisible = true;
741
- }
742
- }
743
- }
744
- else {
745
- this.s.topRowFloat = this.fnPixelsToRow( iScrollTop, false, true );
746
- }
747
-
748
- this.s.lastScrollTop = iScrollTop;
749
- this.s.stateSaveThrottle();
750
- },
751
-
752
-
753
- /**
754
- * Convert from one domain to another. The physical domain is the actual
755
- * pixel count on the screen, while the virtual is if we had browsers which
756
- * had scrolling containers of infinite height (i.e. the absolute value)
757
- *
758
- * @param {string} dir Domain transform direction, `virtualToPhysical` or
759
- * `physicalToVirtual`
760
- * @returns {number} Calculated transform
761
- * @private
762
- */
763
- _domain: function ( dir, val )
764
- {
765
- var heights = this.s.heights;
766
- var coeff;
767
-
768
- // If the virtual and physical height match, then we use a linear
769
- // transform between the two, allowing the scrollbar to be linear
770
- if ( heights.virtual === heights.scroll ) {
771
- return val;
772
- }
773
-
774
- // Otherwise, we want a non-linear scrollbar to take account of the
775
- // redrawing regions at the start and end of the table, otherwise these
776
- // can stutter badly - on large tables 30px (for example) scroll might
777
- // be hundreds of rows, so the table would be redrawing every few px at
778
- // the start and end. Use a simple quadratic to stop this. It does mean
779
- // the scrollbar is non-linear, but with such massive data sets, the
780
- // scrollbar is going to be a best guess anyway
781
- var xMax = (heights.scroll - heights.viewport) / 2;
782
- var yMax = (heights.virtual - heights.viewport) / 2;
783
-
784
- coeff = yMax / ( xMax * xMax );
785
-
786
- if ( dir === 'virtualToPhysical' ) {
787
- if ( val < yMax ) {
788
- return Math.pow(val / coeff, 0.5);
789
- }
790
- else {
791
- val = (yMax*2) - val;
792
- return val < 0 ?
793
- heights.scroll :
794
- (xMax*2) - Math.pow(val / coeff, 0.5);
795
- }
796
- }
797
- else if ( dir === 'physicalToVirtual' ) {
798
- if ( val < xMax ) {
799
- return val * val * coeff;
800
- }
801
- else {
802
- val = (xMax*2) - val;
803
- return val < 0 ?
804
- heights.virtual :
805
- (yMax*2) - (val * val * coeff);
806
- }
807
- }
808
- },
809
-
810
- /**
811
- * Parse CSS height property string as number
812
- *
813
- * An attempt is made to parse the string as a number. Currently supported units are 'px',
814
- * 'vh', and 'rem'. 'em' is partially supported; it works as long as the parent element's
815
- * font size matches the body element. Zero is returned for unrecognized strings.
816
- * @param {string} cssHeight CSS height property string
817
- * @returns {number} height
818
- * @private
819
- */
820
- _parseHeight: function(cssHeight) {
821
- var height;
822
- var matches = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(px|em|rem|vh)$/.exec(cssHeight);
823
-
824
- if (matches === null) {
825
- return 0;
826
- }
827
-
828
- var value = parseFloat(matches[1]);
829
- var unit = matches[2];
830
-
831
- if ( unit === 'px' ) {
832
- height = value;
833
- }
834
- else if ( unit === 'vh' ) {
835
- height = ( value / 100 ) * $(window).height();
836
- }
837
- else if ( unit === 'rem' ) {
838
- height = value * parseFloat($(':root').css('font-size'));
839
- }
840
- else if ( unit === 'em' ) {
841
- height = value * parseFloat($('body').css('font-size'));
842
- }
843
-
844
- return height ?
845
- height :
846
- 0;
847
- },
848
-
849
-
850
- /**
851
- * Draw callback function which is fired when the DataTable is redrawn. The main function of
852
- * this method is to position the drawn table correctly the scrolling container for the rows
853
- * that is displays as a result of the scrolling position.
854
- * @returns {void}
855
- * @private
856
- */
857
- "_fnDrawCallback": function ()
858
- {
859
- var
860
- that = this,
861
- heights = this.s.heights,
862
- iScrollTop = this.dom.scroller.scrollTop,
863
- iActualScrollTop = iScrollTop,
864
- iScrollBottom = iScrollTop + heights.viewport,
865
- iTableHeight = $(this.s.dt.nTable).height(),
866
- displayStart = this.s.dt._iDisplayStart,
867
- displayLen = this.s.dt._iDisplayLength,
868
- displayEnd = this.s.dt.fnRecordsDisplay();
869
-
870
- // Disable the scroll event listener while we are updating the DOM
871
- this.s.skip = true;
872
-
873
- // If paging is reset
874
- if ( (this.s.dt.bSorted || this.s.dt.bFiltered) && displayStart === 0 ) {
875
- this.s.topRowFloat = 0;
876
- }
877
-
878
- // Reposition the scrolling for the updated virtual position if needed
879
- if ( displayStart === 0 ) {
880
- // Linear calculation at the top of the table
881
- iScrollTop = this.s.topRowFloat * heights.row;
882
- }
883
- else if ( displayStart + displayLen >= displayEnd ) {
884
- // Linear calculation that the bottom as well
885
- iScrollTop = heights.scroll - ((displayEnd - this.s.topRowFloat) * heights.row);
886
- }
887
- else {
888
- // Domain scaled in the middle
889
- iScrollTop = this._domain( 'virtualToPhysical', this.s.topRowFloat * heights.row );
890
- }
891
-
892
- this.dom.scroller.scrollTop = iScrollTop;
893
-
894
- // Store positional information so positional calculations can be based
895
- // upon the current table draw position
896
- this.s.baseScrollTop = iScrollTop;
897
- this.s.baseRowTop = this.s.topRowFloat;
898
-
899
- // Position the table in the virtual scroller
900
- var tableTop = iScrollTop - ((this.s.topRowFloat - displayStart) * heights.row);
901
- if ( displayStart === 0 ) {
902
- tableTop = 0;
903
- }
904
- else if ( displayStart + displayLen >= displayEnd ) {
905
- tableTop = heights.scroll - iTableHeight;
906
- }
907
-
908
- this.dom.table.style.top = tableTop+'px';
909
-
910
- /* Cache some information for the scroller */
911
- this.s.tableTop = tableTop;
912
- this.s.tableBottom = iTableHeight + this.s.tableTop;
698
+ /* Cache some information for the scroller */
699
+ this.s.tableTop = tableTop;
700
+ this.s.tableBottom = iTableHeight + this.s.tableTop;
913
701
 
914
702
  // Calculate the boundaries for where a redraw will be triggered by the
915
703
  // scroll event listener
@@ -957,7 +745,7 @@ $.extend( Scroller.prototype, {
957
745
  // needed. Only add the thread break if bInfo is set
958
746
  if ( this.s.dt.oFeatures.bInfo ) {
959
747
  setTimeout( function () {
960
- that._fnInfo.call( that );
748
+ that._info.call( that );
961
749
  }, 0 );
962
750
  }
963
751
 
@@ -968,83 +756,59 @@ $.extend( Scroller.prototype, {
968
756
  }
969
757
  },
970
758
 
971
-
972
759
  /**
973
- * Force the scrolling container to have height beyond that of just the
974
- * table that has been drawn so the user can scroll the whole data set.
760
+ * Convert from one domain to another. The physical domain is the actual
761
+ * pixel count on the screen, while the virtual is if we had browsers which
762
+ * had scrolling containers of infinite height (i.e. the absolute value)
975
763
  *
976
- * Note that if the calculated required scrolling height exceeds a maximum
977
- * value (1 million pixels - hard-coded) the forcing element will be set
978
- * only to that maximum value and virtual / physical domain transforms will
979
- * be used to allow Scroller to display tables of any number of records.
980
- * @returns {void}
764
+ * @param {string} dir Domain transform direction, `virtualToPhysical` or
765
+ * `physicalToVirtual`
766
+ * @returns {number} Calculated transform
981
767
  * @private
982
768
  */
983
- _fnScrollForce: function ()
769
+ _domain: function ( dir, val )
984
770
  {
985
771
  var heights = this.s.heights;
986
- var max = 1000000;
772
+ var diff;
773
+ var magic = 10000; // the point at which the non-linear calculations start to happen
987
774
 
988
- heights.virtual = heights.row * this.s.dt.fnRecordsDisplay();
989
- heights.scroll = heights.virtual;
990
-
991
- if ( heights.scroll > max ) {
992
- heights.scroll = max;
775
+ // If the virtual and physical height match, then we use a linear
776
+ // transform between the two, allowing the scrollbar to be linear
777
+ if ( heights.virtual === heights.scroll ) {
778
+ return val;
993
779
  }
994
780
 
995
- // Minimum height so there is always a row visible (the 'no rows found'
996
- // if reduced to zero filtering)
997
- this.dom.force.style.height = heights.scroll > this.s.heights.row ?
998
- heights.scroll+'px' :
999
- this.s.heights.row+'px';
1000
- },
1001
-
1002
-
1003
- /**
1004
- * Automatic calculation of table row height. This is just a little tricky here as using
1005
- * initialisation DataTables has tale the table out of the document, so we need to create
1006
- * a new table and insert it into the document, calculate the row height and then whip the
1007
- * table out.
1008
- * @returns {void}
1009
- * @private
1010
- */
1011
- "_fnCalcRowHeight": function ()
1012
- {
1013
- var dt = this.s.dt;
1014
- var origTable = dt.nTable;
1015
- var nTable = origTable.cloneNode( false );
1016
- var tbody = $('<tbody/>').appendTo( nTable );
1017
- var container = $(
1018
- '<div class="'+dt.oClasses.sWrapper+' DTS">'+
1019
- '<div class="'+dt.oClasses.sScrollWrapper+'">'+
1020
- '<div class="'+dt.oClasses.sScrollBody+'"></div>'+
1021
- '</div>'+
1022
- '</div>'
1023
- );
1024
-
1025
- // Want 3 rows in the sizing table so :first-child and :last-child
1026
- // CSS styles don't come into play - take the size of the middle row
1027
- $('tbody tr:lt(4)', origTable).clone().appendTo( tbody );
1028
- while( $('tr', tbody).length < 3 ) {
1029
- tbody.append( '<tr><td>&nbsp;</td></tr>' );
781
+ // In the first 10k pixels and the last 10k pixels, we want the scrolling
782
+ // to be linear. After that it can be non-linear. It would be unusual for
783
+ // anyone to mouse wheel through that much.
784
+ if ( val < magic ) {
785
+ return val;
1030
786
  }
1031
-
1032
- $('div.'+dt.oClasses.sScrollBody, container).append( nTable );
1033
-
1034
- // If initialised using `dom`, use the holding element as the insert point
1035
- var insertEl = this.s.dt.nHolding || origTable.parentNode;
1036
-
1037
- if ( ! $(insertEl).is(':visible') ) {
1038
- insertEl = 'body';
787
+ else if ( dir === 'virtualToPhysical' && val >= heights.virtual - magic ) {
788
+ diff = heights.virtual - val;
789
+ return heights.scroll - diff;
790
+ }
791
+ else if ( dir === 'physicalToVirtual' && val >= heights.scroll - magic ) {
792
+ diff = heights.scroll - val;
793
+ return heights.virtual - diff;
1039
794
  }
1040
795
 
1041
- container.appendTo( insertEl );
1042
- this.s.heights.row = $('tr', tbody).eq(1).outerHeight();
1043
-
1044
- container.remove();
796
+ // Otherwise, we want a non-linear scrollbar to take account of the
797
+ // redrawing regions at the start and end of the table, otherwise these
798
+ // can stutter badly - on large tables 30px (for example) scroll might
799
+ // be hundreds of rows, so the table would be redrawing every few px at
800
+ // the start and end. Use a simple linear eq. to stop this, effectively
801
+ // causing a kink in the scrolling ratio. It does mean the scrollbar is
802
+ // non-linear, but with such massive data sets, the scrollbar is going
803
+ // to be a best guess anyway
804
+ var m = (heights.virtual - magic - magic) / (heights.scroll - magic - magic);
805
+ var c = magic - (m*magic);
806
+
807
+ return dir === 'virtualToPhysical' ?
808
+ (val-c) / m :
809
+ (m*val) + c;
1045
810
  },
1046
811
 
1047
-
1048
812
  /**
1049
813
  * Update any information elements that are controlled by the DataTable based on the scrolling
1050
814
  * viewport and what rows are visible in it. This function basically acts in the same way as
@@ -1052,7 +816,7 @@ $.extend( Scroller.prototype, {
1052
816
  * @returns {void}
1053
817
  * @private
1054
818
  */
1055
- "_fnInfo": function ()
819
+ _info: function ()
1056
820
  {
1057
821
  if ( !this.s.dt.oFeatures.bInfo )
1058
822
  {
@@ -1063,10 +827,10 @@ $.extend( Scroller.prototype, {
1063
827
  dt = this.s.dt,
1064
828
  language = dt.oLanguage,
1065
829
  iScrollTop = this.dom.scroller.scrollTop,
1066
- iStart = Math.floor( this.fnPixelsToRow(iScrollTop, false, this.s.ani)+1 ),
830
+ iStart = Math.floor( this.pixelsToRow(iScrollTop, false, this.s.ani)+1 ),
1067
831
  iMax = dt.fnRecordsTotal(),
1068
832
  iTotal = dt.fnRecordsDisplay(),
1069
- iPossibleEnd = Math.ceil( this.fnPixelsToRow(iScrollTop+this.s.heights.viewport, false, this.s.ani) ),
833
+ iPossibleEnd = Math.ceil( this.pixelsToRow(iScrollTop+this.s.heights.viewport, false, this.s.ani) ),
1070
834
  iEnd = iTotal < iPossibleEnd ? iTotal : iPossibleEnd,
1071
835
  sStart = dt.fnFormatNumber( iStart ),
1072
836
  sEnd = dt.fnFormatNumber( iEnd ),
@@ -1130,6 +894,210 @@ $.extend( Scroller.prototype, {
1130
894
 
1131
895
  // DT doesn't actually (yet) trigger this event, but it will in future
1132
896
  $(dt.nTable).triggerHandler( 'info.dt' );
897
+ },
898
+
899
+ /**
900
+ * Parse CSS height property string as number
901
+ *
902
+ * An attempt is made to parse the string as a number. Currently supported units are 'px',
903
+ * 'vh', and 'rem'. 'em' is partially supported; it works as long as the parent element's
904
+ * font size matches the body element. Zero is returned for unrecognized strings.
905
+ * @param {string} cssHeight CSS height property string
906
+ * @returns {number} height
907
+ * @private
908
+ */
909
+ _parseHeight: function(cssHeight) {
910
+ var height;
911
+ var matches = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(px|em|rem|vh)$/.exec(cssHeight);
912
+
913
+ if (matches === null) {
914
+ return 0;
915
+ }
916
+
917
+ var value = parseFloat(matches[1]);
918
+ var unit = matches[2];
919
+
920
+ if ( unit === 'px' ) {
921
+ height = value;
922
+ }
923
+ else if ( unit === 'vh' ) {
924
+ height = ( value / 100 ) * $(window).height();
925
+ }
926
+ else if ( unit === 'rem' ) {
927
+ height = value * parseFloat($(':root').css('font-size'));
928
+ }
929
+ else if ( unit === 'em' ) {
930
+ height = value * parseFloat($('body').css('font-size'));
931
+ }
932
+
933
+ return height ?
934
+ height :
935
+ 0;
936
+ },
937
+
938
+ /**
939
+ * Scrolling function - fired whenever the scrolling position is changed.
940
+ * This method needs to use the stored values to see if the table should be
941
+ * redrawn as we are moving towards the end of the information that is
942
+ * currently drawn or not. If needed, then it will redraw the table based on
943
+ * the new position.
944
+ * @returns {void}
945
+ * @private
946
+ */
947
+ _scroll: function ()
948
+ {
949
+ var
950
+ that = this,
951
+ heights = this.s.heights,
952
+ iScrollTop = this.dom.scroller.scrollTop,
953
+ iTopRow;
954
+
955
+ if ( this.s.skip ) {
956
+ return;
957
+ }
958
+
959
+ if ( this.s.ingnoreScroll ) {
960
+ return;
961
+ }
962
+
963
+ if ( iScrollTop === this.s.lastScrollTop ) {
964
+ return;
965
+ }
966
+
967
+ /* If the table has been sorted or filtered, then we use the redraw that
968
+ * DataTables as done, rather than performing our own
969
+ */
970
+ if ( this.s.dt.bFiltered || this.s.dt.bSorted ) {
971
+ this.s.lastScrollTop = 0;
972
+ return;
973
+ }
974
+
975
+ /* Update the table's information display for what is now in the viewport */
976
+ this._info();
977
+
978
+ /* We don't want to state save on every scroll event - that's heavy
979
+ * handed, so use a timeout to update the state saving only when the
980
+ * scrolling has finished
981
+ */
982
+ clearTimeout( this.s.stateTO );
983
+ this.s.stateTO = setTimeout( function () {
984
+ that.s.dtApi.state.save();
985
+ }, 250 );
986
+
987
+ this.s.scrollType = Math.abs(iScrollTop - this.s.lastScrollTop) > heights.viewport ?
988
+ 'jump' :
989
+ 'cont';
990
+
991
+ this.s.topRowFloat = this.s.scrollType === 'cont' ?
992
+ this.pixelsToRow( iScrollTop, false, false ) :
993
+ this._domain( 'physicalToVirtual', iScrollTop ) / heights.row;
994
+
995
+ if ( this.s.topRowFloat < 0 ) {
996
+ this.s.topRowFloat = 0;
997
+ }
998
+
999
+ /* Check if the scroll point is outside the trigger boundary which would required
1000
+ * a DataTables redraw
1001
+ */
1002
+ if ( this.s.forceReposition || iScrollTop < this.s.redrawTop || iScrollTop > this.s.redrawBottom ) {
1003
+ var preRows = Math.ceil( ((this.s.displayBuffer-1)/2) * this.s.viewportRows );
1004
+
1005
+ iTopRow = parseInt(this.s.topRowFloat, 10) - preRows;
1006
+ this.s.forceReposition = false;
1007
+
1008
+ if ( iTopRow <= 0 ) {
1009
+ /* At the start of the table */
1010
+ iTopRow = 0;
1011
+ }
1012
+ else if ( iTopRow + this.s.dt._iDisplayLength > this.s.dt.fnRecordsDisplay() ) {
1013
+ /* At the end of the table */
1014
+ iTopRow = this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength;
1015
+ if ( iTopRow < 0 ) {
1016
+ iTopRow = 0;
1017
+ }
1018
+ }
1019
+ else if ( iTopRow % 2 !== 0 ) {
1020
+ // For the row-striping classes (odd/even) we want only to start
1021
+ // on evens otherwise the stripes will change between draws and
1022
+ // look rubbish
1023
+ iTopRow++;
1024
+ }
1025
+
1026
+
1027
+ if ( iTopRow != this.s.dt._iDisplayStart ) {
1028
+ /* Cache the new table position for quick lookups */
1029
+ this.s.tableTop = $(this.s.dt.nTable).offset().top;
1030
+ this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
1031
+
1032
+ var draw = function () {
1033
+ if ( that.s.scrollDrawReq === null ) {
1034
+ that.s.scrollDrawReq = iScrollTop;
1035
+ }
1036
+
1037
+ that.s.dt._iDisplayStart = iTopRow;
1038
+ that.s.dt.oApi._fnDraw( that.s.dt );
1039
+ };
1040
+
1041
+ /* Do the DataTables redraw based on the calculated start point - note that when
1042
+ * using server-side processing we introduce a small delay to not DoS the server...
1043
+ */
1044
+ if ( this.s.dt.oFeatures.bServerSide ) {
1045
+ clearTimeout( this.s.drawTO );
1046
+ this.s.drawTO = setTimeout( draw, this.s.serverWait );
1047
+ }
1048
+ else {
1049
+ draw();
1050
+ }
1051
+
1052
+ if ( this.dom.loader && ! this.s.loaderVisible ) {
1053
+ this.dom.loader.css( 'display', 'block' );
1054
+ this.s.loaderVisible = true;
1055
+ }
1056
+ }
1057
+ }
1058
+ else {
1059
+ this.s.topRowFloat = this.pixelsToRow( iScrollTop, false, true );
1060
+ }
1061
+
1062
+ this.s.lastScrollTop = iScrollTop;
1063
+ this.s.stateSaveThrottle();
1064
+
1065
+ if ( this.s.scrollType === 'jump' && this.s.mousedown ) {
1066
+ this.dom.label
1067
+ .html( this.s.dt.fnFormatNumber( parseInt( this.s.topRowFloat, 10 )+1 ) )
1068
+ .css( 'top', iScrollTop + (iScrollTop * heights.labelFactor ) )
1069
+ .css( 'display', 'block' );
1070
+ }
1071
+ },
1072
+
1073
+ /**
1074
+ * Force the scrolling container to have height beyond that of just the
1075
+ * table that has been drawn so the user can scroll the whole data set.
1076
+ *
1077
+ * Note that if the calculated required scrolling height exceeds a maximum
1078
+ * value (1 million pixels - hard-coded) the forcing element will be set
1079
+ * only to that maximum value and virtual / physical domain transforms will
1080
+ * be used to allow Scroller to display tables of any number of records.
1081
+ * @returns {void}
1082
+ * @private
1083
+ */
1084
+ _scrollForce: function ()
1085
+ {
1086
+ var heights = this.s.heights;
1087
+ var max = 1000000;
1088
+
1089
+ heights.virtual = heights.row * this.s.dt.fnRecordsDisplay();
1090
+ heights.scroll = heights.virtual;
1091
+
1092
+ if ( heights.scroll > max ) {
1093
+ heights.scroll = max;
1094
+ }
1095
+
1096
+ // Minimum height so there is always a row visible (the 'no rows found'
1097
+ // if reduced to zero filtering)
1098
+ this.dom.force.style.height = heights.scroll > this.s.heights.row ?
1099
+ heights.scroll+'px' :
1100
+ this.s.heights.row+'px';
1133
1101
  }
1134
1102
  } );
1135
1103
 
@@ -1146,62 +1114,19 @@ $.extend( Scroller.prototype, {
1146
1114
  * @name Scroller.defaults
1147
1115
  * @static
1148
1116
  */
1149
- Scroller.defaults = /** @lends Scroller.defaults */{
1150
- /**
1151
- * Indicate if Scroller show show trace information on the console or not. This can be
1152
- * useful when debugging Scroller or if just curious as to what it is doing, but should
1153
- * be turned off for production.
1154
- * @type bool
1155
- * @default false
1156
- * @static
1157
- * @example
1158
- * var oTable = $('#example').dataTable( {
1159
- * "sScrollY": "200px",
1160
- * "sDom": "frtiS",
1161
- * "bDeferRender": true,
1162
- * "oScroller": {
1163
- * "trace": true
1164
- * }
1165
- * } );
1166
- */
1167
- "trace": false,
1168
-
1117
+ Scroller.defaults = {
1169
1118
  /**
1170
- * Scroller will attempt to automatically calculate the height of rows for it's internal
1171
- * calculations. However the height that is used can be overridden using this parameter.
1172
- * @type int|string
1173
- * @default auto
1174
- * @static
1175
- * @example
1176
- * var oTable = $('#example').dataTable( {
1177
- * "sScrollY": "200px",
1178
- * "sDom": "frtiS",
1179
- * "bDeferRender": true,
1180
- * "oScroller": {
1181
- * "rowHeight": 30
1182
- * }
1183
- * } );
1184
- */
1185
- "rowHeight": "auto",
1186
-
1187
- /**
1188
- * When using server-side processing, Scroller will wait a small amount of time to allow
1189
- * the scrolling to finish before requesting more data from the server. This prevents
1190
- * you from DoSing your own server! The wait time can be configured by this parameter.
1191
- * @type int
1192
- * @default 200
1119
+ * Scroller uses the boundary scaling factor to decide when to redraw the table - which it
1120
+ * typically does before you reach the end of the currently loaded data set (in order to
1121
+ * allow the data to look continuous to a user scrolling through the data). If given as 0
1122
+ * then the table will be redrawn whenever the viewport is scrolled, while 1 would not
1123
+ * redraw the table until the currently loaded data has all been shown. You will want
1124
+ * something in the middle - the default factor of 0.5 is usually suitable.
1125
+ * @type float
1126
+ * @default 0.5
1193
1127
  * @static
1194
- * @example
1195
- * var oTable = $('#example').dataTable( {
1196
- * "sScrollY": "200px",
1197
- * "sDom": "frtiS",
1198
- * "bDeferRender": true,
1199
- * "oScroller": {
1200
- * "serverWait": 100
1201
- * }
1202
- * } );
1203
1128
  */
1204
- "serverWait": 200,
1129
+ boundaryScale: 0.5,
1205
1130
 
1206
1131
  /**
1207
1132
  * The display buffer is what Scroller uses to calculate how many rows it should pre-fetch
@@ -1216,39 +1141,8 @@ Scroller.defaults = /** @lends Scroller.defaults */{
1216
1141
  * @type int
1217
1142
  * @default 7
1218
1143
  * @static
1219
- * @example
1220
- * var oTable = $('#example').dataTable( {
1221
- * "sScrollY": "200px",
1222
- * "sDom": "frtiS",
1223
- * "bDeferRender": true,
1224
- * "oScroller": {
1225
- * "displayBuffer": 10
1226
- * }
1227
- * } );
1228
- */
1229
- "displayBuffer": 9,
1230
-
1231
- /**
1232
- * Scroller uses the boundary scaling factor to decide when to redraw the table - which it
1233
- * typically does before you reach the end of the currently loaded data set (in order to
1234
- * allow the data to look continuous to a user scrolling through the data). If given as 0
1235
- * then the table will be redrawn whenever the viewport is scrolled, while 1 would not
1236
- * redraw the table until the currently loaded data has all been shown. You will want
1237
- * something in the middle - the default factor of 0.5 is usually suitable.
1238
- * @type float
1239
- * @default 0.5
1240
- * @static
1241
- * @example
1242
- * var oTable = $('#example').dataTable( {
1243
- * "sScrollY": "200px",
1244
- * "sDom": "frtiS",
1245
- * "bDeferRender": true,
1246
- * "oScroller": {
1247
- * "boundaryScale": 0.75
1248
- * }
1249
- * } );
1250
1144
  */
1251
- "boundaryScale": 0.5,
1145
+ displayBuffer: 9,
1252
1146
 
1253
1147
  /**
1254
1148
  * Show (or not) the loading element in the background of the table. Note that you should
@@ -1256,17 +1150,27 @@ Scroller.defaults = /** @lends Scroller.defaults */{
1256
1150
  * @type boolean
1257
1151
  * @default false
1258
1152
  * @static
1259
- * @example
1260
- * var oTable = $('#example').dataTable( {
1261
- * "sScrollY": "200px",
1262
- * "sDom": "frtiS",
1263
- * "bDeferRender": true,
1264
- * "oScroller": {
1265
- * "loadingIndicator": true
1266
- * }
1267
- * } );
1268
1153
  */
1269
- "loadingIndicator": false
1154
+ loadingIndicator: false,
1155
+
1156
+ /**
1157
+ * Scroller will attempt to automatically calculate the height of rows for it's internal
1158
+ * calculations. However the height that is used can be overridden using this parameter.
1159
+ * @type int|string
1160
+ * @default auto
1161
+ * @static
1162
+ */
1163
+ rowHeight: "auto",
1164
+
1165
+ /**
1166
+ * When using server-side processing, Scroller will wait a small amount of time to allow
1167
+ * the scrolling to finish before requesting more data from the server. This prevents
1168
+ * you from DoSing your own server! The wait time can be configured by this parameter.
1169
+ * @type int
1170
+ * @default 200
1171
+ * @static
1172
+ */
1173
+ serverWait: 200
1270
1174
  };
1271
1175
 
1272
1176
  Scroller.oDefaults = Scroller.defaults;
@@ -1284,7 +1188,7 @@ Scroller.oDefaults = Scroller.defaults;
1284
1188
  * @name Scroller.version
1285
1189
  * @static
1286
1190
  */
1287
- Scroller.version = "1.5.1";
1191
+ Scroller.version = "2.0.1";
1288
1192
 
1289
1193
 
1290
1194
 
@@ -1292,27 +1196,6 @@ Scroller.version = "1.5.1";
1292
1196
  * Initialisation
1293
1197
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1294
1198
 
1295
- // Legacy `dom` parameter initialisation support
1296
- if ( typeof $.fn.dataTable == "function" &&
1297
- typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
1298
- $.fn.dataTableExt.fnVersionCheck('1.10.0') )
1299
- {
1300
- $.fn.dataTableExt.aoFeatures.push( {
1301
- "fnInit": function( oDTSettings ) {
1302
- var init = oDTSettings.oInit;
1303
- var opts = init.scroller || init.oScroller || {};
1304
-
1305
- new Scroller( oDTSettings, opts );
1306
- },
1307
- "cFeature": "S",
1308
- "sFeature": "Scroller"
1309
- } );
1310
- }
1311
- else
1312
- {
1313
- alert( "Warning: Scroller requires DataTables 1.10.0 or greater - www.datatables.net/download");
1314
- }
1315
-
1316
1199
  // Attach a listener to the document which listens for DataTables initialisation
1317
1200
  // events so we can automatically initialise
1318
1201
  $(document).on( 'preInit.dt.dtscroller', function (e, settings) {
@@ -1350,7 +1233,7 @@ Api.register( 'scroller().rowToPixels()', function ( rowIdx, intParse, virtual )
1350
1233
  var ctx = this.context;
1351
1234
 
1352
1235
  if ( ctx.length && ctx[0].oScroller ) {
1353
- return ctx[0].oScroller.fnRowToPixels( rowIdx, intParse, virtual );
1236
+ return ctx[0].oScroller.rowToPixels( rowIdx, intParse, virtual );
1354
1237
  }
1355
1238
  // undefined
1356
1239
  } );
@@ -1360,7 +1243,7 @@ Api.register( 'scroller().pixelsToRow()', function ( pixels, intParse, virtual )
1360
1243
  var ctx = this.context;
1361
1244
 
1362
1245
  if ( ctx.length && ctx[0].oScroller ) {
1363
- return ctx[0].oScroller.fnPixelsToRow( pixels, intParse, virtual );
1246
+ return ctx[0].oScroller.pixelsToRow( pixels, intParse, virtual );
1364
1247
  }
1365
1248
  // undefined
1366
1249
  } );
@@ -1369,7 +1252,7 @@ Api.register( 'scroller().pixelsToRow()', function ( pixels, intParse, virtual )
1369
1252
  Api.register( ['scroller().scrollToRow()', 'scroller.toPosition()'], function ( idx, ani ) {
1370
1253
  this.iterator( 'table', function ( ctx ) {
1371
1254
  if ( ctx.oScroller ) {
1372
- ctx.oScroller.fnScrollToRow( idx, ani );
1255
+ ctx.oScroller.scrollToRow( idx, ani );
1373
1256
  }
1374
1257
  } );
1375
1258
 
@@ -1386,7 +1269,7 @@ Api.register( 'row().scrollTo()', function ( ani ) {
1386
1269
  .indexes()
1387
1270
  .indexOf( rowIdx );
1388
1271
 
1389
- ctx.oScroller.fnScrollToRow( displayIdx, ani );
1272
+ ctx.oScroller.scrollToRow( displayIdx, ani );
1390
1273
  }
1391
1274
  } );
1392
1275
 
@@ -1396,7 +1279,7 @@ Api.register( 'row().scrollTo()', function ( ani ) {
1396
1279
  Api.register( 'scroller.measure()', function ( redraw ) {
1397
1280
  this.iterator( 'table', function ( ctx ) {
1398
1281
  if ( ctx.oScroller ) {
1399
- ctx.oScroller.fnMeasure( redraw );
1282
+ ctx.oScroller.measure( redraw );
1400
1283
  }
1401
1284
  } );
1402
1285
 
@@ -1407,7 +1290,7 @@ Api.register( 'scroller.page()', function() {
1407
1290
  var ctx = this.context;
1408
1291
 
1409
1292
  if ( ctx.length && ctx[0].oScroller ) {
1410
- return ctx[0].oScroller.fnPageInfo();
1293
+ return ctx[0].oScroller.pageInfo();
1411
1294
  }
1412
1295
  // undefined
1413
1296
  } );