From ff226c520eb59e4a144fd293b251f043f8a4f59e Mon Sep 17 00:00:00 2001 From: Andreas Fernandez <a.fernandez@scripting-base.de> Date: Mon, 13 Apr 2020 15:56:21 +0200 Subject: [PATCH] [TASK] Auto focus search field in "New Content Element" filter To improve the user experience, the search filter in the "New Content Element" wizard is automatically focussed when the modal appears. Resolves: #91014 Releases: master Change-Id: I3e0f18bd454955af63cd797138de7b2118d9d2ac Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64129 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Josef Glatz <josefglatz@gmail.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Josef Glatz <josefglatz@gmail.com> Reviewed-by: Benni Mack <benni@typo3.org> --- .../Public/TypeScript/NewContentElementWizard.ts | 4 ++++ .../Public/TypeScript/Wizard/NewContentElement.ts | 12 +++++++++++- .../Public/JavaScript/NewContentElementWizard.js | 2 +- .../Public/JavaScript/Wizard/NewContentElement.js | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/NewContentElementWizard.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/NewContentElementWizard.ts index 3d92e190c631..bd232d24341e 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/NewContentElementWizard.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/NewContentElementWizard.ts @@ -37,6 +37,10 @@ export default class NewContentElementWizard { this.registerEvents(); } + public focusSearchField(): void { + this.searchField.focus(); + } + private registerClearable(): void { this.searchField.clearable({ onClear: (input: HTMLInputElement): void => { diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Wizard/NewContentElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Wizard/NewContentElement.ts index 48728c483f89..b609a4591ca5 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Wizard/NewContentElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Wizard/NewContentElement.ts @@ -32,7 +32,17 @@ class NewContentElement { title, type: Modal.types.ajax, }).on('modal-loaded', (): void => { - new NewContentElementWizard($modal); + // This rather works in local environments only + $modal.on('shown.bs.modal', (): void => { + const wizard = new NewContentElementWizard($modal); + wizard.focusSearchField(); + }); + }).on('shown.bs.modal', (): void => { + // This is the common case with any latency that the modal is rendered before the content is loaded + $modal.on('modal-loaded', (): void => { + const wizard = new NewContentElementWizard($modal); + wizard.focusSearchField(); + }); }); } } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/NewContentElementWizard.js b/typo3/sysext/backend/Resources/Public/JavaScript/NewContentElementWizard.js index ecd755458e32..124579dd74f3 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/NewContentElementWizard.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/NewContentElementWizard.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -define(["require","exports","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Core/Event/RegularEvent","./Input/Clearable"],(function(e,t,s,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});class i{constructor(e){this.context=e.get(0),this.searchField=this.context.querySelector(".t3js-contentWizard-search"),this.registerClearable(),this.registerEvents()}static getTabIdentifier(e){const t=e.querySelector("a"),[,s]=t.href.split("#");return s}static countVisibleContentElements(e){return e.querySelectorAll(".media-new-content-element-wizard:not(.hidden)").length}registerClearable(){this.searchField.clearable({onClear:e=>{e.value="",this.filterElements(e)}})}registerEvents(){new n("keydown",e=>{const t=e.target;"Escape"===e.code&&(e.stopImmediatePropagation(),t.value="")}).bindTo(this.searchField),new s("keyup",e=>{this.filterElements(e.target)},150).bindTo(this.searchField),new n("submit",e=>{e.preventDefault()}).bindTo(this.searchField.closest("form")),new n("click",e=>{e.preventDefault(),e.stopPropagation()}).delegateTo(this.context,".t3js-tabs .disabled")}filterElements(e){const t=e.closest("form"),s=t.querySelector(".t3js-tabs"),n=t.querySelector(".t3js-filter-noresult");t.querySelectorAll(".media.media-new-content-element-wizard").forEach(t=>{const s=t.textContent.trim().replace(/\s+/g," ");t.classList.toggle("hidden",""!==e.value&&!RegExp(e.value,"i").test(s))});const r=i.countVisibleContentElements(t);s.parentElement.classList.toggle("hidden",0===r),n.classList.toggle("hidden",r>0),this.switchTabIfNecessary(s)}switchTabIfNecessary(e){const t=e.querySelector(".active"),s=Array.from(t.parentNode.children);for(let e of s){const t=i.getTabIdentifier(e);e.classList.toggle("disabled",!this.hasTabContent(t))}if(!this.hasTabContent(i.getTabIdentifier(t)))for(let n of s){if(n===t)continue;const s=i.getTabIdentifier(n);if(this.hasTabContent(s)){this.switchTab(e.parentElement,s);break}}}hasTabContent(e){const t=this.context.querySelector(`#${e}`);return i.countVisibleContentElements(t)>0}switchTab(e,t){const s=e.querySelector(`a[href="#${t}"]`),n=this.context.querySelector(`#${t}`);e.querySelector(".t3js-tabmenu-item.active").classList.remove("active"),e.querySelector(".tab-pane.active").classList.remove("active"),s.parentElement.classList.add("active"),n.classList.add("active")}}t.default=i})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Core/Event/RegularEvent","./Input/Clearable"],(function(e,t,s,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0});class n{constructor(e){this.context=e.get(0),this.searchField=this.context.querySelector(".t3js-contentWizard-search"),this.registerClearable(),this.registerEvents()}static getTabIdentifier(e){const t=e.querySelector("a"),[,s]=t.href.split("#");return s}static countVisibleContentElements(e){return e.querySelectorAll(".media-new-content-element-wizard:not(.hidden)").length}focusSearchField(){this.searchField.focus()}registerClearable(){this.searchField.clearable({onClear:e=>{e.value="",this.filterElements(e)}})}registerEvents(){new i("keydown",e=>{const t=e.target;"Escape"===e.code&&(e.stopImmediatePropagation(),t.value="")}).bindTo(this.searchField),new s("keyup",e=>{this.filterElements(e.target)},150).bindTo(this.searchField),new i("submit",e=>{e.preventDefault()}).bindTo(this.searchField.closest("form")),new i("click",e=>{e.preventDefault(),e.stopPropagation()}).delegateTo(this.context,".t3js-tabs .disabled")}filterElements(e){const t=e.closest("form"),s=t.querySelector(".t3js-tabs"),i=t.querySelector(".t3js-filter-noresult");t.querySelectorAll(".media.media-new-content-element-wizard").forEach(t=>{const s=t.textContent.trim().replace(/\s+/g," ");t.classList.toggle("hidden",""!==e.value&&!RegExp(e.value,"i").test(s))});const r=n.countVisibleContentElements(t);s.parentElement.classList.toggle("hidden",0===r),i.classList.toggle("hidden",r>0),this.switchTabIfNecessary(s)}switchTabIfNecessary(e){const t=e.querySelector(".active"),s=Array.from(t.parentNode.children);for(let e of s){const t=n.getTabIdentifier(e);e.classList.toggle("disabled",!this.hasTabContent(t))}if(!this.hasTabContent(n.getTabIdentifier(t)))for(let i of s){if(i===t)continue;const s=n.getTabIdentifier(i);if(this.hasTabContent(s)){this.switchTab(e.parentElement,s);break}}}hasTabContent(e){const t=this.context.querySelector(`#${e}`);return n.countVisibleContentElements(t)>0}switchTab(e,t){const s=e.querySelector(`a[href="#${t}"]`),i=this.context.querySelector(`#${t}`);e.querySelector(".t3js-tabmenu-item.active").classList.remove("active"),e.querySelector(".tab-pane.active").classList.remove("active"),s.parentElement.classList.add("active"),i.classList.add("active")}}t.default=n})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/NewContentElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/NewContentElement.js index b393a99960c9..fe8a2e6e1115 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/NewContentElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/NewContentElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -define(["require","exports","../Enum/Severity","../Modal","TYPO3/CMS/Backend/NewContentElementWizard"],(function(e,t,n,a,d){"use strict";return class{static wizard(e,t){const i=a.advanced({callback:e=>{e.find(".t3js-modal-body").addClass("t3-new-content-element-wizard-window")},content:e,severity:n.SeverityEnum.notice,size:a.sizes.medium,title:t,type:a.types.ajax}).on("modal-loaded",()=>{new d.default(i)})}}})); \ No newline at end of file +define(["require","exports","../Enum/Severity","../Modal","TYPO3/CMS/Backend/NewContentElementWizard"],(function(e,n,t,d,a){"use strict";return class{static wizard(e,n){const o=d.advanced({callback:e=>{e.find(".t3js-modal-body").addClass("t3-new-content-element-wizard-window")},content:e,severity:t.SeverityEnum.notice,size:d.sizes.medium,title:n,type:d.types.ajax}).on("modal-loaded",()=>{o.on("shown.bs.modal",()=>{new a.default(o).focusSearchField()})}).on("shown.bs.modal",()=>{o.on("modal-loaded",()=>{new a.default(o).focusSearchField()})})}}})); \ No newline at end of file -- GitLab