diff --git a/extension/Classes/Core/AbstractBuildForm.php b/extension/Classes/Core/AbstractBuildForm.php index ba1b8b9f8c41a95c0cd1f04fbb7ee433ce198b7a..c936c6096db45a3a88d758febc0e3c7a4f6f1dce 100644 --- a/extension/Classes/Core/AbstractBuildForm.php +++ b/extension/Classes/Core/AbstractBuildForm.php @@ -3436,9 +3436,29 @@ abstract class AbstractBuildForm { } else { $completeUrl = '?action=imageUpload'; } + + // Prepare maxLength and characterCount for tinyMce + $maxLength = $formElement[FE_MAX_LENGTH]; + $elementCharacterCount = ''; + if (isset($formElement[FE_CHARACTER_COUNT_WRAP])) { + $attribute .= Support::doAttribute('data-character-count-id', $formElement[FE_HTML_ID] . HTML_ID_EXTENSION_CHARACTER_COUNT); + $attributeCC = Support::doAttribute('id', $formElement[FE_HTML_ID] . HTML_ID_EXTENSION_CHARACTER_COUNT); + $classCC = ($formElement[FE_CHARACTER_COUNT_WRAP] == '') ? Support::doAttribute('class', 'qfq-cc-style') : ''; + $elementCharacterCount = "<span $attributeCC $classCC></span>"; + + if ($formElement[FE_CHARACTER_COUNT_WRAP] != '') { + $arr = explode('|', $formElement[FE_CHARACTER_COUNT_WRAP], 2); + $arr[] = ''; + $arr[] = ''; //skip check that at least 2 elements exist + $elementCharacterCount = $arr[0] . $elementCharacterCount . $arr[1]; + } + } + //TODO: static setup for TinyMCE ImagePlugin - needs to be activated / dynamically set by QFQ parameter. $preSettings = [ # "plugins" => "image", + "plugins" => "charmap", + "maxLength" => $maxLength, "file_picker_types" => "file image media", "image_advtab" => true, "automatic_uploads" => true, @@ -3460,7 +3480,7 @@ abstract class AbstractBuildForm { $html = Support::wrapTag("<textarea $attribute>", htmlentities($value), false); $formElement = HelperFormElement::prepareExtraButton($formElement, false); - return $html . HelperFormElement::getHelpBlock() . $formElement[FE_TMP_EXTRA_BUTTON_HTML] . $formElement[FE_INPUT_EXTRA_BUTTON_INFO]; + return $html . HelperFormElement::getHelpBlock() . $formElement[FE_TMP_EXTRA_BUTTON_HTML] . $elementCharacterCount . $formElement[FE_INPUT_EXTRA_BUTTON_INFO]; } /** diff --git a/javascript/src/Helper/tinyMCE.js b/javascript/src/Helper/tinyMCE.js index 892ef1b4be8b957a1f30162f1f6d122a19467932..095bbbe5c4f9e6e69831e3fa6a23f33bec2258d2 100644 --- a/javascript/src/Helper/tinyMCE.js +++ b/javascript/src/Helper/tinyMCE.js @@ -59,6 +59,36 @@ QfqNS.Helper = QfqNS.Helper || {}; config.setup = function (editor) { myEditor = editor; var element = document.getElementById(QfqNS.escapeJqueryIdSelector(tinyMCEId)); + + var counterFlag = false; + if ($this.data('character-count-id') !== undefined) { + counterFlag = true; + } + var maxLength = config.maxLength; // set the maximum length here + var maxLengthDisplay = maxLength; + if (maxLength === '' || maxLength === 0) { + maxLength = false; + maxLengthDisplay = "∞"; + } + + var pattern = /[^\r\n\t\v\f ]/g; + + editor.on('init', function() { + if (maxLength) { + editor.dom.setAttrib(editor.getBody(), 'maxlength', maxLength); + } + + // initialize counter after first load + if (counterFlag) { + var content = editor.getContent({format: 'text'}); + var charCount = (content.match(pattern) || []).length; + var characterCountTarget = "#" + $this.data('character-count-id'); + + $this.data('character-count-display', $(characterCountTarget)); + $this.data('character-count-display').text(charCount + "/" + maxLengthDisplay); + } + }); + editor.on('Change drop', function (e) { // Ensure the associated form is notified of changes in editor. QfqNS.Log.debug('Editor was changed'); @@ -70,11 +100,36 @@ QfqNS.Helper = QfqNS.Helper || {}; $parentForm.trigger("change"); }); + var inputFlag = false; + // Needed for accurate character count. Update counter after input or keyup. + editor.on('input keyup', function() { + if (counterFlag) { + var content = editor.getContent({format: 'text'}); + var charCount = (content.match(pattern) || []).length; + $this.data('character-count-display').text(charCount + "/" + maxLengthDisplay); + } + inputFlag = true; + }); + + // Preventing input of more than maxLength + editor.on('keydown', function(e) { + if (maxLength) { + var content = editor.getContent({format: 'text'}); // get content without HTML tags + var charCount = (content.match(pattern) || []).length; + if (charCount >= maxLength && e.keyCode !== 8) { // prevent input when maximum length is reached + e.preventDefault(); + e.stopPropagation(); + } + } + }); + // Trigger enabled dynamic update for tinyMce after focus out // To get content via dynamic update: It needs to be written in textarea value editor.on('blur', function () { element.value = tinymce.get(QfqNS.escapeJqueryIdSelector(tinyMCEId)).getContent(); - $(config.selector).trigger('change'); + if (inputFlag) { + $(config.selector).trigger('change'); + } }); /* Remove ReadOnly Again - we have to implement tinymce differently