0

私がこのhtmlを持っているとしましょう:

<div class="edit" contenteditable="true">
   <b>Example text</b>
   Text outside
   <b>
      <i>
         <u>underlined and italic and bold</u>
      italic and bold</i></b>
   more Text
   <br>
   after the line break
</div>

そして、便宜上、指定された要素内の選択範囲の終わりのオフセットを返すこの JavaScript 関数があります。

var getCaretCharacterOffsetWithin = function(element) {
  var caretOffset = 0;
  if (typeof window.getSelection != "undefined") {
    var range = window.getSelection().getRangeAt(0);
    var preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(element);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    caretOffset = preCaretRange.toString().length;
  } else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
    var textRange = document.selection.createRange();
    var preCaretTextRange = document.body.createTextRange();
    preCaretTextRange.moveToElementText(element);
    preCaretTextRange.setEndPoint("EndToEnd", textRange);
    caretOffset = preCaretTextRange.text.length;
  }
  return caretOffset;
 }

outsideユーザーが で始まり、その範囲内で終わる選択を行ったとしますitalic and bold。これは次のようになります。

"outsideunderlined and italic and bolditalic and bo"

<b>Example text</b>この文字列全体を、選択した後のテキストを損傷することなく置き換えるにはどうすればよいでしょうか。置き換える文字列が空の文字列""の場合、結果は次のようになります。

<div class="edit" contenteditable="true">
   <b>Example text</b>
   Text 
   ld
   more Text
   <br>
   after the line break
</div>

選択範囲内のタグが保持されているかどうかは気にしません。どちらの方法が簡単かわかりません。

ご不明な点がございましたら、お尋ねください。

よろしくお願いいたします。

4

1 に答える 1

1

この回答は IE8 向けではありません (今のところ)。この関数は、選択したテキストを置き換え、replaceString新しく挿入されたノードを選択します。後で DOM を正規化する必要がある場合があります。これは、隣接するテキスト ノードまたは空のテキスト ノードである可能性があります。

わからないことがあれば聞いてください。

function replSel(replaceString) {
    var sel = getSelection(), rng, startNode, endNode, comAnc, sOff;
    if (sel.rangeCount) {
        rng = sel.getRangeAt(0);
        sOff = rng.startOffset;
        if (rng.startContainer === rng.endContainer) {
            rng.endContainer.nodeValue =
                  rng.endContainer.nodeValue.substring(0, sOff) + replaceString
                  + rng.endContainer.nodeValue.substring(rng.endOffset);
            rng.setStart(rng.startContainer, sOff);
            rng.setEnd(rng.endContainer, sOff + replaceString.length);
        } else {
            comAnc = rng.commonAncestorContainer;
            rng.startContainer.nodeValue =
                    rng.startContainer.nodeValue.substring(0, sOff);
            // rng.startOffset is set to 0 when the node value is changed
            // That's fine for the range's end, but not for the start.
            rng.setStart(rng.startContainer, sOff);
            rng.endContainer.nodeValue =
                    rng.endContainer.nodeValue.substring(rng.endOffset);
            startNode = rng.startContainer;
            while (startNode.parentNode !== comAnc) {
                while (startNode.nextSibling)
                    startNode.parentNode.removeChild(startNode.nextSibling);
                startNode = startNode.parentNode;
            }
            endNode = rng.endContainer;
            while (endNode.parentNode !== comAnc) {
                while (endNode.previousSibling)
                    endNode.parentNode.removeChild(endNode.previousSibling);
                endNode = endNode.parentNode;
            }
            while (startNode.nextSibling !== endNode)
                comAnc.removeChild(startNode.nextSibling);
            comAnc.insertBefore(
                    document.createTextNode(replaceString), endNode);
        }
        sel.removeAllRanges();
        sel.addRange(rng);
    }
}
于 2013-04-24T20:17:15.040 に答える