可滚动文本区域在文本剪切上跳跃

问题描述 投票:0回答:1

我有一个带有这些样式的文本区域:

textarea {
    width: 300px;
    min-height: 105px;
    max-height: 500px;
    overflow-y: auto;
    line-height: 20px;
}

当我选择文本并向下滚动直到看不到选择开始的位置并尝试剪切时,滚动只会在文本区域的底部跳跃。当我尝试撤消或重做文本时也会发生同样的情况,基本上它不会返回到插入符号位置所在的位置。

解决这个问题确实很有帮助,但即使是找到插入符所在行的代码也会有很大帮助,因为我可以用它来管理它。 找到插入符线的位置也很困难,因为用 (' ') 不会完成这项工作,因为有些句子可能会分成多行,并且它会将它们算作一行,所以找到它的行位置也可能很困难。

提前感谢您,如果您需要更多信息请告诉我

javascript html css textarea caret
1个回答
0
投票

解决这个问题不需要很多代码,只需要一些技巧。首先这是您需要的代码:

<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 已使用回调加载。

现在这里发生了什么:

  1. 找到所有文本区域并循环它们

    let textareas = document.querySelectorAll("textarea");
    textareas.forEach(textarea => {
    
  2. 添加用于剪切文本和撤消/重做的事件侦听器。后者有点棘手,但这会起作用:

    textarea.addEventListener("cut", () => jumpToCaret(textarea));
    textarea.addEventListener("input", function(e) {
       if (e.inputType == "historyUndo" || e.inputType == "historyRedo") {
          jumpToCaret(textarea);
       }
    });
    
  3. 跳回到插入符号:技巧是模糊并再次聚焦。焦点浏览器将自动滚动到插入符号。但你必须将其放入 setTimeout(func, 0) 中。我不会详细介绍这一点。如果您对 JS 事件循环感兴趣,请检查 为什么 setTimeout(fn, 0) 有时有用?

    function jumpToCaret(textarea) {
       setTimeout(function() {
          textarea.blur();
          textarea.focus();
       }, 0);
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.