Commit 507a3716 authored by Oliver Bartsch's avatar Oliver Bartsch Committed by Benni Mack
Browse files

[BUGFIX] Fix several issues regarding Recordlist search

Since #93892, clearing the search field did not longer
submit the form. This is now fixed by adding a dedicated
JS module, listening on the browsers "search" event.

When using the search in the Record selector, the search
options dropdown is now not longer cut off, in case no
search results are present.

Additionally, the functionality to toggle the search field
in the recordlist module is now moved into the Recordlist
JS module, as it does not belong to EXT:backend and
furthermore does not require a dedicated JS module.

Resolves: #94463
Resolves: #94557
Releases: master
Change-Id: I504a27fc6cb3d3689555169ac3e39813e2029544
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69830

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: default avatarGuido Schmechel <guido.schmechel@brandung.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 3b3321ba
......@@ -54,7 +54,7 @@ $elementbrowser-breakpoint: 600px;
}
.element-browser-body {
overflow: auto;
overflow: unset;
padding: ($grid-gutter-width / 2);
> *:first-child {
......
......@@ -11,29 +11,34 @@
* The TYPO3 project - inspiring people to share!
*/
import $ from 'jquery';
import DocumentService = require('TYPO3/CMS/Core/DocumentService');
import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent');
enum Selectors {
searchFieldSelector = '#search_field',
}
/**
* Module: TYPO3/CMS/Backend/ToggleSearchToolbox
* Toggle the search toolbox
* @exports TYPO3/CMS/Backend/ToggleSearchToolbox
* Module: TYPO3/CMS/Recordlist/RecordSearch
* Usability improvements for the record search
* @exports TYPO3/CMS/Recordlist/RecordSearch
*/
class ToggleSearchToolbox {
constructor() {
$((): void => {
this.initialize();
});
}
class RecordSearch {
private searchField: HTMLInputElement = document.querySelector(Selectors.searchFieldSelector);
private activeSearch: boolean = this.searchField ? (this.searchField.value !== '') : false;
private initialize(): void {
const $toolbar = $('#db_list-searchbox-toolbar');
$('.t3js-toggle-search-toolbox').on('click', (): void => {
$toolbar.toggle();
if ($toolbar.is(':visible')) {
$('#search_field').focus();
constructor() {
DocumentService.ready().then((): void => {
// Respond to browser related clearable event
if (this.searchField) {
new RegularEvent('search', (): void => {
if (this.searchField.value === '' && this.activeSearch) {
this.searchField.closest('form').submit();
}
}).bindTo(this.searchField);
}
});
}
}
export = new ToggleSearchToolbox();
export = new RecordSearch();
......@@ -27,6 +27,9 @@ interface RecordlistIdentifier {
entity: string;
toggle: string;
localize: string;
searchboxToolbar: string;
searchboxToggle: string;
searchField: string;
icons: IconIdentifier;
}
interface DataHandlerEventPayload {
......@@ -46,6 +49,9 @@ class Recordlist {
entity: '.t3js-entity',
toggle: '.t3js-toggle-recordlist',
localize: '.t3js-action-localize',
searchboxToolbar: '#db_list-searchbox-toolbar',
searchboxToggle: '.t3js-toggle-search-toolbox',
searchField: '#search_field',
icons: {
collapse: 'actions-view-list-collapse',
expand: 'actions-view-list-expand',
......@@ -57,6 +63,7 @@ class Recordlist {
$(document).on('click', this.identifier.toggle, this.toggleClick);
$(document).on('click', this.identifier.icons.editMultiple, this.onEditMultiple);
$(document).on('click', this.identifier.localize, this.disableButton);
$(document).on('click', this.identifier.searchboxToggle, this.toggleSearchbox);
DocumentService.ready().then((): void => {
Tooltip.initialize('.table-fit a[title]');
this.registerPaginationEvents();
......@@ -173,6 +180,14 @@ class Recordlist {
$me.prop('disable', true).addClass('disabled');
}
private toggleSearchbox = (): void => {
const toolbar: JQuery = $(this.identifier.searchboxToolbar);
toolbar.toggle();
if (toolbar.is(':visible')) {
$(this.identifier.searchField).focus();
}
};
private handleDataHandlerResult(e: CustomEvent): void {
const payload = e.detail.payload;
if (payload.hasErrors) {
......
......@@ -47,6 +47,7 @@ class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserIn
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tree/PageBrowser');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/RecordDownloadButton');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/ColumnSelectorButton');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/RecordSearch');
}
protected function initVariables()
......
......@@ -112,6 +112,7 @@ class RecordListController
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/RecordDownloadButton');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/ColumnSelectorButton');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/ClearCache');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/RecordSearch');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
$this->pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
......@@ -407,7 +408,6 @@ class RecordListController
->setSearchLevel($searchLevels)
->render($dblist->listURL('', '-1', 'pointer,search_field'));
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
$buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
$searchButton = $buttonBar->makeLinkButton();
$searchButton
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery"],(function(t,e,i){"use strict";i=__importDefault(i);return new class{constructor(){i.default(()=>{this.initialize()})}initialize(){const t=i.default("#db_list-searchbox-toolbar");i.default(".t3js-toggle-search-toolbox").on("click",()=>{t.toggle(),t.is(":visible")&&i.default("#search_field").focus()})}}}));
\ No newline at end of file
define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,r,i,s){"use strict";var t;!function(e){e.searchFieldSelector="#search_field"}(t||(t={}));return new class{constructor(){this.searchField=document.querySelector(t.searchFieldSelector),this.activeSearch=!!this.searchField&&""!==this.searchField.value,i.ready().then(()=>{this.searchField&&new s("search",()=>{""===this.searchField.value&&this.activeSearch&&this.searchField.closest("form").submit()}).bindTo(this.searchField)})}}}));
\ No newline at end of file
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","TYPO3/CMS/Backend/Icons","TYPO3/CMS/Backend/Storage/Persistent","TYPO3/CMS/Core/Event/RegularEvent","TYPO3/CMS/Backend/Tooltip","TYPO3/CMS/Core/DocumentService"],(function(t,e,a,i,n,l,s,d){"use strict";a=__importDefault(a);return new class{constructor(){this.identifier={entity:".t3js-entity",toggle:".t3js-toggle-recordlist",localize:".t3js-action-localize",icons:{collapse:"actions-view-list-collapse",expand:"actions-view-list-expand",editMultiple:".t3js-record-edit-multiple"}},this.toggleClick=t=>{t.preventDefault();const e=a.default(t.currentTarget),l=e.data("table"),s=a.default(e.data("bs-target")),d="expanded"===s.data("state"),r=e.find(".collapseIcon"),o=d?this.identifier.icons.expand:this.identifier.icons.collapse;i.getIcon(o,i.sizes.small).done(t=>{r.html(t)});let c={};n.isset("moduleData.list")&&(c=n.get("moduleData.list"));const u={};u[l]=d?1:0,a.default.extend(c,u),n.set("moduleData.list",c).done(()=>{s.data("state",d?"collapsed":"expanded")})},this.onEditMultiple=t=>{let e,i,n,l,s;t.preventDefault(),e=a.default(t.currentTarget).closest("[data-table]"),0!==e.length&&(l=a.default(t.currentTarget).data("uri"),i=e.data("table"),n=e.find(this.identifier.entity+'[data-uid][data-table="'+i+'"]').map((t,e)=>a.default(e).data("uid")).toArray().join(","),s=l.match(/{[^}]+}/g),a.default.each(s,(t,e)=>{const s=e.substr(1,e.length-2).split(":");let d;switch(s.shift()){case"entityIdentifiers":d=n;break;default:return}a.default.each(s,(t,e)=>{"editList"===e&&(d=this.editList(i,d))}),l=l.replace(e,d)}),window.location.href=l)},this.disableButton=t=>{a.default(t.currentTarget).prop("disable",!0).addClass("disabled")},this.deleteRow=t=>{const e=a.default(`table[data-table="${t.table}"]`),i=e.find(`tr[data-uid="${t.uid}"]`),n=e.closest(".panel"),l=n.find(".panel-heading"),s=e.find(`[data-l10nparent="${t.uid}"]`),d=a.default().add(i).add(s);if(d.fadeTo("slow",.4,()=>{d.slideUp("slow",()=>{d.remove(),0===e.find("tbody tr").length&&n.slideUp("slow")})}),"0"===i.data("l10nparent")||""===i.data("l10nparent")){const t=Number(l.find(".t3js-table-total-items").html());l.find(".t3js-table-total-items").text(t-1)}"pages"===t.table&&top.document.dispatchEvent(new CustomEvent("typo3:pagetree:refresh"))},this.registerPaginationEvents=()=>{document.querySelectorAll(".t3js-recordlist-paging").forEach(t=>{t.addEventListener("keyup",e=>{e.preventDefault();let a=parseInt(t.value,10);a<parseInt(t.min,10)&&(a=parseInt(t.min,10)),a>parseInt(t.max,10)&&(a=parseInt(t.max,10)),"Enter"===e.key&&a!==parseInt(t.dataset.currentpage,10)&&(window.location.href=t.dataset.currenturl+a.toString())})})},a.default(document).on("click",this.identifier.toggle,this.toggleClick),a.default(document).on("click",this.identifier.icons.editMultiple,this.onEditMultiple),a.default(document).on("click",this.identifier.localize,this.disableButton),d.ready().then(()=>{s.initialize(".table-fit a[title]"),this.registerPaginationEvents()}),new l("typo3:datahandler:process",this.handleDataHandlerResult.bind(this)).bindTo(document)}editList(t,e){const a=[];let i=0,n=e.indexOf(",");for(;-1!==n;)this.getCheckboxState(t+"|"+e.substr(i,n-i))&&a.push(e.substr(i,n-i)),i=n+1,n=e.indexOf(",",i);return this.getCheckboxState(t+"|"+e.substr(i))&&a.push(e.substr(i)),a.length>0?a.join(","):e}handleDataHandlerResult(t){const e=t.detail.payload;e.hasErrors||"datahandler"!==e.component&&"delete"===e.action&&this.deleteRow(e)}getCheckboxState(t){const e="CBC["+t+"]",a=document.querySelector('input[name="'+e+'"]');return null!==a&&a.checked}}}));
\ No newline at end of file
var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","TYPO3/CMS/Backend/Icons","TYPO3/CMS/Backend/Storage/Persistent","TYPO3/CMS/Core/Event/RegularEvent","TYPO3/CMS/Backend/Tooltip","TYPO3/CMS/Core/DocumentService"],(function(t,e,a,i,l,s,n,d){"use strict";a=__importDefault(a);return new class{constructor(){this.identifier={entity:".t3js-entity",toggle:".t3js-toggle-recordlist",localize:".t3js-action-localize",searchboxToolbar:"#db_list-searchbox-toolbar",searchboxToggle:".t3js-toggle-search-toolbox",searchField:"#search_field",icons:{collapse:"actions-view-list-collapse",expand:"actions-view-list-expand",editMultiple:".t3js-record-edit-multiple"}},this.toggleClick=t=>{t.preventDefault();const e=a.default(t.currentTarget),s=e.data("table"),n=a.default(e.data("bs-target")),d="expanded"===n.data("state"),o=e.find(".collapseIcon"),r=d?this.identifier.icons.expand:this.identifier.icons.collapse;i.getIcon(r,i.sizes.small).done(t=>{o.html(t)});let c={};l.isset("moduleData.list")&&(c=l.get("moduleData.list"));const u={};u[s]=d?1:0,a.default.extend(c,u),l.set("moduleData.list",c).done(()=>{n.data("state",d?"collapsed":"expanded")})},this.onEditMultiple=t=>{let e,i,l,s,n;t.preventDefault(),e=a.default(t.currentTarget).closest("[data-table]"),0!==e.length&&(s=a.default(t.currentTarget).data("uri"),i=e.data("table"),l=e.find(this.identifier.entity+'[data-uid][data-table="'+i+'"]').map((t,e)=>a.default(e).data("uid")).toArray().join(","),n=s.match(/{[^}]+}/g),a.default.each(n,(t,e)=>{const n=e.substr(1,e.length-2).split(":");let d;switch(n.shift()){case"entityIdentifiers":d=l;break;default:return}a.default.each(n,(t,e)=>{"editList"===e&&(d=this.editList(i,d))}),s=s.replace(e,d)}),window.location.href=s)},this.disableButton=t=>{a.default(t.currentTarget).prop("disable",!0).addClass("disabled")},this.toggleSearchbox=()=>{const t=a.default(this.identifier.searchboxToolbar);t.toggle(),t.is(":visible")&&a.default(this.identifier.searchField).focus()},this.deleteRow=t=>{const e=a.default(`table[data-table="${t.table}"]`),i=e.find(`tr[data-uid="${t.uid}"]`),l=e.closest(".panel"),s=l.find(".panel-heading"),n=e.find(`[data-l10nparent="${t.uid}"]`),d=a.default().add(i).add(n);if(d.fadeTo("slow",.4,()=>{d.slideUp("slow",()=>{d.remove(),0===e.find("tbody tr").length&&l.slideUp("slow")})}),"0"===i.data("l10nparent")||""===i.data("l10nparent")){const t=Number(s.find(".t3js-table-total-items").html());s.find(".t3js-table-total-items").text(t-1)}"pages"===t.table&&top.document.dispatchEvent(new CustomEvent("typo3:pagetree:refresh"))},this.registerPaginationEvents=()=>{document.querySelectorAll(".t3js-recordlist-paging").forEach(t=>{t.addEventListener("keyup",e=>{e.preventDefault();let a=parseInt(t.value,10);a<parseInt(t.min,10)&&(a=parseInt(t.min,10)),a>parseInt(t.max,10)&&(a=parseInt(t.max,10)),"Enter"===e.key&&a!==parseInt(t.dataset.currentpage,10)&&(window.location.href=t.dataset.currenturl+a.toString())})})},a.default(document).on("click",this.identifier.toggle,this.toggleClick),a.default(document).on("click",this.identifier.icons.editMultiple,this.onEditMultiple),a.default(document).on("click",this.identifier.localize,this.disableButton),a.default(document).on("click",this.identifier.searchboxToggle,this.toggleSearchbox),d.ready().then(()=>{n.initialize(".table-fit a[title]"),this.registerPaginationEvents()}),new s("typo3:datahandler:process",this.handleDataHandlerResult.bind(this)).bindTo(document)}editList(t,e){const a=[];let i=0,l=e.indexOf(",");for(;-1!==l;)this.getCheckboxState(t+"|"+e.substr(i,l-i))&&a.push(e.substr(i,l-i)),i=l+1,l=e.indexOf(",",i);return this.getCheckboxState(t+"|"+e.substr(i))&&a.push(e.substr(i)),a.length>0?a.join(","):e}handleDataHandlerResult(t){const e=t.detail.payload;e.hasErrors||"datahandler"!==e.component&&"delete"===e.action&&this.deleteRow(e)}getCheckboxState(t){const e="CBC["+t+"]",a=document.querySelector('input[name="'+e+'"]');return null!==a&&a.checked}}}));
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment