diff --git a/src/money-input/money-input.test.tsx b/src/money-input/money-input.test.tsx index 3c56e8f045..40694e43bb 100644 --- a/src/money-input/money-input.test.tsx +++ b/src/money-input/money-input.test.tsx @@ -99,4 +99,24 @@ describe('money-input', () => { expect(moneyInput.find('input').prop('value')).toBe('1 234,56'); }); + + it('should stay caret before comma', (done) => { + const moneyInput = mount(); + const inputNode = moneyInput.find('input'); + + setTimeout(() => { + jest.useFakeTimers(); + + inputNode.getDOMNode().selectionStart = 3; + inputNode.getDOMNode().selectionEnd = 3; + + inputNode.simulate('beforeInput'); + inputNode.simulate('input', { target: { value: '123,34' } }); + jest.runAllTimers(); + + expect(inputNode.getDOMNode().selectionStart).toBe(3); + expect(inputNode.getDOMNode().selectionEnd).toBe(3); + done(); + }, 0); + }); }); diff --git a/src/money-input/money-input.tsx b/src/money-input/money-input.tsx index 3ea259f015..b51e1a45ee 100644 --- a/src/money-input/money-input.tsx +++ b/src/money-input/money-input.tsx @@ -20,6 +20,8 @@ const DEFAULT_FRACTION_SIZE = 2; const DEFAULT_INTEGER_SIZE = 9; const INTEGER_PART_SIZE = 3; +const IS_ANDROID = typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent); + /** * Возвращает целую и дробную часть значения в виде массива. * Если дробная часть не равна `undefined`, значит введена дробная часть @@ -106,6 +108,8 @@ export class MoneyInput extends React.PureComponent = null; + // eslint-disable-next-line camelcase UNSAFE_componentWillMount() { this.updateMaskByValue(this.getValue()); @@ -117,6 +121,9 @@ export class MoneyInput extends React.PureComponent { - 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 +180,19 @@ export class MoneyInput extends React.PureComponent currentValue.length && newValue[currentSelection] === ',') { + setTimeout((() => { + + // Фикс бага смещения каретки в браузере на андроидах Jelly Bean (c 4.1 по 4.3) + 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 +268,39 @@ export class MoneyInput extends React.PureComponent { + this.root.control.input.selectionStart = selection; + this.root.control.input.selectionEnd = selection; + }, 0); + } } class ThemedMoneyInput extends MoneyInput {}