代码之家  ›  专栏  ›  技术社区  ›  Michael Clerx

歌剧中的滚动问题

  •  2
  • Michael Clerx  · 技术社区  · 15 年前

    更新:我留下了下面的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);
    });
    

    其思想是,每次加载页面后,包含菜单的内容都会滚动到当前活动项可见的位置。最好滚动到第一个父项(菜单项在树中),否则滚动到项本身。

    它向下滚动到正确的元素,然后在再次向上滚动之前短暂暂停

    有人知道吗

    1. 怎么回事,还有
    2. 我怎样才能阻止它?


    更新:我正在linux上测试10.63版(Fedora)


    更新:看来我完全是在错误的方向搜索。问题似乎是一个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搜索浪费了大家的时间:(


    更新:在Opera10.63上的windows中测试了上述代码。同样的奇怪行为也会发生。


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

    4 回复  |  直到 8 年前
        1
  •  2
  •   300 baud    15 年前

    不确定原因,但这个问题似乎与 .main:after content CSS设置。你能用jQuery吗?如果是,如果你 注释或删除 这个 CSS设置并将其替换为 <head>

    <script type="text/javascript">
      $(document).ready(function(){
        $(".main").append("abc");
      });
    </script>
    
        2
  •  2
  •   Steven de Salas Alexander Bollaert    15 年前

    我知道发生了什么,但我尝试了你的代码,到目前为止,我似乎无法复制问题。Chrome和Opera的表现是一样的。

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

    至于为什么在歌剧中不起作用: 你在用哪个版本的歌剧?

    既然我不能再现这个问题,我就瞎拍它:

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

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

    以后添加:

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

    至于对于速度较慢的计算机是否需要更长的延迟,我个人不这么认为,关键是延迟会迫使您的代码在document.onload事件触发的每个其他脚本之后执行。因为我怀疑任何有智慧的东西 直接继承 在加载文档之后,您实际上不需要很长的延迟,甚至可能需要50毫秒,关键是延迟会迫使您的代码进入队列的后面。

    希望这能让事情更清楚。

        3
  •  1
  •   roberkules    15 年前

    我玩了一会儿,想出了一个例子:

    <!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>
    

    干杯

        4
  •  1
  •   Alex KeySmith    15 年前

    这只是一个理论,但可能会让你开始。

    当您在浏览器上按后退键时,它通常会将您带到上一次查看页面的位置。

    有没有可能opera正试图把你带到那个会干扰你的代码的地方?

    推荐文章