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

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

  • DEV: Don’t listen for deprecated events

Element: DOMMouseScroll event - Web APIs | MDN

Element: mousewheel event - Web APIs | MDN

  • 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

diff --git a/app/assets/javascripts/discourse/app/lib/lock-on.js b/app/assets/javascripts/discourse/app/lib/lock-on.js
index bdcddfc..57817b6 100644
--- a/app/assets/javascripts/discourse/app/lib/lock-on.js
+++ b/app/assets/javascripts/discourse/app/lib/lock-on.js
@@ -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);
   }
 }

GitHub sha: e66f95de

1 Like