From e2d3dcb34442096ed7195fe33cb0124bac4b205d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 20 Dec 2021 11:54:52 +0100 Subject: [PATCH] Integrate the search bar into the mobile header --- ts/WoltLabSuite/Core/Ui/Mobile.ts | 62 +++++++++++++------ ts/WoltLabSuite/Core/Ui/Page/Header/Fixed.ts | 4 +- .../files/js/WoltLabSuite/Core/Ui/Mobile.js | 51 ++++++++++----- .../WoltLabSuite/Core/Ui/Page/Header/Fixed.js | 4 +- .../files/style/layout/pageHeader.scss | 6 ++ 5 files changed, 90 insertions(+), 37 deletions(-) diff --git a/ts/WoltLabSuite/Core/Ui/Mobile.ts b/ts/WoltLabSuite/Core/Ui/Mobile.ts index d366b0bb50..642dc7db03 100644 --- a/ts/WoltLabSuite/Core/Ui/Mobile.ts +++ b/ts/WoltLabSuite/Core/Ui/Mobile.ts @@ -10,19 +10,14 @@ import * as Core from "../Core"; import DomChangeListener from "../Dom/Change/Listener"; import * as Environment from "../Environment"; -import * as EventHandler from "../Event/Handler"; import * as UiAlignment from "./Alignment"; import UiCloseOverlay from "./CloseOverlay"; import * as UiDropdownReusable from "./Dropdown/Reusable"; +import { closeSearchBar, openSearchBar } from "./Page/Header/Fixed"; import { PageMenuMain } from "./Page/Menu/Main"; import { hasValidUserMenu, PageMenuUser } from "./Page/Menu/User"; import * as UiScreen from "./Screen"; -interface MainMenuMorePayload { - identifier: string; - handler: any; //UiPageMenuMain; -} - let _dropdownMenu: HTMLUListElement | null = null; let _dropdownMenuMessage: HTMLElement | null = null; let _enabled = false; @@ -38,7 +33,7 @@ const _sidebars: HTMLElement[] = []; function init(): void { _enabled = true; - initSearchBar(); + initSearchButton(); initButtonGroupNavigation(); initMessages(); initMobileMenu(); @@ -50,20 +45,29 @@ function init(): void { }); } -function initSearchBar(): void { +function initSearchButton(): void { const searchBar = document.getElementById("pageHeaderSearch")!; const searchInput = document.getElementById("pageHeaderSearchInput")!; let scrollTop: number | null = null; - EventHandler.add("com.woltlab.wcf.MainMenuMobile", "more", (data: MainMenuMorePayload) => { - if (data.identifier === "com.woltlab.wcf.search") { - data.handler.close(); + 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"); @@ -72,20 +76,40 @@ function initSearchBar(): void { if (Environment.platform() === "ios") { document.body.scrollTop = 0; } + + searchButton.setAttribute("aria-expanded", "true"); } }); - document.getElementById("main")!.addEventListener("click", () => { - if (searchBar) { - searchBar.classList.remove("open"); - } + searchBar.addEventListener("click", (event) => { + if (event.target === searchBar) { + event.preventDefault(); + + closeSearch(searchBar, scrollTop); + closeSearchBar(); - if (Environment.platform() === "ios" && scrollTop) { - UiScreen.scrollEnable(); - document.body.scrollTop = scrollTop; - scrollTop = null; + searchButton.setAttribute("aria-expanded", "false"); } }); + + UiCloseOverlay.add("WoltLabSuite/Core/Ui/MobileSearch", () => { + closeSearch(searchBar, scrollTop); + closeSearchBar(); + + searchButton.setAttribute("aria-expanded", "false"); + }); +} + +function closeSearch(searchBar: HTMLElement, scrollTop: number | null): void { + if (searchBar) { + searchBar.classList.remove("open"); + } + + if (Environment.platform() === "ios" && scrollTop) { + UiScreen.scrollEnable(); + document.body.scrollTop = scrollTop; + scrollTop = null; + } } function initButtonGroupNavigation(): void { diff --git a/ts/WoltLabSuite/Core/Ui/Page/Header/Fixed.ts b/ts/WoltLabSuite/Core/Ui/Page/Header/Fixed.ts index 69e36484be..1295f3396d 100644 --- a/ts/WoltLabSuite/Core/Ui/Page/Header/Fixed.ts +++ b/ts/WoltLabSuite/Core/Ui/Page/Header/Fixed.ts @@ -65,7 +65,7 @@ function initSearchBar(): void { /** * Opens the search bar. */ -function openSearchBar(): void { +export function openSearchBar(): void { UiCloseOverlay.execute(); _pageHeader.classList.add("searchBarOpen"); @@ -89,7 +89,7 @@ function openSearchBar(): void { /** * Closes the search bar. */ -function closeSearchBar(): void { +export function closeSearchBar(): void { _pageHeader.classList.remove("searchBarOpen"); _userPanelSearchButton.parentElement!.classList.remove("open"); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js index 7b6e0f7b84..32bb9478f5 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js @@ -6,14 +6,13 @@ * @license GNU Lesser General Public License * @module WoltLabSuite/Core/Ui/Mobile */ -define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../Environment", "../Event/Handler", "./Alignment", "./CloseOverlay", "./Dropdown/Reusable", "./Page/Menu/Main", "./Page/Menu/User", "./Screen"], function (require, exports, tslib_1, Core, Listener_1, Environment, EventHandler, UiAlignment, CloseOverlay_1, UiDropdownReusable, Main_1, User_1, UiScreen) { +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) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeShadow = exports.rebuildShadow = exports.disableShadow = exports.disable = exports.enableShadow = exports.enable = exports.setup = void 0; Core = (0, tslib_1.__importStar)(Core); Listener_1 = (0, tslib_1.__importDefault)(Listener_1); Environment = (0, tslib_1.__importStar)(Environment); - EventHandler = (0, tslib_1.__importStar)(EventHandler); UiAlignment = (0, tslib_1.__importStar)(UiAlignment); CloseOverlay_1 = (0, tslib_1.__importDefault)(CloseOverlay_1); UiDropdownReusable = (0, tslib_1.__importStar)(UiDropdownReusable); @@ -31,7 +30,7 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../ const _sidebars = []; function init() { _enabled = true; - initSearchBar(); + initSearchButton(); initButtonGroupNavigation(); initMessages(); initMobileMenu(); @@ -41,17 +40,25 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../ initMessages(); }); } - function initSearchBar() { + function initSearchButton() { const searchBar = document.getElementById("pageHeaderSearch"); const searchInput = document.getElementById("pageHeaderSearchInput"); let scrollTop = null; - EventHandler.add("com.woltlab.wcf.MainMenuMobile", "more", (data) => { - if (data.identifier === "com.woltlab.wcf.search") { - data.handler.close(); + 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"); @@ -59,18 +66,32 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "../ if (Environment.platform() === "ios") { document.body.scrollTop = 0; } + searchButton.setAttribute("aria-expanded", "true"); } }); - document.getElementById("main").addEventListener("click", () => { - if (searchBar) { - searchBar.classList.remove("open"); - } - if (Environment.platform() === "ios" && scrollTop) { - UiScreen.scrollEnable(); - document.body.scrollTop = scrollTop; - scrollTop = null; + searchBar.addEventListener("click", (event) => { + 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", () => { + closeSearch(searchBar, scrollTop); + (0, Fixed_1.closeSearchBar)(); + searchButton.setAttribute("aria-expanded", "false"); + }); + } + function closeSearch(searchBar, scrollTop) { + if (searchBar) { + searchBar.classList.remove("open"); + } + if (Environment.platform() === "ios" && scrollTop) { + UiScreen.scrollEnable(); + document.body.scrollTop = scrollTop; + scrollTop = null; + } } function initButtonGroupNavigation() { document.querySelectorAll(".buttonGroupNavigation").forEach((navigation) => { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Header/Fixed.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Header/Fixed.js index 53328fa3f3..b55cdeff55 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Header/Fixed.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Header/Fixed.js @@ -9,7 +9,7 @@ define(["require", "exports", "tslib", "../../../Event/Handler", "../../Alignment", "../../CloseOverlay", "../../Dropdown/Simple", "../../Screen"], function (require, exports, tslib_1, EventHandler, UiAlignment, CloseOverlay_1, Simple_1, UiScreen) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.init = void 0; + exports.init = exports.closeSearchBar = exports.openSearchBar = void 0; EventHandler = (0, tslib_1.__importStar)(EventHandler); UiAlignment = (0, tslib_1.__importStar)(UiAlignment); CloseOverlay_1 = (0, tslib_1.__importDefault)(CloseOverlay_1); @@ -74,6 +74,7 @@ define(["require", "exports", "tslib", "../../../Event/Handler", "../../Alignmen _searchInput.selectionStart = _searchInput.selectionEnd = _searchInput.value.length; }, 1); } + exports.openSearchBar = openSearchBar; /** * Closes the search bar. */ @@ -88,6 +89,7 @@ define(["require", "exports", "tslib", "../../../Event/Handler", "../../Alignmen const scope = _pageHeaderSearch.querySelector(".pageHeaderSearchType"); Simple_1.default.close(scope.id); } + exports.closeSearchBar = closeSearchBar; /** * Initializes the sticky page header handler. */ diff --git a/wcfsetup/install/files/style/layout/pageHeader.scss b/wcfsetup/install/files/style/layout/pageHeader.scss index e93616e174..e4ee20eec7 100644 --- a/wcfsetup/install/files/style/layout/pageHeader.scss +++ b/wcfsetup/install/files/style/layout/pageHeader.scss @@ -493,6 +493,10 @@ .pageHeaderSearchMobile { grid-area: search; + + &[aria-expanded="true"] .icon::before { + content: $fa-var-times; + } } .userPanel { @@ -562,6 +566,8 @@ } .pageHeaderSearch { + background-color: rgba(0, 0, 0, 0.34); + bottom: 0; left: 0 !important; right: 0 !important; -- 2.20.1