FIX: CLS jumpiness in post-stream when ?page=N (#25034)
With certain conditions, this issue does not show up. The easiest way to reproduce this is probably to do either of this - Use a 3G slow connection or; - Add a breakpoint to scrolling-post-stream.topRefresh (anon) - (and optionally lock-on.lock) This issue is happening because there are multiple areas that set scroll location in the post stream when loading a topic. In our case, sometimes lock-on is triggering and scrolling to post_1, before ?page=2's post_21 is being scrolled to, due to posts above post_21 can finishing loading at different times. This causes some calculations to not add up, as being in the middle of a post stream has different calculations than being at the top of the post stream.
This commit is contained in:
parent
bf3e121323
commit
12131c8e21
|
@ -181,10 +181,7 @@ export default MountWidget.extend({
|
||||||
const first = posts.objectAt(onscreen[0]);
|
const first = posts.objectAt(onscreen[0]);
|
||||||
if (this._topVisible !== first) {
|
if (this._topVisible !== first) {
|
||||||
this._topVisible = first;
|
this._topVisible = first;
|
||||||
const elem = postsNodes.item(onscreen[0]);
|
const elemId = postsNodes.item(onscreen[0]).id;
|
||||||
const elemId = elem.id;
|
|
||||||
const elemPos = domUtils.position(elem);
|
|
||||||
const distToElement = elemPos?.top || 0;
|
|
||||||
|
|
||||||
const topRefresh = () => {
|
const topRefresh = () => {
|
||||||
refresh(() => {
|
refresh(() => {
|
||||||
|
@ -194,16 +191,30 @@ export default MountWidget.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const position = domUtils.position(refreshedElem);
|
// The getOffsetTop function calculates the total offset distance of
|
||||||
const top = position.top - distToElement;
|
// an element from the top of the document. Unlike element.offsetTop
|
||||||
document.documentElement.scroll({ top, left: 0 });
|
// which only returns the offset relative to its nearest positioned
|
||||||
|
// ancestor, this function recursively accumulates the offsetTop
|
||||||
|
// of an element and all of its offset parents (ancestors).
|
||||||
|
// This ensures the total distance is measured from the very top of
|
||||||
|
// the document, accounting for any nested elements and their
|
||||||
|
// respective offsets.
|
||||||
|
const getOffsetTop = (element) => {
|
||||||
|
if (!element) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return element.offsetTop + getOffsetTop(element.offsetParent);
|
||||||
|
};
|
||||||
|
|
||||||
|
const top = getOffsetTop(refreshedElem) - offsetCalculator();
|
||||||
|
window.scrollTo({ top });
|
||||||
|
|
||||||
// This seems weird, but somewhat infrequently a rerender
|
// This seems weird, but somewhat infrequently a rerender
|
||||||
// will cause the browser to scroll to the top of the document
|
// will cause the browser to scroll to the top of the document
|
||||||
// in Chrome. This makes sure the scroll works correctly if that
|
// in Chrome. This makes sure the scroll works correctly if that
|
||||||
// happens.
|
// happens.
|
||||||
schedule("afterRender", () => {
|
schedule("afterRender", () => {
|
||||||
document.documentElement.scroll({ top, left: 0 });
|
window.scrollTo({ top });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue