InsertHtml for GWT RichTextArea without exiting formatting

I am using GWT RichTextArea and I need to paste the text at the current cursor position. I read about using the RichTextArea.getFormatter () method. InsertHTML () as a way to do this, and it works great.

My problem is that instead of pasting my text as raw HTML at the cursor position, it closes the current HTML formatting tags and then re-opens new ones around my HTML. To clarify, I am not actually inserting any type of HTML string, just text. Here is an example:

Original HTML:

<font size="2">Walk the dog</font> 

If my cursor is placed after "d" and I call insertHTML ("ASDF"), my resulting html will be as follows:

 <font size="2">Walk the d</font>ASDF<font size="2">og</font> 

Is there any way to avoid this formatting? I need the text to be formatted in the same way as the surrounding text. When a user enters text manually, he does it correctly. I need to do the same in a script.

I am not familiar with coding my own javascript in GWT, but I decided that there might be an easy way to achieve this using my own method. Any ideas on how I can achieve this will be appreciated. I can obviously do some HTML post processing to remove the tags, but I would like to avoid this.

+4
source share
2 answers

Disclaimer: I am not a JavaScript expert, and my answer may not work in all browsers. Feel free to point out any errors or ways to improve my answer so that it works in all browsers.

The RichTextArea.getFormatter().insertHTML() method calls the JavaScript executeCommand("insertHTML", ...) method, which, as I understand it, creates a node child at the current position if the parent formatting is violated. Therefore, any insertHTML method insertHTML not give the desired behavior.

Rather, you should get a text object that contains the current position, and use insertData(pos, text) to insert new text. This can be easily done by extending the RichTextArea class and adding the JSNI method.

<h / "> In the following example, I extended the RichTextArea class and added the following JSNI method:

 public class CustomRichTextArea extends RichTextArea { public native void insertText(String text, int pos) /*-{ var elem = this.@com.google.gwt.user.client.ui.UIObject ::getElement()(); var refNode = elem.contentWindow.getSelection().getRangeAt(0).endContainer; refNode.insertData(pos, text); }-*/; } 

The insertText method gets the text object associated with the current selection, and then inserts the text at the specified position in this text object. This code provides your desired behavior, but I only tested it in Chrome.
In addition, this method can be improved by automatically searching for the current position - getting the current position of RichTextArea is a completely different topic .

I tested the above snippet with the following entry point:

  private CustomRichTextArea crta; public void onModuleLoad() { crta = new CustomRichTextArea(); crta.ensureDebugId("cwRichText-area"); crta.setSize("100%", "14em"); RichTextToolbar toolbar = new RichTextToolbar(crta); toolbar.ensureDebugId("cwRichText-toolbar"); toolbar.setWidth("100%"); Button b = new Button(); b.setText("Insert HTML"); b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { crta.setFocus(true); crta.insertText("ASDF", ((int)crta.getText().length() / 2)); } }); Grid grid = new Grid(2, 1); grid.setStyleName("cw-RichText"); grid.setWidget(0, 0, toolbar); grid.setWidget(1, 0, crta); // display: RootPanel.get().add(grid); RootPanel.get().add(b); } 

Where I got the RichTextToolbar from a project in GoogleCode.

+1
source

So, right after I published the generosity, I thought of an imperfect but reliable way.

I realized that I have full HTML before and after I call insertHtml. With these two lines of HTML, I can safely identify the HTML block that was inserted through my insertHtml call. Therefore, I can easily remove the HTML that was inserted and replace it with the original again. Here is my code snippet to do this if this is not clear.

 String originalHtml = richTextArea.getHTML(); richTextArea.getFormatter().insertHTML(text); String newHtml = richTextArea.getHTML(); int origLength = originalHtml.length(); int newLength = newHtml.length(); int startPos = -1; int endPos = -1; for (int i = 0; i < origLength; i++) { if (originalHtml.charAt(i) != newHtml.charAt(i)) { startPos = i; break; } } for (int i = 0; i < origLength; i++) { if (originalHtml.charAt(origLength - i - 1) != newHtml.charAt(newLength - i - 1)) { endPos = newLength - i; break; } } String finalHtml = newHtml.substring(0, startPos) + text + newHtml.substring(endPos); richTextArea.setHTML(finalHtml); 

So this is not the cleanest solution, but as far as I know, it should always work. I call getHTML, insertHTML, getHTML and setHTML in RichTextArea when only one insertion algorithm is needed. I still prefer a direct solution if anyone comes up with a better option.

+1
source

Source: https://habr.com/ru/post/1483387/


All Articles