Merged the search handling into a single module
authorAlexander Ebert <ebert@woltlab.com>
Fri, 31 Dec 2021 17:14:55 +0000 (18:14 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 31 Dec 2021 17:14:55 +0000 (18:14 +0100)
It was previously split between the `Ui/Page/Header/Fixed` and `Ui/Mobile` module. This commit only merges the two with purely compatibility related changes.

ts/WoltLabSuite/Core/Bootstrap.ts
ts/WoltLabSuite/Core/Ui/Mobile.ts
ts/WoltLabSuite/Core/Ui/Search.ts [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Search.js [new file with mode: 0644]

index c889aeec0cc6bbd5319afedd90dc571e6d9268d9..5d5c7d7b486869c4b3afcabe20ec62e7d3a9d6a0 100644 (file)
@@ -30,6 +30,7 @@ import * as UiEmpty from "./Ui/Empty";
 import * as UiObjectAction from "./Ui/Object/Action";
 import * as UiObjectActionDelete from "./Ui/Object/Action/Delete";
 import * as UiObjectActionToggle from "./Ui/Object/Action/Toggle";
+import { init as initSearch } from "./Ui/Search";
 
 // perfectScrollbar does not need to be bound anywhere, it just has to be loaded for WCF.js
 import "perfect-scrollbar";
@@ -101,6 +102,7 @@ export function setup(options: BoostrapOptions): void {
   UiObjectAction.setup();
   UiObjectActionDelete.setup();
   UiObjectActionToggle.setup();
+  initSearch();
 
   // Convert forms with `method="get"` into `method="post"`
   document.querySelectorAll("form[method=get]").forEach((form: HTMLFormElement) => {
index ec04d873463cb1a1263654a4df74e968aa027974..4d881acb17622cda6a9cc5942d347f110f1c5c71 100644 (file)
@@ -11,15 +11,13 @@ import * as Core from "../Core";
 import DomChangeListener from "../Dom/Change/Listener";
 import * as Environment from "../Environment";
 import * as UiAlignment from "./Alignment";
-import UiCloseOverlay, { Origin } from "./CloseOverlay";
+import UiCloseOverlay from "./CloseOverlay";
 import * as UiDropdownReusable from "./Dropdown/Reusable";
-import { closeSearchBar, openSearchBar } from "./Page/Header/Fixed";
 import { PageMenuMain } from "./Page/Menu/Main";
 import { PageMenuMainProvider } from "./Page/Menu/Main/Provider";
 import { hasValidUserMenu, PageMenuUser } from "./Page/Menu/User";
 import * as UiScreen from "./Screen";
 
-const _isAcp = document.body.classList.contains("wcfAcp");
 let _dropdownMenu: HTMLUListElement | null = null;
 let _dropdownMenuMessage: HTMLElement | null = null;
 let _enabled = false;
@@ -36,7 +34,6 @@ const _sidebars: HTMLElement[] = [];
 function init(): void {
   _enabled = true;
 
-  initSearchButton();
   initButtonGroupNavigation();
   initMessages();
   initMobileMenu();
@@ -48,92 +45,6 @@ function init(): void {
   });
 }
 
-function initSearchButton(): void {
-  const searchBar = document.getElementById("pageHeaderSearch")!;
-  const searchInput = document.getElementById("pageHeaderSearchInput")!;
-
-  // The search bar is unavailable during WCFSetup or the login.
-  if (_isAcp && searchBar === null) {
-    return;
-  }
-
-  let scrollTop: number | null = null;
-  const searchButton = document.getElementById("pageHeaderSearchMobile")!;
-  searchButton.addEventListener("click", (event) => {
-    event.preventDefault();
-    event.stopPropagation();
-
-    if (searchButton.getAttribute("aria-expanded") === "true") {
-      closeSearch(searchBar, scrollTop);
-      closeSearchBar();
-
-      searchButton.setAttribute("aria-expanded", "false");
-    } else {
-      if (Environment.platform() === "ios") {
-        scrollTop = document.body.scrollTop;
-        UiScreen.scrollDisable();
-      }
-
-      openSearchBar();
-
-      const pageHeader = document.getElementById("pageHeader")!;
-      searchBar.style.setProperty("top", `${pageHeader.offsetHeight}px`, "");
-      searchBar.classList.add("open");
-      searchInput.focus();
-
-      if (Environment.platform() === "ios") {
-        document.body.scrollTop = 0;
-      }
-
-      searchButton.setAttribute("aria-expanded", "true");
-    }
-  });
-
-  searchBar.addEventListener("click", (event) => {
-    event.stopPropagation();
-
-    if (event.target === searchBar) {
-      event.preventDefault();
-
-      closeSearch(searchBar, scrollTop);
-      closeSearchBar();
-
-      searchButton.setAttribute("aria-expanded", "false");
-    }
-  });
-
-  UiCloseOverlay.add("WoltLabSuite/Core/Ui/MobileSearch", (origin, identifier) => {
-    if (!_isAcp && origin === Origin.DropDown) {
-      const button = document.getElementById("pageHeaderSearchTypeSelect")!;
-      if (button.dataset.target === identifier) {
-        return;
-      }
-    }
-
-    closeSearch(searchBar, scrollTop);
-    if (!_isAcp) {
-      closeSearchBar();
-    }
-
-    searchButton.setAttribute("aria-expanded", "false");
-  });
-}
-
-function closeSearch(searchBar: HTMLElement, scrollTop: number | null): void {
-  if (searchBar) {
-    searchBar.classList.remove("open");
-  }
-
-  if (Environment.platform() === "ios") {
-    UiScreen.scrollEnable();
-
-    if (scrollTop !== null) {
-      document.body.scrollTop = scrollTop;
-      scrollTop = null;
-    }
-  }
-}
-
 function initButtonGroupNavigation(): void {
   document.querySelectorAll(".buttonGroupNavigation").forEach((navigation) => {
     if (navigation.classList.contains("jsMobileButtonGroupNavigation")) {
diff --git a/ts/WoltLabSuite/Core/Ui/Search.ts b/ts/WoltLabSuite/Core/Ui/Search.ts
new file mode 100644 (file)
index 0000000..2426862
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * Manages the sticky page header.
+ *
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Ui/Page/Header/Fixed
+ */
+
+import * as EventHandler from "../Event/Handler";
+import * as UiAlignment from "./Alignment";
+import UiCloseOverlay, { Origin } from "./CloseOverlay";
+import UiDropdownSimple from "./Dropdown/Simple";
+import * as UiScreen from "./Screen";
+import * as Environment from "../Environment";
+
+let _isMobile = false;
+
+const _isAcp = document.body.classList.contains("wcfAcp");
+const _pageHeader = document.getElementById("pageHeader")!;
+const _pageHeaderPanel = document.getElementById("pageHeaderPanel")!;
+const _pageHeaderSearch = document.getElementById("pageHeaderSearch")!;
+const _pageHeaderSearchInput = document.getElementById("pageHeaderSearchInput") as HTMLInputElement;
+const _topMenu = document.getElementById("topMenu")!;
+const _userPanelSearchButton = document.getElementById("userPanelSearchButton");
+
+/**
+ * Provides the collapsible search bar.
+ */
+function initSearchBar(): void {
+  _pageHeaderSearch.addEventListener("click", (event) => event.stopPropagation());
+
+  _userPanelSearchButton?.addEventListener("click", (event) => {
+    event.preventDefault();
+    event.stopPropagation();
+
+    if (_pageHeader.classList.contains("searchBarOpen")) {
+      closeSearchBar();
+    } else {
+      openSearchBar();
+    }
+  });
+
+  UiCloseOverlay.add("WoltLabSuite/Core/Ui/Search", (origin, identifier) => {
+    if (origin === Origin.DropDown) {
+      const button = document.getElementById("pageHeaderSearchTypeSelect");
+      if (button && button.dataset.target === identifier) {
+        return;
+      }
+    }
+
+    if (_pageHeader.classList.contains("searchBarForceOpen")) {
+      return;
+    }
+
+    closeSearchBar();
+  });
+}
+
+function initSearchButton(): void {
+  let scrollTop: number | null = null;
+  const searchButton = document.getElementById("pageHeaderSearchMobile")!;
+  searchButton.addEventListener("click", (event) => {
+    event.preventDefault();
+    event.stopPropagation();
+
+    if (searchButton.getAttribute("aria-expanded") === "true") {
+      closeSearch(_pageHeaderSearch, scrollTop);
+      closeSearchBar();
+
+      searchButton.setAttribute("aria-expanded", "false");
+    } else {
+      if (Environment.platform() === "ios") {
+        scrollTop = document.body.scrollTop;
+        UiScreen.scrollDisable();
+      }
+
+      openSearchBar();
+
+      const pageHeader = document.getElementById("pageHeader")!;
+      _pageHeaderSearch.style.setProperty("top", `${pageHeader.offsetHeight}px`, "");
+      _pageHeaderSearch.classList.add("open");
+      _pageHeaderSearchInput.focus();
+
+      if (Environment.platform() === "ios") {
+        document.body.scrollTop = 0;
+      }
+
+      searchButton.setAttribute("aria-expanded", "true");
+    }
+  });
+
+  _pageHeaderSearch.addEventListener("click", (event) => {
+    event.stopPropagation();
+
+    if (event.target === _pageHeaderSearch) {
+      event.preventDefault();
+
+      closeSearch(_pageHeaderSearch, scrollTop);
+      closeSearchBar();
+
+      searchButton.setAttribute("aria-expanded", "false");
+    }
+  });
+
+  UiCloseOverlay.add("WoltLabSuite/Core/Ui/MobileSearch", (origin, identifier) => {
+    if (!_isAcp && origin === Origin.DropDown) {
+      const button = document.getElementById("pageHeaderSearchTypeSelect")!;
+      if (button.dataset.target === identifier) {
+        return;
+      }
+    }
+
+    closeSearch(_pageHeaderSearch, scrollTop);
+    if (!_isAcp) {
+      closeSearchBar();
+    }
+
+    searchButton.setAttribute("aria-expanded", "false");
+  });
+}
+
+function closeSearch(searchBar: HTMLElement, scrollTop: number | null): void {
+  if (searchBar) {
+    searchBar.classList.remove("open");
+  }
+
+  if (Environment.platform() === "ios") {
+    UiScreen.scrollEnable();
+
+    if (scrollTop !== null) {
+      document.body.scrollTop = scrollTop;
+      scrollTop = null;
+    }
+  }
+}
+
+function openSearchBar(): void {
+  UiCloseOverlay.execute();
+
+  _pageHeader.classList.add("searchBarOpen");
+  _userPanelSearchButton?.parentElement!.classList.add("open");
+
+  if (!_isMobile) {
+    // calculate value for `right` on desktop
+    UiAlignment.set(_pageHeaderSearch, _topMenu, {
+      horizontal: "right",
+    });
+  }
+
+  _pageHeaderSearch.style.setProperty("top", `${_pageHeaderPanel.clientHeight}px`, "");
+  _pageHeaderSearchInput.focus();
+
+  window.setTimeout(() => {
+    _pageHeaderSearchInput.selectionStart = _pageHeaderSearchInput.selectionEnd = _pageHeaderSearchInput.value.length;
+  }, 1);
+}
+
+function closeSearchBar(): void {
+  _pageHeader.classList.remove("searchBarOpen");
+  _userPanelSearchButton?.parentElement!.classList.remove("open");
+
+  ["bottom", "left", "right", "top"].forEach((propertyName) => {
+    _pageHeaderSearch.style.removeProperty(propertyName);
+  });
+
+  _pageHeaderSearchInput.blur();
+
+  // close the scope selection
+  const scope = _pageHeaderSearch.querySelector(".pageHeaderSearchType")!;
+  UiDropdownSimple.close(scope.id);
+}
+
+/**
+ * Initializes the sticky page header handler.
+ */
+export function init(): void {
+  // The search bar is unavailable during WCFSetup or the login.
+  if (_isAcp && _pageHeaderSearch === null) {
+    return;
+  }
+
+  initSearchBar();
+  initSearchButton();
+
+  UiScreen.on("screen-md-down", {
+    match() {
+      _isMobile = true;
+    },
+    unmatch() {
+      _isMobile = false;
+    },
+    setup() {
+      _isMobile = true;
+    },
+  });
+
+  EventHandler.add("com.woltlab.wcf.Search", "close", closeSearchBar);
+}
index fe08e20d4872a9e0215318f6674b37a9b96fafd0..5c7775345c96e60f7aa466f3287d6dd9b5bf7f54 100644 (file)
@@ -8,7 +8,7 @@
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @module  WoltLabSuite/Core/Bootstrap
  */
-define(["require", "exports", "tslib", "./Core", "./Date/Picker", "./Date/Time/Relative", "./Devtools", "./Dom/Change/Listener", "./Environment", "./Event/Handler", "./Language", "./StringUtil", "./Ui/Dialog", "./Ui/Dropdown/Simple", "./Ui/Mobile", "./Ui/Page/Action", "./Ui/TabMenu", "./Ui/Tooltip", "./Ui/Page/JumpTo", "./Ui/Password", "./Ui/Empty", "./Ui/Object/Action", "./Ui/Object/Action/Delete", "./Ui/Object/Action/Toggle", "perfect-scrollbar"], function (require, exports, tslib_1, Core, Picker_1, DateTimeRelative, Devtools_1, Listener_1, Environment, EventHandler, Language, StringUtil, Dialog_1, Simple_1, UiMobile, UiPageAction, UiTabMenu, UiTooltip, UiPageJumpTo, UiPassword, UiEmpty, UiObjectAction, UiObjectActionDelete, UiObjectActionToggle) {
+define(["require", "exports", "tslib", "./Core", "./Date/Picker", "./Date/Time/Relative", "./Devtools", "./Dom/Change/Listener", "./Environment", "./Event/Handler", "./Language", "./StringUtil", "./Ui/Dialog", "./Ui/Dropdown/Simple", "./Ui/Mobile", "./Ui/Page/Action", "./Ui/TabMenu", "./Ui/Tooltip", "./Ui/Page/JumpTo", "./Ui/Password", "./Ui/Empty", "./Ui/Object/Action", "./Ui/Object/Action/Delete", "./Ui/Object/Action/Toggle", "./Ui/Search", "perfect-scrollbar"], function (require, exports, tslib_1, Core, Picker_1, DateTimeRelative, Devtools_1, Listener_1, Environment, EventHandler, Language, StringUtil, Dialog_1, Simple_1, UiMobile, UiPageAction, UiTabMenu, UiTooltip, UiPageJumpTo, UiPassword, UiEmpty, UiObjectAction, UiObjectActionDelete, UiObjectActionToggle, Search_1) {
     "use strict";
     Object.defineProperty(exports, "__esModule", { value: true });
     exports.setup = void 0;
@@ -85,6 +85,7 @@ define(["require", "exports", "tslib", "./Core", "./Date/Picker", "./Date/Time/R
         UiObjectAction.setup();
         UiObjectActionDelete.setup();
         UiObjectActionToggle.setup();
+        (0, Search_1.init)();
         // Convert forms with `method="get"` into `method="post"`
         document.querySelectorAll("form[method=get]").forEach((form) => {
             form.method = "post";
index 2fce71ff8d91ea1f5a73c3bdf24b7aac6944bc52..956570bd027368fff8d3a94c073004802e1feec6 100644 (file)
@@ -6,7 +6,7 @@
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @module  WoltLabSuite/Core/Ui/Mobile
  */
-define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../Environment", "./Alignment", "./CloseOverlay", "./Dropdown/Reusable", "./Page/Header/Fixed", "./Page/Menu/Main", "./Page/Menu/User", "./Screen"], function (require, exports, tslib_1, Core, Listener_1, Environment, UiAlignment, CloseOverlay_1, UiDropdownReusable, Fixed_1, Main_1, User_1, UiScreen) {
+define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../Environment", "./Alignment", "./CloseOverlay", "./Dropdown/Reusable", "./Page/Menu/Main", "./Page/Menu/User", "./Screen"], function (require, exports, tslib_1, Core, Listener_1, Environment, UiAlignment, CloseOverlay_1, UiDropdownReusable, Main_1, User_1, UiScreen) {
     "use strict";
     Object.defineProperty(exports, "__esModule", { value: true });
     exports.removeShadow = exports.rebuildShadow = exports.disableShadow = exports.disable = exports.enableShadow = exports.enable = exports.setup = void 0;
@@ -14,10 +14,9 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../
     Listener_1 = (0, tslib_1.__importDefault)(Listener_1);
     Environment = (0, tslib_1.__importStar)(Environment);
     UiAlignment = (0, tslib_1.__importStar)(UiAlignment);
-    CloseOverlay_1 = (0, tslib_1.__importStar)(CloseOverlay_1);
+    CloseOverlay_1 = (0, tslib_1.__importDefault)(CloseOverlay_1);
     UiDropdownReusable = (0, tslib_1.__importStar)(UiDropdownReusable);
     UiScreen = (0, tslib_1.__importStar)(UiScreen);
-    const _isAcp = document.body.classList.contains("wcfAcp");
     let _dropdownMenu = null;
     let _dropdownMenuMessage = null;
     let _enabled = false;
@@ -32,7 +31,6 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../
     const _sidebars = [];
     function init() {
         _enabled = true;
-        initSearchButton();
         initButtonGroupNavigation();
         initMessages();
         initMobileMenu();
@@ -42,74 +40,6 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../
             initMessages();
         });
     }
-    function initSearchButton() {
-        const searchBar = document.getElementById("pageHeaderSearch");
-        const searchInput = document.getElementById("pageHeaderSearchInput");
-        // The search bar is unavailable during WCFSetup or the login.
-        if (_isAcp && searchBar === null) {
-            return;
-        }
-        let scrollTop = null;
-        const searchButton = document.getElementById("pageHeaderSearchMobile");
-        searchButton.addEventListener("click", (event) => {
-            event.preventDefault();
-            event.stopPropagation();
-            if (searchButton.getAttribute("aria-expanded") === "true") {
-                closeSearch(searchBar, scrollTop);
-                (0, Fixed_1.closeSearchBar)();
-                searchButton.setAttribute("aria-expanded", "false");
-            }
-            else {
-                if (Environment.platform() === "ios") {
-                    scrollTop = document.body.scrollTop;
-                    UiScreen.scrollDisable();
-                }
-                (0, Fixed_1.openSearchBar)();
-                const pageHeader = document.getElementById("pageHeader");
-                searchBar.style.setProperty("top", `${pageHeader.offsetHeight}px`, "");
-                searchBar.classList.add("open");
-                searchInput.focus();
-                if (Environment.platform() === "ios") {
-                    document.body.scrollTop = 0;
-                }
-                searchButton.setAttribute("aria-expanded", "true");
-            }
-        });
-        searchBar.addEventListener("click", (event) => {
-            event.stopPropagation();
-            if (event.target === searchBar) {
-                event.preventDefault();
-                closeSearch(searchBar, scrollTop);
-                (0, Fixed_1.closeSearchBar)();
-                searchButton.setAttribute("aria-expanded", "false");
-            }
-        });
-        CloseOverlay_1.default.add("WoltLabSuite/Core/Ui/MobileSearch", (origin, identifier) => {
-            if (!_isAcp && origin === CloseOverlay_1.Origin.DropDown) {
-                const button = document.getElementById("pageHeaderSearchTypeSelect");
-                if (button.dataset.target === identifier) {
-                    return;
-                }
-            }
-            closeSearch(searchBar, scrollTop);
-            if (!_isAcp) {
-                (0, Fixed_1.closeSearchBar)();
-            }
-            searchButton.setAttribute("aria-expanded", "false");
-        });
-    }
-    function closeSearch(searchBar, scrollTop) {
-        if (searchBar) {
-            searchBar.classList.remove("open");
-        }
-        if (Environment.platform() === "ios") {
-            UiScreen.scrollEnable();
-            if (scrollTop !== null) {
-                document.body.scrollTop = scrollTop;
-                scrollTop = null;
-            }
-        }
-    }
     function initButtonGroupNavigation() {
         document.querySelectorAll(".buttonGroupNavigation").forEach((navigation) => {
             if (navigation.classList.contains("jsMobileButtonGroupNavigation")) {
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Search.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Search.js
new file mode 100644 (file)
index 0000000..96e4a7e
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * Manages the sticky page header.
+ *
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Ui/Page/Header/Fixed
+ */
+define(["require", "exports", "tslib", "../Event/Handler", "./Alignment", "./CloseOverlay", "./Dropdown/Simple", "./Screen", "../Environment"], function (require, exports, tslib_1, EventHandler, UiAlignment, CloseOverlay_1, Simple_1, UiScreen, Environment) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.init = void 0;
+    EventHandler = (0, tslib_1.__importStar)(EventHandler);
+    UiAlignment = (0, tslib_1.__importStar)(UiAlignment);
+    CloseOverlay_1 = (0, tslib_1.__importStar)(CloseOverlay_1);
+    Simple_1 = (0, tslib_1.__importDefault)(Simple_1);
+    UiScreen = (0, tslib_1.__importStar)(UiScreen);
+    Environment = (0, tslib_1.__importStar)(Environment);
+    let _isMobile = false;
+    const _isAcp = document.body.classList.contains("wcfAcp");
+    const _pageHeader = document.getElementById("pageHeader");
+    const _pageHeaderPanel = document.getElementById("pageHeaderPanel");
+    const _pageHeaderSearch = document.getElementById("pageHeaderSearch");
+    const _pageHeaderSearchInput = document.getElementById("pageHeaderSearchInput");
+    const _topMenu = document.getElementById("topMenu");
+    const _userPanelSearchButton = document.getElementById("userPanelSearchButton");
+    /**
+     * Provides the collapsible search bar.
+     */
+    function initSearchBar() {
+        _pageHeaderSearch.addEventListener("click", (event) => event.stopPropagation());
+        _userPanelSearchButton === null || _userPanelSearchButton === void 0 ? void 0 : _userPanelSearchButton.addEventListener("click", (event) => {
+            event.preventDefault();
+            event.stopPropagation();
+            if (_pageHeader.classList.contains("searchBarOpen")) {
+                closeSearchBar();
+            }
+            else {
+                openSearchBar();
+            }
+        });
+        CloseOverlay_1.default.add("WoltLabSuite/Core/Ui/Search", (origin, identifier) => {
+            if (origin === CloseOverlay_1.Origin.DropDown) {
+                const button = document.getElementById("pageHeaderSearchTypeSelect");
+                if (button && button.dataset.target === identifier) {
+                    return;
+                }
+            }
+            if (_pageHeader.classList.contains("searchBarForceOpen")) {
+                return;
+            }
+            closeSearchBar();
+        });
+    }
+    function initSearchButton() {
+        let scrollTop = null;
+        const searchButton = document.getElementById("pageHeaderSearchMobile");
+        searchButton.addEventListener("click", (event) => {
+            event.preventDefault();
+            event.stopPropagation();
+            if (searchButton.getAttribute("aria-expanded") === "true") {
+                closeSearch(_pageHeaderSearch, scrollTop);
+                closeSearchBar();
+                searchButton.setAttribute("aria-expanded", "false");
+            }
+            else {
+                if (Environment.platform() === "ios") {
+                    scrollTop = document.body.scrollTop;
+                    UiScreen.scrollDisable();
+                }
+                openSearchBar();
+                const pageHeader = document.getElementById("pageHeader");
+                _pageHeaderSearch.style.setProperty("top", `${pageHeader.offsetHeight}px`, "");
+                _pageHeaderSearch.classList.add("open");
+                _pageHeaderSearchInput.focus();
+                if (Environment.platform() === "ios") {
+                    document.body.scrollTop = 0;
+                }
+                searchButton.setAttribute("aria-expanded", "true");
+            }
+        });
+        _pageHeaderSearch.addEventListener("click", (event) => {
+            event.stopPropagation();
+            if (event.target === _pageHeaderSearch) {
+                event.preventDefault();
+                closeSearch(_pageHeaderSearch, scrollTop);
+                closeSearchBar();
+                searchButton.setAttribute("aria-expanded", "false");
+            }
+        });
+        CloseOverlay_1.default.add("WoltLabSuite/Core/Ui/MobileSearch", (origin, identifier) => {
+            if (!_isAcp && origin === CloseOverlay_1.Origin.DropDown) {
+                const button = document.getElementById("pageHeaderSearchTypeSelect");
+                if (button.dataset.target === identifier) {
+                    return;
+                }
+            }
+            closeSearch(_pageHeaderSearch, scrollTop);
+            if (!_isAcp) {
+                closeSearchBar();
+            }
+            searchButton.setAttribute("aria-expanded", "false");
+        });
+    }
+    function closeSearch(searchBar, scrollTop) {
+        if (searchBar) {
+            searchBar.classList.remove("open");
+        }
+        if (Environment.platform() === "ios") {
+            UiScreen.scrollEnable();
+            if (scrollTop !== null) {
+                document.body.scrollTop = scrollTop;
+                scrollTop = null;
+            }
+        }
+    }
+    function openSearchBar() {
+        CloseOverlay_1.default.execute();
+        _pageHeader.classList.add("searchBarOpen");
+        _userPanelSearchButton === null || _userPanelSearchButton === void 0 ? void 0 : _userPanelSearchButton.parentElement.classList.add("open");
+        if (!_isMobile) {
+            // calculate value for `right` on desktop
+            UiAlignment.set(_pageHeaderSearch, _topMenu, {
+                horizontal: "right",
+            });
+        }
+        _pageHeaderSearch.style.setProperty("top", `${_pageHeaderPanel.clientHeight}px`, "");
+        _pageHeaderSearchInput.focus();
+        window.setTimeout(() => {
+            _pageHeaderSearchInput.selectionStart = _pageHeaderSearchInput.selectionEnd = _pageHeaderSearchInput.value.length;
+        }, 1);
+    }
+    function closeSearchBar() {
+        _pageHeader.classList.remove("searchBarOpen");
+        _userPanelSearchButton === null || _userPanelSearchButton === void 0 ? void 0 : _userPanelSearchButton.parentElement.classList.remove("open");
+        ["bottom", "left", "right", "top"].forEach((propertyName) => {
+            _pageHeaderSearch.style.removeProperty(propertyName);
+        });
+        _pageHeaderSearchInput.blur();
+        // close the scope selection
+        const scope = _pageHeaderSearch.querySelector(".pageHeaderSearchType");
+        Simple_1.default.close(scope.id);
+    }
+    /**
+     * Initializes the sticky page header handler.
+     */
+    function init() {
+        // The search bar is unavailable during WCFSetup or the login.
+        if (_isAcp && _pageHeaderSearch === null) {
+            return;
+        }
+        initSearchBar();
+        initSearchButton();
+        UiScreen.on("screen-md-down", {
+            match() {
+                _isMobile = true;
+            },
+            unmatch() {
+                _isMobile = false;
+            },
+            setup() {
+                _isMobile = true;
+            },
+        });
+        EventHandler.add("com.woltlab.wcf.Search", "close", closeSearchBar);
+    }
+    exports.init = init;
+});