From 5e2310d5b3a079e2ab687937b822899d92c12acf Mon Sep 17 00:00:00 2001 From: Georg Ringer <georg.ringer@gmail.com> Date: Mon, 30 Jan 2017 23:25:56 +0100 Subject: [PATCH] [FEATURE] Show link information below input field Render link information below a link field to help editors. Instead of 't3://page?uid=92 _top "a class" "a title"' the user will get relevant information. Resolves: #28171 Releases: master Change-Id: Ic285a10e1de67bf60dd5235885a8d0037792999a Reviewed-on: https://review.typo3.org/51479 Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Andreas Fernandez <typo3@scripting-base.de> Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Markus Klein <markus.klein@typo3.org> Tested-by: Andreas Fernandez <typo3@scripting-base.de> --- .../Classes/Form/Element/InputLinkElement.php | 115 +++++++++++++++++- .../Resources/Public/JavaScript/FormEngine.js | 23 ++++ .../Public/JavaScript/jquery.clearable.js | 3 +- ...re-28171-ImprovedLinkFieldInFormEngine.rst | 22 ++++ 4 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-28171-ImprovedLinkFieldInFormEngine.rst diff --git a/typo3/sysext/backend/Classes/Form/Element/InputLinkElement.php b/typo3/sysext/backend/Classes/Form/Element/InputLinkElement.php index 796d8d32a322..e66bca8b7033 100644 --- a/typo3/sysext/backend/Classes/Form/Element/InputLinkElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/InputLinkElement.php @@ -16,9 +16,15 @@ namespace TYPO3\CMS\Backend\Form\Element; use TYPO3\CMS\Backend\Form\FieldWizard\DefaultLanguageDifferences; use TYPO3\CMS\Backend\Form\FieldWizard\OtherLanguageContent; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\LinkHandling\LinkService; +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Utility\StringUtility; +use TYPO3\CMS\Frontend\Service\TypoLinkCodecService; use TYPO3\CMS\Lang\LanguageService; /** @@ -123,6 +129,8 @@ class InputLinkElement extends AbstractFormElement 'class' => implode(' ', [ 'form-control', 't3js-clearable', + 't3js-form-field-inputlink-input', + 'hidden', 'hasDefaultValue', ]), 'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config), @@ -186,12 +194,23 @@ class InputLinkElement extends AbstractFormElement $fieldControlHtml = $legacyFieldControlHtml . $fieldControlResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false); + $linkExplanation = $this->getLinkExplanation($itemValue); + $expansionHtml = []; $expansionHtml[] = '<div class="form-control-wrap" style="max-width: ' . $width . 'px">'; $expansionHtml[] = '<div class="form-wizards-wrap">'; $expansionHtml[] = '<div class="form-wizards-element">'; - $expansionHtml[] = '<input type="text"' . GeneralUtility::implodeAttributes($attributes, true) . ' />'; - $expansionHtml[] = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($itemValue) . '" />'; + $expansionHtml[] = '<div class="input-group t3js-form-field-inputlink">'; + $expansionHtml[] = '<span class="input-group-addon">' . $linkExplanation['icon'] . '</span>'; + $expansionHtml[] = '<input class="form-control t3js-form-field-inputlink-explanation" disabled value="' . htmlspecialchars($linkExplanation['text']) . '">'; + $expansionHtml[] = '<input type="text"' . GeneralUtility::implodeAttributes($attributes, true) . ' />'; + $expansionHtml[] = '<span class="input-group-btn">'; + $expansionHtml[] = '<button class="btn btn-default t3js-form-field-inputlink-explanation-toggle" type="button">'; + $expansionHtml[] = $this->iconFactory->getIcon('actions-version-workspaces-preview-link', Icon::SIZE_SMALL)->render(); + $expansionHtml[] = '</button>'; + $expansionHtml[] = '</span>'; + $expansionHtml[] = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($itemValue) . '" />'; + $expansionHtml[] = '</div>'; $expansionHtml[] = '</div>'; $expansionHtml[] = '<div class="form-wizards-items-aside">'; $expansionHtml[] = '<div class="btn-group">'; @@ -200,6 +219,7 @@ class InputLinkElement extends AbstractFormElement $expansionHtml[] = '</div>'; $expansionHtml[] = '</div>'; $expansionHtml[] = '<div class="form-wizards-items-bottom">'; + $expansionHtml[] = $linkExplanation['additionalAttributes']; $expansionHtml[] = $fieldWizardHtml; $expansionHtml[] = '</div>'; $expansionHtml[] = '</div>'; @@ -269,6 +289,97 @@ class InputLinkElement extends AbstractFormElement return $resultArray; } + /** + * @param string $itemValue + * @return array + */ + protected function getLinkExplanation(string $itemValue): array + { + if (empty($itemValue)) { + return []; + } + $data = []; + $typolinkService = GeneralUtility::makeInstance(TypoLinkCodecService::class); + $linkParts = $typolinkService->decode($itemValue); + $linkService = GeneralUtility::makeInstance(LinkService::class); + $linkData = $linkService->resolve($linkParts['url']); + switch ($linkData['type']) { + case LinkService::TYPE_PAGE: + $pageRecord = BackendUtility::readPageAccess($linkData['pageuid'], '1=1'); + // Is this a real page + if ($pageRecord['uid']) { + $data = [ + 'text' => htmlspecialchars($pageRecord['_thePathFull']) . '[' . $pageRecord['uid'] . ']', + 'icon' => $this->iconFactory->getIconForRecord('pages', $pageRecord, Icon::SIZE_SMALL)->render() + ]; + } + break; + case LinkService::TYPE_EMAIL: + $data = [ + 'text' => htmlspecialchars($linkData['email']), + 'icon' => $this->iconFactory->getIcon('content-elements-mailform', Icon::SIZE_SMALL)->render() + ]; + break; + case LinkService::TYPE_URL: + $data = [ + 'text' => htmlspecialchars($linkData['url']), + 'icon' => $this->iconFactory->getIcon('apps-pagetree-page-shortcut-external', Icon::SIZE_SMALL)->render() + + ]; + break; + case LinkService::TYPE_FILE: + /** @var File $file */ + $file = $linkData['file']; + if ($file) { + $data = [ + 'text' => htmlspecialchars($file->getPublicUrl()), + 'icon' => $this->iconFactory->getIconForFileExtension($file->getExtension(), Icon::SIZE_SMALL)->render() + ]; + } + break; + case LinkService::TYPE_FOLDER: + /** @var Folder $folder */ + $folder = $linkData['folder']; + if ($folder) { + $data = [ + 'text' => htmlspecialchars($folder->getPublicUrl()), + 'icon' => $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL)->render() + ]; + } + break; + default: + $data = [ + 'text' => htmlspecialchars('not implemented type ' . $linkData['type']), + 'icon' => '' + ]; + } + + $additionalAttributes = []; + unset($linkParts['url']); + foreach ($linkParts as $key => $value) { + if ($value) { + switch ($key) { + case 'class': + $label = $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_browse_links.xlf:class'); + break; + case 'title': + $label = $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_browse_links.xlf:title'); + break; + case 'additionalParams': + $label = $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_browse_links.xlf:params'); + break; + default: + $label = $key; + } + + $additionalAttributes[] = '<span><strong>' . htmlspecialchars($label) . ': </strong> ' . htmlspecialchars($value) . '</span>'; + } + } + $data['additionalAttributes'] = '<div class="help-block">' . implode(' - ', $additionalAttributes) . '</div>'; + + return $data; + } + /** * @return LanguageService */ diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js index 659601f17f85..51b1f92e1840 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js @@ -955,6 +955,29 @@ define(['jquery', FormEngine.convertTextareasEnableTab(); FormEngine.initializeNullNoPlaceholderCheckboxes(); FormEngine.initializeNullWithPlaceholderCheckboxes(); + FormEngine.initializeInputLinkToggle(); + }; + + /** + * Toggle for input link explanation + */ + FormEngine.initializeInputLinkToggle = function () { + $(document).on('click', '.t3js-form-field-inputlink-explanation-toggle', function(e) { + e.preventDefault(); + + var $group = $(this).closest('.t3js-form-field-inputlink'), + $inputField = $group.find('.t3js-form-field-inputlink-input'), + $explanationField = $group.find('.t3js-form-field-inputlink-explanation'), + explanationShown; + + explanationShown = !$explanationField.hasClass('hidden'); + $explanationField.toggleClass('hidden', explanationShown); + $inputField.toggleClass('hidden', !explanationShown); + $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown) + }).on('change', '.t3js-form-field-inputlink-input', function() { + var $group = $(this).closest('.t3js-form-field-inputlink'); + $group.find('.t3js-form-field-inputlink-explanation, .t3js-form-field-inputlink-explanation-toggle').remove(); + }); }; /** diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js index 833825c3dfdb..812db1cb7e70 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js @@ -50,11 +50,12 @@ // or the input field is a colorpicker, because it breaks the colorpicker. if (!$input.data('clearable') && !$input.hasClass('t3js-color-picker')) { $input.data('clearable', 'loaded'); + var hiddenClass = $input.hasClass('hidden') ? ' hidden' : ''; // Wrap it with a div and add a span that is the trigger for // clearing. $input.wrap('<div class="form-control-clearable" />'); - $input.after('<button type="button" class="close" tabindex="-1" aria-hidden="true"><span class="fa fa-times" /></button>'); + $input.after('<button type="button" class="close' + hiddenClass + '" tabindex="-1" aria-hidden="true"><span class="fa fa-times" /></button>'); $input.addClass('t3js-clearable'); var $clearer = $input.next(); diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-28171-ImprovedLinkFieldInFormEngine.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-28171-ImprovedLinkFieldInFormEngine.rst new file mode 100644 index 000000000000..629afb49125b --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-28171-ImprovedLinkFieldInFormEngine.rst @@ -0,0 +1,22 @@ +.. include:: ../../Includes.txt + +=================================================== +Feature: #28171 - Improved link field in FormEngine +=================================================== + +See :issue:`28171` + +Description +=========== + +The handling of link fields when managing records has been improved and now shows a speaking string, +an icon and an additional help text instead of the cryptic :code:`t3://` syntaxt. This is enabled +by default for all :code:`renderType="inputLink"` elements. + + +Impact +====== + +Better UX of link fields in the Backend + +.. index:: Backend, TCA \ No newline at end of file -- GitLab