假设我有这个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>
我不关心选择中的标签是否保留我不确定哪种方式更容易。
如果您不清楚,请询问。
提前感谢您的帮助。
答案 0 :(得分: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);
}
}