-
Notifications
You must be signed in to change notification settings - Fork 109
fix(money-input): caret position in integer part #1096
Changes from 8 commits
65a23a8
83f4b2f
0d9a643
e9c8353
203a8e7
09ad1c4
009b814
c8e464f
122e6f1
de75ddb
68de0a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,11 @@ const DEFAULT_FRACTION_SIZE = 2; | |
const DEFAULT_INTEGER_SIZE = 9; | ||
const INTEGER_PART_SIZE = 3; | ||
|
||
// В эту проверку попадают IE9 и IE10, которые не могут корректно работать с кареткой на событии `input`. | ||
const IS_IE9_10 = typeof window !== 'undefined' && !!(window as any).ActiveXObject; | ||
|
||
const IS_ANDROID = typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent); | ||
|
||
/** | ||
* Возвращает целую и дробную часть значения в виде массива. | ||
* Если дробная часть не равна `undefined`, значит введена дробная часть | ||
|
@@ -106,6 +111,8 @@ export class MoneyInput extends React.PureComponent<MoneyInputProps, MoneyInputS | |
|
||
root: HTMLInputElement; | ||
|
||
private caretFixTimeout: ReturnType<typeof setTimeout> = null; | ||
|
||
// eslint-disable-next-line camelcase | ||
UNSAFE_componentWillMount() { | ||
this.updateMaskByValue(this.getValue()); | ||
|
@@ -117,6 +124,12 @@ export class MoneyInput extends React.PureComponent<MoneyInputProps, MoneyInputS | |
this.updateMaskByValue(nextProps.value || ''); | ||
} | ||
} | ||
componentWillUnmount() { | ||
if (this.caretFixTimeout) { | ||
clearTimeout(this.caretFixTimeout); | ||
this.caretFixTimeout = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Для чего эта проверка и установка прям перед дестроем этого флага в null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Переносил часть кода из masked-input. |
||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
|
@@ -155,11 +168,13 @@ export class MoneyInput extends React.PureComponent<MoneyInputProps, MoneyInputS | |
} | ||
|
||
private handleProcessMaskInputEvent = (event) => { | ||
const currentValue = this.mask.format(this.getValue()); | ||
const currentValue = this.getValue(); | ||
const currentFormattedValue = this.mask.format(this.getValue()); | ||
let newValue = event.target.value; | ||
const currentSelection = this.root.control.input.selectionStart; | ||
|
||
// При удалении отрезаем запятую, если исчезла дробная часть. | ||
if (newValue.length < currentValue.length) { | ||
if (newValue.length < currentFormattedValue.length) { | ||
const fractionPart = getValueParts(newValue)[1]; // Берем значение после запятой | ||
|
||
// `fractionPart !== undefined` - значит запятая введена, но | ||
|
@@ -171,6 +186,19 @@ export class MoneyInput extends React.PureComponent<MoneyInputProps, MoneyInputS | |
} | ||
|
||
this.updateMaskByValue(newValue); | ||
|
||
// При добавлении последней цифры целой части каретка должна | ||
// оставаться перед запятой | ||
if (newValue.length > currentValue.length && newValue[currentSelection] === ',') { | ||
setTimeout((() => { | ||
|
||
// Фикс бага смещения каретки в браузере на андроидах Jelly Bean (c 4.1 по 4.3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. мы поддерживаем такие старые версии? |
||
const offsetSection = IS_ANDROID && parseFloat(getAndroidVersion() as string) < 4.4 ? 1 : 0; | ||
const newSelectionStart = this.root.control.input.selectionStart - 1; | ||
|
||
this.setInputSelection(newSelectionStart + offsetSection); | ||
}), 0); | ||
} | ||
}; | ||
|
||
private handleChange = (value) => { | ||
|
@@ -246,6 +274,44 @@ export class MoneyInput extends React.PureComponent<MoneyInputProps, MoneyInputS | |
private getValue() { | ||
return this.props.value === undefined ? this.state.value : this.props.value; | ||
} | ||
|
||
/** | ||
* Устанавливает каретку поля ввода в новую позицию. | ||
* | ||
* @param selection Новое положение каретки | ||
*/ | ||
private setInputSelection(selection: number) { | ||
this.root.control.input.selectionStart = selection; | ||
this.root.control.input.selectionEnd = selection; | ||
// IE10 не умеет синхронно в событие `change` переставлять каретку. | ||
// Android chrome имеет дефект с автоматической установкой каретки | ||
// при использовании клавиатуры отличной от type="text". | ||
if (IS_IE9_10 || IS_ANDROID) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SiebenSieben IE11 у нас же уже |
||
this.setInputSelectionByTimeout(selection); | ||
} | ||
} | ||
|
||
/** | ||
* Устанавливает каретку поля ввода в заданную позицию асинхронно. | ||
* | ||
* Во-избежание дефекта с установкой каретки, наблюдаемом в мобильных браузерах, а так же | ||
* браузерах IE9-10, установка происходит асинхронно, с минимальной задержкой, | ||
* с помощью [setTimeout] обертки. | ||
* | ||
* @param selection Положение каретки | ||
*/ | ||
private setInputSelectionByTimeout(selection: number) { | ||
if (this.caretFixTimeout) { | ||
clearTimeout(this.caretFixTimeout); | ||
this.caretFixTimeout = null; | ||
} | ||
|
||
this.caretFixTimeout = setTimeout(() => { | ||
this.caretFixTimeout = null; | ||
this.root.control.input.selectionStart = selection; | ||
this.root.control.input.selectionEnd = selection; | ||
}, 0); | ||
} | ||
} | ||
|
||
class ThemedMoneyInput extends MoneyInput {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это надо убрать. IE 11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Убрал