4

我正在使用 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 进行一些后期处理以删除标签,但我想避免这种情况。

4

2 回答 2

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。如果有人提出更好的解决方案,我仍然更喜欢直接解决方案。

于 2013-06-03T21:15:39.740 回答
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 的当前位置是完全不同的主题

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

    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的地方。

于 2013-06-08T22:18:28.037 回答