无法在Chrome扩展程序弹出框中保存滚动位置

时间:2012-09-22 23:52:01

标签: javascript google-chrome-extension scroll

我对编程比较陌生,正在开发一个带弹出窗口的Chrome扩展程序。我想在弹出调用之间保存滚动位置。好像我在互联网上发现了很多信息,但到目前为止我还没能解决我的问题。保存滚动位置几乎适用于我的扩展程序,但我看到2个问题:

1)要在每个滚动事件中保存滚动位置,我使用:

addEventListener('scroll', function(){
   localStorage.scrollTop = document.body.scrollTop;
});

打开弹出窗口时,我使用:

document.body.scrollTop = localStorage.scrollTop

这似乎工作正常,直到我的滚动位置超过弹出高度。 Chrome扩展程序中可见内容的最大弹出窗口高度为600px。 document.body.style.height也始终是大于600px的固定值。当滚动位置大于document.body.style.height - 600px,比如900px - 600px时,document.body.scrollTop将重置为300px。即使最后一个滚动位置(document.body.scrollTop)在弹出窗口关闭之前是400px,当重新打开弹出窗口时,滚动位置也会重置为300px。显然,我得到错误的滚动位置,因为正确的滚动位置值400px(例如)被300px覆盖。

然而,并非总是如此。有时我可以正确保存滚动位置,例如500px,窗口高度为900px,有时我不能。我不确定为什么会产生任何影响,但由于弹出窗口中的内容较高,问题似乎神奇地消失了,保存了正确的滚动位置。

在这种情况下,如何在滚动位置时正确保存滚动位置?也许我在做一些根本错误的事情?

(这看起来很混乱。我希望可以帮助解决上面的代码。)

2)我认为可能与上述问题交织在一起,但我不确定。对于每个滚动事件(本文中的第一个代码块),我看到一对滚动事件被触发。

如果我只是打开弹出窗口但不滚动鼠标滚轮,我会在事件监听器内部看到代码。当第一个事件发生时,document.body.scrollTop将重置为“错误”值(上例中为300px)。我认为这可能是两个问题的根本原因。

如果移动鼠标滚轮,事件监听器不应该只触发,因此如果打开弹出窗口但未触摸鼠标滚轮,则事件监听器内的代码不会执行?

2 个答案:

答案 0 :(得分:3)

问题实际上是在相应的CSS代码中。 <div>不可滚动,因此不允许保存大于弹出窗口可见区域的滚动位置。

解决方案是将position: relative;overflow-y: auto;overflow-y: scroll;也适用)属性添加到CSS元素中。

添加这些属性后,我可以将滚动位置正确保存到对象。

答案 1 :(得分:0)

我知道这不应该是一个答案,但我不能在评论中格式化代码:

我打算走出困境并建议你尝试测试一个基本假设:滚动事件是否按顺序触发?

试试这个,看看是否添加了一些有用的调试信息:

var scrollCounter = 0;
addEventListener('scroll', function(){
   localStorage.scrollTop = document.body.scrollTop;
   console.log({counter: scrollCounter, scrollTop: document.body.scrollTop});
   scrollCounter++
})

查看这些数字是否会跳跃,或者它们是否按顺序排列。

编辑:可能解决方案的P代码

我想我对fix有一个想法,虽然我在这里松散地使用了修复这个词。

var captureSemaphore; // Use this to flag exactly when we want the `scrollTop` captured.
captureSemaphore = true; // Go into catch mode

addEventListener('scroll', function(){
   if (captureSemaphore) {
     localStorage.scrollTop = document.body.scrollTop;
    }
});

// then later, right before you open your popup
captureSemaphore = false; // Disable catch mode because the screen is about to change
openPopup();              // Open the popup

// Elsewhere

closePopup();            // Close the popup
captureSemaphore = true; // Go into catch mode