Skip to content
Permalink
Browse files

[TASK] Move "Refresh required" modal interception into JavaScript land

The "Refresh required" is currently built in PHP and invoked when changing
a field that is explictly configured as "onChange => reload" in TCA. Since
we aren't limited to the technology of our time anymore, the main logic
can get moved into FormEngine.js and only registration is kept in
FormEngine for now.

This commit also removed some superfluous usages of
`TBE_EDITOR_fieldChanged`, as those are already handled by FormEngine.

Resolves: #88665
Releases: master
Change-Id: I255b70fba7af8253c6bc02611029a74a57a2a043
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61204
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
  • Loading branch information
andreasfernandez authored and NeoBlack committed Jul 1, 2019
1 parent 87268b6 commit f274f58d0a10c5540a97fcd5a90f24559ee0b647
@@ -121,16 +121,6 @@ public function containerAdd(ServerRequestInterface $request): ResponseInterface

$formData['parameterArray']['itemFormElName'] = 'data[' . $tableName . '][' . $formData['databaseRow']['uid'] . '][' . $fieldName . ']';

// JavaScript code for event handlers:
// @todo: see if we can get rid of this - used in group elements, and also for the "reload" on type field changes
$formData['parameterArray']['fieldChangeFunc'] = [];
$formData['parameterArray']['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged('
. GeneralUtility::quoteJSvalue($tableName)
. ',' . GeneralUtility::quoteJSvalue($formData['databaseRow']['uid'])
. ',' . GeneralUtility::quoteJSvalue($fieldName)
. ',' . GeneralUtility::quoteJSvalue($formData['parameterArray']['itemFormElName'])
. ');';

// @todo: check GroupElement for usage of elementBaseName ... maybe kick that thing?
// Feed resulting form data to container structure to render HTML and other result data
@@ -18,6 +18,7 @@
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.
@@ -84,25 +85,6 @@ public function render()
$fakeParameterArray['fieldConf']['description'] = $flexFormFieldArray['description'];
}

$alertMsgOnChange = '';
if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') {
if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
$alertMsgOnChange = 'top.TYPO3.Modal.confirm('
. 'TYPO3.lang["FormEngine.refreshRequiredTitle"],'
. ' TYPO3.lang["FormEngine.refreshRequiredContent"]'
. ')'
. '.on('
. '"button.clicked",'
. ' function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); }'
. ');';
} else {
$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
}
}
if ($alertMsgOnChange) {
$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
}

$originalFieldName = $parameterArray['itemFormElName'];
$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]';
if ($fakeParameterArray['itemFormElName'] !== $originalFieldName) {
@@ -138,6 +120,14 @@ public function render()
}
$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']));
@@ -110,43 +110,8 @@ public function render()
$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 = 'top.TYPO3.Modal.confirm('
. 'TYPO3.lang["FormEngine.refreshRequiredTitle"],'
. ' TYPO3.lang["FormEngine.refreshRequiredContent"]'
. ')'
. '.on('
. '"button.clicked",'
. ' function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); }'
. ');';
} else {
$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
}
} else {
$alertMsgOnChange = '';
}

// JavaScript code for event handlers:
$parameterArray['fieldChangeFunc'] = [];
$parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged('
. GeneralUtility::quoteJSvalue($table) . ','
. GeneralUtility::quoteJSvalue($row['uid']) . ','
. GeneralUtility::quoteJSvalue($fieldName) . ','
. GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
. ');';
if ($alertMsgOnChange) {
$parameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
}

// Based on the type of the item, call a render function on a child element
$options = $this->data;
@@ -159,6 +124,25 @@ public function render()
$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;
}

@@ -201,7 +201,10 @@ protected function JSbottom()
$html = implode(LF, $this->hiddenFieldAccum);
$pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/md5.js');
// load the main module for FormEngine with all important JS functions
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = 'function(FormEngine) {
if (!is_array($this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] ?? null)) {
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = [$this->requireJsModules['TYPO3/CMS/Backend/FormEngine']];
}
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'][] = 'function(FormEngine) {
FormEngine.initialize(
' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('wizard_element_browser')) . ',
' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '
@@ -799,9 +799,8 @@ define(['jquery',
callback.call(null, true);
} else if (e.target.name === 'save') {
$('form[name=' + FormEngine.formName + ']').append($elem);
$('input[name=doSave]').val(1);
Modal.dismiss();
document.editform.submit();
FormEngine.saveDocument();
}
});
} else {
@@ -833,6 +832,28 @@ define(['jquery',
return true;
};

FormEngine.requestConfirmationOnFieldChange = function(fieldName, showConfirmation) {
const $field = FormEngine.getFieldElement(fieldName);
$field.on('change', function() {
if (showConfirmation) {
const $modal = Modal.confirm(
TYPO3.lang['FormEngine.refreshRequiredTitle'],
TYPO3.lang['FormEngine.refreshRequiredContent']
);

$modal.on('button.clicked', function(e) {
if (e.target.name === 'ok') {
FormEngine.saveDocument();
}

Modal.dismiss();
});
} else {
FormEngine.saveDocument();
}
});
};

/**
* Preview action
*
@@ -877,9 +898,8 @@ define(['jquery',
break;
case 'save':
$('form[name=' + FormEngine.formName + ']').append($actionElement);
$('input[name=doSave]').val(1);
window.open('', 'newTYPO3frontendWindow');
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
@@ -977,8 +997,7 @@ define(['jquery',
break;
case 'yes':
$form.append($actionElement);
$('input[name=doSave]').val(1);
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
@@ -1070,8 +1089,7 @@ define(['jquery',
break;
case 'yes':
$form.append($actionElement);
$('input[name=doSave]').val(1);
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
@@ -1201,6 +1219,11 @@ define(['jquery',
document.editform.submit();
};

FormEngine.saveDocument = function() {
document.editform.doSave.value = 1;
document.editform.submit();
};

/**
* Main init function called from outside
*

0 comments on commit f274f58

Please sign in to comment.
You can’t perform that action at this time.