【问题标题】:Unexpected caret reposition in Android ChromeAndroid Chrome 中意外的插入符号重新定位
【发布时间】:2017-06-29 16:08:17
【问题描述】:

当我是reinventing the wheel for fun and profit 时,我发现了一个似乎只发生在 Android Chrome 中的有趣行为。

我在用户键入时格式化文本输入,这意味着设置输入值,丢失插入符号位置。没问题 - 只需跟踪插入符号的位置,并在您更改输入事件回调中的值(调整添加/删除的字符)后将其设置回来。

效果很好!除了 Android Chrome (Android 7, Chrome 58.0.3029.83) - 我设置了插入符号的位置,观察了我期望的插入符号的位置 - 然后在 keyup 事件上它被神奇地移动了 - after 输入事件但是 按键事件之前。

跟踪插入符号位置

您可以在this (exceedingly simplified) fiddle 中亲自查看。我什至在屏幕上输出相关数据,这样您就不必连接调试器来查看它。

键入“abcd”并获得:
数字是 this.selectionStart 中的插入符号位置
D = keyDown,I = 输入,C = 位置更改为,U =向上键

D: 0 | I: 0 | C: 1 | U: 1
D: 1 | I: 1 | C: 2 | U: 2
D: 2 | I: 2 | C: 3 | U: 3
D: 3 | I: 3 | C: 5 | U: 4 //<- This 4 is the culprit

其他所有经过测试的浏览器(IE11、iOS Safari、桌面 Chrome)都会为您提供:

D: 0 | I: 1 | C: 1 | U: 1
D: 1 | I: 2 | C: 2 | U: 2
D: 2 | I: 3 | C: 3 | U: 3
D: 3 | I: 4 | C: 5 | U: 5

那里有我错过的活动吗? It's not in the docs 我可以找到,虽然我知道虚拟键盘有点笨拙。我很想知道发生这种情况的确切位置这样我就可以对其进行核对


也试过了

beforeinputcompositionstartcompositionend 事件。唯一被触发的是compositionstart,在keydowninput 事件之间。它显示了我当时希望看到的插入符号位置。

在 Android Chrome 中键入“abcd”然后按退格键可以:

D: 4 | I: 3 | C: 5 | U: 5

似乎表明在这种情况下移动插入符号的任何东西都没有这样做。


不寻找解决方法。解决方法是在 keyup 事件中再次设置插入符号。我想看看是否有人知道一个不太错误的答案。

【问题讨论】:

  • 您确定您为 android chrome 显示的值是您实际看到的吗?你说你看到D: 0 | I: 1 | C: 1 | U: 1 但我看到D: 0 | I: 0 | C: 1 | U: 1
  • @Clonkex 非常确定。你用的是什么版本的android和chrome?第四排你得到了什么?
  • @Clonkex 哇,现在不太确定了。更新中...
  • 编辑了我的答案并尝试了解决方法。希望这对您有用,但我认为必须有更好的方法来进行电话号码自动格式化。

标签: javascript android google-chrome events


【解决方案1】:

如您所见,在 Android Chrome 中的软键盘上键入不会像 PC Chrome 那样更新 input 事件中的插入符号位置。这是非常典型的 Web 开发;总有一种情况,它的工作方式不同。

D: 0 | I: 0 | C: 1 | U: 1

根据我自己的测试,插入时插入符号位置在input 中更新,但在键入时仅在keyup 中更新。这意味着,如果您复制一个字母并重复粘贴,当您进行第四次粘贴时,您的文本框格式化代码将按预期工作(和在 PC 上一样)。

这也意味着,如果您希望您的代码可靠地工作,您需要跟踪插入符是否在 input 中更新,但也要抢先在 input 中更新它,因为 keyup 不会触发如果你正在粘贴。但是,这可能很困难,因为 keydown 在粘贴时也不会触发,因此您不会知道之前的插入符号位置。

您说您不是在寻找解决方法,但根据对您帖子的编辑,我怀疑您现在需要一个解决方法。我不确定有什么好的解决方法。可能tracking caret position changes 并手动存储它们(可能在文本框的数据属性中)将是您最好的选择。真正的困难在于粘贴时,您可以粘贴任意数量的字符,因此您不能仅仅假设如果input 被触发而keydown 未触发,则使用currentCaretPosition - 1


经过一些实验,这是我想出的解决方法:

https://jsfiddle.net/smfaenvb/10/

它并不完美,但它确实可以在 Android Chrome 上运行,就像您的原始测试代码在 PC Chrome 上运行一样。

【讨论】:

  • 我实际上可能会尝试自己想出一个好的解决方法。如果我成功了,我会编辑我的帖子。
  • 有趣的是,在 keyup 事件中添加 stopPropagationpreventDefaultreturn false 仍然不会阻止更新。这真的让我觉得缺少一个事件,但也许它真的只是浏览器在事件之间做的事情
  • 另请参阅我的工作设置jsfiddle.net/freer4/uz9hr6b6 - 与您的解决方法基本相同 - 跟踪位置,然后在 keyup 或 keydown 上再次设置,因为并发 keydown 可能在下一次 keyup 之前发生。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2023-03-15
  • 2017-12-15
  • 2014-09-24
相关资源
最近更新 更多