| Line 1... |
Line 1... |
| 1 |
/*! Scroller 1.5.1
|
1 |
/*!
|
| 2 |
* ©2011-2018 SpryMedia Ltd - datatables.net/license
|
2 |
Scroller 1.4.2
|
| 3 |
*/
|
3 |
©2011-2016 SpryMedia Ltd - datatables.net/license
|
| 4 |
|
4 |
*/
|
| 5 |
/**
|
5 |
(function(e){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(h){return e(h,window,document)}):"object"===typeof exports?module.exports=function(h,j){h||(h=window);if(!j||!j.fn.dataTable)j=require("datatables.net")(h,j).$;return e(j,h,h.document)}:e(jQuery,window,document)})(function(e,h,j,l){var m=e.fn.dataTable,g=function(a,b){this instanceof g?(b===l&&(b={}),this.s={dt:e.fn.dataTable.Api(a).settings()[0],tableTop:0,tableBottom:0,redrawTop:0,redrawBottom:0,autoHeight:!0,
|
| 6 |
* @summary Scroller
|
6 |
viewportRows:0,stateTO:null,drawTO:null,heights:{jump:null,page:null,virtual:null,scroll:null,row:null,viewport:null},topRowFloat:0,scrollDrawDiff:null,loaderVisible:!1},this.s=e.extend(this.s,g.oDefaults,b),this.s.heights.row=this.s.rowHeight,this.dom={force:j.createElement("div"),scroller:null,table:null,loader:null},this.s.dt.oScroller||(this.s.dt.oScroller=this,this._fnConstruct())):alert("Scroller warning: Scroller must be initialised with the 'new' keyword.")};e.extend(g.prototype,{fnRowToPixels:function(a,
|
| 7 |
* @description Virtual rendering for DataTables
|
7 |
b,c){a=c?this._domain("virtualToPhysical",a*this.s.heights.row):this.s.baseScrollTop+(a-this.s.baseRowTop)*this.s.heights.row;return b||b===l?parseInt(a,10):a},fnPixelsToRow:function(a,b,c){var d=a-this.s.baseScrollTop,a=c?this._domain("physicalToVirtual",a)/this.s.heights.row:d/this.s.heights.row+this.s.baseRowTop;return b||b===l?parseInt(a,10):a},fnScrollToRow:function(a,b){var c=this,d=!1,f=this.fnRowToPixels(a),i=a-(this.s.displayBuffer-1)/2*this.s.viewportRows;0>i&&(i=0);if((f>this.s.redrawBottom||
|
| 8 |
* @version 1.5.1
|
8 |
f<this.s.redrawTop)&&this.s.dt._iDisplayStart!==i)d=!0,f=this.fnRowToPixels(a,!1,!0);"undefined"==typeof b||b?(this.s.ani=d,e(this.dom.scroller).animate({scrollTop:f},function(){setTimeout(function(){c.s.ani=!1},25)})):e(this.dom.scroller).scrollTop(f)},fnMeasure:function(a){this.s.autoHeight&&this._fnCalcRowHeight();var b=this.s.heights;b.row&&(b.viewport=e(this.dom.scroller).height(),this.s.viewportRows=parseInt(b.viewport/b.row,10)+1,this.s.dt._iDisplayLength=this.s.viewportRows*this.s.displayBuffer);
|
| 9 |
* @file dataTables.scroller.js
|
9 |
(a===l||a)&&this.s.dt.oInstance.fnDraw(!1)},fnPageInfo:function(){var a=this.dom.scroller.scrollTop,b=this.s.dt.fnRecordsDisplay(),c=Math.ceil(this.fnPixelsToRow(a+this.s.heights.viewport,!1,this.s.ani));return{start:Math.floor(this.fnPixelsToRow(a,!1,this.s.ani)),end:b<c?b-1:c-1}},_fnConstruct:function(){var a=this;if(this.s.dt.oFeatures.bPaginate){this.dom.force.style.position="relative";this.dom.force.style.top="0px";this.dom.force.style.left="0px";this.dom.force.style.width="1px";this.dom.scroller=
|
| 10 |
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
10 |
e("div."+this.s.dt.oClasses.sScrollBody,this.s.dt.nTableWrapper)[0];this.dom.scroller.appendChild(this.dom.force);this.dom.scroller.style.position="relative";this.dom.table=e(">table",this.dom.scroller)[0];this.dom.table.style.position="absolute";this.dom.table.style.top="0px";this.dom.table.style.left="0px";e(this.s.dt.nTableWrapper).addClass("DTS");this.s.loadingIndicator&&(this.dom.loader=e('<div class="dataTables_processing DTS_Loading">'+this.s.dt.oLanguage.sLoadingRecords+"</div>").css("display",
|
| 11 |
* @contact www.sprymedia.co.uk/contact
|
11 |
"none"),e(this.dom.scroller.parentNode).css("position","relative").append(this.dom.loader));this.s.heights.row&&"auto"!=this.s.heights.row&&(this.s.autoHeight=!1);this.fnMeasure(!1);this.s.ingnoreScroll=!0;this.s.stateSaveThrottle=this.s.dt.oApi._fnThrottle(function(){a.s.dt.oApi._fnSaveState(a.s.dt)},500);e(this.dom.scroller).on("scroll.DTS",function(){a._fnScroll.call(a)});e(this.dom.scroller).on("touchstart.DTS",function(){a._fnScroll.call(a)});this.s.dt.aoDrawCallback.push({fn:function(){a.s.dt.bInitialised&&
|
| 12 |
* @copyright Copyright 2011-2018 SpryMedia Ltd.
|
12 |
a._fnDrawCallback.call(a)},sName:"Scroller"});e(h).on("resize.DTS",function(){a.fnMeasure(false);a._fnInfo()});var b=!0;this.s.dt.oApi._fnCallbackReg(this.s.dt,"aoStateSaveParams",function(c,d){if(b&&a.s.dt.oLoadedState){d.iScroller=a.s.dt.oLoadedState.iScroller;d.iScrollerTopRow=a.s.dt.oLoadedState.iScrollerTopRow;b=false}else{d.iScroller=a.dom.scroller.scrollTop;d.iScrollerTopRow=a.s.topRowFloat}},"Scroller_State");this.s.dt.oLoadedState&&(this.s.topRowFloat=this.s.dt.oLoadedState.iScrollerTopRow||
|
| 13 |
*
|
13 |
0);e(this.s.dt.nTable).one("init.dt",function(){a.fnMeasure()});this.s.dt.aoDestroyCallback.push({sName:"Scroller",fn:function(){e(h).off("resize.DTS");e(a.dom.scroller).off("touchstart.DTS scroll.DTS");e(a.s.dt.nTableWrapper).removeClass("DTS");e("div.DTS_Loading",a.dom.scroller.parentNode).remove();e(a.s.dt.nTable).off("init.dt");a.dom.table.style.position="";a.dom.table.style.top="";a.dom.table.style.left=""}})}else this.s.dt.oApi._fnLog(this.s.dt,0,"Pagination must be enabled for Scroller")},
|
| 14 |
* This source file is free software, available under the following license:
|
14 |
_fnScroll:function(){var a=this,b=this.s.heights,c=this.dom.scroller.scrollTop,d;if(!this.s.skip&&!this.s.ingnoreScroll)if(this.s.dt.bFiltered||this.s.dt.bSorted)this.s.lastScrollTop=0;else{this._fnInfo();clearTimeout(this.s.stateTO);this.s.stateTO=setTimeout(function(){a.s.dt.oApi._fnSaveState(a.s.dt)},250);if(c<this.s.redrawTop||c>this.s.redrawBottom){var f=Math.ceil((this.s.displayBuffer-1)/2*this.s.viewportRows);Math.abs(c-this.s.lastScrollTop)>b.viewport||this.s.ani?(d=parseInt(this._domain("physicalToVirtual",
|
| 15 |
* MIT license - http://datatables.net/license/mit
|
15 |
c)/b.row,10)-f,this.s.topRowFloat=this._domain("physicalToVirtual",c)/b.row):(d=this.fnPixelsToRow(c)-f,this.s.topRowFloat=this.fnPixelsToRow(c,!1));0>=d?d=0:d+this.s.dt._iDisplayLength>this.s.dt.fnRecordsDisplay()?(d=this.s.dt.fnRecordsDisplay()-this.s.dt._iDisplayLength,0>d&&(d=0)):0!==d%2&&d++;if(d!=this.s.dt._iDisplayStart&&(this.s.tableTop=e(this.s.dt.nTable).offset().top,this.s.tableBottom=e(this.s.dt.nTable).height()+this.s.tableTop,b=function(){if(a.s.scrollDrawReq===null)a.s.scrollDrawReq=
|
| 16 |
*
|
16 |
c;a.s.dt._iDisplayStart=d;a.s.dt.oApi._fnDraw(a.s.dt)},this.s.dt.oFeatures.bServerSide?(clearTimeout(this.s.drawTO),this.s.drawTO=setTimeout(b,this.s.serverWait)):b(),this.dom.loader&&!this.s.loaderVisible))this.dom.loader.css("display","block"),this.s.loaderVisible=!0}else this.s.topRowFloat=this._domain("physicalToVirtual",c)/b.row;this.s.lastScrollTop=c;this.s.stateSaveThrottle()}},_domain:function(a,b){var c=this.s.heights,d;if(c.virtual===c.scroll)return b;var e=(c.scroll-c.viewport)/2,i=(c.virtual-
|
| 17 |
* This source file is distributed in the hope that it will be useful, but
|
17 |
c.viewport)/2;d=i/(e*e);if("virtualToPhysical"===a){if(b<i)return Math.pow(b/d,0.5);b=2*i-b;return 0>b?c.scroll:2*e-Math.pow(b/d,0.5)}if("physicalToVirtual"===a){if(b<e)return b*b*d;b=2*e-b;return 0>b?c.virtual:2*i-b*b*d}},_fnDrawCallback:function(){var a=this,b=this.s.heights,c=this.dom.scroller.scrollTop,d=e(this.s.dt.nTable).height(),f=this.s.dt._iDisplayStart,i=this.s.dt._iDisplayLength,g=this.s.dt.fnRecordsDisplay();this.s.skip=!0;this._fnScrollForce();c=0===f?this.s.topRowFloat*b.row:f+i>=g?
|
| 18 |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
18 |
b.scroll-(g-this.s.topRowFloat)*b.row:this._domain("virtualToPhysical",this.s.topRowFloat*b.row);this.dom.scroller.scrollTop=c;this.s.baseScrollTop=c;this.s.baseRowTop=this.s.topRowFloat;var h=c-(this.s.topRowFloat-f)*b.row;0===f?h=0:f+i>=g&&(h=b.scroll-d);this.dom.table.style.top=h+"px";this.s.tableTop=h;this.s.tableBottom=d+this.s.tableTop;d=(c-this.s.tableTop)*this.s.boundaryScale;this.s.redrawTop=c-d;this.s.redrawBottom=c+d;this.s.skip=!1;this.s.dt.oFeatures.bStateSave&&null!==this.s.dt.oLoadedState&&
|
| 19 |
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
19 |
"undefined"!=typeof this.s.dt.oLoadedState.iScroller?((c=(this.s.dt.sAjaxSource||a.s.dt.ajax)&&!this.s.dt.oFeatures.bServerSide?!0:!1)&&2==this.s.dt.iDraw||!c&&1==this.s.dt.iDraw)&&setTimeout(function(){e(a.dom.scroller).scrollTop(a.s.dt.oLoadedState.iScroller);a.s.redrawTop=a.s.dt.oLoadedState.iScroller-b.viewport/2;setTimeout(function(){a.s.ingnoreScroll=!1},0)},0):a.s.ingnoreScroll=!1;this.s.dt.oFeatures.bInfo&&setTimeout(function(){a._fnInfo.call(a)},0);this.dom.loader&&this.s.loaderVisible&&
|
| 20 |
*
|
20 |
(this.dom.loader.css("display","none"),this.s.loaderVisible=!1)},_fnScrollForce:function(){var a=this.s.heights;a.virtual=a.row*this.s.dt.fnRecordsDisplay();a.scroll=a.virtual;1E6<a.scroll&&(a.scroll=1E6);this.dom.force.style.height=a.scroll>this.s.heights.row?a.scroll+"px":this.s.heights.row+"px"},_fnCalcRowHeight:function(){var a=this.s.dt,b=a.nTable,c=b.cloneNode(!1),d=e("<tbody/>").appendTo(c),f=e('<div class="'+a.oClasses.sWrapper+' DTS"><div class="'+a.oClasses.sScrollWrapper+'"><div class="'+
|
| 21 |
* For details please refer to: http://www.datatables.net
|
21 |
a.oClasses.sScrollBody+'"></div></div></div>');for(e("tbody tr:lt(4)",b).clone().appendTo(d);3>e("tr",d).length;)d.append("<tr><td> </td></tr>");e("div."+a.oClasses.sScrollBody,f).append(c);a=this.s.dt.nHolding||b.parentNode;e(a).is(":visible")||(a="body");f.appendTo(a);this.s.heights.row=e("tr",d).eq(1).outerHeight();f.remove()},_fnInfo:function(){if(this.s.dt.oFeatures.bInfo){var a=this.s.dt,b=a.oLanguage,c=this.dom.scroller.scrollTop,d=Math.floor(this.fnPixelsToRow(c,!1,this.s.ani)+1),f=a.fnRecordsTotal(),
|
| 22 |
*/
|
22 |
i=a.fnRecordsDisplay(),c=Math.ceil(this.fnPixelsToRow(c+this.s.heights.viewport,!1,this.s.ani)),c=i<c?i:c,g=a.fnFormatNumber(d),h=a.fnFormatNumber(c),j=a.fnFormatNumber(f),k=a.fnFormatNumber(i),g=0===a.fnRecordsDisplay()&&a.fnRecordsDisplay()==a.fnRecordsTotal()?b.sInfoEmpty+b.sInfoPostFix:0===a.fnRecordsDisplay()?b.sInfoEmpty+" "+b.sInfoFiltered.replace("_MAX_",j)+b.sInfoPostFix:a.fnRecordsDisplay()==a.fnRecordsTotal()?b.sInfo.replace("_START_",g).replace("_END_",h).replace("_MAX_",j).replace("_TOTAL_",
|
| 23 |
|
23 |
k)+b.sInfoPostFix:b.sInfo.replace("_START_",g).replace("_END_",h).replace("_MAX_",j).replace("_TOTAL_",k)+" "+b.sInfoFiltered.replace("_MAX_",a.fnFormatNumber(a.fnRecordsTotal()))+b.sInfoPostFix;(b=b.fnInfoCallback)&&(g=b.call(a.oInstance,a,d,c,f,i,g));d=a.aanFeatures.i;if("undefined"!=typeof d){f=0;for(i=d.length;f<i;f++)e(d[f]).html(g)}e(a.nTable).triggerHandler("info.dt")}}});g.defaults={trace:!1,rowHeight:"auto",serverWait:200,displayBuffer:9,boundaryScale:0.5,loadingIndicator:!1};g.oDefaults=
|
| 24 |
(function( factory ){
|
24 |
g.defaults;g.version="1.4.2";"function"==typeof e.fn.dataTable&&"function"==typeof e.fn.dataTableExt.fnVersionCheck&&e.fn.dataTableExt.fnVersionCheck("1.10.0")?e.fn.dataTableExt.aoFeatures.push({fnInit:function(a){var b=a.oInit;new g(a,b.scroller||b.oScroller||{})},cFeature:"S",sFeature:"Scroller"}):alert("Warning: Scroller requires DataTables 1.10.0 or greater - www.datatables.net/download");e(j).on("preInit.dt.dtscroller",function(a,b){if("dt"===a.namespace){var c=b.oInit.scroller,d=m.defaults.scroller;
|
| 25 |
if ( typeof define === 'function' && define.amd ) {
|
25 |
if(c||d)d=e.extend({},c,d),!1!==c&&new g(b,d)}});e.fn.dataTable.Scroller=g;e.fn.DataTable.Scroller=g;var k=e.fn.dataTable.Api;k.register("scroller()",function(){return this});k.register("scroller().rowToPixels()",function(a,b,c){var d=this.context;if(d.length&&d[0].oScroller)return d[0].oScroller.fnRowToPixels(a,b,c)});k.register("scroller().pixelsToRow()",function(a,b,c){var d=this.context;if(d.length&&d[0].oScroller)return d[0].oScroller.fnPixelsToRow(a,b,c)});k.register("scroller().scrollToRow()",
|
| 26 |
// AMD
|
26 |
function(a,b){this.iterator("table",function(c){c.oScroller&&c.oScroller.fnScrollToRow(a,b)});return this});k.register("row().scrollTo()",function(a){var b=this;this.iterator("row",function(c,d){if(c.oScroller){var e=b.rows({order:"applied",search:"applied"}).indexes().indexOf(d);c.oScroller.fnScrollToRow(e,a)}});return this});k.register("scroller.measure()",function(a){this.iterator("table",function(b){b.oScroller&&b.oScroller.fnMeasure(a)});return this});k.register("scroller.page()",function(){var a=
|
| 27 |
define( ['jquery', 'datatables.net'], function ( $ ) {
|
27 |
this.context;if(a.length&&a[0].oScroller)return a[0].oScroller.fnPageInfo()});return g});
|
| 28 |
return factory( $, window, document );
|
- |
|
| 29 |
} );
|
- |
|
| 30 |
}
|
- |
|
| 31 |
else if ( typeof exports === 'object' ) {
|
- |
|
| 32 |
// CommonJS
|
- |
|
| 33 |
module.exports = function (root, $) {
|
- |
|
| 34 |
if ( ! root ) {
|
- |
|
| 35 |
root = window;
|
- |
|
| 36 |
}
|
- |
|
| 37 |
|
- |
|
| 38 |
if ( ! $ || ! $.fn.dataTable ) {
|
- |
|
| 39 |
$ = require('datatables.net')(root, $).$;
|
- |
|
| 40 |
}
|
- |
|
| 41 |
|
- |
|
| 42 |
return factory( $, root, root.document );
|
- |
|
| 43 |
};
|
- |
|
| 44 |
}
|
- |
|
| 45 |
else {
|
- |
|
| 46 |
// Browser
|
- |
|
| 47 |
factory( jQuery, window, document );
|
- |
|
| 48 |
}
|
- |
|
| 49 |
}(function( $, window, document, undefined ) {
|
- |
|
| 50 |
'use strict';
|
- |
|
| 51 |
var DataTable = $.fn.dataTable;
|
- |
|
| 52 |
|
- |
|
| 53 |
|
- |
|
| 54 |
/**
|
- |
|
| 55 |
* Scroller is a virtual rendering plug-in for DataTables which allows large
|
- |
|
| 56 |
* datasets to be drawn on screen every quickly. What the virtual rendering means
|
- |
|
| 57 |
* is that only the visible portion of the table (and a bit to either side to make
|
- |
|
| 58 |
* the scrolling smooth) is drawn, while the scrolling container gives the
|
- |
|
| 59 |
* visual impression that the whole table is visible. This is done by making use
|
- |
|
| 60 |
* of the pagination abilities of DataTables and moving the table around in the
|
- |
|
| 61 |
* scrolling container DataTables adds to the page. The scrolling container is
|
- |
|
| 62 |
* forced to the height it would be for the full table display using an extra
|
- |
|
| 63 |
* element.
|
- |
|
| 64 |
*
|
- |
|
| 65 |
* Note that rows in the table MUST all be the same height. Information in a cell
|
- |
|
| 66 |
* which expands on to multiple lines will cause some odd behaviour in the scrolling.
|
- |
|
| 67 |
*
|
- |
|
| 68 |
* Scroller is initialised by simply including the letter 'S' in the sDom for the
|
- |
|
| 69 |
* table you want to have this feature enabled on. Note that the 'S' must come
|
- |
|
| 70 |
* AFTER the 't' parameter in `dom`.
|
- |
|
| 71 |
*
|
- |
|
| 72 |
* Key features include:
|
- |
|
| 73 |
* <ul class="limit_length">
|
- |
|
| 74 |
* <li>Speed! The aim of Scroller for DataTables is to make rendering large data sets fast</li>
|
- |
|
| 75 |
* <li>Full compatibility with deferred rendering in DataTables for maximum speed</li>
|
- |
|
| 76 |
* <li>Display millions of rows</li>
|
- |
|
| 77 |
* <li>Integration with state saving in DataTables (scrolling position is saved)</li>
|
- |
|
| 78 |
* <li>Easy to use</li>
|
- |
|
| 79 |
* </ul>
|
- |
|
| 80 |
*
|
- |
|
| 81 |
* @class
|
- |
|
| 82 |
* @constructor
|
- |
|
| 83 |
* @global
|
- |
|
| 84 |
* @param {object} dt DataTables settings object or API instance
|
- |
|
| 85 |
* @param {object} [opts={}] Configuration object for FixedColumns. Options
|
- |
|
| 86 |
* are defined by {@link Scroller.defaults}
|
- |
|
| 87 |
*
|
- |
|
| 88 |
* @requires jQuery 1.7+
|
- |
|
| 89 |
* @requires DataTables 1.10.0+
|
- |
|
| 90 |
*
|
- |
|
| 91 |
* @example
|
- |
|
| 92 |
* $(document).ready(function() {
|
- |
|
| 93 |
* $('#example').DataTable( {
|
- |
|
| 94 |
* "scrollY": "200px",
|
- |
|
| 95 |
* "ajax": "media/dataset/large.txt",
|
- |
|
| 96 |
* "dom": "frtiS",
|
- |
|
| 97 |
* "deferRender": true
|
- |
|
| 98 |
* } );
|
- |
|
| 99 |
* } );
|
- |
|
| 100 |
*/
|
- |
|
| 101 |
var Scroller = function ( dt, opts ) {
|
- |
|
| 102 |
/* Sanity check - you just know it will happen */
|
- |
|
| 103 |
if ( ! (this instanceof Scroller) ) {
|
- |
|
| 104 |
alert( "Scroller warning: Scroller must be initialised with the 'new' keyword." );
|
- |
|
| 105 |
return;
|
- |
|
| 106 |
}
|
- |
|
| 107 |
|
- |
|
| 108 |
if ( opts === undefined ) {
|
- |
|
| 109 |
opts = {};
|
- |
|
| 110 |
}
|
- |
|
| 111 |
|
- |
|
| 112 |
var dtApi = $.fn.dataTable.Api( dt );
|
- |
|
| 113 |
|
- |
|
| 114 |
/**
|
- |
|
| 115 |
* Settings object which contains customisable information for the Scroller instance
|
- |
|
| 116 |
* @namespace
|
- |
|
| 117 |
* @private
|
- |
|
| 118 |
* @extends Scroller.defaults
|
- |
|
| 119 |
*/
|
- |
|
| 120 |
this.s = {
|
- |
|
| 121 |
/**
|
- |
|
| 122 |
* DataTables settings object
|
- |
|
| 123 |
* @type object
|
- |
|
| 124 |
* @default Passed in as first parameter to constructor
|
- |
|
| 125 |
*/
|
- |
|
| 126 |
"dt": dtApi.settings()[0],
|
- |
|
| 127 |
|
- |
|
| 128 |
/**
|
- |
|
| 129 |
* DataTables API instance
|
- |
|
| 130 |
* @type DataTable.Api
|
- |
|
| 131 |
*/
|
- |
|
| 132 |
"dtApi": dtApi,
|
- |
|
| 133 |
|
- |
|
| 134 |
/**
|
- |
|
| 135 |
* Pixel location of the top of the drawn table in the viewport
|
- |
|
| 136 |
* @type int
|
- |
|
| 137 |
* @default 0
|
- |
|
| 138 |
*/
|
- |
|
| 139 |
"tableTop": 0,
|
- |
|
| 140 |
|
- |
|
| 141 |
/**
|
- |
|
| 142 |
* Pixel location of the bottom of the drawn table in the viewport
|
- |
|
| 143 |
* @type int
|
- |
|
| 144 |
* @default 0
|
- |
|
| 145 |
*/
|
- |
|
| 146 |
"tableBottom": 0,
|
- |
|
| 147 |
|
- |
|
| 148 |
/**
|
- |
|
| 149 |
* Pixel location of the boundary for when the next data set should be loaded and drawn
|
- |
|
| 150 |
* when scrolling up the way.
|
- |
|
| 151 |
* @type int
|
- |
|
| 152 |
* @default 0
|
- |
|
| 153 |
* @private
|
- |
|
| 154 |
*/
|
- |
|
| 155 |
"redrawTop": 0,
|
- |
|
| 156 |
|
- |
|
| 157 |
/**
|
- |
|
| 158 |
* Pixel location of the boundary for when the next data set should be loaded and drawn
|
- |
|
| 159 |
* when scrolling down the way. Note that this is actually calculated as the offset from
|
- |
|
| 160 |
* the top.
|
- |
|
| 161 |
* @type int
|
- |
|
| 162 |
* @default 0
|
- |
|
| 163 |
* @private
|
- |
|
| 164 |
*/
|
- |
|
| 165 |
"redrawBottom": 0,
|
- |
|
| 166 |
|
- |
|
| 167 |
/**
|
- |
|
| 168 |
* Auto row height or not indicator
|
- |
|
| 169 |
* @type bool
|
- |
|
| 170 |
* @default 0
|
- |
|
| 171 |
*/
|
- |
|
| 172 |
"autoHeight": true,
|
- |
|
| 173 |
|
- |
|
| 174 |
/**
|
- |
|
| 175 |
* Number of rows calculated as visible in the visible viewport
|
- |
|
| 176 |
* @type int
|
- |
|
| 177 |
* @default 0
|
- |
|
| 178 |
*/
|
- |
|
| 179 |
"viewportRows": 0,
|
- |
|
| 180 |
|
- |
|
| 181 |
/**
|
- |
|
| 182 |
* setTimeout reference for state saving, used when state saving is enabled in the DataTable
|
- |
|
| 183 |
* and when the user scrolls the viewport in order to stop the cookie set taking too much
|
- |
|
| 184 |
* CPU!
|
- |
|
| 185 |
* @type int
|
- |
|
| 186 |
* @default 0
|
- |
|
| 187 |
*/
|
- |
|
| 188 |
"stateTO": null,
|
- |
|
| 189 |
|
- |
|
| 190 |
/**
|
- |
|
| 191 |
* setTimeout reference for the redraw, used when server-side processing is enabled in the
|
- |
|
| 192 |
* DataTables in order to prevent DoSing the server
|
- |
|
| 193 |
* @type int
|
- |
|
| 194 |
* @default null
|
- |
|
| 195 |
*/
|
- |
|
| 196 |
"drawTO": null,
|
- |
|
| 197 |
|
- |
|
| 198 |
heights: {
|
- |
|
| 199 |
jump: null,
|
- |
|
| 200 |
page: null,
|
- |
|
| 201 |
virtual: null,
|
- |
|
| 202 |
scroll: null,
|
- |
|
| 203 |
|
- |
|
| 204 |
/**
|
- |
|
| 205 |
* Height of rows in the table
|
- |
|
| 206 |
* @type int
|
- |
|
| 207 |
* @default 0
|
- |
|
| 208 |
*/
|
- |
|
| 209 |
row: null,
|
- |
|
| 210 |
|
- |
|
| 211 |
/**
|
- |
|
| 212 |
* Pixel height of the viewport
|
- |
|
| 213 |
* @type int
|
- |
|
| 214 |
* @default 0
|
- |
|
| 215 |
*/
|
- |
|
| 216 |
viewport: null
|
- |
|
| 217 |
},
|
- |
|
| 218 |
|
- |
|
| 219 |
topRowFloat: 0,
|
- |
|
| 220 |
scrollDrawDiff: null,
|
- |
|
| 221 |
loaderVisible: false,
|
- |
|
| 222 |
forceReposition: false,
|
- |
|
| 223 |
baseRowTop: 0,
|
- |
|
| 224 |
baseScrollTop: 0
|
- |
|
| 225 |
};
|
- |
|
| 226 |
|
- |
|
| 227 |
// @todo The defaults should extend a `c` property and the internal settings
|
- |
|
| 228 |
// only held in the `s` property. At the moment they are mixed
|
- |
|
| 229 |
this.s = $.extend( this.s, Scroller.oDefaults, opts );
|
- |
|
| 230 |
|
- |
|
| 231 |
// Workaround for row height being read from height object (see above comment)
|
- |
|
| 232 |
this.s.heights.row = this.s.rowHeight;
|
- |
|
| 233 |
|
- |
|
| 234 |
/**
|
- |
|
| 235 |
* DOM elements used by the class instance
|
- |
|
| 236 |
* @private
|
- |
|
| 237 |
* @namespace
|
- |
|
| 238 |
*
|
- |
|
| 239 |
*/
|
- |
|
| 240 |
this.dom = {
|
- |
|
| 241 |
"force": document.createElement('div'),
|
- |
|
| 242 |
"scroller": null,
|
- |
|
| 243 |
"table": null,
|
- |
|
| 244 |
"loader": null
|
- |
|
| 245 |
};
|
- |
|
| 246 |
|
- |
|
| 247 |
// Attach the instance to the DataTables instance so it can be accessed in
|
- |
|
| 248 |
// future. Don't initialise Scroller twice on the same table
|
- |
|
| 249 |
if ( this.s.dt.oScroller ) {
|
- |
|
| 250 |
return;
|
- |
|
| 251 |
}
|
- |
|
| 252 |
|
- |
|
| 253 |
this.s.dt.oScroller = this;
|
- |
|
| 254 |
|
- |
|
| 255 |
/* Let's do it */
|
- |
|
| 256 |
this._fnConstruct();
|
- |
|
| 257 |
};
|
- |
|
| 258 |
|
- |
|
| 259 |
|
- |
|
| 260 |
|
- |
|
| 261 |
$.extend( Scroller.prototype, {
|
- |
|
| 262 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
- |
|
| 263 |
* Public methods
|
- |
|
| 264 |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
- |
|
| 265 |
|
- |
|
| 266 |
/**
|
- |
|
| 267 |
* Calculate the pixel position from the top of the scrolling container for
|
- |
|
| 268 |
* a given row
|
- |
|
| 269 |
* @param {int} iRow Row number to calculate the position of
|
- |
|
| 270 |
* @returns {int} Pixels
|
- |
|
| 271 |
* @example
|
- |
|
| 272 |
* $(document).ready(function() {
|
- |
|
| 273 |
* $('#example').dataTable( {
|
- |
|
| 274 |
* "sScrollY": "200px",
|
- |
|
| 275 |
* "sAjaxSource": "media/dataset/large.txt",
|
- |
|
| 276 |
* "sDom": "frtiS",
|
- |
|
| 277 |
* "bDeferRender": true,
|
- |
|
| 278 |
* "fnInitComplete": function (o) {
|
- |
|
| 279 |
* // Find where row 25 is
|
- |
|
| 280 |
* alert( o.oScroller.fnRowToPixels( 25 ) );
|
- |
|
| 281 |
* }
|
- |
|
| 282 |
* } );
|
- |
|
| 283 |
* } );
|
- |
|
| 284 |
*/
|
- |
|
| 285 |
"fnRowToPixels": function ( rowIdx, intParse, virtual )
|
- |
|
| 286 |
{
|
- |
|
| 287 |
var pixels;
|
- |
|
| 288 |
var diff = rowIdx - this.s.baseRowTop;
|
- |
|
| 289 |
|
- |
|
| 290 |
if ( virtual ) {
|
- |
|
| 291 |
pixels = this._domain( 'virtualToPhysical', this.s.baseScrollTop );
|
- |
|
| 292 |
pixels += diff * this.s.heights.row;
|
- |
|
| 293 |
}
|
- |
|
| 294 |
else {
|
- |
|
| 295 |
pixels = this.s.baseScrollTop;
|
- |
|
| 296 |
pixels += diff * this.s.heights.row;
|
- |
|
| 297 |
}
|
- |
|
| 298 |
|
- |
|
| 299 |
return intParse || intParse === undefined ?
|
- |
|
| 300 |
parseInt( pixels, 10 ) :
|
- |
|
| 301 |
pixels;
|
- |
|
| 302 |
},
|
- |
|
| 303 |
|
- |
|
| 304 |
|
- |
|
| 305 |
/**
|
- |
|
| 306 |
* Calculate the row number that will be found at the given pixel position
|
- |
|
| 307 |
* (y-scroll).
|
- |
|
| 308 |
*
|
- |
|
| 309 |
* Please note that when the height of the full table exceeds 1 million
|
- |
|
| 310 |
* pixels, Scroller switches into a non-linear mode for the scrollbar to fit
|
- |
|
| 311 |
* all of the records into a finite area, but this function returns a linear
|
- |
|
| 312 |
* value (relative to the last non-linear positioning).
|
- |
|
| 313 |
* @param {int} iPixels Offset from top to calculate the row number of
|
- |
|
| 314 |
* @param {int} [intParse=true] If an integer value should be returned
|
- |
|
| 315 |
* @param {int} [virtual=false] Perform the calculations in the virtual domain
|
- |
|
| 316 |
* @returns {int} Row index
|
- |
|
| 317 |
* @example
|
- |
|
| 318 |
* $(document).ready(function() {
|
- |
|
| 319 |
* $('#example').dataTable( {
|
- |
|
| 320 |
* "sScrollY": "200px",
|
- |
|
| 321 |
* "sAjaxSource": "media/dataset/large.txt",
|
- |
|
| 322 |
* "sDom": "frtiS",
|
- |
|
| 323 |
* "bDeferRender": true,
|
- |
|
| 324 |
* "fnInitComplete": function (o) {
|
- |
|
| 325 |
* // Find what row number is at 500px
|
- |
|
| 326 |
* alert( o.oScroller.fnPixelsToRow( 500 ) );
|
- |
|
| 327 |
* }
|
- |
|
| 328 |
* } );
|
- |
|
| 329 |
* } );
|
- |
|
| 330 |
*/
|
- |
|
| 331 |
"fnPixelsToRow": function ( pixels, intParse, virtual )
|
- |
|
| 332 |
{
|
- |
|
| 333 |
var diff = pixels - this.s.baseScrollTop;
|
- |
|
| 334 |
var row = virtual ?
|
- |
|
| 335 |
(this._domain( 'physicalToVirtual', this.s.baseScrollTop ) + diff) / this.s.heights.row :
|
- |
|
| 336 |
( diff / this.s.heights.row ) + this.s.baseRowTop;
|
- |
|
| 337 |
|
- |
|
| 338 |
return intParse || intParse === undefined ?
|
- |
|
| 339 |
parseInt( row, 10 ) :
|
- |
|
| 340 |
row;
|
- |
|
| 341 |
},
|
- |
|
| 342 |
|
- |
|
| 343 |
|
- |
|
| 344 |
/**
|
- |
|
| 345 |
* Calculate the row number that will be found at the given pixel position (y-scroll)
|
- |
|
| 346 |
* @param {int} iRow Row index to scroll to
|
- |
|
| 347 |
* @param {bool} [bAnimate=true] Animate the transition or not
|
- |
|
| 348 |
* @returns {void}
|
- |
|
| 349 |
* @example
|
- |
|
| 350 |
* $(document).ready(function() {
|
- |
|
| 351 |
* $('#example').dataTable( {
|
- |
|
| 352 |
* "sScrollY": "200px",
|
- |
|
| 353 |
* "sAjaxSource": "media/dataset/large.txt",
|
- |
|
| 354 |
* "sDom": "frtiS",
|
- |
|
| 355 |
* "bDeferRender": true,
|
- |
|
| 356 |
* "fnInitComplete": function (o) {
|
- |
|
| 357 |
* // Immediately scroll to row 1000
|
- |
|
| 358 |
* o.oScroller.fnScrollToRow( 1000 );
|
- |
|
| 359 |
* }
|
- |
|
| 360 |
* } );
|
- |
|
| 361 |
*
|
- |
|
| 362 |
* // Sometime later on use the following to scroll to row 500...
|
- |
|
| 363 |
* var oSettings = $('#example').dataTable().fnSettings();
|
- |
|
| 364 |
* oSettings.oScroller.fnScrollToRow( 500 );
|
- |
|
| 365 |
* } );
|
- |
|
| 366 |
*/
|
- |
|
| 367 |
"fnScrollToRow": function ( iRow, bAnimate )
|
- |
|
| 368 |
{
|
- |
|
| 369 |
var that = this;
|
- |
|
| 370 |
var ani = false;
|
- |
|
| 371 |
var px = this.fnRowToPixels( iRow );
|
- |
|
| 372 |
|
- |
|
| 373 |
// We need to know if the table will redraw or not before doing the
|
- |
|
| 374 |
// scroll. If it will not redraw, then we need to use the currently
|
- |
|
| 375 |
// displayed table, and scroll with the physical pixels. Otherwise, we
|
- |
|
| 376 |
// need to calculate the table's new position from the virtual
|
- |
|
| 377 |
// transform.
|
- |
|
| 378 |
var preRows = ((this.s.displayBuffer-1)/2) * this.s.viewportRows;
|
- |
|
| 379 |
var drawRow = iRow - preRows;
|
- |
|
| 380 |
if ( drawRow < 0 ) {
|
- |
|
| 381 |
drawRow = 0;
|
- |
|
| 382 |
}
|
- |
|
| 383 |
|
- |
|
| 384 |
if ( (px > this.s.redrawBottom || px < this.s.redrawTop) && this.s.dt._iDisplayStart !== drawRow ) {
|
- |
|
| 385 |
ani = true;
|
- |
|
| 386 |
px = this._domain( 'virtualToPhysical', iRow * this.s.heights.row );
|
- |
|
| 387 |
|
- |
|
| 388 |
// If we need records outside the current draw region, but the new
|
- |
|
| 389 |
// scrolling position is inside that (due to the non-linear nature
|
- |
|
| 390 |
// for larger numbers of records), we need to force position update.
|
- |
|
| 391 |
if ( this.s.redrawTop < px && px < this.s.redrawBottom ) {
|
- |
|
| 392 |
this.s.forceReposition = true;
|
- |
|
| 393 |
bAnimate = false;
|
- |
|
| 394 |
}
|
- |
|
| 395 |
}
|
- |
|
| 396 |
|
- |
|
| 397 |
if ( typeof bAnimate == 'undefined' || bAnimate )
|
- |
|
| 398 |
{
|
- |
|
| 399 |
this.s.ani = ani;
|
- |
|
| 400 |
$(this.dom.scroller).animate( {
|
- |
|
| 401 |
"scrollTop": px
|
- |
|
| 402 |
}, function () {
|
- |
|
| 403 |
// This needs to happen after the animation has completed and
|
- |
|
| 404 |
// the final scroll event fired
|
- |
|
| 405 |
setTimeout( function () {
|
- |
|
| 406 |
that.s.ani = false;
|
- |
|
| 407 |
}, 25 );
|
- |
|
| 408 |
} );
|
- |
|
| 409 |
}
|
- |
|
| 410 |
else
|
- |
|
| 411 |
{
|
- |
|
| 412 |
$(this.dom.scroller).scrollTop( px );
|
- |
|
| 413 |
}
|
- |
|
| 414 |
},
|
- |
|
| 415 |
|
- |
|
| 416 |
|
- |
|
| 417 |
/**
|
- |
|
| 418 |
* Calculate and store information about how many rows are to be displayed
|
- |
|
| 419 |
* in the scrolling viewport, based on current dimensions in the browser's
|
- |
|
| 420 |
* rendering. This can be particularly useful if the table is initially
|
- |
|
| 421 |
* drawn in a hidden element - for example in a tab.
|
- |
|
| 422 |
* @param {bool} [bRedraw=true] Redraw the table automatically after the recalculation, with
|
- |
|
| 423 |
* the new dimensions forming the basis for the draw.
|
- |
|
| 424 |
* @returns {void}
|
- |
|
| 425 |
* @example
|
- |
|
| 426 |
* $(document).ready(function() {
|
- |
|
| 427 |
* // Make the example container hidden to throw off the browser's sizing
|
- |
|
| 428 |
* document.getElementById('container').style.display = "none";
|
- |
|
| 429 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 430 |
* "sScrollY": "200px",
|
- |
|
| 431 |
* "sAjaxSource": "media/dataset/large.txt",
|
- |
|
| 432 |
* "sDom": "frtiS",
|
- |
|
| 433 |
* "bDeferRender": true,
|
- |
|
| 434 |
* "fnInitComplete": function (o) {
|
- |
|
| 435 |
* // Immediately scroll to row 1000
|
- |
|
| 436 |
* o.oScroller.fnScrollToRow( 1000 );
|
- |
|
| 437 |
* }
|
- |
|
| 438 |
* } );
|
- |
|
| 439 |
*
|
- |
|
| 440 |
* setTimeout( function () {
|
- |
|
| 441 |
* // Make the example container visible and recalculate the scroller sizes
|
- |
|
| 442 |
* document.getElementById('container').style.display = "block";
|
- |
|
| 443 |
* oTable.fnSettings().oScroller.fnMeasure();
|
- |
|
| 444 |
* }, 3000 );
|
- |
|
| 445 |
*/
|
- |
|
| 446 |
"fnMeasure": function ( bRedraw )
|
- |
|
| 447 |
{
|
- |
|
| 448 |
if ( this.s.autoHeight )
|
- |
|
| 449 |
{
|
- |
|
| 450 |
this._fnCalcRowHeight();
|
- |
|
| 451 |
}
|
- |
|
| 452 |
|
- |
|
| 453 |
var heights = this.s.heights;
|
- |
|
| 454 |
|
- |
|
| 455 |
if ( heights.row ) {
|
- |
|
| 456 |
heights.viewport = $.contains(document, this.dom.scroller) ?
|
- |
|
| 457 |
$(this.dom.scroller).height() :
|
- |
|
| 458 |
this._parseHeight($(this.dom.scroller).css('height'));
|
- |
|
| 459 |
|
- |
|
| 460 |
// If collapsed (no height) use the max-height parameter
|
- |
|
| 461 |
if ( ! heights.viewport ) {
|
- |
|
| 462 |
heights.viewport = this._parseHeight($(this.dom.scroller).css('max-height'));
|
- |
|
| 463 |
}
|
- |
|
| 464 |
|
- |
|
| 465 |
this.s.viewportRows = parseInt( heights.viewport / heights.row, 10 )+1;
|
- |
|
| 466 |
this.s.dt._iDisplayLength = this.s.viewportRows * this.s.displayBuffer;
|
- |
|
| 467 |
}
|
- |
|
| 468 |
|
- |
|
| 469 |
if ( bRedraw === undefined || bRedraw )
|
- |
|
| 470 |
{
|
- |
|
| 471 |
this.s.dt.oInstance.fnDraw( false );
|
- |
|
| 472 |
}
|
- |
|
| 473 |
},
|
- |
|
| 474 |
|
- |
|
| 475 |
|
- |
|
| 476 |
/**
|
- |
|
| 477 |
* Get information about current displayed record range. This corresponds to
|
- |
|
| 478 |
* the information usually displayed in the "Info" block of the table.
|
- |
|
| 479 |
*
|
- |
|
| 480 |
* @returns {object} info as an object:
|
- |
|
| 481 |
* {
|
- |
|
| 482 |
* start: {int}, // the 0-indexed record at the top of the viewport
|
- |
|
| 483 |
* end: {int}, // the 0-indexed record at the bottom of the viewport
|
- |
|
| 484 |
* }
|
- |
|
| 485 |
*/
|
- |
|
| 486 |
"fnPageInfo": function()
|
- |
|
| 487 |
{
|
- |
|
| 488 |
var
|
- |
|
| 489 |
dt = this.s.dt,
|
- |
|
| 490 |
iScrollTop = this.dom.scroller.scrollTop,
|
- |
|
| 491 |
iTotal = dt.fnRecordsDisplay(),
|
- |
|
| 492 |
iPossibleEnd = Math.ceil(this.fnPixelsToRow(iScrollTop + this.s.heights.viewport, false, this.s.ani));
|
- |
|
| 493 |
|
- |
|
| 494 |
return {
|
- |
|
| 495 |
start: Math.floor(this.fnPixelsToRow(iScrollTop, false, this.s.ani)),
|
- |
|
| 496 |
end: iTotal < iPossibleEnd ? iTotal-1 : iPossibleEnd-1
|
- |
|
| 497 |
};
|
- |
|
| 498 |
},
|
- |
|
| 499 |
|
- |
|
| 500 |
|
- |
|
| 501 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
- |
|
| 502 |
* Private methods (they are of course public in JS, but recommended as private)
|
- |
|
| 503 |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
- |
|
| 504 |
|
- |
|
| 505 |
/**
|
- |
|
| 506 |
* Initialisation for Scroller
|
- |
|
| 507 |
* @returns {void}
|
- |
|
| 508 |
* @private
|
- |
|
| 509 |
*/
|
- |
|
| 510 |
"_fnConstruct": function ()
|
- |
|
| 511 |
{
|
- |
|
| 512 |
var that = this;
|
- |
|
| 513 |
var dt = this.s.dtApi;
|
- |
|
| 514 |
|
- |
|
| 515 |
/* Sanity check */
|
- |
|
| 516 |
if ( !this.s.dt.oFeatures.bPaginate ) {
|
- |
|
| 517 |
this.s.dt.oApi._fnLog( this.s.dt, 0, 'Pagination must be enabled for Scroller' );
|
- |
|
| 518 |
return;
|
- |
|
| 519 |
}
|
- |
|
| 520 |
|
- |
|
| 521 |
/* Insert a div element that we can use to force the DT scrolling container to
|
- |
|
| 522 |
* the height that would be required if the whole table was being displayed
|
- |
|
| 523 |
*/
|
- |
|
| 524 |
this.dom.force.style.position = "relative";
|
- |
|
| 525 |
this.dom.force.style.top = "0px";
|
- |
|
| 526 |
this.dom.force.style.left = "0px";
|
- |
|
| 527 |
this.dom.force.style.width = "1px";
|
- |
|
| 528 |
|
- |
|
| 529 |
this.dom.scroller = $('div.'+this.s.dt.oClasses.sScrollBody, this.s.dt.nTableWrapper)[0];
|
- |
|
| 530 |
this.dom.scroller.appendChild( this.dom.force );
|
- |
|
| 531 |
this.dom.scroller.style.position = "relative";
|
- |
|
| 532 |
|
- |
|
| 533 |
this.dom.table = $('>table', this.dom.scroller)[0];
|
- |
|
| 534 |
this.dom.table.style.position = "absolute";
|
- |
|
| 535 |
this.dom.table.style.top = "0px";
|
- |
|
| 536 |
this.dom.table.style.left = "0px";
|
- |
|
| 537 |
|
- |
|
| 538 |
// Add class to 'announce' that we are a Scroller table
|
- |
|
| 539 |
$(dt.table().container()).addClass('DTS');
|
- |
|
| 540 |
|
- |
|
| 541 |
// Add a 'loading' indicator
|
- |
|
| 542 |
if ( this.s.loadingIndicator )
|
- |
|
| 543 |
{
|
- |
|
| 544 |
this.dom.loader = $('<div class="dataTables_processing DTS_Loading">'+this.s.dt.oLanguage.sLoadingRecords+'</div>')
|
- |
|
| 545 |
.css('display', 'none');
|
- |
|
| 546 |
|
- |
|
| 547 |
$(this.dom.scroller.parentNode)
|
- |
|
| 548 |
.css('position', 'relative')
|
- |
|
| 549 |
.append( this.dom.loader );
|
- |
|
| 550 |
}
|
- |
|
| 551 |
|
- |
|
| 552 |
/* Initial size calculations */
|
- |
|
| 553 |
if ( this.s.heights.row && this.s.heights.row != 'auto' )
|
- |
|
| 554 |
{
|
- |
|
| 555 |
this.s.autoHeight = false;
|
- |
|
| 556 |
}
|
- |
|
| 557 |
this.fnMeasure( false );
|
- |
|
| 558 |
|
- |
|
| 559 |
// Scrolling callback to see if a page change is needed - use a throttled
|
- |
|
| 560 |
// function for the save save callback so we aren't hitting it on every
|
- |
|
| 561 |
// scroll
|
- |
|
| 562 |
this.s.ingnoreScroll = true;
|
- |
|
| 563 |
this.s.stateSaveThrottle = this.s.dt.oApi._fnThrottle( function () {
|
- |
|
| 564 |
that.s.dtApi.state.save();
|
- |
|
| 565 |
}, 500 );
|
- |
|
| 566 |
$(this.dom.scroller).on( 'scroll.dt-scroller', function (e) {
|
- |
|
| 567 |
that._fnScroll.call( that );
|
- |
|
| 568 |
} );
|
- |
|
| 569 |
|
- |
|
| 570 |
// In iOS we catch the touchstart event in case the user tries to scroll
|
- |
|
| 571 |
// while the display is already scrolling
|
- |
|
| 572 |
$(this.dom.scroller).on('touchstart.dt-scroller', function () {
|
- |
|
| 573 |
that._fnScroll.call( that );
|
- |
|
| 574 |
} );
|
- |
|
| 575 |
|
- |
|
| 576 |
// On resize, update the information element, since the number of rows shown might change
|
- |
|
| 577 |
$(window).on( 'resize.dt-scroller', function () {
|
- |
|
| 578 |
that.fnMeasure( false );
|
- |
|
| 579 |
that._fnInfo();
|
- |
|
| 580 |
} );
|
- |
|
| 581 |
|
- |
|
| 582 |
// Add a state saving parameter to the DT state saving so we can restore the exact
|
- |
|
| 583 |
// position of the scrolling. Slightly surprisingly the scroll position isn't actually
|
- |
|
| 584 |
// stored, but rather tha base units which are needed to calculate it. This allows for
|
- |
|
| 585 |
// virtual scrolling as well.
|
- |
|
| 586 |
var initialStateSave = true;
|
- |
|
| 587 |
var loadedState = dt.state.loaded();
|
- |
|
| 588 |
|
- |
|
| 589 |
dt.on( 'stateSaveParams.scroller', function ( e, settings, data ) {
|
- |
|
| 590 |
// Need to used the saved position on init
|
- |
|
| 591 |
data.scroller = {
|
- |
|
| 592 |
topRow: initialStateSave && loadedState && loadedState.scroller ?
|
- |
|
| 593 |
loadedState.scroller.topRow :
|
- |
|
| 594 |
that.s.topRowFloat,
|
- |
|
| 595 |
baseScrollTop: that.s.baseScrollTop,
|
- |
|
| 596 |
baseRowTop: that.s.baseRowTop
|
- |
|
| 597 |
};
|
- |
|
| 598 |
|
- |
|
| 599 |
initialStateSave = false;
|
- |
|
| 600 |
} );
|
- |
|
| 601 |
|
- |
|
| 602 |
if ( loadedState && loadedState.scroller ) {
|
- |
|
| 603 |
this.s.topRowFloat = loadedState.scroller.topRow;
|
- |
|
| 604 |
this.s.baseScrollTop = loadedState.scroller.baseScrollTop;
|
- |
|
| 605 |
this.s.baseRowTop = loadedState.scroller.baseRowTop;
|
- |
|
| 606 |
}
|
- |
|
| 607 |
|
- |
|
| 608 |
dt.on( 'init.scroller', function () {
|
- |
|
| 609 |
that.fnMeasure( false );
|
- |
|
| 610 |
|
- |
|
| 611 |
that._fnDrawCallback();
|
- |
|
| 612 |
|
- |
|
| 613 |
// Update the scroller when the DataTable is redrawn
|
- |
|
| 614 |
dt.on( 'draw.scroller', function () {
|
- |
|
| 615 |
that._fnDrawCallback();
|
- |
|
| 616 |
});
|
- |
|
| 617 |
} );
|
- |
|
| 618 |
|
- |
|
| 619 |
// Set height before the draw happens, allowing everything else to update
|
- |
|
| 620 |
// on draw complete without worry for roder.
|
- |
|
| 621 |
dt.on( 'preDraw.dt.scroller', function () {
|
- |
|
| 622 |
that._fnScrollForce();
|
- |
|
| 623 |
} );
|
- |
|
| 624 |
|
- |
|
| 625 |
// Destructor
|
- |
|
| 626 |
dt.on( 'destroy.scroller', function () {
|
- |
|
| 627 |
$(window).off( 'resize.dt-scroller' );
|
- |
|
| 628 |
$(that.dom.scroller).off('.dt-scroller');
|
- |
|
| 629 |
$(that.s.dt.nTable).off( '.scroller' );
|
- |
|
| 630 |
|
- |
|
| 631 |
$(that.s.dt.nTableWrapper).removeClass('DTS');
|
- |
|
| 632 |
$('div.DTS_Loading', that.dom.scroller.parentNode).remove();
|
- |
|
| 633 |
|
- |
|
| 634 |
that.dom.table.style.position = "";
|
- |
|
| 635 |
that.dom.table.style.top = "";
|
- |
|
| 636 |
that.dom.table.style.left = "";
|
- |
|
| 637 |
} );
|
- |
|
| 638 |
},
|
- |
|
| 639 |
|
- |
|
| 640 |
|
- |
|
| 641 |
/**
|
- |
|
| 642 |
* Scrolling function - fired whenever the scrolling position is changed.
|
- |
|
| 643 |
* This method needs to use the stored values to see if the table should be
|
- |
|
| 644 |
* redrawn as we are moving towards the end of the information that is
|
- |
|
| 645 |
* currently drawn or not. If needed, then it will redraw the table based on
|
- |
|
| 646 |
* the new position.
|
- |
|
| 647 |
* @returns {void}
|
- |
|
| 648 |
* @private
|
- |
|
| 649 |
*/
|
- |
|
| 650 |
"_fnScroll": function ()
|
- |
|
| 651 |
{
|
- |
|
| 652 |
var
|
- |
|
| 653 |
that = this,
|
- |
|
| 654 |
heights = this.s.heights,
|
- |
|
| 655 |
iScrollTop = this.dom.scroller.scrollTop,
|
- |
|
| 656 |
iTopRow;
|
- |
|
| 657 |
|
- |
|
| 658 |
if ( this.s.skip ) {
|
- |
|
| 659 |
return;
|
- |
|
| 660 |
}
|
- |
|
| 661 |
|
- |
|
| 662 |
if ( this.s.ingnoreScroll ) {
|
- |
|
| 663 |
return;
|
- |
|
| 664 |
}
|
- |
|
| 665 |
|
- |
|
| 666 |
/* If the table has been sorted or filtered, then we use the redraw that
|
- |
|
| 667 |
* DataTables as done, rather than performing our own
|
- |
|
| 668 |
*/
|
- |
|
| 669 |
if ( this.s.dt.bFiltered || this.s.dt.bSorted ) {
|
- |
|
| 670 |
this.s.lastScrollTop = 0;
|
- |
|
| 671 |
return;
|
- |
|
| 672 |
}
|
- |
|
| 673 |
|
- |
|
| 674 |
/* Update the table's information display for what is now in the viewport */
|
- |
|
| 675 |
this._fnInfo();
|
- |
|
| 676 |
|
- |
|
| 677 |
/* We don't want to state save on every scroll event - that's heavy
|
- |
|
| 678 |
* handed, so use a timeout to update the state saving only when the
|
- |
|
| 679 |
* scrolling has finished
|
- |
|
| 680 |
*/
|
- |
|
| 681 |
clearTimeout( this.s.stateTO );
|
- |
|
| 682 |
this.s.stateTO = setTimeout( function () {
|
- |
|
| 683 |
that.s.dtApi.state.save();
|
- |
|
| 684 |
}, 250 );
|
- |
|
| 685 |
|
- |
|
| 686 |
/* Check if the scroll point is outside the trigger boundary which would required
|
- |
|
| 687 |
* a DataTables redraw
|
- |
|
| 688 |
*/
|
- |
|
| 689 |
if ( this.s.forceReposition || iScrollTop < this.s.redrawTop || iScrollTop > this.s.redrawBottom ) {
|
- |
|
| 690 |
|
- |
|
| 691 |
var preRows = Math.ceil( ((this.s.displayBuffer-1)/2) * this.s.viewportRows );
|
- |
|
| 692 |
|
- |
|
| 693 |
iTopRow = parseInt(this._domain( 'physicalToVirtual', iScrollTop ) / heights.row, 10) - preRows;
|
- |
|
| 694 |
this.s.topRowFloat = this._domain( 'physicalToVirtual', iScrollTop ) / heights.row;
|
- |
|
| 695 |
this.s.forceReposition = false;
|
- |
|
| 696 |
|
- |
|
| 697 |
if ( iTopRow <= 0 ) {
|
- |
|
| 698 |
/* At the start of the table */
|
- |
|
| 699 |
iTopRow = 0;
|
- |
|
| 700 |
}
|
- |
|
| 701 |
else if ( iTopRow + this.s.dt._iDisplayLength > this.s.dt.fnRecordsDisplay() ) {
|
- |
|
| 702 |
/* At the end of the table */
|
- |
|
| 703 |
iTopRow = this.s.dt.fnRecordsDisplay() - this.s.dt._iDisplayLength;
|
- |
|
| 704 |
if ( iTopRow < 0 ) {
|
- |
|
| 705 |
iTopRow = 0;
|
- |
|
| 706 |
}
|
- |
|
| 707 |
}
|
- |
|
| 708 |
else if ( iTopRow % 2 !== 0 ) {
|
- |
|
| 709 |
// For the row-striping classes (odd/even) we want only to start
|
- |
|
| 710 |
// on evens otherwise the stripes will change between draws and
|
- |
|
| 711 |
// look rubbish
|
- |
|
| 712 |
iTopRow++;
|
- |
|
| 713 |
}
|
- |
|
| 714 |
|
- |
|
| 715 |
if ( iTopRow != this.s.dt._iDisplayStart ) {
|
- |
|
| 716 |
/* Cache the new table position for quick lookups */
|
- |
|
| 717 |
this.s.tableTop = $(this.s.dt.nTable).offset().top;
|
- |
|
| 718 |
this.s.tableBottom = $(this.s.dt.nTable).height() + this.s.tableTop;
|
- |
|
| 719 |
|
- |
|
| 720 |
var draw = function () {
|
- |
|
| 721 |
if ( that.s.scrollDrawReq === null ) {
|
- |
|
| 722 |
that.s.scrollDrawReq = iScrollTop;
|
- |
|
| 723 |
}
|
- |
|
| 724 |
|
- |
|
| 725 |
that.s.dt._iDisplayStart = iTopRow;
|
- |
|
| 726 |
that.s.dt.oApi._fnDraw( that.s.dt );
|
- |
|
| 727 |
};
|
- |
|
| 728 |
|
- |
|
| 729 |
/* Do the DataTables redraw based on the calculated start point - note that when
|
- |
|
| 730 |
* using server-side processing we introduce a small delay to not DoS the server...
|
- |
|
| 731 |
*/
|
- |
|
| 732 |
if ( this.s.dt.oFeatures.bServerSide ) {
|
- |
|
| 733 |
clearTimeout( this.s.drawTO );
|
- |
|
| 734 |
this.s.drawTO = setTimeout( draw, this.s.serverWait );
|
- |
|
| 735 |
}
|
- |
|
| 736 |
else {
|
- |
|
| 737 |
draw();
|
- |
|
| 738 |
}
|
- |
|
| 739 |
|
- |
|
| 740 |
if ( this.dom.loader && ! this.s.loaderVisible ) {
|
- |
|
| 741 |
this.dom.loader.css( 'display', 'block' );
|
- |
|
| 742 |
this.s.loaderVisible = true;
|
- |
|
| 743 |
}
|
- |
|
| 744 |
}
|
- |
|
| 745 |
}
|
- |
|
| 746 |
else {
|
- |
|
| 747 |
this.s.topRowFloat = this.fnPixelsToRow( iScrollTop, false, true );
|
- |
|
| 748 |
}
|
- |
|
| 749 |
|
- |
|
| 750 |
this.s.lastScrollTop = iScrollTop;
|
- |
|
| 751 |
this.s.stateSaveThrottle();
|
- |
|
| 752 |
},
|
- |
|
| 753 |
|
- |
|
| 754 |
|
- |
|
| 755 |
/**
|
- |
|
| 756 |
* Convert from one domain to another. The physical domain is the actual
|
- |
|
| 757 |
* pixel count on the screen, while the virtual is if we had browsers which
|
- |
|
| 758 |
* had scrolling containers of infinite height (i.e. the absolute value)
|
- |
|
| 759 |
*
|
- |
|
| 760 |
* @param {string} dir Domain transform direction, `virtualToPhysical` or
|
- |
|
| 761 |
* `physicalToVirtual`
|
- |
|
| 762 |
* @returns {number} Calculated transform
|
- |
|
| 763 |
* @private
|
- |
|
| 764 |
*/
|
- |
|
| 765 |
_domain: function ( dir, val )
|
- |
|
| 766 |
{
|
- |
|
| 767 |
var heights = this.s.heights;
|
- |
|
| 768 |
var coeff;
|
- |
|
| 769 |
//return val;
|
- |
|
| 770 |
|
- |
|
| 771 |
// If the virtual and physical height match, then we use a linear
|
- |
|
| 772 |
// transform between the two, allowing the scrollbar to be linear
|
- |
|
| 773 |
if ( heights.virtual === heights.scroll ) {
|
- |
|
| 774 |
return val;
|
- |
|
| 775 |
}
|
- |
|
| 776 |
|
- |
|
| 777 |
// Otherwise, we want a non-linear scrollbar to take account of the
|
- |
|
| 778 |
// redrawing regions at the start and end of the table, otherwise these
|
- |
|
| 779 |
// can stutter badly - on large tables 30px (for example) scroll might
|
- |
|
| 780 |
// be hundreds of rows, so the table would be redrawing every few px at
|
- |
|
| 781 |
// the start and end. Use a simple quadratic to stop this. It does mean
|
- |
|
| 782 |
// the scrollbar is non-linear, but with such massive data sets, the
|
- |
|
| 783 |
// scrollbar is going to be a best guess anyway
|
- |
|
| 784 |
var xMax = (heights.scroll - heights.viewport) / 2;
|
- |
|
| 785 |
var yMax = (heights.virtual - heights.viewport) / 2;
|
- |
|
| 786 |
|
- |
|
| 787 |
coeff = yMax / ( xMax * xMax );
|
- |
|
| 788 |
|
- |
|
| 789 |
if ( dir === 'virtualToPhysical' ) {
|
- |
|
| 790 |
if ( val < yMax ) {
|
- |
|
| 791 |
return Math.pow(val / coeff, 0.5);
|
- |
|
| 792 |
}
|
- |
|
| 793 |
else {
|
- |
|
| 794 |
val = (yMax*2) - val;
|
- |
|
| 795 |
return val < 0 ?
|
- |
|
| 796 |
heights.scroll :
|
- |
|
| 797 |
(xMax*2) - Math.pow(val / coeff, 0.5);
|
- |
|
| 798 |
}
|
- |
|
| 799 |
}
|
- |
|
| 800 |
else if ( dir === 'physicalToVirtual' ) {
|
- |
|
| 801 |
if ( val < xMax ) {
|
- |
|
| 802 |
return val * val * coeff;
|
- |
|
| 803 |
}
|
- |
|
| 804 |
else {
|
- |
|
| 805 |
val = (xMax*2) - val;
|
- |
|
| 806 |
return val < 0 ?
|
- |
|
| 807 |
heights.virtual :
|
- |
|
| 808 |
(yMax*2) - (val * val * coeff);
|
- |
|
| 809 |
}
|
- |
|
| 810 |
}
|
- |
|
| 811 |
},
|
- |
|
| 812 |
|
- |
|
| 813 |
/**
|
- |
|
| 814 |
* Parse CSS height property string as number
|
- |
|
| 815 |
*
|
- |
|
| 816 |
* An attempt is made to parse the string as a number. Currently supported units are 'px',
|
- |
|
| 817 |
* 'vh', and 'rem'. 'em' is partially supported; it works as long as the parent element's
|
- |
|
| 818 |
* font size matches the body element. Zero is returned for unrecognized strings.
|
- |
|
| 819 |
* @param {string} cssHeight CSS height property string
|
- |
|
| 820 |
* @returns {number} height
|
- |
|
| 821 |
* @private
|
- |
|
| 822 |
*/
|
- |
|
| 823 |
_parseHeight: function(cssHeight) {
|
- |
|
| 824 |
var height;
|
- |
|
| 825 |
var matches = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(px|em|rem|vh)$/.exec(cssHeight);
|
- |
|
| 826 |
|
- |
|
| 827 |
if (matches === null) {
|
- |
|
| 828 |
return 0;
|
- |
|
| 829 |
}
|
- |
|
| 830 |
|
- |
|
| 831 |
var value = parseFloat(matches[1]);
|
- |
|
| 832 |
var unit = matches[2];
|
- |
|
| 833 |
|
- |
|
| 834 |
if ( unit === 'px' ) {
|
- |
|
| 835 |
height = value;
|
- |
|
| 836 |
}
|
- |
|
| 837 |
else if ( unit === 'vh' ) {
|
- |
|
| 838 |
height = ( value / 100 ) * $(window).height();
|
- |
|
| 839 |
}
|
- |
|
| 840 |
else if ( unit === 'rem' ) {
|
- |
|
| 841 |
height = value * parseFloat($(':root').css('font-size'));
|
- |
|
| 842 |
}
|
- |
|
| 843 |
else if ( unit === 'em' ) {
|
- |
|
| 844 |
height = value * parseFloat($('body').css('font-size'));
|
- |
|
| 845 |
}
|
- |
|
| 846 |
|
- |
|
| 847 |
return height ?
|
- |
|
| 848 |
height :
|
- |
|
| 849 |
0;
|
- |
|
| 850 |
},
|
- |
|
| 851 |
|
- |
|
| 852 |
|
- |
|
| 853 |
/**
|
- |
|
| 854 |
* Draw callback function which is fired when the DataTable is redrawn. The main function of
|
- |
|
| 855 |
* this method is to position the drawn table correctly the scrolling container for the rows
|
- |
|
| 856 |
* that is displays as a result of the scrolling position.
|
- |
|
| 857 |
* @returns {void}
|
- |
|
| 858 |
* @private
|
- |
|
| 859 |
*/
|
- |
|
| 860 |
"_fnDrawCallback": function ()
|
- |
|
| 861 |
{
|
- |
|
| 862 |
var
|
- |
|
| 863 |
that = this,
|
- |
|
| 864 |
heights = this.s.heights,
|
- |
|
| 865 |
iScrollTop = this.dom.scroller.scrollTop,
|
- |
|
| 866 |
iActualScrollTop = iScrollTop,
|
- |
|
| 867 |
iScrollBottom = iScrollTop + heights.viewport,
|
- |
|
| 868 |
iTableHeight = $(this.s.dt.nTable).height(),
|
- |
|
| 869 |
displayStart = this.s.dt._iDisplayStart,
|
- |
|
| 870 |
displayLen = this.s.dt._iDisplayLength,
|
- |
|
| 871 |
displayEnd = this.s.dt.fnRecordsDisplay();
|
- |
|
| 872 |
|
- |
|
| 873 |
// Disable the scroll event listener while we are updating the DOM
|
- |
|
| 874 |
this.s.skip = true;
|
- |
|
| 875 |
|
- |
|
| 876 |
// If paging is reset
|
- |
|
| 877 |
if ( (this.s.dt.bSorted || this.s.dt.bFiltered) && displayStart === 0 && !this.s.dt._drawHold ) {
|
- |
|
| 878 |
this.s.topRowFloat = 0;
|
- |
|
| 879 |
}
|
- |
|
| 880 |
|
- |
|
| 881 |
// Reposition the scrolling for the updated virtual position if needed
|
- |
|
| 882 |
if ( displayStart === 0 ) {
|
- |
|
| 883 |
// Linear calculation at the top of the table
|
- |
|
| 884 |
iScrollTop = this.s.topRowFloat * heights.row;
|
- |
|
| 885 |
}
|
- |
|
| 886 |
else if ( displayStart + displayLen >= displayEnd ) {
|
- |
|
| 887 |
// Linear calculation that the bottom as well
|
- |
|
| 888 |
iScrollTop = heights.scroll - ((displayEnd - this.s.topRowFloat) * heights.row);
|
- |
|
| 889 |
}
|
- |
|
| 890 |
else {
|
- |
|
| 891 |
// Domain scaled in the middle
|
- |
|
| 892 |
iScrollTop = this._domain( 'virtualToPhysical', this.s.topRowFloat * heights.row );
|
- |
|
| 893 |
}
|
- |
|
| 894 |
|
- |
|
| 895 |
this.dom.scroller.scrollTop = iScrollTop;
|
- |
|
| 896 |
|
- |
|
| 897 |
// Store positional information so positional calculations can be based
|
- |
|
| 898 |
// upon the current table draw position
|
- |
|
| 899 |
this.s.baseScrollTop = iScrollTop;
|
- |
|
| 900 |
this.s.baseRowTop = this.s.topRowFloat;
|
- |
|
| 901 |
|
- |
|
| 902 |
// Position the table in the virtual scroller
|
- |
|
| 903 |
var tableTop = iScrollTop - ((this.s.topRowFloat - displayStart) * heights.row);
|
- |
|
| 904 |
if ( displayStart === 0 ) {
|
- |
|
| 905 |
tableTop = 0;
|
- |
|
| 906 |
}
|
- |
|
| 907 |
else if ( displayStart + displayLen >= displayEnd ) {
|
- |
|
| 908 |
tableTop = heights.scroll - iTableHeight;
|
- |
|
| 909 |
}
|
- |
|
| 910 |
|
- |
|
| 911 |
this.dom.table.style.top = tableTop+'px';
|
- |
|
| 912 |
|
- |
|
| 913 |
/* Cache some information for the scroller */
|
- |
|
| 914 |
this.s.tableTop = tableTop;
|
- |
|
| 915 |
this.s.tableBottom = iTableHeight + this.s.tableTop;
|
- |
|
| 916 |
|
- |
|
| 917 |
// Calculate the boundaries for where a redraw will be triggered by the
|
- |
|
| 918 |
// scroll event listener
|
- |
|
| 919 |
var boundaryPx = (iScrollTop - this.s.tableTop) * this.s.boundaryScale;
|
- |
|
| 920 |
this.s.redrawTop = iScrollTop - boundaryPx;
|
- |
|
| 921 |
this.s.redrawBottom = iScrollTop + boundaryPx > heights.scroll - heights.viewport - heights.row ?
|
- |
|
| 922 |
heights.scroll - heights.viewport - heights.row :
|
- |
|
| 923 |
iScrollTop + boundaryPx;
|
- |
|
| 924 |
|
- |
|
| 925 |
this.s.skip = false;
|
- |
|
| 926 |
|
- |
|
| 927 |
// Restore the scrolling position that was saved by DataTable's state
|
- |
|
| 928 |
// saving Note that this is done on the second draw when data is Ajax
|
- |
|
| 929 |
// sourced, and the first draw when DOM soured
|
- |
|
| 930 |
if ( this.s.dt.oFeatures.bStateSave && this.s.dt.oLoadedState !== null &&
|
- |
|
| 931 |
typeof this.s.dt.oLoadedState.iScroller != 'undefined' )
|
- |
|
| 932 |
{
|
- |
|
| 933 |
// A quirk of DataTables is that the draw callback will occur on an
|
- |
|
| 934 |
// empty set if Ajax sourced, but not if server-side processing.
|
- |
|
| 935 |
var ajaxSourced = (this.s.dt.sAjaxSource || that.s.dt.ajax) && ! this.s.dt.oFeatures.bServerSide ?
|
- |
|
| 936 |
true :
|
- |
|
| 937 |
false;
|
- |
|
| 938 |
|
- |
|
| 939 |
if ( ( ajaxSourced && this.s.dt.iDraw == 2) ||
|
- |
|
| 940 |
(!ajaxSourced && this.s.dt.iDraw == 1) )
|
- |
|
| 941 |
{
|
- |
|
| 942 |
setTimeout( function () {
|
- |
|
| 943 |
$(that.dom.scroller).scrollTop( that.s.dt.oLoadedState.iScroller );
|
- |
|
| 944 |
that.s.redrawTop = that.s.dt.oLoadedState.iScroller - (heights.viewport/2);
|
- |
|
| 945 |
|
- |
|
| 946 |
// In order to prevent layout thrashing we need another
|
- |
|
| 947 |
// small delay
|
- |
|
| 948 |
setTimeout( function () {
|
- |
|
| 949 |
that.s.ingnoreScroll = false;
|
- |
|
| 950 |
}, 0 );
|
- |
|
| 951 |
}, 0 );
|
- |
|
| 952 |
}
|
- |
|
| 953 |
}
|
- |
|
| 954 |
else {
|
- |
|
| 955 |
that.s.ingnoreScroll = false;
|
- |
|
| 956 |
}
|
- |
|
| 957 |
|
- |
|
| 958 |
// Because of the order of the DT callbacks, the info update will
|
- |
|
| 959 |
// take precedence over the one we want here. So a 'thread' break is
|
- |
|
| 960 |
// needed. Only add the thread break if bInfo is set
|
- |
|
| 961 |
if ( this.s.dt.oFeatures.bInfo ) {
|
- |
|
| 962 |
setTimeout( function () {
|
- |
|
| 963 |
that._fnInfo.call( that );
|
- |
|
| 964 |
}, 0 );
|
- |
|
| 965 |
}
|
- |
|
| 966 |
|
- |
|
| 967 |
// Hide the loading indicator
|
- |
|
| 968 |
if ( this.dom.loader && this.s.loaderVisible ) {
|
- |
|
| 969 |
this.dom.loader.css( 'display', 'none' );
|
- |
|
| 970 |
this.s.loaderVisible = false;
|
- |
|
| 971 |
}
|
- |
|
| 972 |
},
|
- |
|
| 973 |
|
- |
|
| 974 |
|
- |
|
| 975 |
/**
|
- |
|
| 976 |
* Force the scrolling container to have height beyond that of just the
|
- |
|
| 977 |
* table that has been drawn so the user can scroll the whole data set.
|
- |
|
| 978 |
*
|
- |
|
| 979 |
* Note that if the calculated required scrolling height exceeds a maximum
|
- |
|
| 980 |
* value (1 million pixels - hard-coded) the forcing element will be set
|
- |
|
| 981 |
* only to that maximum value and virtual / physical domain transforms will
|
- |
|
| 982 |
* be used to allow Scroller to display tables of any number of records.
|
- |
|
| 983 |
* @returns {void}
|
- |
|
| 984 |
* @private
|
- |
|
| 985 |
*/
|
- |
|
| 986 |
_fnScrollForce: function ()
|
- |
|
| 987 |
{
|
- |
|
| 988 |
var heights = this.s.heights;
|
- |
|
| 989 |
var max = 1000000;
|
- |
|
| 990 |
|
- |
|
| 991 |
heights.virtual = heights.row * this.s.dt.fnRecordsDisplay();
|
- |
|
| 992 |
heights.scroll = heights.virtual;
|
- |
|
| 993 |
|
- |
|
| 994 |
if ( heights.scroll > max ) {
|
- |
|
| 995 |
heights.scroll = max;
|
- |
|
| 996 |
}
|
- |
|
| 997 |
|
- |
|
| 998 |
// Minimum height so there is always a row visible (the 'no rows found'
|
- |
|
| 999 |
// if reduced to zero filtering)
|
- |
|
| 1000 |
this.dom.force.style.height = heights.scroll > this.s.heights.row ?
|
- |
|
| 1001 |
heights.scroll+'px' :
|
- |
|
| 1002 |
this.s.heights.row+'px';
|
- |
|
| 1003 |
},
|
- |
|
| 1004 |
|
- |
|
| 1005 |
|
- |
|
| 1006 |
/**
|
- |
|
| 1007 |
* Automatic calculation of table row height. This is just a little tricky here as using
|
- |
|
| 1008 |
* initialisation DataTables has tale the table out of the document, so we need to create
|
- |
|
| 1009 |
* a new table and insert it into the document, calculate the row height and then whip the
|
- |
|
| 1010 |
* table out.
|
- |
|
| 1011 |
* @returns {void}
|
- |
|
| 1012 |
* @private
|
- |
|
| 1013 |
*/
|
- |
|
| 1014 |
"_fnCalcRowHeight": function ()
|
- |
|
| 1015 |
{
|
- |
|
| 1016 |
var dt = this.s.dt;
|
- |
|
| 1017 |
var origTable = dt.nTable;
|
- |
|
| 1018 |
var nTable = origTable.cloneNode( false );
|
- |
|
| 1019 |
var tbody = $('<tbody/>').appendTo( nTable );
|
- |
|
| 1020 |
var container = $(
|
- |
|
| 1021 |
'<div class="'+dt.oClasses.sWrapper+' DTS">'+
|
- |
|
| 1022 |
'<div class="'+dt.oClasses.sScrollWrapper+'">'+
|
- |
|
| 1023 |
'<div class="'+dt.oClasses.sScrollBody+'"></div>'+
|
- |
|
| 1024 |
'</div>'+
|
- |
|
| 1025 |
'</div>'
|
- |
|
| 1026 |
);
|
- |
|
| 1027 |
|
- |
|
| 1028 |
// Want 3 rows in the sizing table so :first-child and :last-child
|
- |
|
| 1029 |
// CSS styles don't come into play - take the size of the middle row
|
- |
|
| 1030 |
$('tbody tr:lt(4)', origTable).clone().appendTo( tbody );
|
- |
|
| 1031 |
while( $('tr', tbody).length < 3 ) {
|
- |
|
| 1032 |
tbody.append( '<tr><td> </td></tr>' );
|
- |
|
| 1033 |
}
|
- |
|
| 1034 |
|
- |
|
| 1035 |
$('div.'+dt.oClasses.sScrollBody, container).append( nTable );
|
- |
|
| 1036 |
|
- |
|
| 1037 |
// If initialised using `dom`, use the holding element as the insert point
|
- |
|
| 1038 |
var insertEl = this.s.dt.nHolding || origTable.parentNode;
|
- |
|
| 1039 |
|
- |
|
| 1040 |
if ( ! $(insertEl).is(':visible') ) {
|
- |
|
| 1041 |
insertEl = 'body';
|
- |
|
| 1042 |
}
|
- |
|
| 1043 |
|
- |
|
| 1044 |
container.appendTo( insertEl );
|
- |
|
| 1045 |
this.s.heights.row = $('tr', tbody).eq(1).outerHeight();
|
- |
|
| 1046 |
|
- |
|
| 1047 |
container.remove();
|
- |
|
| 1048 |
},
|
- |
|
| 1049 |
|
- |
|
| 1050 |
|
- |
|
| 1051 |
/**
|
- |
|
| 1052 |
* Update any information elements that are controlled by the DataTable based on the scrolling
|
- |
|
| 1053 |
* viewport and what rows are visible in it. This function basically acts in the same way as
|
- |
|
| 1054 |
* _fnUpdateInfo in DataTables, and effectively replaces that function.
|
- |
|
| 1055 |
* @returns {void}
|
- |
|
| 1056 |
* @private
|
- |
|
| 1057 |
*/
|
- |
|
| 1058 |
"_fnInfo": function ()
|
- |
|
| 1059 |
{
|
- |
|
| 1060 |
if ( !this.s.dt.oFeatures.bInfo )
|
- |
|
| 1061 |
{
|
- |
|
| 1062 |
return;
|
- |
|
| 1063 |
}
|
- |
|
| 1064 |
|
- |
|
| 1065 |
var
|
- |
|
| 1066 |
dt = this.s.dt,
|
- |
|
| 1067 |
language = dt.oLanguage,
|
- |
|
| 1068 |
iScrollTop = this.dom.scroller.scrollTop,
|
- |
|
| 1069 |
iStart = Math.floor( this.fnPixelsToRow(iScrollTop, false, this.s.ani)+1 ),
|
- |
|
| 1070 |
iMax = dt.fnRecordsTotal(),
|
- |
|
| 1071 |
iTotal = dt.fnRecordsDisplay(),
|
- |
|
| 1072 |
iPossibleEnd = Math.ceil( this.fnPixelsToRow(iScrollTop+this.s.heights.viewport, false, this.s.ani) ),
|
- |
|
| 1073 |
iEnd = iTotal < iPossibleEnd ? iTotal : iPossibleEnd,
|
- |
|
| 1074 |
sStart = dt.fnFormatNumber( iStart ),
|
- |
|
| 1075 |
sEnd = dt.fnFormatNumber( iEnd ),
|
- |
|
| 1076 |
sMax = dt.fnFormatNumber( iMax ),
|
- |
|
| 1077 |
sTotal = dt.fnFormatNumber( iTotal ),
|
- |
|
| 1078 |
sOut;
|
- |
|
| 1079 |
|
- |
|
| 1080 |
if ( dt.fnRecordsDisplay() === 0 &&
|
- |
|
| 1081 |
dt.fnRecordsDisplay() == dt.fnRecordsTotal() )
|
- |
|
| 1082 |
{
|
- |
|
| 1083 |
/* Empty record set */
|
- |
|
| 1084 |
sOut = language.sInfoEmpty+ language.sInfoPostFix;
|
- |
|
| 1085 |
}
|
- |
|
| 1086 |
else if ( dt.fnRecordsDisplay() === 0 )
|
- |
|
| 1087 |
{
|
- |
|
| 1088 |
/* Empty record set after filtering */
|
- |
|
| 1089 |
sOut = language.sInfoEmpty +' '+
|
- |
|
| 1090 |
language.sInfoFiltered.replace('_MAX_', sMax)+
|
- |
|
| 1091 |
language.sInfoPostFix;
|
- |
|
| 1092 |
}
|
- |
|
| 1093 |
else if ( dt.fnRecordsDisplay() == dt.fnRecordsTotal() )
|
- |
|
| 1094 |
{
|
- |
|
| 1095 |
/* Normal record set */
|
- |
|
| 1096 |
sOut = language.sInfo.
|
- |
|
| 1097 |
replace('_START_', sStart).
|
- |
|
| 1098 |
replace('_END_', sEnd).
|
- |
|
| 1099 |
replace('_MAX_', sMax).
|
- |
|
| 1100 |
replace('_TOTAL_', sTotal)+
|
- |
|
| 1101 |
language.sInfoPostFix;
|
- |
|
| 1102 |
}
|
- |
|
| 1103 |
else
|
- |
|
| 1104 |
{
|
- |
|
| 1105 |
/* Record set after filtering */
|
- |
|
| 1106 |
sOut = language.sInfo.
|
- |
|
| 1107 |
replace('_START_', sStart).
|
- |
|
| 1108 |
replace('_END_', sEnd).
|
- |
|
| 1109 |
replace('_MAX_', sMax).
|
- |
|
| 1110 |
replace('_TOTAL_', sTotal) +' '+
|
- |
|
| 1111 |
language.sInfoFiltered.replace(
|
- |
|
| 1112 |
'_MAX_',
|
- |
|
| 1113 |
dt.fnFormatNumber(dt.fnRecordsTotal())
|
- |
|
| 1114 |
)+
|
- |
|
| 1115 |
language.sInfoPostFix;
|
- |
|
| 1116 |
}
|
- |
|
| 1117 |
|
- |
|
| 1118 |
var callback = language.fnInfoCallback;
|
- |
|
| 1119 |
if ( callback ) {
|
- |
|
| 1120 |
sOut = callback.call( dt.oInstance,
|
- |
|
| 1121 |
dt, iStart, iEnd, iMax, iTotal, sOut
|
- |
|
| 1122 |
);
|
- |
|
| 1123 |
}
|
- |
|
| 1124 |
|
- |
|
| 1125 |
var n = dt.aanFeatures.i;
|
- |
|
| 1126 |
if ( typeof n != 'undefined' )
|
- |
|
| 1127 |
{
|
- |
|
| 1128 |
for ( var i=0, iLen=n.length ; i<iLen ; i++ )
|
- |
|
| 1129 |
{
|
- |
|
| 1130 |
$(n[i]).html( sOut );
|
- |
|
| 1131 |
}
|
- |
|
| 1132 |
}
|
- |
|
| 1133 |
|
- |
|
| 1134 |
// DT doesn't actually (yet) trigger this event, but it will in future
|
- |
|
| 1135 |
$(dt.nTable).triggerHandler( 'info.dt' );
|
- |
|
| 1136 |
}
|
- |
|
| 1137 |
} );
|
- |
|
| 1138 |
|
- |
|
| 1139 |
|
- |
|
| 1140 |
|
- |
|
| 1141 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
- |
|
| 1142 |
* Statics
|
- |
|
| 1143 |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
- |
|
| 1144 |
|
- |
|
| 1145 |
|
- |
|
| 1146 |
/**
|
- |
|
| 1147 |
* Scroller default settings for initialisation
|
- |
|
| 1148 |
* @namespace
|
- |
|
| 1149 |
* @name Scroller.defaults
|
- |
|
| 1150 |
* @static
|
- |
|
| 1151 |
*/
|
- |
|
| 1152 |
Scroller.defaults = /** @lends Scroller.defaults */{
|
- |
|
| 1153 |
/**
|
- |
|
| 1154 |
* Indicate if Scroller show show trace information on the console or not. This can be
|
- |
|
| 1155 |
* useful when debugging Scroller or if just curious as to what it is doing, but should
|
- |
|
| 1156 |
* be turned off for production.
|
- |
|
| 1157 |
* @type bool
|
- |
|
| 1158 |
* @default false
|
- |
|
| 1159 |
* @static
|
- |
|
| 1160 |
* @example
|
- |
|
| 1161 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1162 |
* "sScrollY": "200px",
|
- |
|
| 1163 |
* "sDom": "frtiS",
|
- |
|
| 1164 |
* "bDeferRender": true,
|
- |
|
| 1165 |
* "oScroller": {
|
- |
|
| 1166 |
* "trace": true
|
- |
|
| 1167 |
* }
|
- |
|
| 1168 |
* } );
|
- |
|
| 1169 |
*/
|
- |
|
| 1170 |
"trace": false,
|
- |
|
| 1171 |
|
- |
|
| 1172 |
/**
|
- |
|
| 1173 |
* Scroller will attempt to automatically calculate the height of rows for it's internal
|
- |
|
| 1174 |
* calculations. However the height that is used can be overridden using this parameter.
|
- |
|
| 1175 |
* @type int|string
|
- |
|
| 1176 |
* @default auto
|
- |
|
| 1177 |
* @static
|
- |
|
| 1178 |
* @example
|
- |
|
| 1179 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1180 |
* "sScrollY": "200px",
|
- |
|
| 1181 |
* "sDom": "frtiS",
|
- |
|
| 1182 |
* "bDeferRender": true,
|
- |
|
| 1183 |
* "oScroller": {
|
- |
|
| 1184 |
* "rowHeight": 30
|
- |
|
| 1185 |
* }
|
- |
|
| 1186 |
* } );
|
- |
|
| 1187 |
*/
|
- |
|
| 1188 |
"rowHeight": "auto",
|
- |
|
| 1189 |
|
- |
|
| 1190 |
/**
|
- |
|
| 1191 |
* When using server-side processing, Scroller will wait a small amount of time to allow
|
- |
|
| 1192 |
* the scrolling to finish before requesting more data from the server. This prevents
|
- |
|
| 1193 |
* you from DoSing your own server! The wait time can be configured by this parameter.
|
- |
|
| 1194 |
* @type int
|
- |
|
| 1195 |
* @default 200
|
- |
|
| 1196 |
* @static
|
- |
|
| 1197 |
* @example
|
- |
|
| 1198 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1199 |
* "sScrollY": "200px",
|
- |
|
| 1200 |
* "sDom": "frtiS",
|
- |
|
| 1201 |
* "bDeferRender": true,
|
- |
|
| 1202 |
* "oScroller": {
|
- |
|
| 1203 |
* "serverWait": 100
|
- |
|
| 1204 |
* }
|
- |
|
| 1205 |
* } );
|
- |
|
| 1206 |
*/
|
- |
|
| 1207 |
"serverWait": 200,
|
- |
|
| 1208 |
|
- |
|
| 1209 |
/**
|
- |
|
| 1210 |
* The display buffer is what Scroller uses to calculate how many rows it should pre-fetch
|
- |
|
| 1211 |
* for scrolling. Scroller automatically adjusts DataTables' display length to pre-fetch
|
- |
|
| 1212 |
* rows that will be shown in "near scrolling" (i.e. just beyond the current display area).
|
- |
|
| 1213 |
* The value is based upon the number of rows that can be displayed in the viewport (i.e.
|
- |
|
| 1214 |
* a value of 1), and will apply the display range to records before before and after the
|
- |
|
| 1215 |
* current viewport - i.e. a factor of 3 will allow Scroller to pre-fetch 1 viewport's worth
|
- |
|
| 1216 |
* of rows before the current viewport, the current viewport's rows and 1 viewport's worth
|
- |
|
| 1217 |
* of rows after the current viewport. Adjusting this value can be useful for ensuring
|
- |
|
| 1218 |
* smooth scrolling based on your data set.
|
- |
|
| 1219 |
* @type int
|
- |
|
| 1220 |
* @default 7
|
- |
|
| 1221 |
* @static
|
- |
|
| 1222 |
* @example
|
- |
|
| 1223 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1224 |
* "sScrollY": "200px",
|
- |
|
| 1225 |
* "sDom": "frtiS",
|
- |
|
| 1226 |
* "bDeferRender": true,
|
- |
|
| 1227 |
* "oScroller": {
|
- |
|
| 1228 |
* "displayBuffer": 10
|
- |
|
| 1229 |
* }
|
- |
|
| 1230 |
* } );
|
- |
|
| 1231 |
*/
|
- |
|
| 1232 |
"displayBuffer": 9,
|
- |
|
| 1233 |
|
- |
|
| 1234 |
/**
|
- |
|
| 1235 |
* Scroller uses the boundary scaling factor to decide when to redraw the table - which it
|
- |
|
| 1236 |
* typically does before you reach the end of the currently loaded data set (in order to
|
- |
|
| 1237 |
* allow the data to look continuous to a user scrolling through the data). If given as 0
|
- |
|
| 1238 |
* then the table will be redrawn whenever the viewport is scrolled, while 1 would not
|
- |
|
| 1239 |
* redraw the table until the currently loaded data has all been shown. You will want
|
- |
|
| 1240 |
* something in the middle - the default factor of 0.5 is usually suitable.
|
- |
|
| 1241 |
* @type float
|
- |
|
| 1242 |
* @default 0.5
|
- |
|
| 1243 |
* @static
|
- |
|
| 1244 |
* @example
|
- |
|
| 1245 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1246 |
* "sScrollY": "200px",
|
- |
|
| 1247 |
* "sDom": "frtiS",
|
- |
|
| 1248 |
* "bDeferRender": true,
|
- |
|
| 1249 |
* "oScroller": {
|
- |
|
| 1250 |
* "boundaryScale": 0.75
|
- |
|
| 1251 |
* }
|
- |
|
| 1252 |
* } );
|
- |
|
| 1253 |
*/
|
- |
|
| 1254 |
"boundaryScale": 0.5,
|
- |
|
| 1255 |
|
- |
|
| 1256 |
/**
|
- |
|
| 1257 |
* Show (or not) the loading element in the background of the table. Note that you should
|
- |
|
| 1258 |
* include the dataTables.scroller.css file for this to be displayed correctly.
|
- |
|
| 1259 |
* @type boolean
|
- |
|
| 1260 |
* @default false
|
- |
|
| 1261 |
* @static
|
- |
|
| 1262 |
* @example
|
- |
|
| 1263 |
* var oTable = $('#example').dataTable( {
|
- |
|
| 1264 |
* "sScrollY": "200px",
|
- |
|
| 1265 |
* "sDom": "frtiS",
|
- |
|
| 1266 |
* "bDeferRender": true,
|
- |
|
| 1267 |
* "oScroller": {
|
- |
|
| 1268 |
* "loadingIndicator": true
|
- |
|
| 1269 |
* }
|
- |
|
| 1270 |
* } );
|
- |
|
| 1271 |
*/
|
- |
|
| 1272 |
"loadingIndicator": false
|
- |
|
| 1273 |
};
|
- |
|
| 1274 |
|
- |
|
| 1275 |
Scroller.oDefaults = Scroller.defaults;
|
- |
|
| 1276 |
|
- |
|
| 1277 |
|
- |
|
| 1278 |
|
- |
|
| 1279 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
- |
|
| 1280 |
* Constants
|
- |
|
| 1281 |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
- |
|
| 1282 |
|
- |
|
| 1283 |
/**
|
- |
|
| 1284 |
* Scroller version
|
- |
|
| 1285 |
* @type String
|
- |
|
| 1286 |
* @default See code
|
- |
|
| 1287 |
* @name Scroller.version
|
- |
|
| 1288 |
* @static
|
- |
|
| 1289 |
*/
|
- |
|
| 1290 |
Scroller.version = "1.5.1";
|
- |
|
| 1291 |
|
- |
|
| 1292 |
|
- |
|
| 1293 |
|
- |
|
| 1294 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
- |
|
| 1295 |
* Initialisation
|
- |
|
| 1296 |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
- |
|
| 1297 |
|
- |
|
| 1298 |
// Legacy `dom` parameter initialisation support
|
- |
|
| 1299 |
if ( typeof $.fn.dataTable == "function" &&
|
- |
|
| 1300 |
typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
|
- |
|
| 1301 |
$.fn.dataTableExt.fnVersionCheck('1.10.0') )
|
- |
|
| 1302 |
{
|
- |
|
| 1303 |
$.fn.dataTableExt.aoFeatures.push( {
|
- |
|
| 1304 |
"fnInit": function( oDTSettings ) {
|
- |
|
| 1305 |
var init = oDTSettings.oInit;
|
- |
|
| 1306 |
var opts = init.scroller || init.oScroller || {};
|
- |
|
| 1307 |
|
- |
|
| 1308 |
new Scroller( oDTSettings, opts );
|
- |
|
| 1309 |
},
|
- |
|
| 1310 |
"cFeature": "S",
|
- |
|
| 1311 |
"sFeature": "Scroller"
|
- |
|
| 1312 |
} );
|
- |
|
| 1313 |
}
|
- |
|
| 1314 |
else
|
- |
|
| 1315 |
{
|
- |
|
| 1316 |
alert( "Warning: Scroller requires DataTables 1.10.0 or greater - www.datatables.net/download");
|
- |
|
| 1317 |
}
|
- |
|
| 1318 |
|
- |
|
| 1319 |
// Attach a listener to the document which listens for DataTables initialisation
|
- |
|
| 1320 |
// events so we can automatically initialise
|
- |
|
| 1321 |
$(document).on( 'preInit.dt.dtscroller', function (e, settings) {
|
- |
|
| 1322 |
if ( e.namespace !== 'dt' ) {
|
- |
|
| 1323 |
return;
|
- |
|
| 1324 |
}
|
- |
|
| 1325 |
|
- |
|
| 1326 |
var init = settings.oInit.scroller;
|
- |
|
| 1327 |
var defaults = DataTable.defaults.scroller;
|
- |
|
| 1328 |
|
- |
|
| 1329 |
if ( init || defaults ) {
|
- |
|
| 1330 |
var opts = $.extend( {}, init, defaults );
|
- |
|
| 1331 |
|
- |
|
| 1332 |
if ( init !== false ) {
|
- |
|
| 1333 |
new Scroller( settings, opts );
|
- |
|
| 1334 |
}
|
- |
|
| 1335 |
}
|
- |
|
| 1336 |
} );
|
- |
|
| 1337 |
|
- |
|
| 1338 |
|
- |
|
| 1339 |
// Attach Scroller to DataTables so it can be accessed as an 'extra'
|
- |
|
| 1340 |
$.fn.dataTable.Scroller = Scroller;
|
- |
|
| 1341 |
$.fn.DataTable.Scroller = Scroller;
|
- |
|
| 1342 |
|
- |
|
| 1343 |
|
- |
|
| 1344 |
// DataTables 1.10 API method aliases
|
- |
|
| 1345 |
var Api = $.fn.dataTable.Api;
|
- |
|
| 1346 |
|
- |
|
| 1347 |
Api.register( 'scroller()', function () {
|
- |
|
| 1348 |
return this;
|
- |
|
| 1349 |
} );
|
- |
|
| 1350 |
|
- |
|
| 1351 |
// Undocumented and deprecated - is it actually useful at all?
|
- |
|
| 1352 |
Api.register( 'scroller().rowToPixels()', function ( rowIdx, intParse, virtual ) {
|
- |
|
| 1353 |
var ctx = this.context;
|
- |
|
| 1354 |
|
- |
|
| 1355 |
if ( ctx.length && ctx[0].oScroller ) {
|
- |
|
| 1356 |
return ctx[0].oScroller.fnRowToPixels( rowIdx, intParse, virtual );
|
- |
|
| 1357 |
}
|
- |
|
| 1358 |
// undefined
|
- |
|
| 1359 |
} );
|
- |
|
| 1360 |
|
- |
|
| 1361 |
// Undocumented and deprecated - is it actually useful at all?
|
- |
|
| 1362 |
Api.register( 'scroller().pixelsToRow()', function ( pixels, intParse, virtual ) {
|
- |
|
| 1363 |
var ctx = this.context;
|
- |
|
| 1364 |
|
- |
|
| 1365 |
if ( ctx.length && ctx[0].oScroller ) {
|
- |
|
| 1366 |
return ctx[0].oScroller.fnPixelsToRow( pixels, intParse, virtual );
|
- |
|
| 1367 |
}
|
- |
|
| 1368 |
// undefined
|
- |
|
| 1369 |
} );
|
- |
|
| 1370 |
|
- |
|
| 1371 |
// `scroller().scrollToRow()` is undocumented and deprecated. Use `scroller.toPosition()
|
- |
|
| 1372 |
Api.register( ['scroller().scrollToRow()', 'scroller.toPosition()'], function ( idx, ani ) {
|
- |
|
| 1373 |
this.iterator( 'table', function ( ctx ) {
|
- |
|
| 1374 |
if ( ctx.oScroller ) {
|
- |
|
| 1375 |
ctx.oScroller.fnScrollToRow( idx, ani );
|
- |
|
| 1376 |
}
|
- |
|
| 1377 |
} );
|
- |
|
| 1378 |
|
- |
|
| 1379 |
return this;
|
- |
|
| 1380 |
} );
|
- |
|
| 1381 |
|
- |
|
| 1382 |
Api.register( 'row().scrollTo()', function ( ani ) {
|
- |
|
| 1383 |
var that = this;
|
- |
|
| 1384 |
|
- |
|
| 1385 |
this.iterator( 'row', function ( ctx, rowIdx ) {
|
- |
|
| 1386 |
if ( ctx.oScroller ) {
|
- |
|
| 1387 |
var displayIdx = that
|
- |
|
| 1388 |
.rows( { order: 'applied', search: 'applied' } )
|
- |
|
| 1389 |
.indexes()
|
- |
|
| 1390 |
.indexOf( rowIdx );
|
- |
|
| 1391 |
|
- |
|
| 1392 |
ctx.oScroller.fnScrollToRow( displayIdx, ani );
|
- |
|
| 1393 |
}
|
- |
|
| 1394 |
} );
|
- |
|
| 1395 |
|
- |
|
| 1396 |
return this;
|
- |
|
| 1397 |
} );
|
- |
|
| 1398 |
|
- |
|
| 1399 |
Api.register( 'scroller.measure()', function ( redraw ) {
|
- |
|
| 1400 |
this.iterator( 'table', function ( ctx ) {
|
- |
|
| 1401 |
if ( ctx.oScroller ) {
|
- |
|
| 1402 |
ctx.oScroller.fnMeasure( redraw );
|
- |
|
| 1403 |
}
|
- |
|
| 1404 |
} );
|
- |
|
| 1405 |
|
- |
|
| 1406 |
return this;
|
- |
|
| 1407 |
} );
|
- |
|
| 1408 |
|
- |
|
| 1409 |
Api.register( 'scroller.page()', function() {
|
- |
|
| 1410 |
var ctx = this.context;
|
- |
|
| 1411 |
|
- |
|
| 1412 |
if ( ctx.length && ctx[0].oScroller ) {
|
- |
|
| 1413 |
return ctx[0].oScroller.fnPageInfo();
|
- |
|
| 1414 |
}
|
- |
|
| 1415 |
// undefined
|
- |
|
| 1416 |
} );
|
- |
|
| 1417 |
|
- |
|
| 1418 |
return Scroller;
|
- |
|
| 1419 |
}));
|
- |
|