gpt4 book ai didi

javascript - 替换 contenteditable 中的特定单词

转载 作者:可可西里 更新时间:2023-11-01 02:38:30 26 4
gpt4 key购买 nike

我有一个 contenteditable 的 div

<div id="divTest" contenteditable="true">

我需要从插入符位置获取最后一个词,并且在某些情况下我必须测试并只删除这个特定的词。以下是我的表现

$('#divTest').on('keyup focus', function (e) {
if (e.keyCode == 32) {
var lastWord = getWordPrecedingCaret(this), spanLastWord = $('#lastWord');

}
});

function getWordPrecedingCaret(containerEl) {
var preceding = "",
sel,
range,
precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
preceding = range.toString();


}
} else if ((sel = document.selection) && sel.type != "Control") {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
preceding = precedingRange.text;
}

var words = range.toString().trim().split(' '),
lastWord = words[words.length - 1];
if (lastWord) {

var resultValue = 'some'; // this value is coming from some other function
if (resultValue == lastWord) {
alert('do nothing');
// do nothing
}
else
{
alert('replace word');
// delete That specific word and replace if with resultValue
}
return lastWord;

}
}

演示:http://codepen.io/anon/pen/ogzpXV

我试过 range.deleteContents();但这将删除 div 中的所有内容。我怎样才能只替换特定的单词?

最佳答案

Ranges 一起工作我们需要记住,我们正在使用节点,而不仅仅是渲染的文本。您要操作的结构是:

<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
</div>

但也可能是:

<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
"more text" <-- TextNode
"" <-- TextNode
</div>

要解决您的问题,只处理一个 TextNode 会更简单,我建议使用 normalize()函数将它们全部合并为一个。

那么你只需要将Range设置为deleteContents()之前的单词边界即可.删除后,您可以使用 insertNode() 替换插入新的 TextNode .

var wordStart = range.toString().lastIndexOf(lastWord);
var wordEnd = wordStart + lastWord.length;

/* containerEl.firstChild refers to the div's TextNode */
range.setStart(containerEl.firstChild, wordStart);
range.setEnd(containerEl.firstChild, wordEnd);
range.deleteContents();
range.insertNode(document.createTextNode(resultValue));

为此,您需要文本位于单个 TextNode 中。但在 ìnsertNode 之后,div 将包含多个文本节点。要解决此问题,只需调用 normalize()加入所有 TextNode 元素。

containerEl.normalize();

编辑:

正如 Basj 指出的那样,最初的解决方案对多行无效。那是因为当点击 ENTER 时,结构从:

<div id="divTest" contenteditable="true"> <-- Element Node
"some text" <-- TextNode
</div>

类似于:

<div id="divTest" contenteditable="true"> <-- Element Node
<div>"some text"</div>
<div>"more text"</div>
</div>

我已经更新了这个答案,但也值得一读 Basj's answer在这个问题上:Replace word before cursor, when multiple lines in contenteditable

JSFiddle demo或可运行的代码片段:

document.getElementById('divTest').onkeyup = function (e) {
if (e.keyCode == 32) {
getWordPrecedingCaret(this);
}
};

function getWordPrecedingCaret(containerEl) {
var preceding = "",
sel,
range,
precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
preceding = range.toString();
}
} else if ((sel = document.selection) && sel.type != "Control") {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
preceding = precedingRange.text;
}

var words = range.toString().trim().split(' '),
lastWord = words[words.length - 1];

if (lastWord) {
var resultValue = 'some'; // this value is coming from some other function
if (resultValue == lastWord) {
console.log('do nothing: ' + lastWord);
// do nothing
} else {
console.log('replace word ' + lastWord);

/* Find word start and end */
var wordStart = range.endContainer.data.lastIndexOf(lastWord);
var wordEnd = wordStart + lastWord.length;
console.log("pos: (" + wordStart + ", " + wordEnd + ")");

range.setStart(range.endContainer, wordStart);
range.setEnd(range.endContainer, wordEnd);
range.deleteContents();
range.insertNode(document.createTextNode(resultValue));
// delete That specific word and replace if with resultValue

/* Merge multiple text nodes */
containerEl.normalize();
}
return lastWord;
}
}
<div id="divTest" contenteditable="true">Write words here and hit SPACE BAR</div>

关于javascript - 替换 contenteditable 中的特定单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27656887/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com