Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 65 additions & 49 deletions src/main/java/org/vaadin/tinymce/TinyMce.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,31 @@
*/
@Tag("div")
@JavaScript("context://frontend/tinymceConnector.js")
@StyleSheet("context://frontend/tinymceLumo.css")
@StyleSheet("context://frontend/tinymce.css")
public class TinyMce extends AbstractCompositeField<Div, TinyMce, String>
implements HasSize, Focusable<TinyMce> {
implements HasSize, Focusable<TinyMce> {

/**
* Marks {@code <html>} with a class ("aura" or "lumo") matching the
* application's active theme, so that {@code tinymce.css} can scope its
* rules with the corresponding design tokens.
*/
private static final String DETECT_AND_APPLY_THEME_CLASS = """
const s = getComputedStyle(document.documentElement);
const t = s.getPropertyValue('--vaadin-aura-theme').trim() === '1' ? 'aura'
: (s.getPropertyValue('--vaadin-lumo-theme').trim() === '1' ? 'lumo' : '');
if (t) {
document.documentElement.classList.add(t);
}
""";

private final DomListenerRegistration domListenerRegistration;
private String id;
private boolean initialContentSent;
private String currentValue = "";
private String rawConfig;
ObjectNode config = JsonNodeFactory.instance.objectNode();
private Element ta = new Element("div");
private final Element ta = new Element("div");

private int debounceTimeout = 0;
private boolean basicTinyMCECreated;
Expand All @@ -77,7 +91,7 @@ public class TinyMce extends AbstractCompositeField<Div, TinyMce, String>
* mode.
*
* @deprecated No longer needed since version x.x
*
*
* @param shadowRoot
* true of shadow root hack should be used
*/
Expand All @@ -94,14 +108,14 @@ public TinyMce(boolean shadowRoot) {
}

domListenerRegistration = getElement().addEventListener("tchange",
(DomEventListener) event -> {
boolean value = event.getEventData()
.has("event.htmlString");
String htmlString = event.getEventData()
.get("event.htmlString").asString();
currentValue = htmlString;
setModelValue(htmlString, true);
});
(DomEventListener) event -> {
boolean value = event.getEventData()
.has("event.htmlString");
String htmlString = event.getEventData()
.get("event.htmlString").asString();
currentValue = htmlString;
setModelValue(htmlString, true);
});
domListenerRegistration.addEventData("event.htmlString");
domListenerRegistration.debounce(debounceTimeout);
}
Expand Down Expand Up @@ -193,6 +207,7 @@ protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
if (attachEvent.isInitialAttach())
injectTinyMceScript();
attachEvent.getUI().getPage().executeJs(DETECT_AND_APPLY_THEME_CLASS);
initConnector();
saveOnClose();
}
Expand All @@ -202,8 +217,8 @@ protected void onDetach(DetachEvent detachEvent) {
// See https://github.com/parttio/tinymce-for-flow/issues/33
if (isVisible()) {
detachEvent.getUI().getPage().executeJs("""
tinymce.get($0).remove();
""", id);
tinymce.get($0).remove();
""", id);
}
super.onDetach(detachEvent);
initialContentSent = false;
Expand All @@ -215,7 +230,7 @@ protected void onDetach(DetachEvent detachEvent) {
private void initConnector() {

runBeforeClientResponse(ui -> {
if(rawConfig == null) {
if (rawConfig == null) {
rawConfig = "{}";
}
ui.getPage().executeJs(
Expand All @@ -224,18 +239,19 @@ private void initConnector() {
"window.Vaadin.Flow.tinymceConnector.initLazy(rawconfig, $0, $1, $2, $3, $4)",
getElement(), ta, config, currentValue,
(enabled && !readOnly))
.then(res -> initialContentSent = true);
.then(res -> initialContentSent = true);
});
}
private void saveOnClose(){

private void saveOnClose() {
runBeforeClientResponse(ui -> {
getElement().callJsFunction("$connector.saveOnClose");});
getElement().callJsFunction("$connector.saveOnClose");
});
}

void runBeforeClientResponse(SerializableConsumer<UI> command) {
getElement().getNode().runWhenAttached(ui -> ui
.beforeClientResponse(this, context -> command.accept(ui)));
.beforeClientResponse(this, context -> command.accept(ui)));
}

public String getCurrentValue() {
Expand Down Expand Up @@ -294,7 +310,7 @@ public TinyMce configureLanguage(Language language) {
*/
public void replaceSelectionContent(String htmlString) {
runBeforeClientResponse(ui -> getElement().callJsFunction(
"$connector.replaceSelectionContent", htmlString));
"$connector.replaceSelectionContent", htmlString));
}

/**
Expand All @@ -305,49 +321,49 @@ public void replaceSelectionContent(String htmlString) {
*/
protected void injectTinyMceScript() {
getUI().get().getPage().addJavaScript(
"context://frontend/tinymce_addon/tinymce/tinymce.min.js");
"context://frontend/tinymce_addon/tinymce/tinymce.min.js");
}

@Override
public void focus() {
runBeforeClientResponse(ui -> {
// Dialog has timing issues...
getElement().executeJs("""
const el = this;
if(el.$connector.isInDialog()) {
setTimeout(() => {
el.$connector.focus()
}, 150);
} else {
el.$connetor.focus();
}
""");
const el = this;
if(el.$connector.isInDialog()) {
setTimeout(() => {
el.$connector.focus()
}, 150);
} else {
el.$connetor.focus();
}
""");
;
});
}

