FireFox 4 no longer supports scrollable TBody - wo

2019-03-18 01:35发布

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

7条回答
对你真心纯属浪费
2楼-- · 2019-03-18 02:11

Try the first method of this page, pure CSS with a single table (2 divs around the table, and the thead is positionned absolute) : tablescroll Seems to work on FF4/IE9/IE8 in addition to IE7/FF3.6.

查看更多
Summer. ? 凉城
3楼-- · 2019-03-18 02:17

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

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

查看更多
4楼-- · 2019-03-18 02:19

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 #ffffdffffd;}
            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>
查看更多
闹够了就滚
5楼-- · 2019-03-18 02:21

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

查看更多
老娘就宠你
6楼-- · 2019-03-18 02:21

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"; 
}
查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-03-18 02:29

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

查看更多
登录 后发表回答