简体   繁体   中英

FireFox 4 no longer supports scrollable TBody - workarounds?

Well as mentioned in the Firefox 4 changelog , there will be no longer support for scrollable <tbody> 's.

There are a bunch of workarounds - javascript or 2 seperate tables - but none of them solves all problems. Javascript is obviously slower (with 600 rows you can forget to try to scroll a table), and 2 tables are gonna be problematic with cell-width.

Do you know if there is some cool way to do this? We are using jsf / facelets and now have to redo the tags, starting with a good idea would be awesome :-)

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).

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

  1. 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; }

  2. 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; }

  3. 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"; 
}

PrimeFaces and RichFaces have scrollable datatable components which fetches new rows by ajax.

(both JSF component libraries uses jQuery under the covers anyway)

尝试这个页面的第一个方法,带有单个表的纯CSS(表格周围有两个div,并且thead是绝对定位的): tablescroll除了IE7 / FF3.6之外,似乎可以在FF4 / IE9 / IE8上工作。

Just got slammed with this after I upgraded. Boo.

I found this in the tubes.

This code is working in FFX 4. Not in IE8... could be modified.

http://www.imaputz.com/cssStuff/bigFourVersion.html

Why not use a scrollable div? Maybe one of these two options:

<table>
 <row>
  <cell>
   <div of headers>
   <div of content (scrollable)>
  </cell>
 </row>
</table>

or simpler:

<div of headers>
<div (scrollable)>
 <table of content, no headers>
</div>

Not pretty I know but hey I'm no Michaelangelo :)

I worked on a frameworkless prototype I want to share with you. It's working in Firefox 4+, IE7-8 (haven't checked 6 or 9) Safari and Chrome.

The biggest unsolved problem is what to do when the static headers run out of room to shrink before the data columns do.

For the actual project I was working on frankly I backed out of the scrolling tbody and went with pagination. but I was dealing with 25+ columns with sorting and potentially 1000s of rows.

Anyway this is where I got to before I abandoned it. Please post your additions if you improve it: Hope this helps.

Link to an example

    <!DOCTYPE html>
