【问题标题】:Problem with scrolling in opera歌剧中的滚动问题
【发布时间】:2010-10-26 08:23:16
【问题描述】:

更新:我留下了以下 javascript 代码以显示问题是如何随着时间的推移而发展起来的,但现在事实证明这与 javascript 无关,因为 javascript 不是问题所在。请看下面的 html/css 代码。

对于带有大菜单的概览页面,我实现了以下功能 (most of which I stole from here):

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    alert(elemBottom);

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}

$(document).ready(function(){
 var overview = $('#overview');
 var active = $('#active-item');
 if (!isScrolledIntoView(active))
 {
  $('#overview li.active-parent').each(function(index, value){
   if (!isScrolledIntoView(active)) overview.scrollTo(value);
  });
 }
 if (!isScrolledIntoView(active)) overview.scrollTo(active);
});

这个想法是,在每次页面加载后,包含的菜单都会滚动到当前#active-item 可见的位置。最好滚动到它的第一个父项(菜单项在树中),否则滚动到项目本身。

现在这在 Firefox 和 Chrome 中运行良好(没有苹果人向我抱怨过),但是 Opera 做了一件非常奇怪的事情:它向下滚动到正确的元素,然后在滚动所有之前暂停很短的时间再次上升

有人知道吗

  1. 发生了什么,以及
  2. 我该如何阻止它?

谢谢,


更新:我正在 linux (Fedora) 上使用 10.63 版进行测试


更新:看来我的搜索方向完全错误。这个问题似乎是一个 css 问题,可以使用以下代码复制:

<html>

<head>

<title>Opera scroll test</title>

  <style>
    .main:after
    {
      content: 'abc';
    }

    :focus
    {
      padding: 0px;
    }

    #overview
    {
      display: block;
      float: left;
      width: 219px;
      height: 500px;
      overflow: auto;

    }
  </style>

</head>

<body>

  <div id="main" class="main">

    <div id="overview">
      <ul>
        <?
        for($i = 1; $i < 100; $i++)
          echo '<li>'.$i.'</li>';
        ?>

      </ul>
    </div>
    <div>

      <p>123</p>

    </div>

  </div>

</body>
</html>

现在,如果您在导航窗格上向下滚动,并将鼠标向右移动(在内容窗格上方),导航窗格的滚动将被重置。

很抱歉浪费大家的时间来寻找 javascript :(

如果有任何 css 大师知道如何解决它,或者谁能简单地解释发生了什么,我将非常感激。


更新:在 Opera 10.63 的 windows 中测试了上述代码。发生同样的奇怪行为。


更新:已将此作为错误报告给 Opera。不知道会发生什么......

【问题讨论】:

  • 您能解释一下为什么您不只是为此使用本机“scrollIntoView()”API 吗?
  • 第一次听说...现在试了一下,在opera中也有同样的行为
  • 歌剧版本丢失。 jsFiddle 会很有帮助。提示:尝试使用 scrollTo() 的简单 oneliner 看看它是否有效。
  • 这似乎在多种情况下发生:该问题与上面发布的确切代码没有密切关系。
  • 您为什么不尝试使用不同版本的 Opera / OS 进行测试...?你的代码似乎没问题。

标签: css scroll opera


【解决方案1】:

不确定原因,但问题似乎与 .main:after content CSS 设置直接相关。可以使用 jQuery 吗?如果是这样,如果您注释掉或删除.main:after CSS 设置并将其替换为&lt;head&gt; 标签中的以下脚本,您将获得相同的视觉结果,而不会出现奇怪的滚动问题:

<script type="text/javascript">
  $(document).ready(function(){
    $(".main").append("abc");
  });
</script>

【讨论】:

  • 谢谢!我会把它推荐给我们的 css 人 :)
  • 如果您滚动“overview” div,然后将光标移到该 div 的右侧,但将光标留在“main” div 内(例如,在“123”或“abc”内容上) 然后奇怪的滚动到顶部不会发生。仅当您将光标完全移出“主”div 时才会发生这种情况。如果没有通过 CSS 内容关键字应用“abc”内容,则不会发生这种奇怪的行为。因此,在我看来,Opera 处理 CSS content 关键字的方式似乎是个问题。
  • 很奇怪。好吧,我现在已经将它作为一个错误报告给 Opera。非常感谢您的宝贵时间,抱歉我来不及给您赏金。我希望以前处理过这个问题的人仍然会出现:)
【解决方案2】:

我知道发生了什么,但是我尝试了您的代码,但到目前为止我似乎无法复制该问题。 Chrome 和 Opera 的行为相同。

这是我尝试过的 HTML:

<div id="overview" style="height: 300px;overflow-y: scroll;">
 <ul>   
  <li class="item" style="height: 400px;">item 1</li>
  <li class="item" style="height: 400px;">item 2 </li>
  <li class="active-parent" style="height: 400px;">active-parent<br/><br/>
    <ul>
      <li id="active-item" style="height: 300px;">active-item</li>
    </ul>
  </li>
 </ul>
</div>

至于为什么它在 Opera 中不起作用:您使用的是哪个版本的 Opera? 我尝试了 10.63(最新的)并且在那个版本上没问题。

由于我无法重现该问题,因此我将对其进行盲测:

尝试引入一点延迟,以便在队列中的所有其他内容之后执行此代码:

