FIX: DEV: Lock-on improvements (#10448)

* DEV: Don't listen for deprecated events

https://developer.mozilla.org/en-US/docs/Web/API/Element/DOMMouseScroll_event

https://developer.mozilla.org/en-US/docs/Web/API/Element/mousewheel_event

* DEV: Listen only on the `body` element

* DEV: clearLock after a while if target is missing

* DEV: Bind the callback

* FIX: Use `requestAnimationFrame`

Prevents content jumps
This commit is contained in:
Jarek Radosz 2020-08-25 11:42:00 +02:00 committed by GitHub
parent 6c09fd4289
commit e66f95de3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 13 additions and 15 deletions

View File

@ -20,15 +20,8 @@ import { bind } from "discourse-common/utils/decorators";
// 2. give up on the scrollbar and implement it ourselves (something that will happen)
const LOCK_DURATION_MS = 1000;
const SCROLL_EVENTS = [
"scroll",
"touchmove",
"mousedown",
"wheel",
"DOMMouseScroll",
"mousewheel",
"keyup"
];
const LOCK_TIMEOUT_MS = 5000;
const SCROLL_EVENTS = ["scroll", "touchmove", "mousedown", "wheel", "keyup"];
const SCROLL_TYPES = ["mousedown", "mousewheel", "touchmove", "wheel"];
function within(threshold, x, y) {
@ -55,7 +48,7 @@ export default class LockOn {
clearLock() {
this._removeListener();
clearInterval(this.interval);
window.cancelAnimationFrame(this._requestId);
if (this.options.finished) {
this.options.finished();
@ -70,7 +63,7 @@ export default class LockOn {
window.scrollTo(window.pageXOffset, this.previousTop);
}
this.interval = setInterval(() => this._performLocking(), 50);
this._requestId = window.requestAnimationFrame(this._performLocking);
this._removeListener();
this._addListener();
@ -85,29 +78,32 @@ export default class LockOn {
_addListener() {
const body = document.querySelector("body");
const html = document.querySelector("html");
SCROLL_EVENTS.forEach(event => {
body.addEventListener(event, this._scrollListener);
html.addEventListener(event, this._scrollListener);
});
}
_removeListener() {
const body = document.querySelector("body");
const html = document.querySelector("html");
SCROLL_EVENTS.forEach(event => {
body.removeEventListener(event, this._scrollListener);
html.removeEventListener(event, this._scrollListener);
});
}
@bind
_performLocking() {
const elementTop = this.elementTop();
// If we can't find the element yet, wait a little bit more
if (!this.previousTop && !elementTop) {
// …but not too long
if (Date.now() - this.startedAt > LOCK_TIMEOUT_MS) {
this.clearLock();
}
this._requestId = window.requestAnimationFrame(this._performLocking);
return;
}
@ -129,5 +125,7 @@ export default class LockOn {
if (Date.now() - this.startedAt > LOCK_DURATION_MS) {
return this.clearLock();
}
this._requestId = window.requestAnimationFrame(this._performLocking);
}
}