jquery-datatables 1.10.19.1 → 1.10.20

Sign up to get free protection for your applications and to get access to all the features.
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
  } );