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 回答