Unexpected caret reposition in Android Chrome

Viewed 762

As I was reinventing the wheel for fun and profit, I isolated an interesting behavior that appears to only occur in Android Chrome.

I am formatting a text input as the user types, which means setting the input value, losing the caret position. No problem - just track the caret position, and set it back after you change the value (adjusting for added/removed characters) in the input event callback.

Works great! Except for Android Chrome (Android 7, Chrome 58.0.3029.83) - I set the caret position, observe the caret position where I expect - then on keyup event it is magically moved - after input event but before keyup event.

Tracking caret positions

You can see this for yourself in this (exceedingly simplified) fiddle. I even output the relevant data on screen so you don't have to hook up a debugger to see it.

Type "abcd" and get:
Numbers are caret positions from this.selectionStart
D = keyDown, I = Input, C = position Changed to, U = keyUp

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

Where every other browser tested (IE11, iOS Safari, Desktop Chrome) gives you:

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

Is there an event in there I'm missing? It's not in the docs that I can find, though I know virtual keyboards get a little janky. I'd love to find out exactly where this is happening so I can nuke it.


Also tried

beforeinput, compositionstart, and compositionend events. The only one that is triggered is compositionstart, between the keydown and input events. It shows the caret position I would expect to see at that time.

Typing "abcd" then hitting backspace in Android Chrome gives you:

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

Seeming to indicate that whatever is moving the caret did not do so in this case.


Not looking for a workaround. The workaround is to set the caret again in the keyup event. I'm asking to see if anyone knows a less-wrong answer.

1 Answers
Related