Skip to content

TextInput Events

Maciej Jastrzebski edited this page Aug 13, 2024 · 38 revisions

Single Line - basic flow

RN version: 0.71.6

Setup:

<TextInput
style={styles.textInput}
value={value}
onChangeText={handleChangeText}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onEndEditing={handleEndEditing}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "Test" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406399.731625, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406478.905625, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "T", "target": 75}
LOG Event: change {"eventCount": 1, "target": 75, "text": "T"}
LOG Event: changeText T
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG Event: change {"eventCount": 2, "target": 75, "text": "Te"}
LOG Event: changeText Te
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 19}, "target": 75}
LOG Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG Event: change {"eventCount": 3, "target": 75, "text": "Tes"}
LOG Event: changeText Tes
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 28}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG Event: change {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: changeText Test
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 34}, "target": 75}
LOG Event: submitEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: endEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: blur {"eventCount": 4, "target": 75, "text": "Test"}

Android:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060200, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060255, "touches": []}
LOG Event: change {"eventCount": 2, "target": 53, "text": "T"}
LOG Event: changeText T
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG Event: keyPress {"key": "T"}
LOG Event: change {"eventCount": 4, "target": 53, "text": "Te"}
LOG Event: changeText Te
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG Event: keyPress {"key": "e"}
LOG Event: change {"eventCount": 6, "target": 53, "text": "Tes"}
LOG Event: changeText Tes
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}}
LOG Event: keyPress {"key": "s"}
LOG Event: change {"eventCount": 8, "target": 53, "text": "Test"}
LOG Event: changeText Test
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: keyPress {"key": "t"}
LOG Event: submitEditing {"target": 53, "text": "Test"}
LOG Event: blur {"target": 53}
LOG Event: endEditing {"target": 53, "text": "Test"}

Notes:

  • Sequence of events on focusing both platforms is the same: pressIn - focus - pressOut
  • Sequence of events on pressing Enter on both platforms is slightly:
    • iOS: submitEditing - endEditing - blur
    • Android: submitEditing - blur - endEditing
  • Sequence of events of typing is different:
    • iOS: keyPress - change - changeText - selectionChange - contentSizeChange
    • Android: change - changeText - selectionChange - keyPress
  • The submitEditing event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element
  • In case of unmanaged TextInput (i.e. no value prop being passed) the events are the same on Android

Mutli-Line - basic flow

RN version: 0.71.6

Setup:

<TextInput
style={styles.textInput}
value={value}
mutliline={true}
onChangeText={handleChangeText}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onEndEditing={handleEndEditing}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "AB\nCD" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407822.0294167, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407901.1994168, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "A", "target": 75}
LOG Event: change {"eventCount": 1, "target": 75, "text": "A"}
LOG Event: changeText A
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11.666666666666666}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "B", "target": 75}
LOG Event: change {"eventCount": 2, "target": 75, "text": "AB"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 23.333333333333332}, "target": 75}
// Enter key
LOG Event: keyPress {"eventCount": 2, "key": "Enter", "target": 75}
LOG Event: change {"eventCount": 3, "target": 75, "text": "AB\n"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 43, "width": 23.333333333333332}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "C", "target": 75}
LOG Event: change {"eventCount": 4, "target": 75, "text": "AB\nC"}
LOG Event: changeText AB\nC
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}
LOG Event: keyPress {"eventCount": 4, "key": "D", "target": 75}
LOG Event: change {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG Event: changeText AB\nCD
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 43, "width": 25.333333333333332}, "target": 75}
LOG Event: endEditing {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG Event: blur {"eventCount": 5, "target": 75, "text": "AB\nCD"}

Android:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.09090805053711, "pageX": 277.4545593261719, "pageY": 133.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 168170420, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.818180084228516, "pageX": 277.4545593261719, "pageY": 133.81817626953125, "target": 53, "targetSurface": -1, "timestamp": 168170514, "touches": []}
LOG Event: change {"eventCount": 2, "target": 53, "text": "A"}
LOG Event: changeText A
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG Event: keyPress {"key": "A"}
LOG Event: change {"eventCount": 4, "target": 53, "text": "AB"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG Event: keyPress {"key": "B"}
// Enter
LOG Event: contentSizeChange {"contentSize": {"height": 61.45454406738281, "width": 352.7272644042969}, "target": 53}
LOG Event: change {"eventCount": 6, "target": 53, "text": "AB\n"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}}
LOG Event: change {"eventCount": 8, "target": 53, "text": "AB\nC"}
LOG Event: changeText AB\nC
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: keyPress {"key": "C"}
LOG Event: change {"eventCount": 10, "target": 53, "text": "AB\nCD"}
LOG Event: changeText AB\nCD
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "D"}
LOG Event: blur {"target": 53}
LOG Event: endEditing {"target": 53, "text": "AB\nCD"}

