From cef99dd290b88169bcceaafdeef358e3cccdf9f3 Mon Sep 17 00:00:00 2001 From: Andreas Fernandez <a.fernandez@scripting-base.de> Date: Sun, 8 Mar 2020 15:06:30 +0100 Subject: [PATCH] [BUGFIX] Bind onChange alert to field again The change of #88665 aimed to centralize the onchange behavior for all FormEngine fields. The result of this change is that this didn't work for all field types. Due to the fact the FormEngine rendering is rather cluttered (e.g. sometimes there are hidden fields that hold the actual value) and it's not possible to bind a global event delegation to such fields right now, this patch now uses the onchange handling again which was tried to be replaced. Resolves: #90672 Related: #88665 Releases: master Change-Id: I17d54edfc45dd39735bcc53ed0fd92e9fa061f13 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63621 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Susanne Moog <look@susi.dev> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Susanne Moog <look@susi.dev> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- .../Container/FlexFormElementContainer.php | 28 +++++++---- .../Form/Container/SingleFieldContainer.php | 48 +++++++++++-------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php b/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php index 88cc6da04b4a..1046593d6bbe 100644 --- a/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php +++ b/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php @@ -18,7 +18,6 @@ use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * The container handles single elements. @@ -85,6 +84,25 @@ class FlexFormElementContainer extends AbstractContainer $fakeParameterArray['fieldConf']['description'] = $flexFormFieldArray['description']; } + $alertMsgOnChange = ''; + if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') { + if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { + $alertMsgOnChange = 'Modal.confirm(' + . 'TYPO3.lang["FormEngine.refreshRequiredTitle"],' + . ' TYPO3.lang["FormEngine.refreshRequiredContent"]' + . ')' + . '.on(' + . '"button.clicked",' + . ' function(e) { if (e.target.name == "ok") { FormEngine.saveDocument(); } Modal.dismiss(); }' + . ');'; + } else { + $alertMsgOnChange = 'FormEngine.saveDocument();'; + } + } + if ($alertMsgOnChange) { + $fakeParameterArray['fieldChangeFunc']['alert'] = 'require([\'TYPO3/CMS/Backend/FormEngine\', \'TYPO3/CMS/Backend/Modal\'], function (FormEngine, Modal) {' . $alertMsgOnChange . '});'; + } + $originalFieldName = $parameterArray['itemFormElName']; $fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]'; if ($fakeParameterArray['itemFormElName'] !== $originalFieldName) { @@ -120,14 +138,6 @@ class FlexFormElementContainer extends AbstractContainer } $childResult = $this->nodeFactory->create($options)->render(); - // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. - // This is used for eg. "type" fields and others configured with "onChange" - if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') { - $showConfirmation = $this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE) ? 'true' : 'false'; - - $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine' => 'function (FormEngine) {FormEngine.requestConfirmationOnFieldChange(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', ' . $showConfirmation . ');}']; - } - if (!empty($childResult['html'])) { // Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!) $processedTitle = str_replace('\\n', '<br />', htmlspecialchars($fakeParameterArray['fieldConf']['label'])); diff --git a/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php b/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php index ab2ab44f90f8..22f461ecc0f7 100644 --- a/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php +++ b/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php @@ -110,6 +110,32 @@ class SingleFieldContainer extends AbstractContainer $parameterArray['itemFormElValue'] = $this->data['defaultLanguageRow'][$fieldName]; } + if (strpos($this->data['processedTca']['ctrl']['type'], ':') === false) { + $typeField = $this->data['processedTca']['ctrl']['type']; + } else { + $typeField = substr($this->data['processedTca']['ctrl']['type'], 0, strpos($this->data['processedTca']['ctrl']['type'], ':')); + } + // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. + // This is used for eg. "type" fields and others configured with "onChange" + if (!empty($this->data['processedTca']['ctrl']['type']) && $fieldName === $typeField + || isset($parameterArray['fieldConf']['onChange']) && $parameterArray['fieldConf']['onChange'] === 'reload' + ) { + if ($backendUser->jsConfirmation(JsConfirmation::TYPE_CHANGE)) { + $alertMsgOnChange = 'Modal.confirm(' + . 'TYPO3.lang["FormEngine.refreshRequiredTitle"],' + . ' TYPO3.lang["FormEngine.refreshRequiredContent"]' + . ')' + . '.on(' + . '"button.clicked",' + . ' function(e) { if (e.target.name == "ok") { FormEngine.saveDocument(); } Modal.dismiss(); }' + . ');'; + } else { + $alertMsgOnChange = 'FormEngine.saveDocument();'; + } + } else { + $alertMsgOnChange = ''; + } + // JavaScript code for event handlers: $parameterArray['fieldChangeFunc'] = []; $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged(' @@ -118,6 +144,9 @@ class SingleFieldContainer extends AbstractContainer . GeneralUtility::quoteJSvalue($fieldName) . ',' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ');'; + if ($alertMsgOnChange) { + $parameterArray['fieldChangeFunc']['alert'] = 'require([\'TYPO3/CMS/Backend/FormEngine\', \'TYPO3/CMS/Backend/Modal\'], function (FormEngine, Modal) {' . $alertMsgOnChange . '});'; + } // Based on the type of the item, call a render function on a child element $options = $this->data; @@ -130,25 +159,6 @@ class SingleFieldContainer extends AbstractContainer $options['renderType'] = $parameterArray['fieldConf']['config']['type']; } $resultArray = $this->nodeFactory->create($options)->render(); - - if (strpos($this->data['processedTca']['ctrl']['type'], ':') === false) { - $typeField = $this->data['processedTca']['ctrl']['type']; - } else { - $typeField = substr($this->data['processedTca']['ctrl']['type'], 0, strpos($this->data['processedTca']['ctrl']['type'], ':')); - } - - // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. - // This is used for eg. "type" fields and others configured with "onChange" - if ((!empty($this->data['processedTca']['ctrl']['type']) && $fieldName === $typeField) - || (isset($parameterArray['fieldConf']['onChange']) && $parameterArray['fieldConf']['onChange'] === 'reload') - ) { - $showConfirmation = $backendUser->jsConfirmation(JsConfirmation::TYPE_CHANGE) ? 'true' : 'false'; - - $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine' => 'function (FormEngine) {' - . 'FormEngine.requestConfirmationOnFieldChange(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', ' . $showConfirmation . ');' - . '}']; - } - return $resultArray; } -- GitLab