diff --git a/Build/Sources/TypeScript/t3editor/Resources/Public/TypeScript/T3editor.ts b/Build/Sources/TypeScript/t3editor/Resources/Public/TypeScript/T3editor.ts index 19c616b0278fdc85d4972b431ba72a3cab3b1fc2..c7d61962eb074b45cb5498ab6fbecc3770a36e66 100644 --- a/Build/Sources/TypeScript/t3editor/Resources/Public/TypeScript/T3editor.ts +++ b/Build/Sources/TypeScript/t3editor/Resources/Public/TypeScript/T3editor.ts @@ -46,72 +46,87 @@ class T3editor { } /** - * Initializes CodeMirror on available texteditors + * Initialize the events */ - public findAndInitializeEditors(): void { - $(document).find('textarea.t3editor').each(function(this: Element): void { - const $textarea = $(this); - - if (!$textarea.prop('is_t3editor')) { - const config = $textarea.data('codemirror-config'); - const modeParts = config.mode.split('/'); - const addons = $.merge([modeParts.join('/')], JSON.parse(config.addons)); - const options = JSON.parse(config.options); - - // load mode + registered addons - require(addons, (): void => { - const cm = CodeMirror.fromTextArea($textarea.get(0), { - extraKeys: { - 'Ctrl-F': 'findPersistent', - 'Cmd-F': 'findPersistent', - 'Ctrl-Alt-F': (codemirror: any): void => { - codemirror.setOption('fullScreen', !codemirror.getOption('fullScreen')); - }, - 'Ctrl-Space': 'autocomplete', - 'Esc': (codemirror: any): void => { - if (codemirror.getOption('fullScreen')) { - codemirror.setOption('fullScreen', false); - } - }, - }, - fullScreen: false, - lineNumbers: true, - lineWrapping: true, - mode: modeParts[modeParts.length - 1], - }); - - // set options - $.each(options, (key: string, value: any): void => { - cm.setOption(key, value); - }); - - // Mark form as changed if code editor content has changed - cm.on('change', (): void => { - FormEngine.Validation.markFieldAsChanged($textarea); - }); - - cm.addPanel( - T3editor.createPanelNode('bottom', $textarea.attr('alt')), - { - position: 'bottom', - stable: true, - }, - ); - }); - - $textarea.prop('is_t3editor', true); - } + public initialize(): void { + $((): void => { + this.observeEditorCandidates(); }); } /** - * Initialize the events + * Initializes CodeMirror on available texteditors */ - public initialize(): void { - $((): void => { - this.findAndInitializeEditors(); + public observeEditorCandidates(): void { + const observerOptions = { + root: document.body + }; + + let observer = new IntersectionObserver((entries: IntersectionObserverEntry[]): void => { + entries.forEach((entry: IntersectionObserverEntry): void => { + if (entry.intersectionRatio > 0) { + const $target = $(entry.target); + if (!$target.prop('is_t3editor')) { + this.initializeEditor($target); + } + } + }) + }, observerOptions); + + document.querySelectorAll('textarea.t3editor').forEach((textarea: HTMLTextAreaElement): void => { + observer.observe(textarea); }); } + + private initializeEditor($textarea: JQuery): void { + const config = $textarea.data('codemirror-config'); + const modeParts = config.mode.split('/'); + const addons = $.merge([modeParts.join('/')], JSON.parse(config.addons)); + const options = JSON.parse(config.options); + + // load mode + registered addons + require(addons, (): void => { + const cm = CodeMirror.fromTextArea($textarea.get(0), { + extraKeys: { + 'Ctrl-F': 'findPersistent', + 'Cmd-F': 'findPersistent', + 'Ctrl-Alt-F': (codemirror: any): void => { + codemirror.setOption('fullScreen', !codemirror.getOption('fullScreen')); + }, + 'Ctrl-Space': 'autocomplete', + 'Esc': (codemirror: any): void => { + if (codemirror.getOption('fullScreen')) { + codemirror.setOption('fullScreen', false); + } + }, + }, + fullScreen: false, + lineNumbers: true, + lineWrapping: true, + mode: modeParts[modeParts.length - 1], + }); + + // set options + $.each(options, (key: string, value: any): void => { + cm.setOption(key, value); + }); + + // Mark form as changed if code editor content has changed + cm.on('change', (): void => { + FormEngine.Validation.markFieldAsChanged($textarea); + }); + + cm.addPanel( + T3editor.createPanelNode('bottom', $textarea.attr('alt')), + { + position: 'bottom', + stable: true, + }, + ); + }); + + $textarea.prop('is_t3editor', true); + } } // create an instance and return it diff --git a/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php b/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php index 8f23804b28350fb4467686031b0cfa32a8c32b78..9462abcc9dbde35206243398bbb28198436df4c3 100644 --- a/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php +++ b/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php @@ -100,7 +100,7 @@ class T3editorElement extends AbstractFormElement $this->resultArray['stylesheetFiles'][] = $codeMirrorPath . '/lib/codemirror.css'; $this->resultArray['stylesheetFiles'][] = $this->extPath . '/Resources/Public/Css/t3editor.css'; $this->resultArray['requireJsModules'][] = [ - 'TYPO3/CMS/T3editor/T3editor' => 'function(T3editor) {T3editor.findAndInitializeEditors()}' + 'TYPO3/CMS/T3editor/T3editor' => 'function(T3editor) {T3editor.observeEditorCandidates()}' ]; // Compile and register t3editor configuration diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js index 109676b53979ef302453fbe8b9259aea99cda1ae..61e0438d0a59a40f01a9df1660204dcd4e1d5a72 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -define(["require","exports","cm/lib/codemirror","jquery","TYPO3/CMS/Backend/FormEngine"],(function(e,t,i,n,r){"use strict";class o{static createPanelNode(e,t){return n("<div />",{class:"CodeMirror-panel CodeMirror-panel-"+e,id:"panel-"+e}).append(n("<span />").text(t)).get(0)}constructor(){this.initialize()}findAndInitializeEditors(){n(document).find("textarea.t3editor").each((function(){const t=n(this);if(!t.prop("is_t3editor")){const a=t.data("codemirror-config"),s=a.mode.split("/"),l=n.merge([s.join("/")],JSON.parse(a.addons)),d=JSON.parse(a.options);e(l,()=>{const e=i.fromTextArea(t.get(0),{extraKeys:{"Ctrl-F":"findPersistent","Cmd-F":"findPersistent","Ctrl-Alt-F":e=>{e.setOption("fullScreen",!e.getOption("fullScreen"))},"Ctrl-Space":"autocomplete",Esc:e=>{e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}},fullScreen:!1,lineNumbers:!0,lineWrapping:!0,mode:s[s.length-1]});n.each(d,(t,i)=>{e.setOption(t,i)}),e.on("change",()=>{r.Validation.markFieldAsChanged(t)}),e.addPanel(o.createPanelNode("bottom",t.attr("alt")),{position:"bottom",stable:!0})}),t.prop("is_t3editor",!0)}}))}initialize(){n(()=>{this.findAndInitializeEditors()})}}return new o})); \ No newline at end of file +define(["require","exports","cm/lib/codemirror","jquery","TYPO3/CMS/Backend/FormEngine"],(function(e,t,i,r,o){"use strict";class n{static createPanelNode(e,t){return r("<div />",{class:"CodeMirror-panel CodeMirror-panel-"+e,id:"panel-"+e}).append(r("<span />").text(t)).get(0)}constructor(){this.initialize()}initialize(){r(()=>{this.observeEditorCandidates()})}observeEditorCandidates(){const e={root:document.body};let t=new IntersectionObserver(e=>{e.forEach(e=>{if(e.intersectionRatio>0){const t=r(e.target);t.prop("is_t3editor")||this.initializeEditor(t)}})},e);document.querySelectorAll("textarea.t3editor").forEach(e=>{t.observe(e)})}initializeEditor(t){const a=t.data("codemirror-config"),s=a.mode.split("/"),l=r.merge([s.join("/")],JSON.parse(a.addons)),d=JSON.parse(a.options);e(l,()=>{const e=i.fromTextArea(t.get(0),{extraKeys:{"Ctrl-F":"findPersistent","Cmd-F":"findPersistent","Ctrl-Alt-F":e=>{e.setOption("fullScreen",!e.getOption("fullScreen"))},"Ctrl-Space":"autocomplete",Esc:e=>{e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}},fullScreen:!1,lineNumbers:!0,lineWrapping:!0,mode:s[s.length-1]});r.each(d,(t,i)=>{e.setOption(t,i)}),e.on("change",()=>{o.Validation.markFieldAsChanged(t)}),e.addPanel(n.createPanelNode("bottom",t.attr("alt")),{position:"bottom",stable:!0})}),t.prop("is_t3editor",!0)}}return new n})); \ No newline at end of file