From 7a3a0905a36cc6c92afedb5d698cce46dcab4375 Mon Sep 17 00:00:00 2001 From: Alessandro Schmitz Date: Mon, 25 Mar 2024 19:05:59 +0100 Subject: [PATCH] Add support for TYPO3 12.4 --- .../ShyguyButtonBar.php} | 47 +++--- Classes/Hooks/TCEmainHook.php | 17 +-- Configuration/Icons.php | 14 ++ Configuration/JavaScriptModules.php | 12 ++ Configuration/Services.yaml | 13 ++ .../Public/Icons/Extension.png | Bin Resources/Public/Javascript/Shyguy.js | 143 ++++++++---------- Resources/Public/Javascript/Shyguy.min.js | 2 +- composer.json | 2 +- ext_emconf.php | 8 +- ext_localconf.php | 28 ---- ext_tables.php | 3 +- 12 files changed, 127 insertions(+), 162 deletions(-) rename Classes/{Hooks/ShyGuyHook.php => EventListener/ShyguyButtonBar.php} (50%) create mode 100644 Configuration/Icons.php create mode 100644 Configuration/JavaScriptModules.php create mode 100644 Configuration/Services.yaml rename ext_icon.png => Resources/Public/Icons/Extension.png (100%) delete mode 100644 ext_localconf.php diff --git a/Classes/Hooks/ShyGuyHook.php b/Classes/EventListener/ShyguyButtonBar.php similarity index 50% rename from Classes/Hooks/ShyGuyHook.php rename to Classes/EventListener/ShyguyButtonBar.php index 11a0831..834f6db 100644 --- a/Classes/Hooks/ShyGuyHook.php +++ b/Classes/EventListener/ShyguyButtonBar.php @@ -1,55 +1,42 @@ loadJavaScriptModule('@wapplersystems/shyguy/Shyguy.js'); + + $buttons = $event->getButtons(); $saveButton = $buttons[ButtonBar::BUTTON_POSITION_LEFT][2][0] ?? null; if ($saveButton instanceof InputButton && $saveButton->getName() === '_savedok') { $iconFactory = GeneralUtility::makeInstance(IconFactory::class); - $insertSoftHyphen = $buttonBar->makeLinkButton() + $insertSoftHyphen = $event->getButtonBar()->makeLinkButton() ->setHref('#insertSoftHyphen') - ->setTitle($this->getLanguageService()->sL('LLL:EXT:shyguy/Resources/Private/Language/locallang.xlf:set_hyphen')) + ->setTitle( + $GLOBALS['LANG']->sL( + 'LLL:EXT:shyguy/Resources/Private/Language/locallang.xlf:set_hyphen' + ) + ) ->setIcon($iconFactory->getIcon('insert-soft-hyphen', Icon::SIZE_SMALL)) ->setShowLabelText(true); $pos = max(array_keys($buttons[ButtonBar::BUTTON_POSITION_LEFT])) + 1; $buttons[ButtonBar::BUTTON_POSITION_LEFT][$pos][] = $insertSoftHyphen; - } - return $buttons; - } - - /** - * Returns the language service - * @return LanguageService - */ - protected function getLanguageService(): LanguageService - { - return $GLOBALS['LANG']; + $event->setButtons($buttons); } } diff --git a/Classes/Hooks/TCEmainHook.php b/Classes/Hooks/TCEmainHook.php index a2f2544..7c9784c 100644 --- a/Classes/Hooks/TCEmainHook.php +++ b/Classes/Hooks/TCEmainHook.php @@ -2,24 +2,13 @@ namespace WapplerSystems\Shyguy\Hooks; -use TYPO3\CMS\Core\DataHandling\DataHandler; - class TCEmainHook { - - /** - * - * @param array $fieldArray - * @param string $table - * @param int $id - * @param $parentObject DataHandler - */ - public function processDatamap_preProcessFieldArray(&$fieldArray, $table, $id, $parentObject) - { - array_walk_recursive($fieldArray, [$this, 'makeRealSoftHyphens']); + public function processDatamap_preProcessFieldArray(array &$fieldArray): void { + array_walk_recursive($fieldArray, $this->makeRealSoftHyphens(...)); } - public function makeRealSoftHyphens(&$value, $key) + public function makeRealSoftHyphens(&$value): void { if (is_string($value)) { $value = str_replace("↵", "­", $value); diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 0000000..4ffb90d --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,14 @@ + 'shy.png', +]; + +foreach ($pngIcons as $identifier => $path) { + $icons[$identifier] = [ + 'provider' => BitmapIconProvider::class, + 'source' => 'EXT:shyguy/Resources/Public/Icons/' . $path + ]; +} diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 0000000..6b63540 --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,12 @@ + ['backend', 'rte_ckeditor'], + 'imports' => [ + // recursive definition, all *.js files in this folder are import-mapped + // trailing slash is required per importmap-specification + '@wapplersystems/shyguy/' => 'EXT:shyguy/Resources/Public/Javascript/', + ], +]; diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000..e864b7b --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,13 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + WapplerSystems\Shyguy\: + resource: '../Classes/*' + + WapplerSystems\Shyguy\EventListener\ShyguyButtonBar: + tags: + - name: event.listener + identifier: 'shyguy/button-bar' diff --git a/ext_icon.png b/Resources/Public/Icons/Extension.png similarity index 100% rename from ext_icon.png rename to Resources/Public/Icons/Extension.png diff --git a/Resources/Public/Javascript/Shyguy.js b/Resources/Public/Javascript/Shyguy.js index ec8c919..4751440 100644 --- a/Resources/Public/Javascript/Shyguy.js +++ b/Resources/Public/Javascript/Shyguy.js @@ -1,89 +1,72 @@ -require(["jquery","ckeditor"], function($) { - $(document).ready(function() { - - // Insert ↵ glyph to active element by clicking - if($('a[href="#insertSoftHyphen"]').length){ - $('a[href="#insertSoftHyphen"]').on('mousedown', function(e){ - e.preventDefault(); - - let activeElement = document.activeElement; - let $activeElement = $(activeElement); - let activeCKEDITOR; - - // Get the active CKEditor - for (let ckInstance in CKEDITOR.instances){ - if($activeElement.closest('.form-wizards-element #' + $(CKEDITOR.instances[ckInstance].container).attr('id')).length){ - activeCKEDITOR = CKEDITOR.instances[ckInstance].dataProcessor.editor; - } - } - - // CKEditor source mode works native, so get the other(s) or use natvie behavior instead - if(activeCKEDITOR && activeCKEDITOR.mode !== "source" && activeCKEDITOR.focusManager.hasFocus === true){ - activeCKEDITOR.insertText('↵'); - }else{ - let activeElementRange = getCaretPosition(activeElement); - - $activeElement.val(replaceRange($activeElement.val(), activeElementRange['start'], activeElementRange['end'], '↵')); - $activeElement.change(); - $activeElement.keyup(); - } - }); - } - - replaceDomGlyphes(); - - CKEDITOR.on( 'instanceReady', function( evt ) { - - evt.editor.setData(evt.editor.getData().replace(/(\­|\­)/gi, "↵")); - - }); +class InsertSoftHyphenHandler { + constructor() { + this.btnInsertShy = document.querySelector("a[href=\"#insertSoftHyphen\"]"); + + this.init(); + } + + /** + * @return {InsertSoftHyphenHandler} + */ + init() { + if (this.btnInsertShy) { + this.btnInsertShy.addEventListener("mousedown", this.handleInsertShyClick.bind(this)); + } - }); + this.replaceDomGlyphes(); - // Replace Existing ↵ with ­ glyph in plain text, input fields and text areas - function replaceDomGlyphes(){ + return this; + } - $('body :not(script,textarea), body textarea[id^="formengine-textarea-"]').contents().filter(function() { - return this.nodeType === 3; - }).replaceWith(function() { - return this.nodeValue.replace(/(\­|\­)/gi, "↵").replace(/[\u00A0-\u9999<>\&]/g, function (i) { - return '&#' + i.charCodeAt(0) + ';'; - }); - }); + /** + * Handle insert soft-hyphen button click + * https://ckeditor.com/docs/ckeditor5/latest/examples/how-tos.html#how-to-get-the-editor-instance-object-from-the-dom-element + */ + handleInsertShyClick(event) { + event.preventDefault(); - $('input, .form-wizards-element textarea[id^="formengine-textarea-"]').each(function(){ - $(this).val($(this).val().replace(/(\­|\­)/gi, "↵")); - }); - } + let activeElement = document.activeElement; + const domEditableElement = document.querySelector(".ck-editor__editable_inline"); + const editorInstance = domEditableElement.ckeditorInstance; -}); + if (editorInstance.editing.view.document.isFocused === true) { + editorInstance.execute("insertText", { text: "­" }); + editorInstance.editing.view.focus(); + } else if (activeElement.tagName.toLowerCase() === "input" || activeElement.tagName.toLowerCase() === "textarea") { + let activeElementRange = this.getCaretPosition(activeElement); -function getCaretPosition(ctrl) { - // IE < 9 Support - if (document.selection) { - ctrl.focus(); - var range = document.selection.createRange(); - var rangelen = range.text.length; - range.moveStart('character', -ctrl.value.length); - var start = range.text.length - rangelen; - return { - 'start': start, - 'end': start + rangelen - }; - } // IE >=9 and other browsers - else if (ctrl.selectionStart || ctrl.selectionStart == '0') { - return { - 'start': ctrl.selectionStart, - 'end': ctrl.selectionEnd - }; - } else { - return { - 'start': 0, - 'end': 0 - }; + activeElement.value = this.replaceRange(activeElement.value, activeElementRange["start"], activeElementRange["end"], "↵"); + activeElement.dispatchEvent(new Event("change", { "bubbles": true })); + activeElement.dispatchEvent(new Event("keyup", { "bubbles": true })); } + } + + /** + * Replace Existing ↵ with ­ glyph in input fields and text areas + */ + replaceDomGlyphes() { + const elements = document.querySelectorAll("input, .form-wizards-element textarea[id^=\"formengine-textarea-\"]"); + elements.forEach(function(element) { + element.value = element.value.replace(/(\­|\­)/gi, "↵"); + }); + } + + /** + * Get caret position + */ + getCaretPosition(ctrl) { + return { + "start": ctrl.selectionStart ?? 0, + "end": ctrl.selectionEnd ?? 0 + }; + } + + /** + * @return {InsertSoftHyphenHandler} + */ + replaceRange(s, start, end, substitute) { + return s.substring(0, start) + substitute + s.substring(end); + } } -function replaceRange(s, start, end, substitute) { - return s.substring(0, start) + substitute + s.substring(end); -} \ No newline at end of file +export default new InsertSoftHyphenHandler(); diff --git a/Resources/Public/Javascript/Shyguy.min.js b/Resources/Public/Javascript/Shyguy.min.js index dc77325..47037f8 100644 --- a/Resources/Public/Javascript/Shyguy.min.js +++ b/Resources/Public/Javascript/Shyguy.min.js @@ -1 +1 @@ -function getCaretPosition(e){if(document.selection){e.focus();var t=document.selection.createRange(),n=t.text.length;t.moveStart("character",-e.value.length);var r=t.text.length-n;return{start:r,end:r+n}}return e.selectionStart||"0"==e.selectionStart?{start:e.selectionStart,end:e.selectionEnd}:{start:0,end:0}}function replaceRange(e,t,n,r){return e.substring(0,t)+r+e.substring(n)}require(["jquery","ckeditor"],function(e){e(document).ready(function(){e('a[href="#insertSoftHyphen"]').length&&e('a[href="#insertSoftHyphen"]').on("mousedown",function(t){t.preventDefault();let n,r=document.activeElement,a=e(r);for(let t in CKEDITOR.instances)a.closest(".form-wizards-element #"+e(CKEDITOR.instances[t].container).attr("id")).length&&(n=CKEDITOR.instances[t].dataProcessor.editor);if(n&&"source"!==n.mode&&!0===n.focusManager.hasFocus)n.insertText("↵");else{let e=getCaretPosition(r);a.val(replaceRange(a.val(),e.start,e.end,"↵")),a.change(),a.keyup()}}),e('body :not(script,textarea), body textarea[id^="formengine-textarea-"]').contents().filter(function(){return 3===this.nodeType}).replaceWith(function(){return this.nodeValue.replace(/(\­|\­)/gi,"↵").replace(/[\u00A0-\u9999<>\&]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}),e('input, .form-wizards-element textarea[id^="formengine-textarea-"]').each(function(){e(this).val(e(this).val().replace(/(\­|\­)/gi,"↵"))}),CKEDITOR.on("instanceReady",function(e){e.editor.setData(e.editor.getData().replace(/(\­|\­)/gi,"↵"))})})}); \ No newline at end of file +class InsertSoftHyphenHandler{constructor(){this.btnInsertShy=document.querySelector('a[href="#insertSoftHyphen"]'),this.init()}init(){return this.btnInsertShy&&this.btnInsertShy.addEventListener("mousedown",this.handleInsertShyClick.bind(this)),this.replaceDomGlyphes(),this}handleInsertShyClick(e){e.preventDefault();let t=document.activeElement,n=document.querySelector(".ck-editor__editable_inline"),i=n.ckeditorInstance;if(!0===i.editing.view.document.isFocused)i.execute("insertText",{text:"\xad"}),i.editing.view.focus();else if("input"===t.tagName.toLowerCase()||"textarea"===t.tagName.toLowerCase()){let r=this.getCaretPosition(t);t.value=this.replaceRange(t.value,r.start,r.end,"↵"),t.dispatchEvent(new Event("change",{bubbles:!0})),t.dispatchEvent(new Event("keyup",{bubbles:!0}))}}replaceDomGlyphes(){let e=document.querySelectorAll('input, .form-wizards-element textarea[id^="formengine-textarea-"]');e.forEach(function(e){e.value=e.value.replace(/(\­|\­)/gi,"↵")})}getCaretPosition(e){return{start:e.selectionStart??0,end:e.selectionEnd??0}}replaceRange(e,t,n,i){return e.substring(0,t)+i+e.substring(n)}}export default new InsertSoftHyphenHandler; diff --git a/composer.json b/composer.json index 78f9d5c..89447a8 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "source": "https://github.com/WapplerSystems/Shyguy" }, "require": { - "typo3/cms-core": " ^9.5 || ^10.0 || 10.*@dev || ^11.0 || 11.*@dev" + "typo3/cms-core": " ^12.4" }, "autoload": { "psr-4": { diff --git a/ext_emconf.php b/ext_emconf.php index 97d5ea8..3f789c0 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -7,18 +7,14 @@ 'author' => 'Patrik Tschersich', 'author_email' => 'tschersich@vodafone.de', 'state' => 'beta', - 'uploadfolder' => false, - 'createDirs' => '', - 'clearCacheOnLoad' => 0, - 'version' => '1.0.8', + 'version' => '1.0.9', 'constraints' => [ 'depends' => [ - 'typo3' => '9.5.0-11.99.0', + 'typo3' => '12.0-12.99.0', ], 'conflicts' => [], 'suggests' => [], ], - 'clearcacheonload' => false, 'author_company' => 'WapplerSystems', ]; diff --git a/ext_localconf.php b/ext_localconf.php deleted file mode 100644 index 8739597..0000000 --- a/ext_localconf.php +++ /dev/null @@ -1,28 +0,0 @@ -addJsFile('EXT:shyguy/Resources/Public/Javascript/Shyguy.min.js', 'text/javascript'); -} - -$pngIcons = [ - 'insert-soft-hyphen' => 'shy.png', -]; -/** @var IconRegistry $iconRegistry */ -$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); -foreach ($pngIcons as $identifier => $path) { - $iconRegistry->registerIcon( - $identifier, - BitmapIconProvider::class, - ['source' => 'EXT:shyguy/Resources/Public/Icons/' . $path] - ); -} diff --git a/ext_tables.php b/ext_tables.php index 4ec90c9..c68d958 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -2,9 +2,8 @@ use WapplerSystems\Shyguy\Hooks\TCEmainHook; -if (!defined('TYPO3_MODE')) { +if (!defined('TYPO3')) { die('Access denied.'); } -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['Backend\Template\Components\ButtonBar']['getButtonsHook'][] = 'WapplerSystems\Shyguy\Hooks\ShyGuyHook->addSoftHyphenInitial'; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = TCEmainHook::class;