From df7ae7ed00ecabc42427ebeb71637a02daab6f2b Mon Sep 17 00:00:00 2001 From: Phil Caisip Date: Fri, 7 Jun 2024 12:28:17 +1000 Subject: [PATCH 01/11] Add base code and unit test for RTF port Starting simple code to port RTF registration from XSLT into HTML custom components. Still need some way of testing actual TinyMCE import and use. --- wcomponents-theme/src/main/js/wc/ui/rtf.mjs | 11 +++++++++++ .../src/test/spec/wc.ui.rtf.test.mjs | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 wcomponents-theme/src/test/spec/wc.ui.rtf.test.mjs diff --git a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs index 51a1058a7..8a29fb657 100755 --- a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs +++ b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs @@ -72,3 +72,14 @@ export default { } } }; + +const rtfTag = "wc-rtf"; +class WRichTextField extends HTMLElement { + connectedCallback() { + instance.register([this.getAttribute("id")]); + } +} + +if (!customElements.get(rtfTag)) { + customElements.define(rtfTag, WRichTextField); +} diff --git a/wcomponents-theme/src/test/spec/wc.ui.rtf.test.mjs b/wcomponents-theme/src/test/spec/wc.ui.rtf.test.mjs new file mode 100644 index 000000000..350c3f21c --- /dev/null +++ b/wcomponents-theme/src/test/spec/wc.ui.rtf.test.mjs @@ -0,0 +1,17 @@ +import rtf from "wc/ui/rtf.mjs"; +import timers from "wc/timers.mjs"; +import initialise from "wc/dom/initialise.mjs"; + +describe("wc/ui/rtf", () => { + + it("it sets a callback for every nonempty invocation of register", (done) => { + spyOn(initialise, "addCallback"); + rtf.register(["exID", "anotherEx"]); + rtf.register(["exID"]); + rtf.register([]); + timers.setTimeout(function() { + expect(initialise.addCallback).toHaveBeenCalledTimes(2); + done(); + }, 100); + }); +}); From 25911d24809f0d076b0716866d628d0633d5fa8d Mon Sep 17 00:00:00 2001 From: Phil Caisip Date: Fri, 14 Jun 2024 15:12:31 +1000 Subject: [PATCH 02/11] Fix TinyMCE url formation bug TinyMCE adds its own forward slash when stringing together urls for loading plugins ands themes etc. This made a double // in the url since resourceLoader takes urls with the / suffix already there. This extra / is currently being cut off in rtf.mjs. Although, it may be better off getting cut in resourceLoader.getUrlFromImportMap(). --- wcomponents-theme/src/main/js/wc/ui/rtf.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs index 8a29fb657..07fff3e81 100755 --- a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs +++ b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs @@ -45,7 +45,7 @@ function processNow(idArr) { } } -export default { +const instance = { /** * Register Rich Text Fields that need to be initialised. * @@ -58,7 +58,10 @@ export default { const callback = () => processNow(idArr); initialise.addCallback((element) => { if (!tinyMCE) { - const baseUrl = resourceLoader.getUrlFromImportMap("tinymce/"); + let baseUrl = resourceLoader.getUrlFromImportMap("tinymce/"); + while (baseUrl.charAt(baseUrl.length - 1) === '/') { + baseUrl = baseUrl.substring(0, baseUrl.length - 1); + } return import("tinymce/tinymce.js").then(() => { tinyMCE = element.ownerDocument.defaultView.tinymce; if (baseUrl) { @@ -73,10 +76,12 @@ export default { } }; +export default instance; + const rtfTag = "wc-rtf"; class WRichTextField extends HTMLElement { connectedCallback() { - instance.register([this.getAttribute("id")]); + // instance.register([this.getAttribute("id")]); } } From 5783ef36b73b84aaec3b9e3d0a94964f49d5e795 Mon Sep 17 00:00:00 2001 From: Phil Caisip Date: Tue, 18 Jun 2024 13:39:11 +1000 Subject: [PATCH 03/11] Remodel renderers and XSLT to fit new HTML customs Switched from using the ui:rtf element in the raw XML to using wc-rtf custom HTML components. Still need a way to import the rtf module without the XSLT and to do further unit testing to get better coverage on rtf.mjs. --- .../wcomponents/render/webxml/WTextAreaRenderer.java | 2 +- wcomponents-theme/src/main/js/wc/ui/rtf.mjs | 5 ++++- wcomponents-xslt/src/main/xslt/all.xsl | 6 ++---- wcomponents-xslt/src/main/xslt/wc.ui.textarea.xsl | 9 +++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WTextAreaRenderer.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WTextAreaRenderer.java index dde6e0447..9f553589b 100755 --- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WTextAreaRenderer.java +++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WTextAreaRenderer.java @@ -66,7 +66,7 @@ public void doRender(final WComponent component, final WebXmlRenderContext rende * such as turning rich text features on or off, or specifying JSON config either as * a URL attribute or a nested CDATA section. */ - xml.append(""); + xml.append(""); } String textString = textArea.getText(); diff --git a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs index 07fff3e81..b422cd17a 100755 --- a/wcomponents-theme/src/main/js/wc/ui/rtf.mjs +++ b/wcomponents-theme/src/main/js/wc/ui/rtf.mjs @@ -59,9 +59,12 @@ const instance = { initialise.addCallback((element) => { if (!tinyMCE) { let baseUrl = resourceLoader.getUrlFromImportMap("tinymce/"); + + // remove trailing forward slash since TinyMCE adds its own while (baseUrl.charAt(baseUrl.length - 1) === '/') { baseUrl = baseUrl.substring(0, baseUrl.length - 1); } + return import("tinymce/tinymce.js").then(() => { tinyMCE = element.ownerDocument.defaultView.tinymce; if (baseUrl) { @@ -81,7 +84,7 @@ export default instance; const rtfTag = "wc-rtf"; class WRichTextField extends HTMLElement { connectedCallback() { - // instance.register([this.getAttribute("id")]); + instance.register([this.parentElement.getAttribute("id")]); } } diff --git a/wcomponents-xslt/src/main/xslt/all.xsl b/wcomponents-xslt/src/main/xslt/all.xsl index 328c51631..2f8e4ed84 100644 --- a/wcomponents-xslt/src/main/xslt/all.xsl +++ b/wcomponents-xslt/src/main/xslt/all.xsl @@ -334,7 +334,7 @@ select=".//ui:dropdown[@data and not(@type) and not(@readOnly)] | .//ui:listbox[@data and not(@readOnly)] | .//ui:shuffler[@data and not(@readOnly)]" /> - + @@ -388,9 +388,7 @@ ]);}); - import("wc/ui/rtf.mjs").then(({ default: c }) => {c.register([ - - ]);}); + import("wc/ui/rtf.mjs"); import("wc/ui/containerload.mjs").then(({ default: c }) => {c.register([ diff --git a/wcomponents-xslt/src/main/xslt/wc.ui.textarea.xsl b/wcomponents-xslt/src/main/xslt/wc.ui.textarea.xsl index 3be0b89f8..53ac5eb67 100644 --- a/wcomponents-xslt/src/main/xslt/wc.ui.textarea.xsl +++ b/wcomponents-xslt/src/main/xslt/wc.ui.textarea.xsl @@ -21,7 +21,7 @@ - div + div pre @@ -41,7 +41,7 @@ - + @@ -58,7 +58,7 @@ - + div @@ -166,10 +166,11 @@