From da17ddb7314b79d1164ae7eed6a0762700d249ec Mon Sep 17 00:00:00 2001 From: Abhimanyu Singh Date: Sun, 1 Jul 2018 14:53:33 +0530 Subject: [PATCH] Fix cursor Issue#205 --- __tests__/utils.test.js | 26 ++++++++++++++++++++ src/components/IntlTelInputApp.js | 16 +++++++++++-- src/components/TelInput.js | 18 +++++++++++++- src/components/utils.js | 40 +++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/__tests__/utils.test.js b/__tests__/utils.test.js index bb001f085..3bcfbe23a 100644 --- a/__tests__/utils.test.js +++ b/__tests__/utils.test.js @@ -173,4 +173,30 @@ describe('utils', () => { expect(utils.findIndex(array, predicate)).toEqual(-1); }); + + it('getCursorPositionAfterFormating', () => { + let previousStringBeforeCursor = '9123'; + let previousString = '912345'; + let nextString = '912345'; + + expect(utils.getCursorPositionAfterFormating(previousStringBeforeCursor, previousString, nextString)).toEqual(4); + + previousStringBeforeCursor = '0912 345'; + previousString = '0912 345 678'; + nextString = '91234678'; + + expect(utils.getCursorPositionAfterFormating(previousStringBeforeCursor, previousString, nextString)).toEqual(5); + + previousStringBeforeCursor = '91234'; + previousString = '91234678'; + nextString = '0912 345 678'; + + expect(utils.getCursorPositionAfterFormating(previousStringBeforeCursor, previousString, nextString)).toEqual(7); + + previousStringBeforeCursor = '(201) 5'; + previousString = '(201) 55-01'; + nextString = '201-5501'; + + expect(utils.getCursorPositionAfterFormating(previousStringBeforeCursor, previousString, nextString)).toEqual(5); + }); }); diff --git a/src/components/IntlTelInputApp.js b/src/components/IntlTelInputApp.js index ad0e893f3..e91e1649f 100644 --- a/src/components/IntlTelInputApp.js +++ b/src/components/IntlTelInputApp.js @@ -61,6 +61,7 @@ class IntlTelInputApp extends Component { title: '', countryCode: 'us', dialCode: '', + cursorPosition: (props.value || props.defaultValue).length, }; this.selectedCountryData = {}; @@ -1055,14 +1056,24 @@ class IntlTelInputApp extends Component { // Either notify phoneNumber changed if component is controlled // or udpate the state and notify change if component is uncontrolled handleInputChange(e) { + let cursorPosition = e.target.selectionStart; + const previousValue = e.target.value; + const previousStringBeforeCursor = previousValue === '' ? previousValue : previousValue.substring(0, cursorPosition); const value = this.props.format ? this.formatNumber(e.target.value) : e.target.value; + cursorPosition = utils.getCursorPositionAfterFormating(previousStringBeforeCursor, previousValue, value); + if (this.props.value !== undefined) { - this.updateFlagFromNumber(value); - this.notifyPhoneNumberChange(value); + this.setState({ + cursorPosition, + }, () => { + this.updateFlagFromNumber(value); + this.notifyPhoneNumberChange(value); + }); } else { this.setState({ value, + cursorPosition, }, () => { this.updateFlagFromNumber(value); this.notifyPhoneNumberChange(value); @@ -1170,6 +1181,7 @@ class IntlTelInputApp extends Component { autoFocus={ this.props.autoFocus } autoComplete={ this.props.autoComplete } inputProps={ this.props.telInputProps } + cursorPosition={ this.state.cursorPosition } /> ); diff --git a/src/components/TelInput.js b/src/components/TelInput.js index 152cc9185..bfbfab783 100644 --- a/src/components/TelInput.js +++ b/src/components/TelInput.js @@ -2,11 +2,26 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; class TelInput extends Component { + constructor(props) { + super(props); + + this.refHandler = this.refHandler.bind(this); + } + + componentDidUpdate() { + this.tel.setSelectionRange(this.props.cursorPosition, this.props.cursorPosition); + } + + refHandler(element) { + this.tel = element; + this.props.refCallback(element); + } + render() { return ( next.length) { + for (let i = 0, j = 0; i < prevBeforeCursor.length && j < next.length; i += 1) { + if (prevBeforeCursor[i] !== next[j]) { + if (isNaN(next[j]) && !isNaN(prevBeforeCursor[i])) { + i -= 1; + j += 1; + cursorShift += 1; + } else { + cursorShift -= 1; + } + } else { + j += 1; + } + } + } else { + for (let i = 0, j = 0; i < prevBeforeCursor.length && j < next.length; j += 1) { + if (prevBeforeCursor[i] !== next[j]) { + if (isNaN(prevBeforeCursor[i]) && !isNaN(next[j])) { + j -= 1; + i += 1; + cursorShift -= 1; + } else { + cursorShift += 1; + } + } else { + i += 1; + } + } + } + + return prevBeforeCursor.length + cursorShift; + } };