【发布时间】:2011-04-29 04:47:49
【问题描述】:
我一直在寻找答案,但都失败了。
是否有跨浏览器解决方案来替换 contenteditable div 中的选定文本?
我只是希望用户突出显示一些文本并将突出显示的文本替换为xxxxx。
【问题讨论】:
标签: javascript contenteditable
我一直在寻找答案,但都失败了。
是否有跨浏览器解决方案来替换 contenteditable div 中的选定文本?
我只是希望用户突出显示一些文本并将突出显示的文本替换为xxxxx。
【问题讨论】:
标签: javascript contenteditable
以下将在所有主要浏览器中完成这项工作:
function replaceSelectedText(replacementText) {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(replacementText));
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.text = replacementText;
}
}
【讨论】:
rangy 代码(替换 iframe 上的文本节点)。使用sel.setSingleRange(range) 不选择replacementText 是否正常?
getSelection 在使用表单字段时不会在 Firefox 中捕获所选文本:bugzilla.mozilla.org/show_bug.cgi?id=85686
if (document.queryCommandSupported('insertText')) { document.execCommand( 'insertText', false, replacementText ); } else { range.deleteContents(); range.insertNode(document.createTextNode(replacementText)); }
我在how to add emoji in between the letters in contentEditable div? 上发布了一个工作示例,您可以使用它来替换内容可编辑 div 中所需的文本
function pasteHtmlAtCaret(html) {
let sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
const el = document.createElement("div");
el.innerHTML = html;
let frag = document.createDocumentFragment(),
node,
lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
function addToDiv(event) {
const emoji = event.target.value;
const chatBox = document.getElementById("chatbox");
chatBox.focus();
pasteHtmlAtCaret(`<b>${emoji}</b>`);
}
function generateEmojiIcon(emoji) {
const input = document.createElement("input");
input.type = "button";
input.value = emoji;
input.innerText = emoji;
input.addEventListener("click", addToDiv);
return input;
}
const emojis = [
{
emoji: "?",
},
{
emoji: "❤️",
},
];
emojis.forEach((emoji) => {
document
.getElementById("emojis")
.appendChild(generateEmojiIcon(emoji.emoji));
});
#emojis span {
cursor: pointer;
}
#chatbox {
border: 1px solid;
}
<button
type="button"
onclick="document.getElementById('chatbox').focus();
pasteHtmlAtCaret('<b>INSERTED</b>'); "
>
Paste HTML
</button>
<div id="emojis"></div>
<div id="chatbox" contenteditable></div>
【讨论】:
<b>INSERTED</b> 和 <b>${emoji}</b> 中的标签 b。您可以使用 innerText 代替它,只需对 sn-p 代码进行一些更改...
我需要替换文本节点,并在粘贴时保留 html 实体。 这就是我解决问题的方法,不确定 textnodes 中的 data,也许最好使用 textContent 或其他的东西
let selection = window.getSelection()
, range = selection.getRangeAt(0)
, fragment = range.extractContents();
fragment.childNodes.forEach( e => e.data && (e.data = doSomething(e.data)) );
range.insertNode(fragment);
【讨论】: