为什么垂直滚动条会自动移动?

10

我不明白为什么在单击“第9行”时,垂直滚动条会自动移动到最顶部位置。进一步的点击不会移动滚动条。有人可以解释一下原因,并说明如何解决吗? 我使用Firefox 3.6.3。

HTML:

<html>
    <head>
        <link rel="stylesheet" href="test.css" type="text/css" />
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script language="JavaScript" src="test.js"></script>
    </head>

    <body>
        <div>
            <table>
                <tr row='0'><td class='column1'>Line 0</td></tr>
                <tr row='1'><td class='column1'>Line 1</td></tr>
                <tr row='2'><td class='column1'>Line 2</td></tr>
                <tr row='3'><td class='column1'>Line 3</td></tr>
                <tr row='4'><td class='column1'>Line 4</td></tr>
                <tr row='5'><td class='column1'>Line 5</td></tr>
                <tr row='6'><td class='column1'>Line 6</td></tr>
                <tr row='7'><td class='column1'>Line 7</td></tr>
                <tr row='8'><td class='column1'>Line 8</td></tr>
                <tr row='9'><td class='column1'>Line 9</td></tr>
            </table>
        </div>
    </body>
</html>

JS:

$(document).ready(function() {
    $(".column1").each(function(index) {
        $(this).after("<td class='column2'>Details " + index + "</td>");
        $(this).toggle(function() { $("[row='" + index + "'] .column2").fadeIn("fast") },
                       function() { $("[row='" + index + "'] .column2").fadeOut("fast") });
    });
});

CSS:

div {
    overflow: auto;
    height: 100px;
    width: 300px;
    border: 1px solid blue;
}

.column1 {
    cursor: pointer;
    width: 100px;
    background-color: green;
    color: white;
}

.column2 {
    display: none;
    width: 200px;
    background-color: blue;
    color: white;
}

有趣。看起来Opera 10.53也有同样的问题。不过IE8和Chrome没有问题。 - Aoi Karasu
2个回答

6
经过一些试错测试,看起来这与浏览器在淡入/淡出单元格时重新计算和重绘表格的时刻有关。您的代码没有问题,jQuery正确地切换了单元格的“display”属性——看起来这是FF中的一个小错误。
可能最简单的方法是避免切换表格单元格本身,而是切换列2单元格的内容,像这样:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <link rel="stylesheet" href="test.css" type="text/css" />
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script language="JavaScript">
        $(document).ready(function() {
            $("td.column1").each(function(index) {
                $(this).after('<td class="column2"><span class="details">Details ' + index + '</span></td>');
                $(this).toggle(
                  function(){$(this).siblings('.column2').children('span.details').fadeIn("fast")},
                  function(){$(this).siblings('.column2').children('span.details').fadeOut("fast")}
                ) 
            });
        });
        </script>
        <style type="text/css" media="screen">
          div {
              overflow: auto;
              height: 100px;
              width: 300px;
              border: 1px solid blue;
          }

          .column1 {
              cursor: pointer;
          }

          .column2 .details{
              display:none;
          }

        </style>
    </head>

    <body>
        <div>
            <table>
                <tr row='0'><td class='column1'>Line 0</td></tr>
                <tr row='1'><td class='column1'>Line 1</td></tr>
                <tr row='2'><td class='column1'>Line 2</td></tr>
                <tr row='3'><td class='column1'>Line 3</td></tr>
                <tr row='4'><td class='column1'>Line 4</td></tr>
                <tr row='5'><td class='column1'>Line 5</td></tr>
                <tr row='6'><td class='column1'>Line 6</td></tr>
                <tr row='7'><td class='column1'>Line 7</td></tr>
                <tr row='8'><td class='column1'>Line 8</td></tr>
                <tr row='9'><td class='column1'>Line 9</td></tr>
            </table>
        </div>
    </body>
</html>

因此,该脚本添加了column2单元格,并且该单元格始终可见 - 相反,我们在其中显示/隐藏<span class="details">。我已经在FF 3.6.3中测试了这个版本,它的行为符合预期!
哦 - 我还清理了您的jQuery选择器以提高性能。如果您想要更多信息,请告诉我!

很好的解决方法,但并不能完全解决我的问题。在我这种情况下,.column2 有一个固定的 width 和一个 background-color。如果你将这些属性添加到 CSS 代码中,即使详情 span 没有显示,你也会看到 background-color。我将相应地编辑问题,并请告诉我为什么你的 jQuery 选择器比我的性能更好。 - Misha Moroshko
好的 - 我认为,为了消除问题的根源,column2必须始终可见。我相信,显示和隐藏单元格是直接原因 - 原因如下:与大多数元素不同,TD与其周围的元素存在相互依赖关系。一个单元格的大小可以取决于同一行中其他两个单元格以及同一列中的其他单元格的宽度。如果您添加新单元格(通过.fadeIn()),浏览器需要重新计算表中某些或所有其他单元格的尺寸。(续) - Ben Hull
当这种情况发生时,似乎FF会失去在滚动容器中的“位置”,并将您带回到顶部。当然,这只是我的理论,但它似乎符合所有事实。那么 - 怎么办?您能否将当前应用于.column2的样式应用于.column2 .details?可能唯一需要在.column2本身上执行的操作是设置宽度(以避免重绘表格)。如果失败,也许您可以使用不使用表格的标记来标记内容。它是什么类型的数据?它是表格形式的,对吧? - Ben Hull
1
就jQuery选择器性能而言,我的选择器更具体,并且作为一系列快速操作在小节点集合上运行。特别是,您的 $("[row='" + index + "']) 选择器需要检查整个页面中的每个元素,以查找正确的行属性。基于已知节点进行搜索始终更有效:在这种情况下,我们知道单击的TD,因此我们从那里开始搜索,首先获取兄弟姐妹(这是浏览器本地DOM操作),然后搜索它们的子项(也是DOM本地)。 - Ben Hull
设置列2的宽度没有帮助。最终,我使用了scrollTo()函数来获取淡化操作之前的滚动条值,然后在淡化之后将其设置回去。这不是一个理想的解决方案,因为会有一些闪烁效果,但也不算太糟糕。 - Misha Moroshko
如果您仍然通过切换显示到“none”然后再次切换(在这种情况下通过fadeIn()和fadeOut())来显示/隐藏column2,则设置column2的宽度将无济于事。 - Ben Hull

1

我复制并尝试了您的代码,使用Firefox 3.6.3和Chrome 5.0.375.29。但是我没有看到您所描述的任何情况,所以我感到很困惑。

只有在正常滚动时才会移动滚动条,而不是单击文本时。


非常奇怪……你确定你点击了"第9行"?以下是查看问题的步骤:(1)重新加载网页(2)移动滚动条以查看“第9行”(3)点击“第9行”。在此单击后,滚动条会自动向上移动,只能看到“第0行”、“第1行”、“第2行”和“第3行”。我是唯一遇到这个问题的人吗? - Misha Moroshko
@Misha 啊,现在我按照你的指示做了,我明白了。然而为了修复它,我将 .fadeIn() 和 .fadeOut 改成了 .css("display", "block") 和 .css("display", "none"),滚动效果开始按预期工作了。 - Mattijle
Mattijle:将表格单元格设置为“display:block”可以避免问题,但会引起其他问题,因为这些单元格不再有效地成为表格结构的一部分。我认为这个简单的例子并没有展示出这些问题,但在实际情况下这不是一个好主意。当您使用jQuery的fadeIn()或fadeOut()淡入/淡出表格单元格时,jQuery在“none”和“table-cell”之间切换显示,这是正确的。 - Ben Hull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接