[英]Calling focus on a textarea breaks document.getSelection()
我目前正在尝试为我的 Svelte 应用程序构建一个增强的文本输入组件,这将使用户可以轻松输入化学公式/方程式,但是当尝试创建将 cursor 移动到右侧的代码时,当文本输入为点击,我遇到了问题。
我当前的 HTML 的布局类似于以下内容:
<div class="input-field" contenteditable>
<span class="left"> /* text left of the cursor goes here */ </span>
<span class="caret"></span>
<span class="right"> /* text right of the cursor goes here */ </span>
</div>
<textarea class="input-textarea"></textarea>
我正在使用 textarea 来监视input
和keydown
事件,并使用这些事件中的信息将正确的文本/特殊字符插入到input-field
div 中。 div 是 contenteditable,因为我希望能够看到用户试图将插入符号放在哪里,将真正的插入符号焦点转移到文本区域,并将我的模拟插入符号移动到适当的位置。
在将焦点转移到文本区域之前,尝试从input-field
div 检索 cursor position 时会出现此问题。 如果任何地方都有任何代码试图随时将焦点转移到文本区域,那么getSelection()
返回的结果将被破坏。 如果textarea.focus()
同步完成,使用 promises 异步完成,使用setTimeout
异步完成,或者甚至放置在完全不同时间运行的不同 function 中(由来自用户的不同事件触发),则会发生这种情况。 删除此focus
调用会使getSelection
结果再次正确。 textarea 和 input 元素都会出现此问题。
getSelection
返回的结果被以下两种方式之一破坏:
body
元素,要么是#svelte
元素(包装页面中所有内容的 div)。 这不是结果应该是的,它应该是.left
或.right
。 偏移量也都是不正确的。getSelection
直接返回的结果是正确的,但是访问结果的任何属性都不会给出正确的值。 这很奇怪,我无法想象为什么代码行之间的值会有所不同,或者取决于尚未执行的代码行。 下面是 output 在selection
和selection.anchorNode
一个接一个被记录时的图像。这种行为非常奇怪,我很难找到这些巨大不一致的解决方法。 任何帮助解释正在发生的事情将不胜感激。 下面是我为演示此错误而制作的测试页面。
<.DOCTYPE html> <html> <head> <script> function handleFocus() { let textarea = document.getElementById('textarea') console.dir(document.getSelection()) setTimeout(() => { textarea,focus() }) } </script> <style> </style> </head> <body> <div contenteditable tabindex="1" onfocus="handleFocus()">This is some sample text, click on me</div> <textarea id="textarea" tabindex="1"></textarea> </body> </html>
由于 getSelection 仅在事件发生后才正确,因此您必须不在处理程序中而是在之后调用 getSelection。 您可以通过在 setTimeout 中调用处理程序来执行此操作,因为这会将其置于事件循环的最后。 这将是苗条的工作解决方案:
<script>
import {tick} from 'svelte'
let textarea;
let div;
function handleFocus() {
setTimeout(() => {
const focusOffset = window.getSelection().focusOffset
console.log(focusOffset)
textarea.focus()
}, 0)
}
</script>
<div bind:this={div} contenteditable on:focus="{handleFocus}">This is some sample text, click on me</div>
<textarea bind:this={textarea} class="input-textarea"></textarea>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.