Notes:

  • Sequence of events on focusing both platforms is the same: pressIn - focus - pressOut
  • Sequence of events on pressing Enter on both platforms is slightly:
    • iOS: endEditing - blur
    • Android: blur - endEditing
  • Sequence of events of typing is different:
    • iOS: keyPress - change - changeText - selectionChange - contentSizeChange (when it actually changes)
    • Android: contentSizeChange (only for Enter) - change - changeText - selectionChange - keyPress (not for Enter)
  • The submitEditing event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element

Impact of editable={false} prop

Setup:

<TextInput
style={styles.textInput}
value={value}
onChangeText={handleChangeText}
editable={false}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
/>

Steps:

  1. Press TextInput

Output:

iOS:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054389.9047917, "touches": [[Circular]]}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054477.4037917, "touches": []}

Android:

(No events logged)

Managed TextInput rejecting changes

RN version: 0.71.6

Setup:

<TextInput
style={styles.textInput}
value="AAAA"
editable={true}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onChangeText={handleChangeText}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "Test" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401529.229625, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": "AAAA"}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401608.349625, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "t", "target": 75}
LOG Event: change {"eventCount": 1, "target": 75, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG Event: change {"eventCount": 2, "target": 75, "text": "AAAAe"}
LOG Event: changeText AAAAe
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 56}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG Event: change {"eventCount": 3, "target": 75, "text": "AAAAs"}
LOG Event: changeText AAAAs
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 55.666666666666664}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG Event: change {"eventCount": 4, "target": 75, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: submitEditing {"eventCount": 4, "target": 75, "text": "AAAA"}
LOG Event: blur {"eventCount": 4, "target": 75, "text": "AAAA"}

Android:

LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073165, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
// `selectionChange` only happens on first focus. Subsequent focuses skip it.
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073239, "touches": []}
LOG Event: change {"eventCount": 2, "target": 53, "text": "AAAAT"}
LOG Event: changeText AAAAT
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "T"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: change {"eventCount": 4, "target": 53, "text": "AAAAe"}
LOG Event: changeText AAAAe
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "e"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: change {"eventCount": 6, "target": 53, "text": "AAAAs"}
LOG Event: changeText AAAAs
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "s"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: change {"eventCount": 8, "target": 53, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "t"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: submitEditing {"target": 53, "text": "AAAA"}
LOG Event: blur {"target": 53}

Using backspace

Android:

Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 54.54545593261719, "locationY": 20, "pageX": 74.54545593261719, "pageY": 120, "target": 83, "targetSurface": -1, "timestamp": 542793523, "touches": [[Circular]]}
Event: focus {"target": 83}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 54.54545593261719, "locationY": 20, "pageX": 74.54545593261719, "pageY": 120, "target": 83, "targetSurface": -1, "timestamp": 542793571, "touches": []}
Event: change {"eventCount": 2, "target": 83, "text": "A"}
Event: changeText A
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "A"}
Event: change {"eventCount": 4, "target": 83, "text": "Ab"}
Event: changeText Ab
Event: selectionChange {"selection": {"end": 2, "start": 2}}
Event: keyPress {"key": "b"}
Event: change {"eventCount": 6, "target": 83, "text": "A"}
Event: changeText A
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "Backspace"}
Event: change {"eventCount": 8, "target": 83, "text": ""}
Event: changeText Event: selectionChange {"selection": {"end": 0, "start": 0}}
Event: keyPress {"key": "Backspace"}
Event: contentSizeChange {"contentSize": {"height": 45.818180084228516, "width": 352.7272644042969}, "target": 83}
Event: contentSizeChange {"contentSize": {"height": 40.3636360168457, "width": 381316.375}, "target": 83}
Event: change {"eventCount": 10, "target": 83, "text": "C"}
Event: changeText C
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "C"}
Event: submitEditing {"target": 83, "text": "C"}
Event: blur {"target": 83}
Event: endEditing {"target": 83, "text": "C"}

Clearing TextInput

Scenario:

  1. TextInput Events experiment
  2. Fill in TextInput with Random text, focus out
  3. Start recording events
  4. Enter text field
  5. Select all text using context menu
  6. Press backspace
  7. Exit TextInput

iOS

// Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 59.5, "locationY": 6, "pageX": 79.5, "pageY": 90, "target": 75, "timestamp": 166484128.726374, "touches": [[Circular]]}
Event: focus {"eventCount": 23, "target": 75, "text": "Test"}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 59.5, "locationY": 6, "pageX": 79.5, "pageY": 90, "target": 75, "timestamp": 166484183.03356, "touches": []}
// Select all (Cmd+A)
Event: selectionChange {"selection": {"end": 4, "start": 0}, "target": 75}
// Press backspace
Event: keyPress {"eventCount": 23, "key": "Backspace", "target": 75}
Event: change {"eventCount": 24, "target": 75, "text": ""}
Event: changeText Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: contentSizeChange {"contentSize": {"height": 21.5, "width": 143.5}, "target": 75}
// Exit
Event: endEditing {"eventCount": 24, "target": 75, "text": ""}
Event: blur {"eventCount": 24, "target": 75, "text": ""}

iOS (clear button)

Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 321, "locationY": 19.5, "pageX": 341, "pageY": 103.5, "target": 75, "timestamp": 166027702.319404, "touches": [[Circular]]}
Event: keyPress {"eventCount": 18, "key": "Backspace", "target": 75}
Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: contentSizeChange {"contentSize": {"height": 21.5, "width": 143.5}, "target": 75}
Event: change {"eventCount": 19, "target": 75, "text": ""}
Event: changeText Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: focus {"eventCount": 19, "target": 75, "text": ""}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 321, "locationY": 19.5, "pageX": 341, "pageY": 103.5, "target": 75, "timestamp": 166027788.429719, "touches": []}

Android

// Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 18.172496795654297, "locationY": 24.707475662231445, "pageX": 38.1724967956543, "pageY": 124.70747375488281, "target": 53, "targetSurface": -1, "timestamp": 216026, "touches": [[Circular]]}
Event: focus {"target": 53}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 18.172496795654297, "locationY": 24.707475662231445, "pageX": 38.1724967956543, "pageY": 124.70747375488281, "target": 53, "targetSurface": -1, "timestamp": 216070, "touches": []}
// Select all
Event: selectionChange {"selection": {"end": 4, "start": 0}}
// Press backspace
Event: change {"eventCount": 20, "target": 53, "text": ""}
Event: changeText Event: selectionChange {"selection": {"end": 0, "start": 0}}
Event: contentSizeChange {"contentSize": {"height": 45.818180084228516, "width": 352.7272644042969}, "target": 53}
// Exit
Event: blur {"target": 53}
Event: endEditing {"target": 53, "text": ""}

User Event design

// Step 1: enter
- focus (skip pressIn/pressOut in sync with RTL UserEvent clear())
// Step 2: select all
- selectionChange: whole text
// Step 3: clear with backspace key (in sync with type())
- keyPress: backspace
- change: ""
- changeText: ""
- selectionChange: zero range
- contentSizeChange: (for multiline-only)
// Step 4: exit
- blur

Pasting Text

iOS

// Step 1: Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2948717.0664166664, "touches": [[Circular]]}
Event: focus {"eventCount": 2, "target": 153, "text": ""}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2948811.551, "touches": []}
// Step 2. Press to trigger menu
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2949547.4370000004, "touches": [[Circular]]}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2950717.1967916666, "touches": []}
// Step 3. Actual paste
Event: change {"eventCount": 3, "target": 153, "text": "Hello"}
Event: changeText Hello
Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 153}
Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 41}, "target": 153}
// Step 4. Exit
Event: endEditing {"eventCount": 3, "target": 153, "text": "Hello"}
Event: blur {"eventCount": 3, "target": 153, "text": "Hello"}

Android

// Step 1. Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40841617, "touches": [[Circular]]}
Event: focus {"target": 97}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40841721, "touches": []}
// Step 2. Press to trigger menu
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40843111, "touches": [[Circular]]}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40844142, "touches": []}
// Step 3. Actual paste
Event: contentSizeChange {"contentSize": {"height": 40.761905670166016, "width": 399473.53125}, "target": 97}
Event: change {"eventCount": 50, "target": 97, "text": "Hello"}
Event: changeText Hello
Event: selectionChange {"selection": {"end": 5, "start": 5}}
// Step 4. Exit
Event: blur {"target": 97}
Event: endEditing {"target": 97, "text": "pageY"}

User Event design

// Step 1: Enter
- focus
// Step 2: select all
- selectionChange: whole text
// Step 3. Actual paste
- change {"text": "Hello"}
- changeText Hello
- selectionChange {"selection": {"end": 5, "start": 5}, "target": 153}
- contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 41}, "target": 153}
// Step 4. Exit
- endEditing {"eventCount": 3, "target": 153, "text": "Hello"}
- blur {"eventCount": 3, "target": 153, "text": "Hello"}

Clone this wiki locally