[TASK] Align configuration module search bar
authorOliver Bartsch <bo@cedev.de>
Tue, 4 May 2021 20:43:46 +0000 (22:43 +0200)
committerDaniel Goerz <daniel.goerz@posteo.de>
Tue, 11 May 2021 16:57:03 +0000 (18:57 +0200)
As a follow up of #94042, the search bar in
the configuration module is now also aligned
with the rest of the backend. The regular
expression checkbox is therefore moved into
a dropdown, according to the recordlist.

Since browsers nowadays add their own clearable
functionality to type=search fields, it's sufficient
to just register an event for it. Especially because
initialization of our custom clearable functionality
would otherwise lead to duplicated clear icons.

Resolves: #94101
Releated: #94042
Releases: master
Change-Id: I019d1de724d87a9ab074aec062c39295d9e41670
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69023
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Build/Sources/TypeScript/lowlevel/Resources/Public/TypeScript/ConfigurationView.ts
typo3/sysext/core/Tests/Acceptance/Backend/ConfigurationModule/ConfigurationModuleProviderCest.php
typo3/sysext/lowlevel/Resources/Private/Templates/Backend/Configuration.html
typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js

index ff36025..1dd4f53 100644 (file)
  * The TYPO3 project - inspiring people to share!
  */
 
-import $ from 'jquery';
-import 'TYPO3/CMS/Backend/Input/Clearable';
+import DocumentService = require('TYPO3/CMS/Core/DocumentService');
+import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent');
 
 /**
  * Module: TYPO3/CMS/Lowlevel/ConfigurationView
  * JavaScript for Configuration View
  */
 class ConfigurationView {
-  private searchField: HTMLInputElement = document.querySelector('input[name="searchString"]');
+  private searchForm: HTMLFormElement = document.querySelector('#ConfigurationView');
+  private searchField: HTMLInputElement = this.searchForm.querySelector('input[name="searchString"]');
   private searchResultShown: boolean = ('' !== this.searchField.value);
 
   constructor() {
-    // make search field clearable
-    this.searchField.clearable({
-      onClear: (input: HTMLInputElement): void => {
-        if (this.searchResultShown) {
-          input.closest('form').submit();
+    DocumentService.ready().then((): void => {
+      // Respond to browser related clearable event
+      new RegularEvent('search', (): void => {
+        if (this.searchField.value === '' && this.searchResultShown) {
+          this.searchForm.submit();
         }
-      },
+      }).bindTo(this.searchField);
     });
+
     if (self.location.hash) {
       // scroll page down, so the just opened subtree is visible after reload and not hidden by doc header
       $('html, body').scrollTop((document.documentElement.scrollTop || document.body.scrollTop) - 80);
index 547ec73..eef02ec 100644 (file)
@@ -56,8 +56,10 @@ class ConfigurationModuleProviderCest
 
         // Tree search can be applied
         $I->fillField('#lowlevel-searchString', '\/authentication$');
+        $I->click('button.dropdown-toggle');
+        $I->waitForElementVisible('.dropdown-menu');
         $I->checkOption('#lowlevel-regexSearch');
-        $I->click('input#search');
+        $I->click('button[type=submit]');
 
         // Correct tree with search options present and active results is loaded
         $I->waitForElementVisible('#ConfigurationView');
index a474f02..63e5a53 100644 (file)
@@ -3,32 +3,55 @@
 
     <h2>{treeName}</h2>
 
-    <div id="lowlevel-config">
-        <div class="form-group">
-            <label for="lowlevel-searchString">
-                <f:translate key="enterSearchPhrase" />
-            </label>
-            <input class="form-control" type="search" id="lowlevel-searchString" name="searchString" value="{searchString}" />
-        </div>
-        <div class="form-group">
-            <div class="form-check">
-                <input type="hidden" name="regexSearch" value="0" />
-                <input
-                    type="checkbox"
-                    class="form-check-input"
-                    name="regexSearch"
-                    id="lowlevel-regexSearch"
-                    value="1"
-                    {f:if(condition:'{regexSearch}', then: ' checked')}
-                >
-                <label for="lowlevel-regexSearch" class="form-check-label">
-                    <f:translate key="useRegExp" />
+    <div id="lowlevel-config" class="row mb-3">
+        <div class="col-md-6">
+            <div class="input-group">
+                <button class="btn btn-default" type="submit" title="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')}">
+                    <core:icon identifier="actions-search" />
+                </button>
+
+                <label for="lowlevel-searchString" class="visually-hidden">
+                    <f:translate key="enterSearchPhrase"/>
                 </label>
+                <input class="form-control"
+                    type="search"
+                    id="lowlevel-searchString"
+                    name="searchString"
+                    value="{searchString}"
+                    placeholder="{f:translate(key: 'enterSearchPhrase')}"
+                />
+
+                <button class="btn btn-default dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"></button>
+                <div class="dropdown-menu" data-popper-placement="bottom-start">
+                    <div class="row g-3">
+                        <div class="col-12">
+                            <div class="form-check">
+                                <input type="hidden" name="regexSearch" value="0" />
+                                <input type="checkbox"
+                                    class="form-check-input"
+                                    name="regexSearch"
+                                    id="lowlevel-regexSearch"
+                                    value="1"
+                                    {f:if(condition:'{regexSearch}', then: ' checked')}
+                                />
+                                <label for="lowlevel-regexSearch" class="form-check-label">
+                                    <f:translate key="useRegExp" />
+                                </label>
+                            </div>
+                        </div>
+                        <div class="col-12">
+                            <div class="input-group justify-content-end">
+                                <button type="submit" class="text-right btn btn-default" title="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')}">
+                                    <core:icon identifier="actions-search" />
+                                    <f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search"/>
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
             </div>
         </div>
-        <div class="form-group">
-            <input class="btn btn-default" type="submit" name="search" id="search" value="{f:translate(key: 'search')}"/>
-        </div>
     </div>
 
     <div class="nowrap">
index b7e6722..4660883 100644 (file)
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Backend/Input/Clearable"],(function(e,t,r){"use strict";r=__importDefault(r);return new class{constructor(){this.searchField=document.querySelector('input[name="searchString"]'),this.searchResultShown=""!==this.searchField.value,this.searchField.clearable({onClear:e=>{this.searchResultShown&&e.closest("form").submit()}}),self.location.hash&&r.default("html, body").scrollTop((document.documentElement.scrollTop||document.body.scrollTop)-80)}}}));
\ No newline at end of file
+define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,r,t,s){"use strict";return new class{constructor(){this.searchForm=document.querySelector("#ConfigurationView"),this.searchField=this.searchForm.querySelector('input[name="searchString"]'),this.searchResultShown=""!==this.searchField.value,t.ready().then(()=>{new s("search",()=>{""===this.searchField.value&&this.searchResultShown&&this.searchForm.submit()}).bindTo(this.searchField)}),self.location.hash&&$("html, body").scrollTop((document.documentElement.scrollTop||document.body.scrollTop)-80)}}}));
\ No newline at end of file