我正在尝试在网页上制作一个超级简单的编辑器,当用户输入文本时,它会自动突出显示大型猫科动物的名字。
脚本要点如下:
<span>
<span>
中的单词并点击空格键,并且更改后的单词不匹配,则应删除 <span>
。<span>
突出显示,任何现有的 HTML 标签(例如单词周围的 <strong>
标签)都应保留。请注意,我不能使用像 mark.js 这样的匹配库;这应该只在用户点击空格键后检查刚刚输入的单词,并且只应在该特定单词上进行检查。
我的原始脚本按预期工作,但仅满足前两个要求。后两者已经接近我的 JS 技能极限了。
我有以下 HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
Type some words. The names of common big cats should highlight
<div id='myDiv' contenteditable='true' spellcheck='false' style='width:500px;height:300px;border:1px solid red;'></div>
我的CSS非常简单:
.matchCat{position: relative;display: inline-block;color:red;}
还有我的 Javascript/Jquery:
const catArray = ['lion','tiger','cheetah','leopard','puma'];
const catInput = $('#myDiv');
catInput.keyup(function(e) {
if(e.keyCode == 32){
var words = $(this).text().split(' '); // grab user contents and split it
var target_word = words[words.length - 1]; // get the last word of the input
target_word = target_word.trim(); // trim excess spaces
target_word = target_word.replace(/[^\w\s]|_/g, ''); // get just the actual word and no punctutation
if ( $.inArray(target_word, catArray) > -1 ) {
change_cat(target_word, "<span class='matchCat'>"+target_word+"</span>");
} else {
change_cat("<span class='matchCat'>"+target_word+"</span>", target_word);
}
}
});
function change_cat(from,to){
catInput.each(function(){
var text = $(this).text();
text = text.replace(from,to);
$(this).html(text);
});
}
JSFiddle 版本在这里:Mark Cats
此代码无法正常工作,原因如下:
<strong>tiger</strong>
应该变成 <span class='markCat'><strong>tiger</strong></span>
,但我的替换命令会丢失现有样式。编辑:根据此处收到的帮助,我有代码的第二个版本,可以在此处的 JSFiddle 中看到:Mark Cats v2
这比我的代码更好,但仍然无法正常运行,因为在空格键检查后,当光标应保留在按下空格键后的字符位置的窗口中时,它会失去焦点。 第二个问题是在正确突出显示找到的单词之后,如果我返回并更改该单词,因此没有匹配项,然后再次按空格,突出显示不会消失。
尝试将您的 jquery 更新为以下内容
const catArray = ['lion', 'tiger', 'cheetah', 'leopard', 'puma'];
const catInput = $('#myDiv');
// Function to save cursor position
function saveCaretPosition(context) {
let selection = window.getSelection();
let range = selection.getRangeAt(0);
range.setStart(context, 0);
const len = range.toString().length;
return function restore() {
let pos = getTextNodeAtPosition(context, len);
selection.removeAllRanges();
let newRange = new Range();
newRange.setStart(pos.node, pos.position);
selection.addRange(newRange);
}
}
// Function to get text node at position
function getTextNodeAtPosition(root, index) {
const treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
let node;
let count = 0;
while (node = treeWalker.nextNode()) {
count += node.textContent.length;
if (count >= index) {
return {
node: node,
position: node.textContent.length + index - count
};
}
}
return { node: null, position: 0 };
}
catInput.on('keyup', function(e) {
if (e.keyCode === 32) {
const restoreCaret = saveCaretPosition(this.firstChild);
let htmlContent = $(this).html();
catArray.forEach(cat => {
const regex = new RegExp(`(\\b)(${cat})(\\b)(?!<\/span>)`, 'gi');
htmlContent = htmlContent.replace(regex, `$1<span class='matchCat'>$2</span>$3`);
});
$(this).html(htmlContent);
restoreCaret();
}
});