$(document).ready(function() {
  window.setTimeout(function() {
    // Your code goes here
  }, 500);
});

稍后添加:

回应您的陈述:“我真的很想了解这里发生了什么。为什么要延迟?在较慢的计算机上延迟需要更长吗?”:

如果设置延迟可以解决您的问题,那么原因很明显,有一些其他代码干扰了在它之后执行的“滚动到顶部”功能。通过将延迟设置为 500 毫秒,您可以确保您的代码在文档加载时执行每隔一段 Javascript 之后运行,这可能是您在文档加载时显式添加到 jQuery 函数队列中的内容加载(使用$(document).ready(function(){),或由Opera以“小部件”的形式隐式添加(您是否安装了任何翻译工具、谷歌工具栏等?)。

至于较慢的计算机是否需要更长的延迟,我个人不这么认为,关键是延迟迫使您的代码在 document.onload 事件触发的每个其他脚本之后执行。由于我的怀疑是在文档加载后直接连续执行的任何干扰都不需要很长的延迟,即使 50 毫秒也可以做到,关键是延迟会迫使你的代码排在队列的后面。

希望这有助于使事情更清楚。

【讨论】:

  • 谢谢 Steven,我也在使用 10.63 版
  • 感谢史蒂文的所有努力!
【解决方案3】:

正如 Steven de Salas 所说,添加延迟会有所帮助 -> 如果没有延迟,$(window).scrollTop() 将返回 0!

我玩了一下,想出了这个例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Scrolling Test</title>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js" type="text/javascript"></script>
<style type="text/css">
.parent { margin-bottom:100px; border:1px solid red; }
</style>

<script type="text/javascript">

(function ($){
    $.fn.extend({
        viewport : function(){
            if (this.length > 0) {

                var element = $(this.get(0)),
                pad = $.fn.viewport.PADDING,
                vp = {
                    height : element.height() + 2 * pad,
                    top : element.offset().top - pad,
                    docHeight : $(window).height(),
                    docTop : $(window).scrollTop(),
                    completelyInViewport : false
                };
                vp.bottom = vp.top + vp.height + pad;
                vp.docBottom = vp.docTop + vp.docHeight;
                vp.fitsInViewport = vp.height <= vp.docHeight;

                if (vp.top > vp.docTop && vp.bottom < vp.docBottom) {
                    vp.completelyInViewport = true;
                }

                return vp;
            }

            return null;
        }
    });

    $.fn.extend($.fn.viewport, {
        PADDING: 10, // ADJUST TO YOUR NEEDS
        LARGE_PARENT_BEHAVIOR: "bottom" // if parent list is bigger than viewport and 
                                        // the active item is not in the first page of 
                                        // the parents list, where should it be shown
                                        // possible: "bottom", "middle" or "top"
    });

    $.extend({
        ensureViewport: function(element, parent) {
            var e_vp = element.viewport(),
            p_vp = parent.viewport();

            if (null == e_vp || null == p_vp) {
                return;
            }

            if (!p_vp.completelyInViewport) {
                if (p_vp.fitsInViewport || e_vp.bottom - p_vp.top <= e_vp.docHeight) {
                    doScroll(p_vp.top);
                } else {
                    switch($.fn.viewport.LARGE_PARENT_BEHAVIOR) {
                        case "top":
                            doScroll(e_vp.top);
                            break;
                        case "middle":
                            doScroll(e_vp.top - (e_vp.docHeight - e_vp.height)/2);
                            break;
                        case "bottom":
                        default:
                            doScroll(e_vp.bottom - e_vp.docHeight);
                            break;
                    }
                }
            }

            function doScroll(y){
                window.scrollTo(0, y);
                // you could implement instead some sort of smooth scroling mechanism here
                // e.g. http://github.com/kswedberg/jquery-smooth-scroll
            }
        }
    });

    $(function(){
        window.setTimeout(function(){
            var item = $("li.active-item");
            if (item.size() > 0) {
                $.ensureViewport(item, item.closest("li.parent"));
            }
        }, 0);
    });
})(jQuery);

</script> 

</head>
<body>

<div id="overview">
 <ul>
  <li class="parent">
   parent 1
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
  <li class="parent">
   parent 2
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
  <li class="parent">
   parent 3
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
  <li class="parent">
   parent 4
   <ul class="item"><li>item 1</li><li class="active-item">item 2</li></ul>
  </li>
  <li class="parent">
   parent 5
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
  <li class="parent">
   parent 6
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
  <li class="parent">
   parent 7
   <ul class="item"><li>item 1</li><li>item 2</li></ul>
  </li>
 </ul>
</div>

</body>
</html>

在 Opera 10.63 上对其进行了测试,它也可以在那里工作。

干杯

【讨论】:

  • 感谢您的回答!我真的很想了解这里发生了什么。为什么要延迟?在较慢的计算机上延迟是否需要更长的时间?
【解决方案4】:

这只是一个理论,但可能会让你入门。

当您在浏览器上按回时,它通常会将您带到您上次查看的页面点。

Opera 是否有可能试图将你带到那个干扰你的代码的点?

我想知道你是否清除了你的历史/缓存,终止了 opera 进程并开始一个新进程。这有什么区别吗?

【讨论】:

  • 谢谢!好主意,但没有结果:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 1970-01-01
相关资源
最近更新 更多