jQuery 如何在 FF3 中的 div 刷新后重置持久滚动条位置?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2694243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reset persistent scrollbar position after div refresh in FF3?
提问by rcon
I'm experiencing a weird scrollbar issue. I'm building a page that uses jQuery and PHP to dynamically load images into a DIV sequentially. This DIV is a fixed height but uses a scrollbar for its variable width. The problem is that the scrollbar does not reset after a dynamic refresh of the DIV. So when the user scrolls and then refreshes with new content, the scroll bar position stays persistent instead of resetting back to the left.
我遇到了一个奇怪的滚动条问题。我正在构建一个使用 jQuery 和 PHP 将图像按顺序动态加载到 DIV 的页面。这个 DIV 是一个固定的高度,但它的可变宽度使用一个滚动条。问题在于动态刷新 DIV 后滚动条不会重置。因此,当用户滚动然后刷新新内容时,滚动条位置保持不变,而不是重置回左侧。
This seems to only happen in FF3. The scrollbar resets perfectly fine in Chrome, Safari, and IE8.
这似乎只发生在FF3中。滚动条在 Chrome、Safari 和 IE8 中重置得非常好。
For each refresh, the DIV is hidden, emptied, sized with CSS, then sequentially appended with images.
每次刷新时,DIV 都会被隐藏、清空、用 CSS 调整大小,然后依次附加图像。
I've tried resetting white-space: normal
before the nowrap
, playing around with overflow
, and also jQuery's scrollLeft
to no avail. It still behaves strangely in FF3, and only FF3.
我试过white-space: normal
在之前重置nowrap
,玩弄overflow
,还有 jQueryscrollLeft
无济于事。它在FF3中仍然表现得很奇怪,而且只有FF3。
Click a thumbnail, move the scrollbar then click another thumb.
单击缩略图,移动滚动条,然后单击另一个拇指。
Thanks for any help!
谢谢你的帮助!
采纳答案by rcon
OK, after contemplating David M's suggestions, I figured it out. Since #interiors
is a child of #content
it was also being hidden. So I had to show
it first, set scrollLeft
then hide
it again. A bit kludgy, but whatever works...
好的,在考虑了 David M 的建议后,我想通了。既然#interiors
是孩子,#content
它也被隐藏了。所以我必须show
先设置,scrollLeft
然后hide
再设置。有点笨手笨脚,但不管怎样...
$('#landing, #interiors, #caption').empty();
$('#content').show()
$('#interiors').scrollLeft(0);
$('#interiors, #caption').hide();
Regarding the cached data in FF3, I'm still not clear on that. Save that one for a rainy day...
关于FF3中的缓存数据,我还不清楚。把那个留到下雨天……
Thanks
谢谢
回答by Richard S. Hall
Just for reference, here is a relevant Firefox bug:
仅供参考,这是一个相关的 Firefox 错误:
回答by Zze
Just encountered the same issue and solved it by setting a timeout AFTERthe #interiors
has become visible on page.
正好遇到了同样的问题,并通过设置超时解决了这个问题后的#interiors
已成为网页上可见。
$("#interiors").show(function(){
setTimeout(function(){$(this).scrollLeft(0);},10);});
});
回答by cryo
When I type this into the firebug interactive console:
当我在 firebug 交互式控制台中输入以下内容时:
var e = $('#interiors')[0]
e.scrollLeft = 0
e.scrollTop = 0
it seems to reset the scrollbars correctly. The element may also need to be shown with a display
of block
before setting scrollLeft
but I'm not sure - I think that when I tried to do this that Firefox restored the last values when the elements with overflow: auto
changed from hidden to shown.
它似乎正确重置了滚动条。该元素可能还需要在设置之前使用display
of显示,但我不确定 - 我认为当我尝试这样做时,当元素从隐藏更改为显示时,Firefox 恢复了最后一个值。block
scrollLeft
overflow: auto
EDIT:There are a couple of things which you could try to force Firefox to reset the values. First of all, you could remove and then re-add the "content" element when the hash changes:
编辑:有几件事您可以尝试强制 Firefox 重置这些值。首先,您可以在散列更改时删除然后重新添加“内容”元素:
var e = $('#interiors')[0]
var p = e.parentNode
p.removeChild(e)
p.insertBefore(e, p.firstChild) // insert again before the caption
Secondly, you could reset the scrollLeft
/scrollTop
values to 0
before using $('#interiors').empty()
or $('#interiors').hide()
so it doesn't save the values.
其次,您可以在使用之前将scrollLeft
/scrollTop
值重置为0
,$('#interiors').empty()
否则$('#interiors').hide()
它不会保存这些值。
回答by cryo
I edited the javascript to reset the scrollLeft
/scrollTop
values before hiding/clearing/setting the HTML. I put all of those operations into a single function to try to figure out what was happening.
在隐藏/清除/设置 HTML 之前,我编辑了 javascript 以重置scrollLeft
/scrollTop
值。我将所有这些操作放在一个函数中,试图弄清楚发生了什么。
I've tested this in Firefox and it seems to fix the scrolling problems, but I haven't tested any other browsers. It should work though.
我已经在 Firefox 中测试过,它似乎解决了滚动问题,但我还没有测试过任何其他浏览器。不过它应该可以工作。
It seems I was right in my other answer that you need to reset the scrollLeft
and scrollTop
values in Firefox while the element with an overflow of auto
is shown with a display of block
though, as it does seem to restore the old values when shown regardless of whether the scroll values changed while hidden:
似乎我在我的另一个答案中是正确的,您需要在 Firefox 中重置scrollLeft
和scrollTop
值,而溢出的元素auto
显示为block
虽然,因为它似乎在显示时恢复旧值,无论是否滚动隐藏时更改的值:
function setInteriors(html, hide) {
var i = $('#interiors');
// Reset the scrollbar positions BEFORE clearing/setting the HTML
i.scrollLeft(0);
i.scrollTop(0);
// Set the HTML if provided, otherwise empty
if (html) i.html(html);
else i.empty();
// Hide the element if hide is `true`
if (hide) i.hide();
}
function showContent(nav) {
if($.browser.safari) // webkit browsers
{
bodyelement = $("body")
}
else
{
bodyelement = $("html, body")
}
bodyelement.animate({ scrollTop: 0 }, 300);
setInteriors(null, true);
$('#caption').hide();
$('#caption').empty();
$('#landing').empty();
// Detect document window size and use appropriate image heigh images
if ($(window).height() < 832 ) // size of the document window, not browser window
{ // threshold for 600px images + 5 caption lines
var imageHeight = 500;
}
else
{
var imageHeight = 600;
}
// Show #content so we can show/hide #interiors and #caption individually
$('#content').show();
if ((nav == "about") || (nav == "contact"))
{
setInteriors(null); // for fast back/forward button mashing
switch(nav)
{
case "about":
setInteriors($('#hidden-about').html()); // Load from hidden div
break;
case "contact":
setInteriors($('#hidden-contact').html());
break;
}
$('#interiors').css('height', '100%'); // Dimensions for "about" and "contact"
$('#interiors').css('width', '645px');
$('#interiors').css('white-space', 'normal');
$('#interiors').fadeIn(200);
}
// TO DO: Maybe separate #interiors to two classes for dynamic changes?
else
{
switch(imageHeight)
{
case 500:
$('#interiors').css('height', '520px'); // Dimensions for gallery
// Extra 20px for scrollbar
break;
case 600:
$('#interiors').css('height', '620px');
break;
}
$('#interiors').css('width', '100%');
setInteriors(null); // for fast back/forward button mashing
$('#interiors').show();
nav = (location.hash).substring(1); // for fast back/forward button mashing
$('#caption').html('<P class="caption">' + $('#hidden-' + nav).html() + '</P>'); // load hidden captions
$('#caption').fadeIn(300); // show caption before images
getImages = "http://www.shadowshapes.com/uttwerk/getImages.php?id=" + nav + "&height=" + imageHeight;
$.getJSON(getImages, function(json) {
var max = json.length;
if(max > 0)
{
loadImage(0, max, nav);
}
function loadImage(index, max, nav) {
if ((location.hash).substring(1) == nav) // until hash changes, load current nav
{
if(index < max)
{
var newimg = new Image();
$(newimg).load(function () {
if ((location.hash).substring(1) == nav) // after current image loads
{ // continue if no hashchange
$('#interiors').append(this);
$('#interiors').css('white-space', 'nowrap');
$(this).hide();
if (max - index > 1) // add space after each image except last one
{
$(this).css('margin-right', '20px');
}
$(this).css('vertical-align', 'top');
$(this).fadeIn(200, function() {
loadImage(index + 1, max, nav);
});
}
}).attr('src', json[index]);
}
}
}
});
}
}
function arrangeStars() {
$('img.star').each(function () {
thumbposition = $(this).siblings('a.nav').children('img').position();
$(this).css("top", (thumbposition.top - 9));
$(this).css("left", (thumbposition.left - 9));
});
}
function placeStar(nav) {
// clear all stars on hash change
if ($('div.thumb').children('img').hasClass("visiblestar")) {
$('div.thumb').children('img').removeClass("visiblestar").addClass("hiddenstar");
}
// attach star to selected thumbnail
var test = $('div#_' + nav);
if ($(test).children('img').hasClass("hiddenstar")) {
$(test).children('img').removeClass("hiddenstar").addClass("visiblestar");
}
}
$(document).ready(function() {
//$.imgpreload(['', ''], {each: null, all:null});
// bind hover event for empty/contact/about hash only
$(arrangeStars()); // positions stars in the corner of each thumbnail
$('img.thumb, img.thumbwithborder').hover(
function () {
var nav = (location.hash).substring(1);
if ((nav == '') || (nav == "about") || (nav =="contact")) {
nav = $(this).parent().parent().attr("id");
$('div.thumb#' + nav).children('img').removeClass('hiddenstar').addClass('visiblestar');
}
},
function () {
var nav = (location.hash).substring(1);
if ((nav == '') || (nav == "about") || (nav =="contact")) {
nav = $(this).parent().parent().attr("id");
$('div.thumb#' + nav).children('img').removeClass('visiblestar').addClass('hiddenstar');
}
}
);
// hash change event triggers all the navigation and content switching
jQuery.hashchangeDelay = 50;
$(function() {
$(window).bind('hashchange', function() {
var nav = (location.hash).substring(1);
if (nav != '')
{
placeStar(nav);
$('#content').fadeOut(200, function() {
showContent(nav);
});
}
});
})
if (location.hash != '')
{
$(window).trigger('hashchange');
}
// load landing content
$(function() {
$('#content').hide(function() {
var landingdiv = $(document.createElement('div')).attr({id: 'landing'});
landingdiv.html($('#hidden-landing').html());
landingdiv.clone().appendTo('#interiors');
$(this).fadeIn(200);
});
});
});