2013-05-29 14 views
4

我使用GWT RichTextArea,需要在當前光標位置插入文本。我讀了有關使用方法RichTextArea.getFormatter()。insertHTML()的方式來做到這一點,它的正常工作。insertHtml爲GWT RichTextArea而不退出格式化

我的一個問題是,而不是插入我的文字爲原料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上做一些後期處理來刪除標籤,但我想避免這種情況。

回答

1

聲明:我不是一位JavaScript專家,我的答案可能無法在所有瀏覽器中使用。隨意指出任何錯誤或方法來改善我的答案,使其適用於所有瀏覽器。

RichTextArea.getFormatter().insertHTML()方法調用了executeCommand("insertHTML", ...) JavaScript方法,據我所知,它在當前位置創建一個子節點,同時打破父級的格式。因此,任何insertHTML方法都不會提供所需的行爲。

相反,您應該得到包含當前位置的文本對象,並使用insertData(pos, text)插入新文本。這可以通過擴展類和添加JSNI方法輕鬆完成。


在以下示例中,我延長類和增加了以下JSNI方法:

public class CustomRichTextArea extends RichTextArea { 

    public native void insertText(String text, int pos) /*-{ 
     var elem = [email protected]::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

+0

謝謝。這是我正在尋找的。特別是,我實際上將光標移動到令人討厭的文本區域的開始處。將光標放回被證明是困難的。 – Zip184

+0

嘿,我問了一個關於你寫給我的javascript方法的問題。 http://stackoverflow.com/q/17112095/637777你可以回答它;) – Zip184

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