javascript - 重置内容可编辑的插入符号位置
问题描述
我目前正在尝试为Javascript创建一个语法荧光笔,我目前面临的问题是我发现创建类似这样的东西很常见,即在用户键入或编辑 contentEditable 文本时将插入符号位置设置到末尾。
我在 SO 上研究并发现了这个和许多其他解决方案,但没有一个有效。它获取插入符号的位置,但从不重置它,所以我试图找到解决这个问题的方法。
下面是我想出的代码。
html
<div id="editor" contentEditable="true" onkeyup="resetPosition(this)"></div>
<input type="text" onkeyup="resetPosition(this)" />
js
function getPos(e) {
// for contentedit field
if (e.isContentEditable) {
e.focus()
let _range = document.getSelection().getRangeAt(0)
let range = _range.cloneRange()
range.selectNodeContents(e)
range.setEnd(_range.endContainer, _range.endOffset)
return range.toString().length;
}
// for texterea/input element
return e.target.selectionStart
}
function setPos(pos, e) {
// for contentedit field
if (e.isContentEditable) {
e.focus()
document.getSelection().collapse(e, pos);
return
}
e.setSelectionRange(pos, pos)
}
function resetPosition(e) {
if(e.isContentEditable) {
let currentPosition = getPos(e);
e.innerHTML=e.innerHTML.replace(/[0-9]/g, "a");
setPos(currentPosition, e);
return;
}
e.value = e.value.replace(/[0-9]/g, "a");
setPos(currentPosition, e);
}
这适用于文本输入,但不适用于 contentEditable divs
。
当我输入类似的东西时function
,我得到otincfun
.
更新:我能够setPos
通过将这一行从更改为来修复该功能,document.getSelection().collapse(e, pos);
但document.getSelection().collapse(e.firstChild, pos);
出现了一个新错误。
当我按 ENTER 键时,插入符号返回到第一行和第一个字符。请问我该如何解决?
下面是小提琴链接
https://jsfiddle.net/oketega/bfeh9nm5/35/
谢谢。
解决方案
问题
document.getSelection().collapse(element, index)
将光标折叠到指向的子节点,index
而不是字符索引。
setPos
我可以通过将此行从更改为document.getSelection().collapse(e, pos);
来修复该功能document.getSelection().collapse(e.firstChild, pos);
如果您只替换字符,这将起作用,但如果您正在创建语法荧光笔,您将希望将字符包含在span
元素中以设置它们的样式。 e.firstChild
然后只会将位置设置为第一个孩子中的索引,e
不包括后者span
要考虑的另一件事是您可能希望自动完成某些字符。操作文本之前的插入符号位置可能与操作之后不同。
解决方案
我建议创建一个<span id="caret-position"></span>
元素来跟踪插入符号的位置。
它会像这样工作:
function textChanged(element) {
// 1
const text = setCursorMarker(element.innerText, element);
// 2
const html = manipulate(text);
element.innerHTML = html;
// 3
const index = findCursorIndex(element);
document.getSelection().collapse(element, index)
}
- 每次用户键入时,您都可以获得当前插入符号的位置并滑入其中的
#caret-position
元素。 - 用语法高亮文本覆盖现有的 html
- 找出在哪里
#caret-position
并将插入符号放在那里。
注意:当用户在 content-editable 元素中键入内容时,推荐的监听方式是使用
oninput
监听器,而不是onkeyup
. 按住一个键可以插入许多字符。
例子
这里有一个工作js小提琴:https ://jsfiddle.net/Vehmloewff/0j8hzevm/132/
已知问题:点击Enter
两次后,它会丢失插入符号的位置。我不太确定它为什么会这样做。
推荐阅读
- asp.net-core - 负载均衡器是否多次运行 startup.cs?
- python - 从 list_objects_v2 boto3 获取元数据
- docker - M1 上的 Docker:standard_init_linux.go:219:exec 用户进程导致:exec 格式错误
- c++ - 重读 C++ 指针和函数
- r - 在这个使用 Shiny 包的 R 的简单示例中,我将如何“子集”并在输出表中显示特定的数据列?
- node.js - 编辑 XML ProtectedString CDATA
- c# - 为我的玩家手动制作物理,但是当我在空中飞行时,我的运动是相对于旋转的。我该如何解决?
- css - CSS 滚动与两行对齐?
- r - 根据 NA 数量分配组
- java - 在 Java 中获取 Zip 文件大小超过 FTP 连接