<html>
    <head>
        <title>Table with Fixed Header Prototype</title>
        <script type="text/javascript">
        </script>
        <style type="text/css">
            .tableContainer{
                background:#eee;
                width:80%;
            }
            .scrollContainer{
                width:100%;
                height:500px; /** The only thing required */
            }
            .staticHeaderTable{
                -moz-box-shadow: 1px 4px 5px #cccccc;
                -webkit-box-shadow:1px 4px 5px #cccccc;
                box-shadow: 1px 4px 5px #cccccc;
                position: relative;
                z-index: 10;
            }
        /*****************************************************/
        /**** Generic styles outside of problem scope ****/

            table{border-collapse: collapse;font:normal 12px sans-serif;}
            th,td{padding:2px; height:20px;border:1px solid #dddddd;}
            th{background:#ffcc00;}
        </style>
    </head>
<body>
<script>
function makeStaticTableHeaders(tableId){
// Overall Container : wraps everything
    var tableContainer = document.createElement("div");
        tableContainer.className = "tableContainer";

// Scrolling Container : must have a height.(Set in CSSS in this sample) this contains the table without the head or foot   
    var scrollContainer = document.createElement("div");
        scrollContainer.className = "scrollContainer";
        scrollContainer.style.overflowY = "auto"; // just Y since IE7 doesn't add the scrollbar to the width.
        scrollContainer.style.overflowX = "hidden"; // IE7 override. consider a CSS fix
        scrollContainer.style.width = "100%";

// Identifies the actual table to wrap from the dom. exits if it can't be found
    var dataTable = document.getElementById(tableId);
    if(typeof(dataTable) == "undefined"){
        return false;
    }
    dataTable.style.width = "100%";

// Identify the header. If there is none, there is no point in this so exit.
    var header = dataTable.getElementsByTagName("thead");
    if (header.length == 0){
        return false;
    }
    for (var i = 0; i < header.length; i++)
    {
        if(header[i].className.indexOf("static") != -1){ 
            header = header[i];
            break; 
        }
        if(i == header.length - 1){
            header = header[i];// failsafe
        }
    }
// If we are still here, we begin the process of altering the DOM elements
    // 1. Insert the tableContainer in front of the dataTable
    dataTable.parentNode.insertBefore(tableContainer, dataTable);

    // 2. Insert the scrollContainer into the table container
    tableContainer.appendChild(scrollContainer);
    // 3. get the thead tr and create staticHeaderTable with the tr
    var headerRow = header.getElementsByTagName("tr")[header.getElementsByTagName("tr").length - 1]; // gets last tr in case there is more than one
    var staticHeaderTable = document.createElement("table");
        staticHeaderTable.className = "staticHeaderTable";
        staticHeaderTable.appendChild(header);
        staticHeaderTable.style.width = "100%";

    // 4. Put the staticHeaderTable in the scrollContanier 
    tableContainer.insertBefore(staticHeaderTable, scrollContainer);

    // 5. take the datatable out of the dom and put it in the scrollContainer
    scrollContainer.appendChild(dataTable);

    // 6. footer(optional)
    var footer = dataTable.getElementsByTagName("tfoot");
    if (footer.length > 0){
        for (var i = 0; i < footer.length; i++)
        {
            if(footer[i].className.indexOf("static") != -1){
                footer = footer[i];
                break; 
            }
            if(i == footer.length - 1){
                footer = footer[i];// failsafe
            }
        }
        // TODO: footer assumes columns are not linked to the data columns.     
        var staticFooterTable = document.createElement("table");
            staticFooterTable.className = "staticFooterTable";
            staticFooterTable.appendChild(footer);
            staticFooterTable.style.width = "100%";
            tableContainer.appendChild(staticFooterTable);
    }


    function tableResize(){
        var firsttableRow = dataTable.getElementsByTagName("tbody")[0].getElementsByTagName("tr")[0];
        var extra = headerRow.offsetWidth - firsttableRow.offsetWidth;
        var headerCells = (headerRow.getElementsByTagName("td").length > 0 )? headerRow.getElementsByTagName("td") : headerRow.getElementsByTagName("th");
        for(var i=0; i <headerCells.length;i++){
            headerCells[i].style.width = firsttableRow.getElementsByTagName("td")[i].offsetWidth + ((i==headerCells.length-1)? extra: 0) + "px";
        }
    };
    if(window.addEventListener) {window.addEventListener("resize", tableResize, false);}
    else{window.attachEvent("onresize", tableResize);}
    tableResize();
}

window.onload = function(){
    var staticTable = makeStaticTableHeaders("dataTable");
}

</script>
<h2>Datatable</h2>

    <table id="dataTable" class="dataTable">
        <thead class="static">
            <tr>
                <th>Header 1 A long One</th>
                <th>Header 2</th>
                <th>Header 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Cell Content 1 All the good Stuff is in here</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>

            </tr>
            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>

                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>

                <td>And Repeat 3</td>
            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>

            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>

                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>

            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>

                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>

                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>

            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>
                <td>More Cell Content 1</td>

                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>

            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>
            <tr>

                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>

                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>

            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>
            <tr>
                <td>Cell Content 1</td>

                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>

            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>

                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>

                <td>Cell Content 3</td>
            </tr>
            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>

            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>

                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>

            </tr>
            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>

                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>

                <td>And Repeat 3</td>
            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>

            <tr>
                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>

                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>

            </tr>
            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>

                <td>More Cell Content 1</td>
                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>

                <td>Even More Cell Content 3</td>
            </tr>
            <tr>
                <td>And Repeat 1</td>
                <td>And Repeat 2</td>
                <td>And Repeat 3</td>
            </tr>

            <tr>
                <td>Cell Content 1</td>
                <td>Cell Content 2</td>
                <td>Cell Content 3</td>
            </tr>
            <tr>
                <td>More Cell Content 1</td>

                <td>More Cell Content 2</td>
                <td>More Cell Content 3</td>
            </tr>
            <tr>
                <td>Even More Cell Content 1</td>
                <td>Even More Cell Content 2</td>
                <td>Even More Cell Content 3</td>

            </tr>
            <tr>
                <td>End of Cell Content 1</td>
                <td>End of Cell Content 2</td>
                <td>End of Cell Content 3</td>
            </tr>   
        </tbody>
        <tfoot>
            <tr>
                <td colspan="3">Footer Is Here</td>
            </tr>
        </tfoot>
    </table>
</body> 
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM