Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2629 vikas 1
/**
2
 * @summary     Scroller
3
 * @description Virtual rendering for DataTables
4
 * @file        Scroller.js
5
 * @version     1.0.0
6
 * @author      Allan Jardine (www.sprymedia.co.uk)
7
 * @license     GPL v2 or BSD 3 point style
8
 * @contact     www.sprymedia.co.uk/contact
9
 *
10
 * @copyright Copyright 2011 Allan Jardine, all rights reserved.
11
 *
12
 * This source file is free software, under either the GPL v2 license or a
13
 * BSD style license, available at:
14
 *   http://datatables.net/license_gpl2
15
 *   http://datatables.net/license_bsd
16
 */
17
 
18
(function($, window, document) {
19
 
20
 
21
/** 
22
 * Scroller is a virtual rendering plug-in for DataTables which allows large
23
 * datasets to be drawn on screen every quickly. What the virtual rendering means
24
 * is that only the visible portion of the table (and a bit to either side to make
25
 * the scrolling smooth) is drawn, while the scrolling container gives the 
26
 * visual impression that the whole table is visible. This is done by making use
27
 * of the pagination abilities of DataTables and moving the table around in the
28
 * scrolling container DataTables adds to the page. The scrolling container is
29
 * forced to the height it would be for the full table display using an extra 
30
 * element. 
31
 * 
32
 * Note that rows in the table MUST all be the same hight. Information in a cell
33
 * which expands on to multiple lines will cause some odd behaviour in the scrolling.
34
 *
35
 * Scroller is initialised by simply including the letter 'S' in the sDom for the
36
 * table you want to have this feature enabled on. Note that the 'S' must come
37
 * AFTER the 't' parameter in sDom.
38
 * 
39
 * Key features include:
40
 *   <ul class="limit_length">
41
 *     <li>Speed! The aim of Scroller for DataTables is to make rendering large data sets fast</li>
42
 *     <li>Full compatibility with deferred rendering in DataTables 1.8 for maximum speed</li>
43
 *     <li>Correct visual scrolling implementation, similar to "infinite scrolling" in DataTable core</li>
44
 *     <li>Integration with state saving in DataTables (scrolling position is saved)</li>
45
 *     <li>Easy to use</li>
46
 *   </ul>
47
 *
48
 *  @class
49
 *  @constructor
50
 *  @param {object} oDT DataTables settings object
51
 *  @param {object} [oOpts={}] Configuration object for FixedColumns. Options are defined by {@link Scroller.oDefaults}
52
 * 
53
 *  @requires jQuery 1.4+
54
 *  @requires DataTables 1.8.0+
55
 * 
56
 *  @example
57
 * 		$(document).ready(function() {
58
 * 			$('#example').dataTable( {
59
 * 				"sScrollY": "200px",
60
 * 				"sAjaxSource": "media/dataset/large.txt",
61
 * 				"sDom": "frtiS",
62
 * 				"bDeferRender": true
63
 * 			} );
64
 * 		} );
65
 */
66
var Scroller = function ( oDTSettings, oOpts ) {
67
	/* Sanity check - you just know it will happen */
68
	if ( ! this instanceof Scroller )
69
	{
70
		alert( "Scroller warning: Scroller must be initialised with the 'new' keyword." );
71
		return;
72
	}
73
 
74
	if ( typeof oOpts == 'undefined' )
75
	{
76
		oOpts = {};
77
	}
78
 
79
	/**
80
	 * Settings object which contains customisable information for the Scroller instance
81
	 * @namespace
82
	 * @extends Scroller.DEFAULTS
83
	 */
84
	this.s = $.extend( {
85
		/** 
86
		 * DataTables settings object
87
		 *  @type     object
88
		 *  @default  Passed in as first parameter to constructor
89
		 */
90
		"dt": oDTSettings,
91
 
92
		/** 
93
		 * Pixel location of the top of the drawn table in the viewport
94
		 *  @type     int
95
		 *  @default  0
96
		 */
97
		"tableTop": 0,
98
 
99
		/** 
100
		 * Pixel location of the bottom of the drawn table in the viewport
101
		 *  @type     int
102
		 *  @default  0
103
		 */
104
		"tableBottom": 0,
105
 
106
		/** 
107
		 * Pixel location of the boundary for when the next data set should be loaded and drawn
108
		 * when scrolling up the way.
109
		 *  @type     int
110
		 *  @default  0
111
		 *  @private
112
		 */
113
		"redrawTop": 0,
114
 
115
		/** 
116
		 * Pixel location of the boundary for when the next data set should be loaded and drawn
117
		 * when scrolling down the way. Note that this is actually caluated as the offset from
118
		 * the top.
119
		 *  @type     int
120
		 *  @default  0
121
		 *  @private
122
		 */
123
		"redrawBottom": 0,
124
 
125
		/** 
126
		 * Height of rows in the table
127
		 *  @type     int
128
		 *  @default  0
129
		 */
130
		"rowHeight": null,
131
 
132
		/** 
133
		 * Pixel height of the viewport
134
		 *  @type     int
135
		 *  @default  0
136
		 */
137
		"viewportHeight": 0,
138
 
139
		/** 
140
		 * Number of rows calculated as visible in the visible viewport
141
		 *  @type     int
142
		 *  @default  0
143
		 */
144
		"viewportRows": 0,
145
 
146
		/** 
147
		 * setTimeout reference for state saving, used when state saving is enabled in the DataTable
148
		 * and when the user scrolls the viewport in order to stop the cookie set taking too much
149
		 * CPU!
150
		 *  @type     int
151
		 *  @default  0
152
		 */
153
		"stateTO": null,
154
 
155
		/** 
156
		 * setTimeout reference for the redraw, used when server-side processing is enabled in the
157
		 * DataTables in order to prevent DoSing the server
158
		 *  @type     int
159
		 *  @default  null
160
		 */
161
		"drawTO": null
162
	}, Scroller.oDefaults, oOpts );
163
 
164
	/**
165
	 * DOM elements used by the class instance
166
	 * @namespace
167
	 * 
168
	 */
169
	this.dom = {
170
		"force": document.createElement('div'),
171
		"scroller": null,
172
		"table": null
173
	};
174
 
175
	/* Attach the instance to the DataTables instance so it can be accessed */
176
	this.s.dt.oInstance.oScroller = this;
177
 
178
	/* Let's do it */
179
	this._fnConstruct();
180
};
181
 
182
 
183
 
184
Scroller.prototype = {
185
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
186
	 * Public methods
187
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
188
 
189
	/**
190
	 * Calculate the pixel position from the top of the scrolling container for a given row
191
	 *  @param {int} iRow Row number to calculate the position of
192
	 *  @returns {int} Pixels
193
	 *  @example
194
	 *  	$(document).ready(function() {
195
	 *  		$('#example').dataTable( {
196
	 *  			"sScrollY": "200px",
197
	 *  			"sAjaxSource": "media/dataset/large.txt",
198
	 *  			"sDom": "frtiS",
199
	 *  			"bDeferRender": true,
200
	 *  			"fnInitComplete": function () {
201
	 *  				// Find where row 25 is
202
	 *  				alert( this.oScroller.fnRowToPixels( 25 ) );
203
	 *  			}
204
	 *  		} );
205
	 *  	} );
206
	 */
207
	"fnRowToPixels": function ( iRow )
208
	{
209
		return iRow * this.s.rowHeight;
210
	},
211
 
212
 
213
	/**
214
	 * Calculate the row number that will be found at the given pixel position (y-scroll)
215
	 *  @param {int} iPixels Offset from top to caluclate the row number of
216
	 *  @returns {int} Row index
217
	 *  @example
218
	 *  	$(document).ready(function() {
219
	 *  		$('#example').dataTable( {
220
	 *  			"sScrollY": "200px",
221
	 *  			"sAjaxSource": "media/dataset/large.txt",
222
	 *  			"sDom": "frtiS",
223
	 *  			"bDeferRender": true,
224
	 *  			"fnInitComplete": function () {
225
	 *  				// Find what row number is at 500px
226
	 *  				alert( this.oScroller.fnPixelsToRow( 500 ) );
227
	 *  			}
228
	 *  		} );
229
	 *  	} );
230
	 */
231
	"fnPixelsToRow": function ( iPixels )
232
	{
233
		return parseInt( iPixels / this.s.rowHeight, 10 );
234
	},
235
 
236
 
237
	/**
238
	 * Calculate the row number that will be found at the given pixel position (y-scroll)
239
	 *  @param {int} iRow Row index to scroll to
240
	 *  @param {bool} [bAnimate=true] Animate the transision or not 
241
	 *  @returns {void}
242
	 *  @example
243
	 *  	$(document).ready(function() {
244
	 *  		$('#example').dataTable( {
245
	 *  			"sScrollY": "200px",
246
	 *  			"sAjaxSource": "media/dataset/large.txt",
247
	 *  			"sDom": "frtiS",
248
	 *  			"bDeferRender": true,
249
	 *  			"fnInitComplete": function () {
250
	 *  				// Immediately scroll to row 1000
251
	 *  				this.oScroller.fnScrollToRow( 1000 );
252
	 *  			}
253
	 *  		} );
254
	 *  	} );
255
	 */
256
	"fnScrollToRow": function ( iRow, bAnimate )
257
	{
258
		var px = this.fnRowToPixels( iRow );
259
		if ( typeof bAnimate == 'undefined' || bAnimate )
260
		{
261
			$(this.dom.scroller).animate( {
262
				"scrollTop": px
263
			} );
264
		}
265
		else
266
		{
267
			$(this.dom.scroller).scrollTop( px );
268
		}
269
	},
270
 
271
 
272
 
273
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
274
	 * Private methods (they are of course public in JS, but recommended as private)
275
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
276
 
277
	/**
278
	 * Initialisation for Scroller
279
	 *  @returns {void}
280
	 *  @private
281
	 */
282
	"_fnConstruct": function ()
283
	{
284
		var that = this;
285
 
286
		/* Insert a div element that we can use to force the DT scrolling container to
287
		 * the height that would be required if the whole table was being displayed
288
		 */
289
		this.dom.force.style.position = "absolute";
290
		this.dom.force.style.top = "0px";
291
		this.dom.force.style.left = "0px";
292
		this.dom.force.style.width = "1px";
293
		//this.dom.force.style.backgroundColor = "blue";
294
 
295
		this.dom.scroller = $('div.dataTables_scrollBody', this.s.dt.nTableWrapper)[0];
296
		this.dom.scroller.appendChild( this.dom.force );
297
		this.dom.scroller.style.position = "relative";
298
 
299
		this.dom.table = $('>table', this.dom.scroller)[0];
300
		this.dom.table.style.position = "absolute";
301
		this.dom.table.style.top = "0px";
302
		this.dom.table.style.left = "0px";
303
 
304
		/* Calcuate and store information about how many rows are displayed in the scrolling
305
		 * viewport
306
		 */
307
		if ( this.s.rowHeight == 'auto' )
308
		{
309
			this._fnCalcRowHeight();
310
		}
311
 
312
		this.s.viewportHeight = $(this.dom.scroller).height();
313
		this.s.viewportRows = parseInt( this.s.viewportHeight/this.s.rowHeight, 10 )+1;
314
		this.s.dt._iDisplayLength = this.s.viewportRows * 3;
315
 
316
		/* Scrolling callback to see if a page change is needed */
317
		$(this.dom.scroller).scroll( function () {
318
			that._fnScroll.call( that );
319
		} );
320
 
321
		/* Update the scroller when the DataTable is redrawn */
322
		this.s.dt.aoDrawCallback.push( {
323
			"fn": function () {
324
				that._fnDrawCallback.call( that );
325
			},
326
			"sName": "Scroller"
327
		} );
328
 
329
 
330
		/* Add a state saving parameter to the DT state saving so we can restore the exact
331
		 * position of the scrolling
332
		 */
333
		this.s.dt.aoStateSave.push( {
334
			"fn": function (oS, sVal) {
335
				return sVal+',"iScroller":'+that.dom.scroller.scrollTop;
336
			},
337
			"sName": "Scroller_State"
338
		} );
339
	},
340
 
341
 
342
	/**
343
	 * Scrolling function - fired whenever the scrolling position is changed. This method needs
344
	 * to use the stored values to see if the table should be redrawn as we are moving towards
345
	 * the end of the information that is currently drawn or not. If needed, then it will redraw
346
	 * the table based on the new position.
347
	 *  @returns {void}
348
	 *  @private
349
	 */
350
	"_fnScroll": function ()
351
	{
352
		var 
353
			that = this,
354
			iScrollTop = this.dom.scroller.scrollTop,
355
			iTopRow;
356
 
357
		if ( this.s.trace )
358
		{
359
			console.log(
360
				'Scroll: '+iScrollTop+'px - boundaries: '+this.s.redrawTop+' / '+this.s.redrawBottom+'. '+
361
				' Showing rows '+this.fnPixelsToRow(iScrollTop)+
362
				' to '+this.fnPixelsToRow(iScrollTop+$(this.dom.scroller).height())+
363
				' in the viewport, with rows '+this.s.dt._iDisplayStart+
364
				' to '+(this.s.dt._iDisplayEnd)+' rendered by the DataTable');
365
		}
366
 
367
		/* Update the table's information display for what is now in the viewport */
368
		this._fnInfo();
369
 
370
		/* We dont' want to state save on every scroll event - that's heavy handed, so
371
		 * use a timeout to update the state saving only when the scrolling has finished
372
		 */
373
		clearTimeout( this.s.stateTO );
374
		this.s.stateTO = setTimeout( function () {
375
			that.s.dt.oApi._fnSaveState( that.s.dt );
376
		}, 250 );
377
 
378
		/* Check if the scroll point is outside the trigger boundary which would required
379
		 * a DataTables redraw
380
		 */
381
		if ( iScrollTop < this.s.redrawTop || iScrollTop > this.s.redrawBottom )
382
		{
383
			iTopRow = parseInt( iScrollTop / this.s.rowHeight, 10 ) - this.s.viewportRows;
384
			if ( iTopRow < 0 )
385
			{
386
				/* At the start of the table */
387
				iTopRow = 0;
388
			}
389
			else if ( iTopRow + this.s.dt._iDisplayLength > this.s.dt.fnRecordsDisplay() )
390
			{
391
				/* At the end of the table */
392
				iTopRow = this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength;
393
			}
394
			else if ( iTopRow % 2 !== 0 )
395
			{
396
				/* For the row-striping classes (odd/even) we want only to start on evens
397
				 * otherwise the stripes will change between draws and look rubbish
398
				 */
399
				iTopRow++;
400
			}
401
 
402
			if ( iTopRow != this.s.dt._iDisplayStart )
403
			{
404
				/* Cache the new table position for quick lookups */
405
				this.s.tableTop = $(this.s.dt.nTable).offset().top;
406
				this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
407
 
408
				/* Do the DataTables redraw based on the calculated start point - note that when
409
				 * using server-side processing we introduce a small delay to not DoS the server...
410
				 */
411
				if ( this.s.dt.oFeatures.bServerSide ) {
412
					clearTimeout( this.s.drawTO );
413
					this.s.drawTO = setTimeout( function () {
414
						that.s.dt._iDisplayStart = iTopRow;
415
						that.s.dt.oApi._fnCalculateEnd( that.s.dt );
416
						that.s.dt.oApi._fnDraw( that.s.dt );
417
					}, this.s.serverWait );
418
				}
419
				else
420
				{
421
					this.s.dt._iDisplayStart = iTopRow;
422
					this.s.dt.oApi._fnCalculateEnd( this.s.dt );
423
					this.s.dt.oApi._fnDraw( this.s.dt );
424
				}
425
 
426
				if ( this.s.trace )
427
				{
428
					console.log( 'Scroll forcing redraw - top DT render row: '+ iTopRow );
429
				}
430
			}
431
		}
432
	},
433
 
434
 
435
	/**
436
	 * Draw callback function which is fired when the DataTable is redrawn. The main function of
437
	 * this method is to position the drawn table correctly the scrolling container for the rows
438
	 * that is displays as a result of the scrolling position.
439
	 *  @returns {void}
440
	 *  @private
441
	 */
442
	"_fnDrawCallback": function ()
443
	{
444
		var
445
			that = this,
446
			iScrollTop = this.dom.scroller.scrollTop;
447
 
448
		/* Set the height of the scrolling forcer to be suitable for the number of rows
449
		 * in this draw
450
		 */
451
		this.dom.force.style.height = (this.s.rowHeight * this.s.dt.fnRecordsDisplay())+"px";
452
 
453
		/* Calculate the position that the top of the table should be at */
454
		var iTableTop = (this.s.rowHeight*this.s.dt._iDisplayStart);
455
		if ( this.s.dt._iDisplayStart === 0 )
456
		{
457
			iTableTop = 0;
458
		}
459
		else if ( this.s.dt._iDisplayStart === this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength )
460
		{
461
			iTableTop = this.s.rowHeight * this.s.dt._iDisplayStart;
462
		}
463
 
464
		this.dom.table.style.top = iTableTop+"px";
465
 
466
		/* Cache some information for the scroller */
467
		this.s.tableTop = iTableTop;
468
		this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
469
 
470
		this.s.redrawTop = iScrollTop - (this.s.viewportHeight/2);
471
		this.s.redrawBottom = this.s.tableBottom - (1.5 * this.s.viewportHeight);
472
 
473
		if ( this.s.trace )
474
		{
475
			console.log(
476
				"Table redraw. Table top: "+iTableTop+"px. Table bottom: "+
477
				this.s.tableBottom+". Scroll boundary top: "+
478
				this.s.redrawTop+". Scroll boundary bottom: "+
479
				this.s.redrawBottom);
480
		}
481
 
482
		/* Because of the order of the DT callbacks, the info update will
483
		 * take precidence over the one we want here. So a 'thread' break is
484
		 * needed
485
		 */
486
		setTimeout( function () {
487
			that._fnInfo.call( that );
488
		}, 0 );
489
 
490
		/* Restore the scrolling position that was saved by DataTable's state saving
491
		 * Note that this is done on the second draw when data is Ajax sourced, and the
492
		 * first draw when DOM soured
493
		 */
494
		if ( this.s.dt.oFeatures.bStateSave && this.s.dt.oLoadedState !== null &&
495
			 typeof this.s.dt.oLoadedState.iScroller != 'undefined' )
496
		{
497
			if ( (this.s.dt.sAjaxSource !== null && this.s.dt.iDraw == 2) ||
498
			     (this.s.dt.sAjaxSource === null && this.s.dt.iDraw == 1) )
499
			{
500
				setTimeout( function () {
501
					$(that.dom.scroller).scrollTop( that.s.dt.oLoadedState.iScroller );
502
					that.s.redrawTop = that.s.dt.oLoadedState.iScroller - (that.s.viewportHeight/2);
503
				}, 0 );
504
			}
505
		}
506
	},
507
 
508
 
509
	/**
510
	 * Automatic calculation of table row height. This is just a little tricky here as using
511
	 * initialisation DataTables has tale the table out of the document, so we need to create
512
	 * a new table and insert it into the document, calculate the row height and then whip the
513
	 * table out.
514
	 *  @returns {void}
515
	 *  @private
516
	 */
517
	"_fnCalcRowHeight": function ()
518
	{
519
		var
520
			nTable = this.s.dt.nTable.cloneNode( false ),
521
			nBody = document.createElement( 'tbody' ),
522
			nTr = document.createElement('tr'),
523
			nTd = document.createElement('td');
524
 
525
		nTd.innerHTML = "&nbsp;";
526
		nTr.appendChild( nTd );
527
		nBody.appendChild( nTr );
528
		nTable.appendChild( nBody );
529
		document.body.appendChild( nTable );
530
		this.s.rowHeight = $(nTr).height();
531
		document.body.removeChild( nTable );
532
	},
533
 
534
 
535
	/**
536
	 * Update any information elements that are controlled by the DataTable based on the scrolling
537
	 * viewport and what rows are visible in it. This function basically acts in the same way as
538
	 * _fnUpdateInfo in DataTables, and effectively replaces that function.
539
	 *  @returns {void}
540
	 *  @private
541
	 */
542
	"_fnInfo": function ()
543
	{
544
		var
545
			dt = this.s.dt,
546
			iScrollTop = this.dom.scroller.scrollTop,
547
			iStart = this.fnPixelsToRow(iScrollTop)+1, 
548
			iEnd = this.fnPixelsToRow(iScrollTop+$(this.dom.scroller).height()),
549
			iMax = dt.fnRecordsTotal(),
550
			iTotal = dt.fnRecordsDisplay(),
551
			sStart = dt.fnFormatNumber( iStart ),
552
			sEnd = dt.fnFormatNumber( iEnd ),
553
			sMax = dt.fnFormatNumber( iMax ),
554
			sTotal = dt.fnFormatNumber( iTotal ),
555
			sOut;
556
 
557
		if ( dt.fnRecordsDisplay() === 0 && 
558
			   dt.fnRecordsDisplay() == dt.fnRecordsTotal() )
559
		{
560
			/* Empty record set */
561
			sOut = dt.oLanguage.sInfoEmpty+ dt.oLanguage.sInfoPostFix;
562
		}
563
		else if ( dt.fnRecordsDisplay() === 0 )
564
		{
565
			/* Rmpty record set after filtering */
566
			sOut = dt.oLanguage.sInfoEmpty +' '+ 
567
				dt.oLanguage.sInfoFiltered.replace('_MAX_', sMax)+
568
					dt.oLanguage.sInfoPostFix;
569
		}
570
		else if ( dt.fnRecordsDisplay() == dt.fnRecordsTotal() )
571
		{
572
			/* Normal record set */
573
			sOut = dt.oLanguage.sInfo.
574
					replace('_START_', sStart).
575
					replace('_END_',   sEnd).
576
					replace('_TOTAL_', sTotal)+ 
577
				dt.oLanguage.sInfoPostFix;
578
		}
579
		else
580
		{
581
			/* Record set after filtering */
582
			sOut = dt.oLanguage.sInfo.
583
					replace('_START_', sStart).
584
					replace('_END_',   sEnd).
585
					replace('_TOTAL_', sTotal) +' '+ 
586
				dt.oLanguage.sInfoFiltered.replace('_MAX_', 
587
					dt.fnFormatNumber(dt.fnRecordsTotal()))+ 
588
				dt.oLanguage.sInfoPostFix;
589
		}
590
 
591
		var n = dt.aanFeatures.i;
592
		for ( var i=0, iLen=n.length ; i<iLen ; i++ )
593
		{
594
			$(n[i]).html( sOut );
595
		}
596
	}
597
};
598
 
599
 
600
 
601
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
602
 * Statics
603
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
604
 
605
 
606
/**
607
 * Scroller default settings for initialisation
608
 *  @namespace
609
 *  @static
610
 */
611
Scroller.oDefaults = {
612
	/** 
613
	 * Indicate if Scroller show show trace information on the console or not. This can be 
614
	 * useful when debugging Scroller or if just curious as to what it is doing, but should
615
	 * be turned off for production.
616
	 *  @type     bool
617
	 *  @default  false
618
	 *  @static
619
	 *  @example
620
	 *  	var oTable = $('#example').dataTable( {
621
	 *      	"sScrollY": "200px",
622
	 *      	"sDom": "frtiS",
623
	 *      	"bDeferRender": true
624
	 *      	"oScroller": {
625
	 *      		"trace": true
626
	 *      	}
627
	 *  	} );
628
	 */
629
	"trace": false,
630
 
631
	/** 
632
	 * Scroller will attempt to automatically calculate the height of rows for it's internal
633
	 * calculations. However the height that is used can be overridden using this parameter.
634
	 *  @type     int|string
635
	 *  @default  auto
636
	 *  @static
637
	 *  @example
638
	 *  	var oTable = $('#example').dataTable( {
639
	 *      	"sScrollY": "200px",
640
	 *      	"sDom": "frtiS",
641
	 *      	"bDeferRender": true
642
	 *      	"oScroller": {
643
	 *      		"rowHeight": 30
644
	 *      	}
645
	 *  	} );
646
	 */
647
	"rowHeight": "auto",
648
 
649
	/** 
650
	 * When using server-side processing, Scroller will wait a small amount of time to allow
651
	 * the scrolling to finish before requesting more data from the server. This prevents
652
	 * you from DoSing your own server! The wait time can be configured by this parameter.
653
	 *  @type     int
654
	 *  @default  200
655
	 *  @static
656
	 *  @example
657
	 *  	var oTable = $('#example').dataTable( {
658
	 *      	"sScrollY": "200px",
659
	 *      	"sDom": "frtiS",
660
	 *      	"bDeferRender": true
661
	 *      	"oScroller": {
662
	 *      		"serverWait": 100
663
	 *      	}
664
	 *  	} );
665
	 */
666
	"serverWait": 200
667
};
668
 
669
 
670
 
671
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
672
 * Constants
673
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
674
 
675
 
676
/**
677
 * Name of this class
678
 *  @constant CLASS
679
 *  @type     String
680
 *  @default  Scroller
681
 */
682
Scroller.prototype.CLASS = "Scroller";
683
 
684
 
685
/**
686
 * Scroller version
687
 *  @constant  Scroller.VERSION
688
 *  @type      String
689
 *  @default   See code
690
 *  @static
691
 */
692
Scroller.VERSION = "1.0.0";
693
Scroller.prototype.CLASS = Scroller.VERSION;
694
 
695
 
696
 
697
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
698
 * Initialisation
699
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
700
 
701
/*
702
 * Register a new feature with DataTables
703
 */
704
if ( typeof $.fn.dataTable == "function" &&
705
     typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
706
     $.fn.dataTableExt.fnVersionCheck('1.8.0') )
707
{
708
	$.fn.dataTableExt.aoFeatures.push( {
709
		"fnInit": function( oDTSettings ) {
710
			var init = (typeof oDTSettings.oInit.oScroller == 'undefined') ?
711
				{} : oDTSettings.oInit.oScroller;
712
			var oScroller = new Scroller( oDTSettings, init );
713
			return oScroller.dom.wrapper;
714
		},
715
		"cFeature": "S",
716
		"sFeature": "Scroller"
717
	} );
718
}
719
else
720
{
721
	alert( "Warning: Scroller requires DataTables 1.8.0 or greater - www.datatables.net/download");
722
}
723
 
724
 
725
})(jQuery, window, document);