Adopt the page overlay based on `[aria-hidden]`
authorAlexander Ebert <ebert@woltlab.com>
Mon, 6 Nov 2023 17:38:09 +0000 (18:38 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 6 Nov 2023 17:38:09 +0000 (18:38 +0100)
The page overlay must be adopted if there is at least one dialog open and must be released again when the last dialog closed. The previous implementation did not work flawlessly if dialogs were stacked and toggled in arbitrary order.

The mutation observer solves the issue because we do not keep track of the number of open dialogs but only if the overlay is visible at all.

See https://www.woltlab.com/community/thread/302088-sporadisch-auftredende-fehlerhafter-verlinkungsmodus-im-editor/

ts/WoltLabSuite/Core/Ui/Dialog.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Dialog.js

index 3c265d68552f0982368ae0724bf59e403cb3ccd8..c65f04ac591f58f0e9f7f949715199dc421177bf 100644 (file)
@@ -62,6 +62,27 @@ const UiDialog = {
       { passive: false },
     );
 
+    const observer = new MutationObserver((mutations) => {
+      const currentValue = _container.getAttribute("aria-hidden");
+
+      for (const mutation of mutations) {
+        if (mutation.oldValue === currentValue) {
+          continue;
+        }
+
+        if (currentValue === "false") {
+          adoptPageOverlayContainer(_container);
+        } else {
+          releasePageOverlayContainer(_container);
+        }
+      }
+    });
+    observer.observe(_container, {
+      attributes: true,
+      attributeFilter: ["aria-hidden"],
+      attributeOldValue: true,
+    });
+
     document.getElementById("content")!.appendChild(_container);
 
     _keyupListener = (event: KeyboardEvent): boolean => {
@@ -286,8 +307,6 @@ const UiDialog = {
       }, 200);
     }
 
-    adoptPageOverlayContainer(_container);
-
     return data;
   },
 
@@ -816,7 +835,6 @@ const UiDialog = {
       }
     }
 
-    releasePageOverlayContainer(_container);
     UiScreen.pageOverlayClose();
 
     if (_activeDialog === null) {
index 5320f5b9aeaa7a27fb09bc12b00c4156812bb6a9..3125c9817f5cb1caf0a88e8ca952bea5922005ef 100644 (file)
@@ -44,6 +44,25 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
                     event.preventDefault();
                 }
             }, { passive: false });
+            const observer = new MutationObserver((mutations) => {
+                const currentValue = _container.getAttribute("aria-hidden");
+                for (const mutation of mutations) {
+                    if (mutation.oldValue === currentValue) {
+                        continue;
+                    }
+                    if (currentValue === "false") {
+                        (0, PageOverlay_1.adoptPageOverlayContainer)(_container);
+                    }
+                    else {
+                        (0, PageOverlay_1.releasePageOverlayContainer)(_container);
+                    }
+                }
+            });
+            observer.observe(_container, {
+                attributes: true,
+                attributeFilter: ["aria-hidden"],
+                attributeOldValue: true,
+            });
             document.getElementById("content").appendChild(_container);
             _keyupListener = (event) => {
                 if (event.key === "Escape") {
@@ -234,7 +253,6 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
                     data.content.querySelector("input, textarea")?.focus();
                 }, 200);
             }
-            (0, PageOverlay_1.adoptPageOverlayContainer)(_container);
             return data;
         },
         /**
@@ -671,7 +689,6 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
                     break;
                 }
             }
-            (0, PageOverlay_1.releasePageOverlayContainer)(_container);
             UiScreen.pageOverlayClose();
             if (_activeDialog === null) {
                 _container.setAttribute("aria-hidden", "true");