FireFox 4 不再支持可滚动的 TBody - 解决方法?

Posted

技术标签:

【中文标题】FireFox 4 不再支持可滚动的 TBody - 解决方法?【英文标题】:FireFox 4 no longer supports scrollable TBody - workarounds? 【发布时间】:2011-06-18 14:46:24 【问题描述】:

正如 Firefox 4 changelog 中所述,将不再支持可滚动的 <tbody>

有一堆 workarounds - javascript 或 2 个单独的表 - 但它们都不能解决所有问题。 Javascript 显然更慢(有 600 行,您可能会忘记尝试滚动表格),并且 2 个表格的单元格宽度会出现问题。

您知道是否有一些很酷的方法可以做到这一点?我们正在使用 jsf / facelets,现在必须重做标签,从一个好主意开始会很棒:-)

【问题讨论】:

不!所有浏览器都应该支持这个!这是一个很棒的功能。 :( 刚刚发现这个问题,破坏了以前的工作页面,我同意:Nooooooooooooo!!! 不敢相信没有简单的方法来创建如此明显且非常有用的界面元素:/ 我没有 Firefox 4,所以我无法对其进行测试,但这个想法是溢出仅适用于块和内联块元素。你能把 tbody 改成 display:block,这样行吗? CSS 规范明确规定您应该能够独立于thead 和tfoot 滚动tbody。从字面上看,Mozilla 给出的不这样做的唯一原因是“这太难了。” 【参考方案1】:

多亏了 MozillaZine 的 digitaldigs,我只需稍加修改就能让它工作。 该修复适用于 FF4、FF7 和 FF11。

我希望这会有所帮助! :)

我已解决的问题- 1. scrollWidth 对我不起作用,所以必须使用 offsetWidth

    滚动条宽度 16 像素也无济于事,因此将其删除。而是让我的身体风格成为-

    .scrollContent 溢出-x:隐藏; 溢出-y:滚动; /* 我这样做只是为了 Mozilla。如果应用,IE 将显示 2 个滚动条*/ 显示:块;

    通过更改 #2,我必须填充标题的最后一个单元格以容纳滚动条。

    /* 我这样做只是为了 Mozilla。不适用于 IE*/

    .fixedHeader tr th:last-child padding-right: 20px;

    我的固定标题表使用了很多 colspan,因此无法设置宽度,因此我首先查找具有正确单元格数量的正确行,然后进行处理。

我的代码如下所示:

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"; 

【讨论】:

如果您提供小提琴,我可能会调查一下。我想我使用了类似的方法。【参考方案2】:

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

【讨论】:

很好,但你必须指定列宽:(【参考方案3】:

我制作了一个无框架原型,我想与您分享。 它适用于 Firefox 4+、IE7-8(尚未检查 6 或 9)Safari 和 Chrome。

最大的未解决问题是当静态标头在数据列之前没有空间收缩时该怎么办。

坦率地说,对于我正在从事的实际项目,我退出了滚动页面并使用了分页。但我正在处理 25 列以上的排序和可能的 1000 行。

无论如何,这是我在放弃它之前到达的地方。如果您改进它,请发布您的补充: 希望这会有所帮助。

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 ****/

            tableborder-collapse: collapse;font:normal 12px sans-serif;
            th,tdpadding:2px; height:20px;border:1px solid #dddddd;
            thbackground:#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);
    elsewindow.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>

【讨论】:

【参考方案4】:

我知道您正在尝试避免 js/单独的表实现,但这是我能找到的唯一一个可以跨多个浏览器工作的实现。试试http://www.tablefixedheader.com/。这是一个 jquery 解决方案,在我有限的测试中,跨 IE6 / IE8 / FF3 工作。 (未测试FF4)。

【讨论】:

【参考方案5】:

我升级后就被这个猛烈抨击了。嘘。

我在管子里发现了这个。

此代码在 FFX 4 中有效。不在 IE8 中...可以修改。

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

【讨论】:

我对它进行了一些试验,但我正在退出这个。它依赖于知道列数。我正在使用列数可变且冗长的表。【参考方案6】:

为什么不使用可滚动的 div?可能是以下两个选项之一:

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

或更简单:

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

我知道不是很漂亮,但嘿,我不是米开朗基罗 :)

【讨论】:

【参考方案7】:

PrimeFaces 和 RichFaces 具有可滚动的数据表组件,可通过 ajax 获取新行。

(无论如何,两个 JSF 组件库都使用 jQuery)

【讨论】:

这实际上让我觉得即使是这些项目也有他们的小问题看看richfaces演示,当滚动可见的行号时,整个屏幕会闪烁白色。那里甚至没有鼠标滚动。 Primefaces 演示从一开始就没有正确对齐(标题和正文)。没有调整大小。 @Toskan:Richfaces 演示主机确实很差。 需要修复的是底层实现,而不是API。 @Paul:HTML 规范不支持它,所以浏览器在这里没什么可指责的。

以上是关于FireFox 4 不再支持可滚动的 TBody - 解决方法?的主要内容,如果未能解决你的问题,请参考以下文章

HTML / CSS技巧 – 可滚动的 tbody(漂亮表格)

<table> 具有固定的 <thead> 和可滚动的 <tbody> [重复]

通过css样式给表格tbody加垂直滚动条

react-table tbody 不可垂直滚动

jQuery UI 可排序滚动辅助元素偏移 Firefox 问题

既然不再支持 VLC 插件,如何在 Firefox 和 Chrome 中流式传输 RTSP 实时视频?