Skip to content

Commit

Permalink
fix: apply changes before input event
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed Mar 24, 2021
1 parent 9651fcf commit f51a7f8
Showing 1 changed file with 20 additions and 22 deletions.
42 changes: 20 additions & 22 deletions src/keyboard/shared/fireInputEventIfNeeded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,19 @@ export function fireInputEventIfNeeded({
!isClickableInput(el) &&
newValue !== prevValue
) {
// apply the changes before firing the input event, so that input handlers can access the altered dom and selection
if (isContentEditable(el)) {
fireEvent.input(el, {
target: {textContent: newValue},
...eventOverrides,
})
} else {
const newSelection = hasSelectionSupport(el)
? {selectionStart: newSelectionStart, selectionEnd: newSelectionStart}
: undefined
fireEvent.input(el, {
target: {
value: newValue,
...newSelection,
},
...eventOverrides,
})
el.textContent = newValue
} else if (isElementType(el, ['input', 'textarea'])) {
el.value = newValue
}

setSelectionRangeAfterInput(el, newValue, newSelectionStart)

fireEvent.input(el, {
...eventOverrides,
})

setSelectionRangeAfterInputHandler(el, newValue)
}

return {prevValue}
Expand All @@ -64,6 +58,13 @@ function setSelectionRangeAfterInput(
element: Element,
newValue: string,
newSelectionStart: number,
) {
setSelectionRange(element, newSelectionStart, newSelectionStart)
}

function setSelectionRangeAfterInputHandler(
element: Element,
newValue: string
) {
// if we *can* change the selection start, then we will if the new value
// is the same as the current value (so it wasn't programatically changed
Expand All @@ -74,12 +75,9 @@ function setSelectionRangeAfterInput(
const value = getValue(element) as string

// don't apply this workaround on elements that don't necessarily report the visible value - e.g. number
if (
value === newValue ||
(value === '' && hasUnreliableEmptyValue(element))
) {
setSelectionRange(element, newSelectionStart, newSelectionStart)
} else {
// TODO: this could probably be only applied when there is keyboardState.carryValue
const expectedValue = value === newValue || (value === '' && hasUnreliableEmptyValue(element))
if(!expectedValue) {
// If the currentValue is different than the expected newValue and we *can*
// change the selection range, than we should set it to the length of the
// currentValue to ensure that the browser behavior is mimicked.
Expand Down

0 comments on commit f51a7f8

Please sign in to comment.