我有一个带有这些样式的文本区域:
textarea {
width: 300px;
min-height: 105px;
max-height: 500px;
overflow-y: auto;
line-height: 20px;
}
当我选择文本并向下滚动直到看不到选择开始的位置并尝试剪切时,滚动只会在文本区域的底部跳跃。当我尝试撤消或重做文本时也会发生同样的情况,基本上它不会返回到插入符号位置所在的位置。
解决这个问题确实很有帮助,但即使是找到插入符所在行的代码也会有很大帮助,因为我可以用它来管理它。 找到插入符线的位置也很困难,因为用 (' ') 不会完成这项工作,因为有些句子可能会分成多行,并且它会将它们算作一行,所以找到它的行位置也可能很困难。
提前感谢您,如果您需要更多信息请告诉我
解决这个问题不需要很多代码,只需要一些技巧。首先这是您需要的代码:
<script>
let textareas = document.querySelectorAll("textarea");
textareas.forEach(textarea => {
textarea.addEventListener("cut", () => jumpToCaret(textarea));
textarea.addEventListener("input", function(e) {
if (e.inputType == "historyUndo" || e.inputType == "historyRedo") {
jumpToCaret(textarea);
}
});
});
function jumpToCaret(textarea) {
setTimeout(function() {
textarea.blur();
textarea.focus();
}, 0);
}
</script>
确保将其添加到 body 标记的末尾,或者确保 DOM 已使用回调加载。
现在这里发生了什么:
找到所有文本区域并循环它们
let textareas = document.querySelectorAll("textarea");
textareas.forEach(textarea => {
添加用于剪切文本和撤消/重做的事件侦听器。后者有点棘手,但这会起作用:
textarea.addEventListener("cut", () => jumpToCaret(textarea));
textarea.addEventListener("input", function(e) {
if (e.inputType == "historyUndo" || e.inputType == "historyRedo") {
jumpToCaret(textarea);
}
});
跳回到插入符号:技巧是模糊并再次聚焦。焦点浏览器将自动滚动到插入符号。但你必须将其放入 setTimeout(func, 0) 中。我不会详细介绍这一点。如果您对 JS 事件循环感兴趣,请检查 为什么 setTimeout(fn, 0) 有时有用?。
function jumpToCaret(textarea) {
setTimeout(function() {
textarea.blur();
textarea.focus();
}, 0);
}