jQuery scrollTop () не работает в Safari или Chrome (Windows) - PullRequest
38 голосов
/ 02 декабря 2009

У меня есть простая настройка, позволяющая загружать и прокручивать окно в стиле «справки» до определенной точки на странице. Более или менее код выглядит так:

var target = /* code */;
target.offsetParent().scrollTop(target.offset().top - fudgeValue);

Цель прокрутки и значение выдумки определяются парой подсказок, пропущенных на странице, и у меня нет проблем с этой частью этого механизма где-либо. В Firefox и IE8 приведенный выше код работает точно так, как я хочу: поле прокрутки (в данном случае тело страницы) корректно прокручивает содержимое в нужную точку окна, когда ему говорят об этом.

Однако в Chrome и Safari вызов scrollTop (), по-видимому, вообще ничего не делает. Все числа в порядке, и цель ссылается на правильную вещь (а offsetParent () действительно является элементом body), но ничего не происходит. Насколько я могу судить по поиску в интернете, это должно сработать. Что-то смешное в рендере под Safari и Chrome?

Это jQuery 1.3.2, если это имеет значение.

Тестовая страница: http://gutfullofbeer.net/scrolltop.html

Ответы [ 19 ]

45 голосов
/ 10 февраля 2010

У меня была эта проблема в Safari и Chrome (Mac), и я обнаружил, что .scrollTop будет работать на $("body"), но не $("html, body"), однако FF и IE работают наоборот. Простое обнаружение браузера решает проблему:

if($.browser.safari)
    bodyelem = $("body")
else
    bodyelem = $("html,body")

bodyelem.scrollTop(100)

В качестве браузера JQuery для Chrome используется Safari, поэтому вам нужно только обнаружить его.

Надеюсь, это кому-нибудь поможет.

23 голосов
/ 10 декабря 2009

Да, в Chrome возникает ошибка, когда дело доходит до изменения body, пытаясь превратить его в offsetParent. В качестве обходного пути я предлагаю вам просто добавить еще один div, чтобы обернуть #content div, и сделать , что scroll:

