From 2e4e8e07243a4c0cbbc01946d4c2c9d11da1964e Mon Sep 17 00:00:00 2001 From: Andreas Fernandez Date: Fri, 24 May 2019 16:43:22 +0200 Subject: [PATCH] [TASK] Open ElementBrowser event based in FormEngine Currently, the ElementBrowser is used in three different places in FormEngine, all of them trigger it differently. This patch introduces an event-driven approach and streamlines all usages. Resolves: #88436 Releases: master Change-Id: I13e696f29ade0aede6a2466cbca1e27cebc86c61 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60818 Tested-by: TYPO3com Tested-by: Daniel Goerz Tested-by: Benni Mack Reviewed-by: Daniel Goerz Reviewed-by: Benni Mack --- .../Container/InlineControlContainer.ts | 20 ------------------- .../Form/Container/InlineControlContainer.php | 2 +- .../Form/FieldControl/ElementBrowser.php | 9 +++------ .../Classes/Form/FieldWizard/TableList.php | 12 ++--------- .../Resources/Public/JavaScript/FormEngine.js | 9 +++++++++ .../Container/InlineControlContainer.js | 2 +- 6 files changed, 16 insertions(+), 38 deletions(-) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts index 2cf463a00835..3b71ff3ed892 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts @@ -31,7 +31,6 @@ enum Selectors { controlSectionSelector = '.t3js-formengine-irre-control', createNewRecordButtonSelector = '.t3js-create-new-button', createNewRecordBySelectorSelector = '.t3js-create-new-selector', - insertRecordButtonSelector = '.t3js-insert-record-button', deleteRecordButtonSelector = '.t3js-editform-delete-inline-record', enableDisableRecordButtonSelector = '.t3js-toggle-visibility-button', infoWindowButton = '[data-action="infowindow"]', @@ -142,24 +141,6 @@ class InlineControlContainer { InfoWindow.showItem(target.dataset.infoTable, target.dataset.infoUid); } - /** - * @param {Event} e - */ - private static registerInsertRecordButton(e: Event): void { - let target: HTMLElement; - if ((target = InlineControlContainer.getDelegatedEventTarget(e.target, Selectors.insertRecordButtonSelector)) === null) { - return; - } - - e.preventDefault(); - e.stopImmediatePropagation(); - - const mode = target.dataset.mode; - const params = target.dataset.params; - - FormEngine.openPopupWindow(mode, params); - } - /** * @param {string} objectId */ @@ -273,7 +254,6 @@ class InlineControlContainer { this.registerSort(e); this.registerCreateRecordButton(e); this.registerCreateRecordBySelector(e); - InlineControlContainer.registerInsertRecordButton(e); this.registerEnableDisableButton(e); InlineControlContainer.registerInfoButton(e); this.registerDeleteButton(e); diff --git a/typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php b/typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php index 46c17155f80a..60bfdbcef83b 100644 --- a/typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php +++ b/typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php @@ -498,7 +498,7 @@ protected function renderPossibleRecordsSelectorTypeGroupDB(array $inlineConfigu $item = ''; if ($elementBrowserEnabled) { $item .= ' - ' . $this->iconFactory->getIcon('actions-insert-record', Icon::SIZE_SMALL)->render() . ' ' . $createNewRelationText . ' diff --git a/typo3/sysext/backend/Classes/Form/FieldControl/ElementBrowser.php b/typo3/sysext/backend/Classes/Form/FieldControl/ElementBrowser.php index 8d408993bf34..dfce473ab164 100644 --- a/typo3/sysext/backend/Classes/Form/FieldControl/ElementBrowser.php +++ b/typo3/sysext/backend/Classes/Form/FieldControl/ElementBrowser.php @@ -71,17 +71,14 @@ public function render() if (is_array($config['appearance']) && isset($config['appearance']['elementBrowserAllowed'])) { $elementBrowserAllowed = $config['appearance']['elementBrowserAllowed']; } - $elementBrowserOnClick = 'setFormValueOpenBrowser(' - . GeneralUtility::quoteJSvalue($elementBrowserType) . ',' - . GeneralUtility::quoteJSvalue($elementName . '|||' . $elementBrowserAllowed . '|' . $elementBrowserOnClickInline) - . ');' - . ' return false;'; return [ 'iconIdentifier' => 'actions-insert-record', 'title' => $title, 'linkAttributes' => [ - 'onClick' => $elementBrowserOnClick, + 'class' => 't3js-element-browser', + 'data-mode' => htmlspecialchars($elementBrowserType), + 'data-params' => htmlspecialchars($elementName . '|||' . $elementBrowserAllowed . '|' . $elementBrowserOnClickInline) ], ]; } diff --git a/typo3/sysext/backend/Classes/Form/FieldWizard/TableList.php b/typo3/sysext/backend/Classes/Form/FieldWizard/TableList.php index 976d6f4f267a..bae20a2b25fd 100644 --- a/typo3/sysext/backend/Classes/Form/FieldWizard/TableList.php +++ b/typo3/sysext/backend/Classes/Form/FieldWizard/TableList.php @@ -41,9 +41,7 @@ public function render(): array $config = $parameterArray['fieldConf']['config']; $itemName = $parameterArray['itemFormElName']; - if (!isset($config['allowed']) || !is_string($config['allowed']) || empty($config['allowed']) - || !isset($config['internal_type']) || $config['internal_type'] !== 'db' - ) { + if (empty($config['allowed']) || !is_string($config['allowed']) || !isset($config['internal_type']) || $config['internal_type'] !== 'db') { // No handling if the field has no, or funny "allowed" setting, and if internal_type is not "db" return $result; } @@ -59,13 +57,7 @@ public function render(): array $allowedTablesHtml[] = ''; } else { $label = $languageService->sL($GLOBALS['TCA'][$tableName]['ctrl']['title']); - $onClick = []; - $onClick[] = 'setFormValueOpenBrowser('; - $onClick[] = '\'db\','; - $onClick[] = GeneralUtility::quoteJSvalue($itemName . '|||' . $tableName); - $onClick[] = ');'; - $onClick[] = 'return false;'; - $allowedTablesHtml[] = ''; + $allowedTablesHtml[] = ''; $allowedTablesHtml[] = $iconFactory->getIconForRecord($tableName, [], Icon::SIZE_SMALL)->render(); $allowedTablesHtml[] = htmlspecialchars($label); $allowedTablesHtml[] = ''; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js index cb8d220a4b6b..7a681d0429f3 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js @@ -537,6 +537,15 @@ define(['jquery', FormEngine.toggleCheckboxField($(this)); }).on('change', function(event) { $('.module-docheader-bar .btn').removeClass('disabled').prop('disabled', false); + }).on('click', '.t3js-element-browser', function(e) { + e.preventDefault(); + e.stopPropagation(); + + const $me = $(e.currentTarget); + const mode = $me.data('mode'); + const params = $me.data('params'); + + FormEngine.openPopupWindow(mode, params); }); }; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js index b7f728189bd6..537495e17177 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __values=this&&this.__values||function(e){var t="function"==typeof Symbol&&e[Symbol.iterator],n=0;return t?t.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}};define(["require","exports","./../InlineRelation/AjaxDispatcher","../../Utility/MessageUtility","jquery","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Backend/FormEngineValidation","../../Icons","../../InfoWindow","../../Modal","../../Notification","nprogress","../../Severity","Sortable","../../Utility"],function(e,t,n,r,o,i,a,l,s,d,c,u,p,g,h){"use strict";var f,v,m,y,b,S,j;return(v=f||(f={})).toggleSelector='[data-toggle="formengine-inline"]',v.controlSectionSelector=".t3js-formengine-irre-control",v.createNewRecordButtonSelector=".t3js-create-new-button",v.createNewRecordBySelectorSelector=".t3js-create-new-selector",v.insertRecordButtonSelector=".t3js-insert-record-button",v.deleteRecordButtonSelector=".t3js-editform-delete-inline-record",v.enableDisableRecordButtonSelector=".t3js-toggle-visibility-button",v.infoWindowButton='[data-action="infowindow"]',v.synchronizeLocalizeRecordButtonSelector=".t3js-synchronizelocalize-button",v.uniqueValueSelectors="select.t3js-inline-unique",v.revertUniqueness=".t3js-revert-unique",v.controlContainerButtons=".t3js-inline-controls",(y=m||(m={})).new="inlineIsNewRecord",y.visible="panel-visible",y.collapsed="panel-collapsed",(b||(b={})).structureSeparator="-",(j=S||(S={})).DOWN="down",j.UP="up",function(){function e(e){var t=this;this.container=null,this.ajaxDispatcher=null,this.appearance=null,this.xhrQueue={},this.progessQueue={},this.noTitleString=TYPO3.lang?TYPO3.lang["FormEngine.noRecordTitle"]:"[No title]",this.handlePostMessage=function(e){if(!r.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if(void 0===e.data.objectGroup)throw"No object group defined for message";e.data.objectGroup===t.container.dataset.objectGroup&&(t.isUniqueElementUsed(parseInt(e.data.uid,10),e.data.table)?c.error("There is already a relation to the selected element"):t.importRecord([e.data.objectGroup,e.data.uid]))},o(function(){t.container=document.querySelector("#"+e),t.ajaxDispatcher=new n.AjaxDispatcher(t.container.dataset.objectGroup),t.registerEvents()})}return e.getDelegatedEventTarget=function(e,t){var n;return null===(n=e.closest(t))&&e.matches(t)&&(n=e),n},e.getInlineRecordContainer=function(e){return document.querySelector('[data-object-id="'+e+'"]')},e.registerInfoButton=function(t){var n;null!==(n=e.getDelegatedEventTarget(t.target,f.infoWindowButton))&&(t.preventDefault(),t.stopImmediatePropagation(),s.showItem(n.dataset.infoTable,n.dataset.infoUid))},e.registerInsertRecordButton=function(t){var n;if(null!==(n=e.getDelegatedEventTarget(t.target,f.insertRecordButtonSelector))){t.preventDefault(),t.stopImmediatePropagation();var r=n.dataset.mode,o=n.dataset.params;i.openPopupWindow(r,o)}},e.toggleElement=function(t){var n=e.getInlineRecordContainer(t);n.classList.contains(m.collapsed)?(n.classList.remove(m.collapsed),n.classList.add(m.visible)):(n.classList.remove(m.visible),n.classList.add(m.collapsed))},e.isNewRecord=function(t){return e.getInlineRecordContainer(t).classList.contains(m.new)},e.updateExpandedCollapsedStateLocally=function(t,n){var r=e.getInlineRecordContainer(t),o="uc[inlineView]["+r.dataset.topmostParentTable+"]["+r.dataset.topmostParentUid+"]"+r.dataset.fieldName,i=document.getElementsByName(o);i.length&&(i[0].value=n?"1":"0")},e.getValuesFromHashMap=function(e){return Object.keys(e).map(function(t){return e[t]})},e.removeSelectOptionByValue=function(e,t){var n=e.querySelector('option[value="'+t+'"]');null!==n&&n.remove()},e.reAddSelectOption=function(e,t,n){var r=Array.from(e.querySelectorAll("option")),o=-1;try{for(var i=__values(Object.keys(n.possible)),a=i.next();!a.done;a=i.next()){var l=a.value;if(l===t)break;for(var s=0;s-1&&(delete n[r],t.value=n.join(","),t.classList.add("has-change"),o(document).trigger("change"),this.redrawSortingButtons(this.container.dataset.objectGroup,n)),n},e.prototype.changeSortingByButton=function(t,n){var r=e.getInlineRecordContainer(t),o=r.dataset.objectUid,i=document.querySelector("#"+this.container.getAttribute("id")+"_records"),a=Array.from(i.children).map(function(e){return e.dataset.objectUid}),l=a.indexOf(o),s=!1;if(n===S.UP&&l>0?(a[l]=a[l-1],a[l-1]=o,s=!0):n===S.DOWN&&l0?e[0]:null},e.prototype.redrawSortingButtons=function(e,t){if(void 0===t&&(t=[]),0===t.length){var n=this.getFormFieldForElements();null!==n&&(t=h.trimExplode(",",n.value))}0!==t.length&&t.forEach(function(n,r){var o="#"+e+b.structureSeparator+n+"_header",i=document.querySelector(o),a=i.querySelector('[data-action="sort"][data-direction="'+S.UP+'"]');if(null!==a){var s="actions-move-up";0===r?(a.classList.add("disabled"),s="empty-empty"):a.classList.remove("disabled"),l.getIcon(s,l.sizes.small).done(function(e){a.replaceChild(document.createRange().createContextualFragment(e),a.querySelector(".t3js-icon"))})}var d=i.querySelector('[data-action="sort"][data-direction="'+S.DOWN+'"]');if(null!==d){s="actions-move-down";r===t.length-1?(d.classList.add("disabled"),s="empty-empty"):d.classList.remove("disabled"),l.getIcon(s,l.sizes.small).done(function(e){d.replaceChild(document.createRange().createContextualFragment(e),d.querySelector(".t3js-icon"))})}})},e.prototype.isBelowMax=function(){var e=this.getFormFieldForElements();if(null===e)return!0;if(void 0!==TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup]){if(h.trimExplode(",",e.value).length>=TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup].max)return!1;if(this.hasObjectGroupDefinedUniqueConstraints()){var t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if(t.used.length>=t.max&&t.max>=0)return!1}}return!0},e.prototype.isUniqueElementUsed=function(t,n){if(!this.hasObjectGroupDefinedUniqueConstraints())return!1;var r=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],o=e.getValuesFromHashMap(r.used);if("select"===r.type&&-1!==o.indexOf(t))return!0;if("groupdb"===r.type)for(var i=o.length-1;i>=0;i--)if(o[i].table===n&&o[i].uid===t)return!0;return!1},e.prototype.removeUsed=function(t){if(this.hasObjectGroupDefinedUniqueConstraints()){var n=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"===n.type){var r=t.querySelector('[name="data['+n.table+"]["+t.dataset.objectUid+"]["+n.field+']"]'),o=e.getValuesFromHashMap(n.used);if(null!==r)for(var i=r.options[r.selectedIndex].value,a=0;a=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}};define(["require","exports","./../InlineRelation/AjaxDispatcher","../../Utility/MessageUtility","jquery","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Backend/FormEngineValidation","../../Icons","../../InfoWindow","../../Modal","../../Notification","nprogress","../../Severity","Sortable","../../Utility"],function(e,t,n,r,o,i,a,l,s,c,d,u,p,g,h){"use strict";var f,v,m,y,b,S,j;return(v=f||(f={})).toggleSelector='[data-toggle="formengine-inline"]',v.controlSectionSelector=".t3js-formengine-irre-control",v.createNewRecordButtonSelector=".t3js-create-new-button",v.createNewRecordBySelectorSelector=".t3js-create-new-selector",v.deleteRecordButtonSelector=".t3js-editform-delete-inline-record",v.enableDisableRecordButtonSelector=".t3js-toggle-visibility-button",v.infoWindowButton='[data-action="infowindow"]',v.synchronizeLocalizeRecordButtonSelector=".t3js-synchronizelocalize-button",v.uniqueValueSelectors="select.t3js-inline-unique",v.revertUniqueness=".t3js-revert-unique",v.controlContainerButtons=".t3js-inline-controls",(y=m||(m={})).new="inlineIsNewRecord",y.visible="panel-visible",y.collapsed="panel-collapsed",(b||(b={})).structureSeparator="-",(j=S||(S={})).DOWN="down",j.UP="up",function(){function e(e){var t=this;this.container=null,this.ajaxDispatcher=null,this.appearance=null,this.xhrQueue={},this.progessQueue={},this.noTitleString=TYPO3.lang?TYPO3.lang["FormEngine.noRecordTitle"]:"[No title]",this.handlePostMessage=function(e){if(!r.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if(void 0===e.data.objectGroup)throw"No object group defined for message";e.data.objectGroup===t.container.dataset.objectGroup&&(t.isUniqueElementUsed(parseInt(e.data.uid,10),e.data.table)?d.error("There is already a relation to the selected element"):t.importRecord([e.data.objectGroup,e.data.uid]))},o(function(){t.container=document.querySelector("#"+e),t.ajaxDispatcher=new n.AjaxDispatcher(t.container.dataset.objectGroup),t.registerEvents()})}return e.getDelegatedEventTarget=function(e,t){var n;return null===(n=e.closest(t))&&e.matches(t)&&(n=e),n},e.getInlineRecordContainer=function(e){return document.querySelector('[data-object-id="'+e+'"]')},e.registerInfoButton=function(t){var n;null!==(n=e.getDelegatedEventTarget(t.target,f.infoWindowButton))&&(t.preventDefault(),t.stopImmediatePropagation(),s.showItem(n.dataset.infoTable,n.dataset.infoUid))},e.toggleElement=function(t){var n=e.getInlineRecordContainer(t);n.classList.contains(m.collapsed)?(n.classList.remove(m.collapsed),n.classList.add(m.visible)):(n.classList.remove(m.visible),n.classList.add(m.collapsed))},e.isNewRecord=function(t){return e.getInlineRecordContainer(t).classList.contains(m.new)},e.updateExpandedCollapsedStateLocally=function(t,n){var r=e.getInlineRecordContainer(t),o="uc[inlineView]["+r.dataset.topmostParentTable+"]["+r.dataset.topmostParentUid+"]"+r.dataset.fieldName,i=document.getElementsByName(o);i.length&&(i[0].value=n?"1":"0")},e.getValuesFromHashMap=function(e){return Object.keys(e).map(function(t){return e[t]})},e.removeSelectOptionByValue=function(e,t){var n=e.querySelector('option[value="'+t+'"]');null!==n&&n.remove()},e.reAddSelectOption=function(e,t,n){var r=Array.from(e.querySelectorAll("option")),o=-1;try{for(var i=__values(Object.keys(n.possible)),a=i.next();!a.done;a=i.next()){var l=a.value;if(l===t)break;for(var s=0;s-1&&(delete n[r],t.value=n.join(","),t.classList.add("has-change"),o(document).trigger("change"),this.redrawSortingButtons(this.container.dataset.objectGroup,n)),n},e.prototype.changeSortingByButton=function(t,n){var r=e.getInlineRecordContainer(t),o=r.dataset.objectUid,i=document.querySelector("#"+this.container.getAttribute("id")+"_records"),a=Array.from(i.children).map(function(e){return e.dataset.objectUid}),l=a.indexOf(o),s=!1;if(n===S.UP&&l>0?(a[l]=a[l-1],a[l-1]=o,s=!0):n===S.DOWN&&l0?e[0]:null},e.prototype.redrawSortingButtons=function(e,t){if(void 0===t&&(t=[]),0===t.length){var n=this.getFormFieldForElements();null!==n&&(t=h.trimExplode(",",n.value))}0!==t.length&&t.forEach(function(n,r){var o="#"+e+b.structureSeparator+n+"_header",i=document.querySelector(o),a=i.querySelector('[data-action="sort"][data-direction="'+S.UP+'"]');if(null!==a){var s="actions-move-up";0===r?(a.classList.add("disabled"),s="empty-empty"):a.classList.remove("disabled"),l.getIcon(s,l.sizes.small).done(function(e){a.replaceChild(document.createRange().createContextualFragment(e),a.querySelector(".t3js-icon"))})}var c=i.querySelector('[data-action="sort"][data-direction="'+S.DOWN+'"]');if(null!==c){s="actions-move-down";r===t.length-1?(c.classList.add("disabled"),s="empty-empty"):c.classList.remove("disabled"),l.getIcon(s,l.sizes.small).done(function(e){c.replaceChild(document.createRange().createContextualFragment(e),c.querySelector(".t3js-icon"))})}})},e.prototype.isBelowMax=function(){var e=this.getFormFieldForElements();if(null===e)return!0;if(void 0!==TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup]){if(h.trimExplode(",",e.value).length>=TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup].max)return!1;if(this.hasObjectGroupDefinedUniqueConstraints()){var t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if(t.used.length>=t.max&&t.max>=0)return!1}}return!0},e.prototype.isUniqueElementUsed=function(t,n){if(!this.hasObjectGroupDefinedUniqueConstraints())return!1;var r=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],o=e.getValuesFromHashMap(r.used);if("select"===r.type&&-1!==o.indexOf(t))return!0;if("groupdb"===r.type)for(var i=o.length-1;i>=0;i--)if(o[i].table===n&&o[i].uid===t)return!0;return!1},e.prototype.removeUsed=function(t){if(this.hasObjectGroupDefinedUniqueConstraints()){var n=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"===n.type){var r=t.querySelector('[name="data['+n.table+"]["+t.dataset.objectUid+"]["+n.field+']"]'),o=e.getValuesFromHashMap(n.used);if(null!==r)for(var i=r.options[r.selectedIndex].value,a=0;a