Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 替换contenteditable div中的单词并正确设置插入符号位置_Javascript_Range_Selection_Contenteditable - Fatal编程技术网

Javascript 替换contenteditable div中的单词并正确设置插入符号位置

Javascript 替换contenteditable div中的单词并正确设置插入符号位置,javascript,range,selection,contenteditable,Javascript,Range,Selection,Contenteditable,我已经搜索了很多与范围和选择相关的问题(大部分问题的答案是),但我不能完全得到我需要的,尽管我很接近 我想在当前关注的文本节点中搜索单词foo。如果我找到它-将其替换为条,并将插入符号位置设置在替换单词的末尾。例如: "Lorem ipsum dolor foo amet, consectetur adipiscing elit." 变成: "Lorem ipsum dolor bar amet, consectetur adipiscing elit." // ---------------

我已经搜索了很多与范围和选择相关的问题(大部分问题的答案是),但我不能完全得到我需要的,尽管我很接近

我想在当前关注的文本节点中搜索单词
foo
。如果我找到它-将其替换为
,并将插入符号位置设置在替换单词的末尾。例如:

"Lorem ipsum dolor foo amet, consectetur adipiscing elit."
变成:

"Lorem ipsum dolor bar amet, consectetur adipiscing elit."
// -------------------^--- caret position
我的尝试 我目前拥有的东西只起到了一半的作用——它删除了文本,但没有添加任何内容。不过,我不确定这是不是最好的方法:

函数替换器(搜索、替换){
var sel=window.getSelection();
if(!sel.focusNode){
返回;
}
var startIndex=sel.focusNode.nodeValue.indexOf(搜索);
var endIndex=startIndex+search.length;
如果(startIndex==-1){
返回;
}
var range=document.createRange();
range.setStart(选择聚焦节点、起始索引);
range.setEnd(sel.focusNode,endIndex);
range.insertNode(document.createTextNode(“bar”);
选择removeAllRanges();
选择添加范围(范围);
}
document.addEventListener(“按键”,函数(){
替换者(“foo”、“bar”);
});

Lorem ipsum dolor foo amet,Concetetur Adipising Elite.
在代码注释和控制台日志中解释。
了解

函数替换器(搜索、替换){
var sel=window.getSelection();
if(!sel.focusNode){
返回;
}
var startIndex=sel.focusNode.nodeValue.indexOf(搜索);
var endIndex=startIndex+search.length;
如果(startIndex==-1){
返回;
}
log(“第一个焦点节点:”,sel.focusNode.nodeValue);
var range=document.createRange();
//将范围设置为包含搜索文本
range.setStart(选择聚焦节点、起始索引);
range.setEnd(sel.focusNode,endIndex);
//删除搜索文本
range.deleteContents();
log(“删除后的焦点节点:”,sel.focusNode.nodeValue);
//插入替换文本
range.insertNode(document.createTextNode(replace));
log(“插入后的焦点节点:”,sel.focusNode.nodeValue);
//将插入符号移动到替换文本的末尾
选择折叠(选择聚焦节点,0);
}
document.addEventListener(“按键”,函数(){
替换者(“foo”、“bar”);
});

Lorem ipsum dolor foo amet,Concertetur Adipising Elite.
sidoshi,这修复了更换后插入符号的位置

函数替换器(搜索、替换){
var sel=window.getSelection();
if(!sel.focusNode){
返回;
}
var startIndex=sel.focusNode.nodeValue.indexOf(搜索);
var endIndex=startIndex+search.length;
如果(startIndex==-1){
返回;
}
log(“第一个焦点节点:”,sel.focusNode.nodeValue);
var range=document.createRange();
//将范围设置为包含搜索文本
range.setStart(选择聚焦节点、起始索引);
range.setEnd(sel.focusNode,endIndex);
//删除搜索文本
range.deleteContents();
log(“删除后的焦点节点:”,sel.focusNode.nodeValue);
//插入替换文本
range.insertNode(document.createTextNode(replace));
log(“插入后的焦点节点:”,sel.focusNode.nodeValue);
//将插入符号移动到替换文本的末尾
var replacement=document.createTextNode(replace);
range.insertNode(替换);
范围。设置开始后(更换);
//镀铬
选择removeAllRanges();
选择添加范围(范围);
}
document.addEventListener(“按键”,函数(){
替换者(“foo”、“bar”);
});

Lorem ipsum dolor foo amet,连续追踪精英。
使用
createNodeIterator
NodeFilter.SHOW_TEXT
迭代所有文本节点,在这种情况下,很容易找到字符串
foo
的所有匹配项,并用所需的
bar
文本节点替换

第二阶段应与查找和替换函数分离,即插入符号放置请求,由函数
setRangeAtEnd
实现,该函数接收单个参数
node
,该参数可从第一个函数
replacetTextWithNode
的输出中获得,它返回contentEditable中替换的所有节点的数组

const elm=document.querySelector(“[contenteditable]”);
函数replaceTextWithNode(elm、text、replacerNode){
var iter=document.createNodeIterator(elm,NodeFilter.SHOW_TEXT),
textnode、replacedNode、idx、newNode、,
最大迭代次数=100,
addedNodes=[];
while(textnode=iter.nextNode()){
如果(!maxIterations--)中断;
//获取文本位于textNode中的索引(如果有的话)
idx=textnode.nodeValue.indexOf(文本)
如果(idx==-1)继续
replacedNode=textnode.splitText(idx)
newNode=replacerNode.cloneNode()
//清理标记的字符串并放置标记元素
replacedNode.nodeValue=replacedNode.nodeValue.replace(文本“”)
textnode.parentNode.insertBefore(newNode,replacedNode)
addedNodes.push(新节点)
}
返回加法节点
}
函数设置范围结束(节点){
node=node.firstChild | | node;
const sel=document.getSelection()
如果(选择范围计数)
['Start','End'].forEach(位置=>
sel.getRangeAt(0)[“set”+pos](节点,节点长度)
)
}
//将所有“foo”替换为“bar”文本节点
var addedNodes=replaceTextWithNode(elm,'foo',document.createTextNode('bar'))
//将插入符号放在“bar”的最后一次出现处
埃尔姆·福克斯
设置范围结束(addedNodes[addedNodes.length-1])

Lorem ipsum foo dolor foo amet foo,Concetetur adipiscing Elite.
非常感谢!你能解释一下为什么它会起作用吗?插入符号不应该设置在文本节点的第一个字符处,即单词“Lorem”之前吗?我更新我的答案以添加注释和控制台日志。请检查它,并随时提出更多问题。@duanx当我键入foo-caret转到第一位时,您能看到这个吗。我已经将textnode更改为html Node