html, body { height: 100%; padding: 0; } 
html { width: 100%; background-color: #222; overflow: hidden; margin: 0; } 
body 
{ 
   width: 40em; margin: 0px auto; /* narrow center column layout */
   background-color: white; 
   position: relative; /* allow positioning children relative to this element */
} 
#scrollContainer /* wraps #content, scrolls */
{ 
  overflow: auto; /* scroll! */
  position:absolute; /* make offsetParent */
  top: 0; height: 100%; width: 100%; /* fill parent */
} 
#header 
{ 
  position: absolute; 
  top: 0px; height: 50px; width: 38.5em; 
  background-color: white; 
  z-index: 1; /* sit above #content in final layout */
} 
#content { padding: 5px 14px 50px 5px;  } 

Протестировано в FF 3.5.5, Chrome 3.0.195.33, IE8

Живая демонстрация:

$(function() {
        $('#header').find('button').click(function(ev) {
          var button = $(this), target = $('div.' + button.attr('class'));
          var scroll = target.offsetParent().scrollTop(); 
          target.offsetParent().scrollTop(target.offset().top + scroll - 50);
        });
      });
html, body { height: 100%; padding: 0; }
      html { width: 100%; background-color: #222; overflow: hidden; margin: 0; }
      body { width: 40em; margin: 0px auto; background-color: white; position: relative; }
      #scrollContainer { overflow: auto; position:absolute; top: 0; height: 100%; width: 100%; }
      #header { position: absolute; top: 0px; height: 50px; width: 38.5em; background-color: white; z-index: 1; }
      #content { padding: 5px 14px 50px 5px;  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div id='header'> 
      Header Box
      <button class='A'>A</button> 
      <button class='B'>B</button> 
      <button class='C'>C</button> 
    </div> 
    <div id='scrollContainer'>
    <div id='content'> 
      <div style='height: 50px'> </div> 
      <div class='A'> 
        <h1>A</h1> 
        <p>My name is Boffer Bings. I was born of honest parents in one of the humbler walks of life, my father being a manufacturer of dog-oil and my mother having a small studio in the shadow of the village church, where she disposed of unwelcome babes. In my boyhood I was trained to habits of industry; I not only assisted my father in procuring dogs for his vats, but was frequently employed by my mother to carry away the debris of her work in the studio. In performance of this duty I sometimes had need of all my natural intelligence for all the law officers of the vicinity were opposed to my mother's business. They were not elected on an opposition ticket, and the matter had never been made a political issue; it just happened so. My father's business of making dog-oil was, naturally, less unpopular, though the owners of missing dogs sometimes regarded him with suspicion, which was reflected, to some extent, upon me. My father had, as silent partners, all the physicians of the town, who seldom wrote a prescription which did not contain what they were pleased to designate as _Ol. can._ It is really the most valuable medicine ever discovered. But most persons are unwilling to make personal sacrifices for the afflicted, and it was evident that many of the fattest dogs in town had been forbidden to play with me--a fact which pained my young sensibilities, and at one time came near driving me to become a pirate.
      </div> 
      <div class='B'> 
        <h1>B</h1> 
        <p> 
        Looking back upon those days, I cannot but regret, at times, that by indirectly bringing my beloved parents to their death I was the author of misfortunes profoundly affecting my future.
        <p> 
        One evening while passing my father's oil factory with the body of a foundling from my mother's studio I saw a constable who seemed to be closely watching my movements. Young as I was, I had learned that a constable's acts, of whatever apparent character, are prompted by the most reprehensible motives, and I avoided him by dodging into the oilery by a side door which happened to stand ajar. I locked it at once and was alone with my dead. My father had retired for the night. The only light in the place came from the furnace, which glowed a deep, rich crimson under one of the vats, casting ruddy reflections on the walls. Within the cauldron the oil still rolled in indolent ebullition, occasionally pushing to the surface a piece of dog. Seating myself to wait for the constable to go away, I held the naked body of the foundling in my lap and tenderly stroked its short, silken hair. Ah, how beautiful it was! Even at that early age I was passionately fond of children, and as I looked upon this cherub I could almost find it in my heart to wish that the small, red wound upon its breast--the work of my dear mother--had not been mortal.
      </div> 
      <div class='C'> 
        <h1>C</h1> 
        <p>It had been my custom to throw the babes into the river which nature had thoughtfully provided for the purpose, but that night I did not dare to leave the oilery for fear of the constable. "After all," I said to myself, "it cannot greatly matter if I put it into this cauldron. My father will never know the bones from those of a puppy, and the few deaths which may result from administering another kind of oil for the incomparable _ol. can._ are not important in a population which increases so rapidly." In short, I took the first step in crime and brought myself untold sorrow by casting the babe into the cauldron.
      </div> 
      <div style='height: 75em;'> </div> 
    </div> 
    </div>
17 голосов
/ 12 ноября 2010
 $("body,html,document").scrollTop($("#map_canvas").position().top);

Это работает для Chrome 7, IE6, IE7, IE8, IE9, FF 3.6 и Safari 5.

ОБНОВЛЕНИЕ 2012
Это все еще хорошо, но мне пришлось использовать его снова. Иногда position не работает, так что это альтернатива:

$("body,html,document").scrollTop($("#map_canvas").offset().top);
9 голосов
/ 11 марта 2010

Состояние поддержки браузера:

IE8, Firefox, Opera: $("html")

Chrome, Safari: $("body")

Так что это работает:

bodyelem = $.browser.safari ? $("body") : $("html") ;
bodyelem.animate( {scrollTop: 0}, 500 );
7 голосов
/ 28 октября 2011

Для прокрутки: 'html' или 'body' для сеттера (зависит от браузера) ... 'window' для геттера ...

JsFiddle для тестирования здесь: http://jsfiddle.net/molokoloco/uCrLa/

var $window = $(window), // Set in cache, intensive use !
    $document = $(document),
    $body = $('body'),
    scrollElement = 'html, body',
    $scrollElement = $();

var isAnimated = false;

// Find scrollElement
// Inspired by http://www.zachstronaut.com/posts/2009/01/18/jquery-smooth-scroll-bugs.html
$(scrollElement).each(function(i) {
    // 'html, body' for setter... window for getter... 
    var initScrollTop = parseInt($(this).scrollTop(), 10);
    $(this).scrollTop(initScrollTop + 1);
    if ($window.scrollTop() == initScrollTop + 1) {
        scrollElement = this.nodeName.toLowerCase(); // html OR body
        return false; // Break
    }
});
$scrollElement = $(scrollElement);

// UTILITIES...
var getHash = function() {
        return window.location.hash || '';
    },
    setHash = function(hash) {
        if (hash && getHash() != hash) window.location.hash = hash;
    },
    getWinWidth = function() {
        return $window.width();
    },
    // iphone ? ((window.innerWidth && window.innerWidth > 0) ? window.innerWidth : $window.width());
    getWinHeight = function() {
        return $window.height();
    },
    // iphone ? ((window.innerHeight && window.innerHeight > 0) ? window.innerHeight : $window.height());
    getPageWidth = function() {
        return $document.width();
    },
    getPageHeight = function() {
        return $document.height();
    },
    getScrollTop = function() {
        return parseInt($scrollElement.scrollTop() || $window.scrollTop(), 10);
    },
    setScrollTop = function(y) {
        $scrollElement.stop(true, false).scrollTop(y);
    },
    myScrollTo = function(y, newAnchror) { // Call page scrolling to a value (like native window.scrollBy(x, y)) // Can be flooded
        isAnimated = true; // kill waypoint AUTO hash
        var duration = 360 + (Math.abs(y - getScrollTop()) * 0.42); // Duration depend on distance...
        if (duration > 2222) duration = 0; // Instant go !! ^^
        $scrollElement.stop(true, false).animate({
            scrollTop: y
        }, {
            duration: duration,
            complete: function() { // Listenner of scroll finish...
                if (newAnchror) setHash(newAnchror); // If new anchor
                isAnimated = false;
            }
        });
    },
    goToScreen = function(dir) { // Scroll viewport page by paginette // 1, -1 or factor
        var winH = parseInt((getWinHeight() * 0.75) * dir); // 75% de la hauteur visible comme unite
        myScrollTo(getScrollTop() + winH);
    };


myScrollTo((getPageHeight() / 2), 'iamAMiddleAnchor');
2 голосов
/ 03 мая 2010

Работает для Safari, Firefox и IE7 (не пробовал IE8). Простой тест:

<button onclick='$("body,html").scrollTop(0);'>  Top </button>

<button onclick='$("body,html").scrollTop(100);'> Middle </button>

<button onclick='$("body,html").scrollTop(250);'> Bottom </button>

В большинстве примеров используется один или оба, но в обратном порядке (т. Е. "Html, body").

Приветствие.

(И семантические пуристы, не ломайте мои отбивные - я искал это неделями, это простой пример, который подтверждает строгий XHTML. Не стесняйтесь создавать 27 слои абстракции и связывания событий раздуваются для вашего спокойствия OCD. Просто, пожалуйста, отдайте должное, так как люди на форумах jQuery, SO и G. не могли выкашлять товар. Мир.)

2 голосов
/ 06 декабря 2009

В Chrome есть ошибка (не в Safari на момент проверки), которая дает неожиданные результаты при различных измерениях ширины и высоты в Javascript при открытии вкладок в фоновом режиме ( подробности об ошибках здесь ) - мы зарегистрировались ошибка в июне, и она осталась нерешенной с тех пор.

Возможно, вы столкнулись с ошибкой в ​​том, что пытаетесь сделать.

2 голосов
/ 27 октября 2011
setTimeout(function() { 
   $("body,html,document").scrollTop( $('body').height() ); 
}, 100);

Это, вероятно, должно работать, даже если время составляет 10 мс.

1 голос
/ 13 апреля 2011

Это похоже на работу в FF и WebKit; IE пока не тестировался.

$(document).scrollTop();
1 голос
/ 02 декабря 2009

Какой элемент является offsetParent другого, не очень точно указан и может отличаться в разных браузерах. Не гарантируется, что вы ищите прокручиваемого родителя.

Само тело также не должно быть основным прокручиваемым элементом страницы. Это только в режиме «Причуды», которого вы вообще хотели бы избежать.

Измерения offsetTop / offsetLeft / offsetParent не очень полезны сами по себе, они действительно очень надежны, только когда вы используете их в цикле, чтобы получить общую относительную страницу относительно ординаты (как position() в jQuery). Вы должны знать, какой элемент вы хотите прокрутить, и выяснить разницу в координатах страницы между ним и потомком target, чтобы выяснить, на сколько его прокрутить.

Или, если вы всегда говорите о прокрутке самой страницы, просто используйте вместо нее навигацию location.href= '#'+target.id.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...