不退出格式的GWT RichTextArea的insertHtml

时间:2013-05-29 15:49:44

标签: javascript gwt

我正在使用GWT RichTextArea,需要在当前光标位置插入文本。我读到了使用方法RichTextArea.getFormatter()。insertHTML()作为一种方法来做到这一点并且它工作正常。

我的一个问题是,不是将我的文本作为原始HTML插入光标位置,而是关闭当前格式化HTML标记,然后在HTML周围重新打开新标记。为了澄清,我实际上并没有插入任何类型的HTML字符串,只是文本。这是一个例子:

原始HTML:

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

如果我的光标位于“d”之后,并且我调用了insertHTML(“ASDF”),那么我生成的html将是:

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

有没有办法可以避免这种格式转义?我需要将文本格式化为与周围文本相同的格式。当用户手动输入文本时,它会正确执行此操作。我需要在脚本中做同样的事情。

我不熟悉GWT中的原生javascript编码,但我想可能有一种简单的方法可以使用本机方法实现这一点。关于如何实现这一点的任何想法将不胜感激。我显然可以对HTML进行一些后处理以删除标签,但我想避免这种情况。

2 个答案:

答案 0 :(得分:1)

因此,在我发布赏金之后,我想到了一个非理想但有力的方法。

我意识到在调用insertHtml之前和之后我都有完整的HTML。使用这两个HTML字符串,我可以安全地识别通过我的insertHtml调用插入的HTML块。因此,我可以轻松删除插入的HTML,并将其替换为原始文本。这是我的代码片段,以便在不清楚的情况下执行此操作。

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);

所以这不是最干净的解决方案,但据我所知,它应该始终有效。当只需要一个插入算法时,我在RichTextArea上调用getHTML,insertHTML,getHTML和setHTML。如果有人提出更好的解决方案,我仍然更喜欢直接的解决方案。

答案 1 :(得分:1)

免责声明:我不是JavaScript专家,我的回答可能不适用于所有浏览器。请随意指出任何错误或方法来改进我的答案,使其适用于所有浏览器。

RichTextArea.getFormatter().insertHTML()方法调用executeCommand("insertHTML", ...) JavaScript方法,据我所知,该方法在打破父级格式的同时在当前位置创建子节点。因此,任何insertHTML方法都不会提供所需的行为。

相反,您应该获取包含当前位置的文本对象,并使用 insertData(pos, text) 插入新文本。这可以通过扩展RichTextArea类并添加JSNI方法轻松完成。

<小时/> 在以下示例中,我扩展了RichTextArea类并添加了以下JSNI方法:

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);
    }-*/;
}

insertText方法获取与当前选择关联的文本对象,然后将文本插入该文本对象中的指定位置。此代码提供了您想要的行为,但我仅在Chrome中对此进行了测试 此外,可以通过自动查找当前位置来改进此方法 - 获取RichTextArea的当前位置是completely different topic

我使用以下入口点测试了上面的代码:

    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);
    }

我从GoogleCode上的项目中获得了RichTextToolbar