Do not scroll the editor into the view if it is already (partially) visible
authorAlexander Ebert <ebert@woltlab.com>
Mon, 10 Jul 2023 11:51:13 +0000 (13:51 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 10 Jul 2023 11:51:13 +0000 (13:51 +0200)
See https://www.woltlab.com/community/thread/300513-durch-ein-im-editor-eingef%C3%BCgter-smiley-wird-die-seite-nach-oben-geschoben/

ts/WoltLabSuite/Core/Component/Ckeditor.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Ckeditor.js

index 9e5905230f09e5fda21799f78534556e81ebc413..f50c77852a81a559b94f310323752d778e47c8cb 100644 (file)
@@ -53,9 +53,26 @@ class Ckeditor {
   }
 
   focus(): void {
-    scrollToElement(this.#editor.ui.element!, () => {
+    // Check if the editor is (at least partially) in the viewport otherwise
+    // scroll to it before setting the focus.
+    const editorContainer = this.#editor.ui.element!;
+    const { bottom, top } = editorContainer.getBoundingClientRect();
+    const viewportHeight = window.innerHeight;
+
+    let isPartiallyVisible = false;
+    if (top > 0 && top < viewportHeight) {
+      isPartiallyVisible = true;
+    } else if (bottom > 0 && bottom < viewportHeight) {
+      isPartiallyVisible = true;
+    }
+
+    if (isPartiallyVisible) {
       this.#editor.editing.view.focus();
-    });
+    } else {
+      scrollToElement(editorContainer, () => {
+        this.#editor.editing.view.focus();
+      });
+    }
   }
 
   getHtml(): string {
index b4eade59ed658d3be80e50c9421e6c4a1dcd9373..51ed4e8c1ff3e22e268031a6105fdda5f6072f52 100644 (file)
@@ -34,9 +34,26 @@ define(["require", "exports", "tslib", "./Ckeditor/Attachment", "./Ckeditor/Medi
             }
         }
         focus() {
-            (0, Scroll_1.element)(this.#editor.ui.element, () => {
+            // Check if the editor is (at least partially) in the viewport otherwise
+            // scroll to it before setting the focus.
+            const editorContainer = this.#editor.ui.element;
+            const { bottom, top } = editorContainer.getBoundingClientRect();
+            const viewportHeight = window.innerHeight;
+            let isPartiallyVisible = false;
+            if (top > 0 && top < viewportHeight) {
+                isPartiallyVisible = true;
+            }
+            else if (bottom > 0 && bottom < viewportHeight) {
+                isPartiallyVisible = true;
+            }
+            if (isPartiallyVisible) {
                 this.#editor.editing.view.focus();
-            });
+            }
+            else {
+                (0, Scroll_1.element)(editorContainer, () => {
+                    this.#editor.editing.view.focus();
+                });
+            }
         }
         getHtml() {
             return this.#editor.data.get();