FireFox 4 no longer supports scrollable TBody - workarounds?
I know you're trying to avoid js/separate table implementations, but it was the only one I could find that worked across multiple browsers. Try http://www.tablefixedheader.com/. It's a jquery solution and worked, in my limited testing, across IE6 / IE8 / FF3. (Haven't tested FF4).
PrimeFaces and RichFaces have scrollable datatable components which fetches new rows by ajax.
(both JSF component libraries uses jQuery under the covers anyway)
Thanks to digitaldigs from MozillaZine, I was able to make it work with few modifications.The fix works great for FF4, FF7 and FF11.
I hope this helps! :)
Issues I have fixed-1. scrollWidth did not work for me so had to go for offsetWidth
Scroll bar width 16 pixel also was not helping so removed it. Instead made my tbody style as-
.scrollContent {overflow-x:hidden;overflow-y:scroll; /* I did this only for Mozilla. IE will show 2 scroll bars if applied*/display:block;}
With change #2, I had to pad the last cell of the header to accomodate scroll bar.
/* I did this only for Mozilla. Not for IE*/
.fixedHeader tr th:last-child {padding-right: 20px;}
My fixed header table has colspan used a lot hence was not able to set width, so I first look for a correct row with correct number of cells and then I process.
My code looks like below:
function makeMeFixedHeader(){ var tbodys = document.getElementsByName("scrollTableBody"); if (tbodys){ for(var i=0;i<tbodys.length;i++){ // We can put logic here to check if the current height // of tbody has crossed the specified limit or not do_tbodyscroll(tbodys[i]); } }}function do_tbodyscroll(_tbody){ // get the table node var table = _tbody.parentNode; // Get the Last row in Thead ... // COLGROUPS USING COLSPAN NOT YET SUPPORTED var thead = table.getElementsByTagName("THEAD")[0]; var _rows = thead.getElementsByTagName("TR"); var tableheader = _rows[_rows.length - 1]; var headercells = tableheader.cells; // rows of tbody var _frows = _tbody.getElementsByTagName("TR"); // first row of tbody var _fr = _tbody.getElementsByTagName("TR")[0]; //var _fr = _tbody.getElementsByName("scrollTableRow")[0]; // first row cells .. var _frcells = _fr.cells; if (_frcells.length < headercells.length){ var rowCount = 1; while (rowCount < _frows.length){ // nth row of tbody _fr = _tbody.getElementsByTagName("TR")[rowCount]; //var _fr = _tbody.getElementsByName("scrollTableRow")[rowCount]; // nth row cells .. _frcells = _fr.cells; if (headercells.length == _frcells.length){ break; } rowCount++; } } // Apply width to header .. for(var i=0; i<headercells.length; i++){ if (tableheader.cells[i].offsetWidth != _fr.cells[i].offsetWidth){ var lastColumn = (i == headercells.length-1)?true:false; var changeWidth = (lastColumn)? ((rowCount >= 1)?true:false) :true; var headerW = tableheader.cells[i].offsetWidth; var cellW = _fr.cells[i].offsetWidth; if (headerW < cellW){ tableheader.cells[i].width = cellW; _fr.cells[i].width = tableheader.cells[i].width; if (lastColumn) tableheader.cells[i].width = tableheader.cells[i].offsetWidth-20; }else{ tableheader.cells[i].width = headerW; _fr.cells[i].width = tableheader.cells[i].width; if (lastColumn) _fr.cells[i].width = tableheader.cells[i].offsetWidth-20; } } } //var j = headercells.length-1; // ADD 16 Pixel of scroll bar to last column .. //tableheader.cells[j].width = _fr.cells[j].offsetWidth + 20; tableheader.style.display = "block"; _tbody.style.display = "block"; }