Scroller behavior for variable-height table
Scroller behavior for variable-height table
Enigma
Posts: 2Questions: 0Answers: 0
Hello Allan,
First off, thanks for a fantastic plugin; really impressive work. I recently switched out infinite scrolling in favor of the Scroller plug-in, but have experienced some unusual behavior for a variable-height table. When I scroll to the bottom of my table, it periodically fails to render the last few rows. My guess is that this is due to the way I have the sScrollY value configured, as the table may not be triggering the last re-render.
Table Settings:
[code]
"sScrollY": 800,
"bAutoWidth": false,
"bDeferRender": true,
"bFilter": true,
"bSort": true,
"fnRowCallback": function (nRow, aData) {
// Customer column class
jQuery("td:eq(4)", nRow).addClass("name_column");
},
"fnInitComplete": function () {
// Adjust scroll areas for table
adjustTable();
}
[/code]
If I understand the plug-in correctly, the sScrollY value of 800px is used for the initial scrolling calculation and represents 1/3 of the scrollable area (for a total of 2400px.) If every row in my table is set to a static height of 80px and I want to render 30 rows, then the height of the sScrollY should be 800. Each time the scroll breaks the 1600px mark, an additional 800 pixels are rendered, while the first 800 are "forgotten."
The resize function called during the InitComplete callback, used to adjust the display area of the table to match the container:
[code]
adjustTable = function () {
var wrapperHeight = jQuery("#BlockList_Table_wrapper").height();
var headerHeight = jQuery(".dataTables_scrollHead").height();
var infoPadding = 20;
var infoHeight = jQuery("#BlockList_Table_info").height() + infoPadding;
// Adjust scroll area
jQuery(".dataTables_scroll").height(wrapperHeight - infoHeight);
jQuery(".dataTables_scrollBody").height(wrapperHeight - headerHeight - infoHeight);
// Adjust column sizing
bController.bList.fnAdjustColumnSizing();
};
[/code]
I wouldn't think this resize would affect the scrolling calculation, but I could definitely be wrong. If you (or anyone reading this) could provide some insight, it would be much appreciated. I don't have a mock-up of the table on hand, but would be happy to explain further if my explanation wasn't clear enough.
Thanks in advance,
Quinn
First off, thanks for a fantastic plugin; really impressive work. I recently switched out infinite scrolling in favor of the Scroller plug-in, but have experienced some unusual behavior for a variable-height table. When I scroll to the bottom of my table, it periodically fails to render the last few rows. My guess is that this is due to the way I have the sScrollY value configured, as the table may not be triggering the last re-render.
Table Settings:
[code]
"sScrollY": 800,
"bAutoWidth": false,
"bDeferRender": true,
"bFilter": true,
"bSort": true,
"fnRowCallback": function (nRow, aData) {
// Customer column class
jQuery("td:eq(4)", nRow).addClass("name_column");
},
"fnInitComplete": function () {
// Adjust scroll areas for table
adjustTable();
}
[/code]
If I understand the plug-in correctly, the sScrollY value of 800px is used for the initial scrolling calculation and represents 1/3 of the scrollable area (for a total of 2400px.) If every row in my table is set to a static height of 80px and I want to render 30 rows, then the height of the sScrollY should be 800. Each time the scroll breaks the 1600px mark, an additional 800 pixels are rendered, while the first 800 are "forgotten."
The resize function called during the InitComplete callback, used to adjust the display area of the table to match the container:
[code]
adjustTable = function () {
var wrapperHeight = jQuery("#BlockList_Table_wrapper").height();
var headerHeight = jQuery(".dataTables_scrollHead").height();
var infoPadding = 20;
var infoHeight = jQuery("#BlockList_Table_info").height() + infoPadding;
// Adjust scroll area
jQuery(".dataTables_scroll").height(wrapperHeight - infoHeight);
jQuery(".dataTables_scrollBody").height(wrapperHeight - headerHeight - infoHeight);
// Adjust column sizing
bController.bList.fnAdjustColumnSizing();
};
[/code]
I wouldn't think this resize would affect the scrolling calculation, but I could definitely be wrong. If you (or anyone reading this) could provide some insight, it would be much appreciated. I don't have a mock-up of the table on hand, but would be happy to explain further if my explanation wasn't clear enough.
Thanks in advance,
Quinn
This discussion has been closed.
Replies
This won't work I'm afraid. As noted on the Scroller "home page" ( http://datatables.net/extras/scroller/ ):
> Note that rows in the table must all be the same height. Information in a cell which expands on to multiple lines will cause some odd behaviour in the scrolling.
This blog post has more details about how Scroller works: http://datatables.net/blog/Introducing_Scroller_-_Virtual_Scrolling_for_DataTables
Allan
Thanks for the quick response. Via CSS, I've set all rows to a static height, whereas the table itself is resizable. I'd expect the Scroller calculation would still be fine in this case?
Thanks,
Quinn
Allan
I'm making a full page media library (like iTunes) and because I always want the application to fill the entire page I have two divs (#top and #middle) absolutely positioned. The #top div has [code]top: 0; right: 0; left: 0; height: 72px[/code] and the #middle div has [code]top: 72px; right: 0; bottom: 0; left: 0[/code] so that both divs completely fill the screen.
My DataTable is inside #middle with [code]"yScroll" : $("#middle").height()+"px"[/code] but only WebKit seems to be correctly filling the entire page with rows. Firefox only appears to be filling about half of that space. I think it has to do with the fact that #middle is absolutely positioned and that it doesn't have an explicitly set height property. I'm guessing that's the issue because it worked fine when I wasn't absolutely positioning the table's wrapper, but it's kind of confusing because after looking through oTable.oOptions I can see a "y" property that is correctly set to 870px (the height of #middle). So it clearly is getting the correct height value, but it's not respecting it.
Any ideas?
Do you have the elements as display:none on initial load?
Allan
Here is all the options I'm initializing it with:
[code]dom.oTable = $("#list").dataTable({
"aaData": Temp.aaData, // Arrays
"aaSorting": [[0,'asc'], [2,'asc'], [1,'asc']],
"aoColumnDefs": [
{ "sType": "song", "aTargets": [ 0, 1, 2, 3 ] },
{ "sType": "numeric", "aTargets": [ 4, 5, 6, 8 ] }
],
"aoColumns": [
{ "sName": "artist", "sClass": "artist" },
{ "sName": "title", "sClass": "title" },
{ "sName": "album", "sClass": "album" },
{ "sName": "genre", "sClass": "genre", "bSortable": false },
{ "sName": "dev-origin-id", "sClass": "source", "bSearchable": false, "bSortable": false, "bVisible": true },
{ "sName": "length", "sClass": "length", "bSearchable": false, "bVisible": true, "fnRender": function (oObj) { return hhmmss(oObj.aData[oObj.iDataColumn]); }, "bUseRendered": false },
{ "sName": "playcount", "sClass": "plays", "bSearchable": false, "bVisible": true },
{ "sName": "idhash", "bSearchable": false, "bVisible": false },
{ "sName": "art", "bSearchable": false, "bVisible": false }
],
"oScroller": { // Objects
"serverWait": 100,
"trace": false
}
"bScrollAutoCss": true, // Booleans
"bDestroy": true,
"bInfo": false,
"bAutoWidth": true,
"bDeferRender": true,
"bProcessing": false,
"bRetrieve": true,
"bStateSave": true,
"iScrollLoadGap": 100, // Integers
"iDisplayLength": 200,
"sDom": "RtrS", // Strings
"sScrollY": $('#middle').height()+'px',
// Functions
"fnStateSave": function (oSettings, oData) { localStorage.setItem('oData', JSON.stringify(oData)); },
"fnStateLoad": function (oSettings) { return JSON.parse(localStorage.getItem('oData')); },
});[/code]
The (LESS) CSS for the portions of the page:
[code]@navbarHeight: 72px;
#top {
position: absolute;
top: 0; right: 0; left: 0;
height: @navbarHeight;
box-shadow: 0 -1px 0 black inset, 0 -2px 0 rgba(255,255,255,.2) inset;
}
#middle {
position: absolute;
top: @navbarHeight; right: 0; bottom: 0; left: 0;
div#list_wrapper { // DataTable wrapper
width: 100%;
height: 100%;
.dataTables_scroll { // Scroller wrapper
.box-sizing(border-box); // Adds vendor prefixes
width: 100%;
height: 100% !important // Override inline styles
position: relative;
}
.dataTables_scrollHead { // Faux fixed header wrapper
position: absolute;
z-index: 99999;
height: 33px;
overflow: visible;
.dataTables_scrollHeadInner { // Inner wrapper for header
width: 100% !important; // Override inline styles
}
}
.dataTables_scrollBody { // Real table with tbody content
height: 100% !important // Override inline styles
thead { display: none } // No need to have two header rows
}
td.plays, // Force correct widths for columns
td.length,
td.source { width: 6% !important; }
td.genre { width: 10% !important; }
td.album { width: 24% !important; }
td.title { width: 24% !important; }
td.artist { width: 24% !important; }
th.plays, // Could do this in one step if DataTables
th.length, // used s inside a
th.source { width: 6% !important; } // by only setting the width on each
th.genre { width: 10% !important; }
th.album { width: 24% !important; }
th.title { width: 24% !important; }
th.artist { width: 24% !important; }
}
}[/code]
Allan