如何在包含许多 html 标签的内容可编辑 div 中的插入符号之前替换自定义文本?



var input = document.getElementById("div_id");
var username = "TEST";
input.focus();
var selection = window.getSelection();
var range = selection.getRangeAt(0);
var span = document.createElement('span');
span.setAttribute('class', 'tagged-user');
span.setAttribute('id', 55);
span.innerHTML = username;
//var initialText = input.textContent;
//var before_caret = initialText.slice(0,getCaretPosition(input));
// var after_caret = initialText.slice(getCaretPosition(input), initialText.length);
// // var before_caret = input.textContent;
// console.log("before_caret " + before_caret);
// *******************************
//this is the regex that match last @something before caret and it work good.
//var droped_at = before_caret.replace(/@w+(?!.*@w+)/g, '');
// *******************************

// input.textContent = droped_at + after_caret;
// console.log("before_caret " + before_caret);

range.deleteContents();
range.insertNode(span);
range.collapse(false);
range.insertNode(document.createTextNode("u00a0"));
// cursor at the last
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
.tagged-user {
color: #1e81d6;
font-weight: bold;
}
<div contenteditable="true" id="div_id">
First person <span class="tagged-user" id="1">@Joe </span> and @te and <span class="tagged-user"  id="2">@Emilie</span> want to go to the beach.
</div>

文本示例:hello man, @te @emilie how are you?(@emilie是一个跨度标记( 在此示例中,如果光标在@te之后,我想用 TEST 替换@te。

你好

我正在尝试制作一个类似Facebook的提及系统。只要我键入"@",我就可以触发一条消息,显示我所有联系人的列表。 一切正常,唯一的问题是当我输入"@te"以在列表中查找"TEST"时,它应该能够将"@te"替换为"TEST"。它输入@teTEST,任何线索如何做到这一点?我正在使用带有contenteditablediv.

多谢。

在内容可编辑的div元素中获取/设置插入符号位置似乎非常复杂。

无论如何,我创建了一个工作片段,其中包含我在这些主题中找到的功能......在内容中获取插入符号位置可编辑div

在具有子项的"内容可编辑"div 中设置插入符号位置
...并添加了一个函数oninput来进行您想要的替换:
(有关详细信息,请参阅我的代码中的注释(

var input = document.getElementById("div_id");
var replaced = "@te";  // TAKIT: Added this variable
var replacer = "@TEST"; // TAKIT: Renamed this variable
var replacer_tags = ['<span class="tagged-user" id="0">', '</span>']; // TAKIT: Added after comment
input.focus();
// TAKIT: Added functions from these solutions:
// https://stackoverflow.com/questions/3972014/get-caret-position-in-contenteditable-div
function GetCaretPosition(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
// https://stackoverflow.com/questions/36869503/set-caret-position-in-contenteditable-div-that-has-children
function SetCaretPosition(el, pos) {
// Loop through all child nodes
for (var node of el.childNodes) {
if (node.nodeType == 3) { // we have a text node
if (node.length >= pos) {
// finally add our range
var range = document.createRange(),
sel = window.getSelection();
range.setStart(node, pos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
return -1; // we are done
} else {
pos -= node.length;
}
} else {
pos = SetCaretPosition(node, pos);
if (pos == -1) {
return -1; // no need to finish the for loop
}
}
}
return pos; // needed because of recursion stuff
}
// TAKIT: Added this whole function
input.oninput = function() {
var caretPos = GetCaretPosition(input); // Gets caret position
if (this.innerHTML.includes(replaced)) { // Filters the calling of the function
this.innerHTML = this.innerHTML.replace(replaced, replacer_tags.join(replacer) + '&nbsp;'); // Replace
caretPos += replacer.length - replaced.length + 1; // Offset due to strings length difference
SetCaretPosition(input, caretPos); // Restores caret position
}
// console.clear(); console.log(this.innerHTML); // For tests
}
.tagged-user {
color: #1e81d6;
font-weight: bold;
}
<div contenteditable="true" id="div_id">
First person <span class="tagged-user" id="1">@Joe</span> and (add "te" to test) @ and <span class="tagged-user" id="2">@Emilie</span> want to go to the beach.
</div>

希望对您有所帮助。

最新更新