在 textarea 或 contenteditable 中键入 TAB 时检测最后写入的单词 div
Detect the last written word when typing TAB in a textarea or contenteditable div
如何在 textarea
或 contenteditable [=12= 中按下 TAB 时检测和 select 最后一个书写的单词]?
我开始用最后写入的字符或按键的缓冲区来做这件事,但后来我注意到有多个极端情况:
假设用户写 HELLUBACKSPACEO
用户使用方向键移动
用户可以用 SPACE 分隔单词(这就是我使用的),但也可以 ENTER 或逗号等
有什么好的方法可以检测最后写的字吗?
目标:编写自动完成功能代码,示例:thx + <TAB>
=> 文本被替换为 "Thank you very much."
您可以使用当前光标位置来检测最后一个单词。下面给出一个简单的例子。
document.getElementById('foobar').addEventListener('keydown', e => {
if( e.which == 9 ) {
e.preventDefault();
let endingIndex = e.target.selectionStart;
let startingIndex = endingIndex && endingIndex - 1;
let value = e.target.value;
// putt all delemeters in it by which word can be splitted
let regex = /[ ]/;
while(startingIndex > -1){
if(regex.test(value[startingIndex])){
++startingIndex;
break;
}
--startingIndex;
}
// note you will have you apply check to avoid negative index
if(startingIndex < 0) {
startingIndex = 0;
}
console.log(value.substring(startingIndex, endingIndex));
let newText = "replaced";
value = value.substring(0, startingIndex) + newText + value.substring(endingIndex);
let cursorPosition = startingIndex + newText.length;
e.target.value = value;
e.target.setSelectionRange(cursorPosition, cursorPosition);
}
});
<textarea id="foobar"></textarea>
这完全适用于 textarea
和 contenteditable
div:
var newText = 'hello\nnewline';
var newHtml = '<b>test</b> and<br>a <a href="hjkh">link</a>';
document.addEventListener("keydown", function(e) {
var elt = e.target;
if (elt.tagName.toLowerCase() === 'textarea' || elt.isContentEditable)
{
if (e.keyCode == 9) {
e.preventDefault();
if (elt.isContentEditable) { // for contenteditable
elt.focus();
sel = document.getSelection();
sel.modify("extend", "backward", "word");
range = sel.getRangeAt(0);
console.log(range.toString().trim());
range.deleteContents();
var el = document.createElement("div");
el.innerHTML = newHtml;
var frag = document.createDocumentFragment(), node;
while (node = el.firstChild) {
frag.appendChild(node);
}
range.insertNode(frag);
range.collapse();
} else { // for texterea/input element
var endingIndex = elt.selectionStart;
var startingIndex = endingIndex && endingIndex - 1;
var value = elt.value;
var regex = /[ ]/;
while (startingIndex > -1) {
if (regex.test(value[startingIndex])) {
++startingIndex;
break;
}
--startingIndex;
}
if (startingIndex < 0) {
startingIndex = 0;
}
value = value.substring(0, startingIndex) + newText + value.substring(endingIndex);
var cursorPosition = startingIndex + newText.length;
e.target.value = value;
e.target.setSelectionRange(cursorPosition, cursorPosition);
}
}
}
});
<div contenteditable>Hello, press TAB to replace this WORD<br>Also press TAB after this ONE</div>
<textarea rows="8" cols="50" id="a">Hello, press TAB to replace this WORD
Also press TAB after this ONE</textarea>
如何在 textarea
或 contenteditable [=12= 中按下 TAB 时检测和 select 最后一个书写的单词]?
我开始用最后写入的字符或按键的缓冲区来做这件事,但后来我注意到有多个极端情况:
假设用户写 HELLUBACKSPACEO
用户使用方向键移动
用户可以用 SPACE 分隔单词(这就是我使用的),但也可以 ENTER 或逗号等
有什么好的方法可以检测最后写的字吗?
目标:编写自动完成功能代码,示例:thx + <TAB>
=> 文本被替换为 "Thank you very much."
您可以使用当前光标位置来检测最后一个单词。下面给出一个简单的例子。
document.getElementById('foobar').addEventListener('keydown', e => {
if( e.which == 9 ) {
e.preventDefault();
let endingIndex = e.target.selectionStart;
let startingIndex = endingIndex && endingIndex - 1;
let value = e.target.value;
// putt all delemeters in it by which word can be splitted
let regex = /[ ]/;
while(startingIndex > -1){
if(regex.test(value[startingIndex])){
++startingIndex;
break;
}
--startingIndex;
}
// note you will have you apply check to avoid negative index
if(startingIndex < 0) {
startingIndex = 0;
}
console.log(value.substring(startingIndex, endingIndex));
let newText = "replaced";
value = value.substring(0, startingIndex) + newText + value.substring(endingIndex);
let cursorPosition = startingIndex + newText.length;
e.target.value = value;
e.target.setSelectionRange(cursorPosition, cursorPosition);
}
});
<textarea id="foobar"></textarea>
这完全适用于 textarea
和 contenteditable
div:
var newText = 'hello\nnewline';
var newHtml = '<b>test</b> and<br>a <a href="hjkh">link</a>';
document.addEventListener("keydown", function(e) {
var elt = e.target;
if (elt.tagName.toLowerCase() === 'textarea' || elt.isContentEditable)
{
if (e.keyCode == 9) {
e.preventDefault();
if (elt.isContentEditable) { // for contenteditable
elt.focus();
sel = document.getSelection();
sel.modify("extend", "backward", "word");
range = sel.getRangeAt(0);
console.log(range.toString().trim());
range.deleteContents();
var el = document.createElement("div");
el.innerHTML = newHtml;
var frag = document.createDocumentFragment(), node;
while (node = el.firstChild) {
frag.appendChild(node);
}
range.insertNode(frag);
range.collapse();
} else { // for texterea/input element
var endingIndex = elt.selectionStart;
var startingIndex = endingIndex && endingIndex - 1;
var value = elt.value;
var regex = /[ ]/;
while (startingIndex > -1) {
if (regex.test(value[startingIndex])) {
++startingIndex;
break;
}
--startingIndex;
}
if (startingIndex < 0) {
startingIndex = 0;
}
value = value.substring(0, startingIndex) + newText + value.substring(endingIndex);
var cursorPosition = startingIndex + newText.length;
e.target.value = value;
e.target.setSelectionRange(cursorPosition, cursorPosition);
}
}
}
});
<div contenteditable>Hello, press TAB to replace this WORD<br>Also press TAB after this ONE</div>
<textarea rows="8" cols="50" id="a">Hello, press TAB to replace this WORD
Also press TAB after this ONE</textarea>