@Override
public Registration addFocusListener(
ComponentEventListener<FocusEvent<TinyMce>> listener) {
ComponentEventListener<FocusEvent<TinyMce>> listener) {
DomListenerRegistration domListenerRegistration = getElement()
.addEventListener("tfocus", event -> listener
.onComponentEvent(new FocusEvent<>(this, false)));
.addEventListener("tfocus", event -> listener
.onComponentEvent(new FocusEvent<>(this, false)));
return domListenerRegistration;
}

@Override
public Registration addBlurListener(
ComponentEventListener<BlurEvent<TinyMce>> listener) {
ComponentEventListener<BlurEvent<TinyMce>> listener) {
DomListenerRegistration domListenerRegistration = getElement()
.addEventListener("tblur", event -> listener
.onComponentEvent(new BlurEvent<>(this, false)));
.addEventListener("tblur", event -> listener
.onComponentEvent(new BlurEvent<>(this, false)));
return domListenerRegistration;
}

@Override
public void blur() {
throw new RuntimeException(
"Not implemented, TinyMce does not support programmatic blur.");
"Not implemented, TinyMce does not support programmatic blur.");
}

@Override
Expand All @@ -360,7 +376,7 @@ private void adjustEnabledState() {
boolean reallyEnabled = this.enabled && !this.readOnly;
super.setEnabled(reallyEnabled);
runBeforeClientResponse(ui -> getElement()
.callJsFunction("$connector.setEnabled", reallyEnabled));
.callJsFunction("$connector.setEnabled", reallyEnabled));
}

@Override
Expand All @@ -375,7 +391,7 @@ protected void setPresentationValue(String html) {
this.currentValue = html;
if (initialContentSent) {
runBeforeClientResponse(ui -> getElement()
.callJsFunction("$connector.setEditorContent", html));
.callJsFunction("$connector.setEditorContent", html));
}
}

Expand All @@ -384,15 +400,15 @@ private TinyMce createBasicTinyMce() {
this.configure("branding", false);
this.basicTinyMCECreated = true;
this.configurePlugin(false, Plugin.AUTOLINK,
Plugin.LISTS, Plugin.SEARCH_REPLACE);
Plugin.LISTS, Plugin.SEARCH_REPLACE);
this.configureMenubar(false, Menubar.FILE, Menubar.EDIT, Menubar.VIEW,
Menubar.FORMAT);
Menubar.FORMAT);
this.configureToolbar(false, Toolbar.UNDO, Toolbar.REDO,
Toolbar.SEPARATOR, Toolbar.BLOCKS, Toolbar.SEPARATOR,
Toolbar.BOLD, Toolbar.ITALIC, Toolbar.SEPARATOR,
Toolbar.ALIGN_LEFT, Toolbar.ALIGN_CENTER, Toolbar.ALIGN_RIGHT,
Toolbar.ALIGN_JUSTIFY, Toolbar.SEPARATOR, Toolbar.OUTDENT,
Toolbar.INDENT);
Toolbar.SEPARATOR, Toolbar.BLOCKS, Toolbar.SEPARATOR,
Toolbar.BOLD, Toolbar.ITALIC, Toolbar.SEPARATOR,
Toolbar.ALIGN_LEFT, Toolbar.ALIGN_CENTER, Toolbar.ALIGN_RIGHT,
Toolbar.ALIGN_JUSTIFY, Toolbar.SEPARATOR, Toolbar.OUTDENT,
Toolbar.INDENT);
return this;

}
Expand Down Expand Up @@ -422,7 +438,7 @@ public TinyMce configureMenubar(boolean basicTinyMCE, Menubar... menubars) {
}

String newconfig = Arrays.stream(menubars).map(m -> m.menubarLabel)
.collect(Collectors.joining(" "));
.collect(Collectors.joining(" "));

String menubar;
if (config.has("menubar")) {
Expand Down Expand Up @@ -450,7 +466,7 @@ public TinyMce configureToolbar(boolean basicTinyMCE, Toolbar... toolbars) {

for (int i = 0; i < toolbars.length; i++) {
toolbarStr = toolbarStr.concat(" ").concat(toolbars[i].toolbarLabel)
.concat(" ");
.concat(" ");
}

config.put("toolbar", toolbarStr);
Expand Down
Loading