Skip to content

Commit

Permalink
Improve InputNumber implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Sep 8, 2020
1 parent 5735dff commit 04937f4
Showing 1 changed file with 82 additions and 45 deletions.
127 changes: 82 additions & 45 deletions src/components/inputnumber/InputNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ export class InputNumber extends Component {

getGroupingExpression() {
const formatter = new Intl.NumberFormat(this.props.locale, {useGrouping: true});
return new RegExp(`[${formatter.format(1000).trim().replace(this._numeral, '')}]`, 'g');
this.groupChar = formatter.format(1000000).trim().replace(this._numeral, '').charAt(0);
return new RegExp(`[${this.groupChar}]`, 'g');
}

getMinusSignExpression() {
Expand Down Expand Up @@ -210,12 +211,13 @@ export class InputNumber extends Component {
}

parseValue(text) {
let filteredText = text.trim()
let filteredText = text
.replace(this._suffix, '')
.replace(this._prefix, '')
.trim()
.replace(/\s/g, '')
.replace(this._currency, '')
.replace(this._group, '')
.replace(this._suffix, '')
.replace(this._prefix, '')
.replace(this._minusSign, '-')
.replace(this._decimal, '.')
.replace(this._numeral, this._index);
Expand All @@ -227,9 +229,8 @@ export class InputNumber extends Component {
let parsedValue = +filteredText;
return isNaN(parsedValue) ? null : parsedValue;
}
else {
return null;
}

return null;
}

repeat(event, interval, dir) {
Expand All @@ -248,7 +249,7 @@ export class InputNumber extends Component {
let currentValue = this.parseValue(this.inputEl.value) || 0;
let newValue = this.validateValue(currentValue + step);

this.updateInput(newValue, 'spin');
this.updateInput(newValue, null, 'spin');
this.updateModel(event, newValue);

this.handleOnChange(event, currentValue, newValue);
Expand Down Expand Up @@ -401,11 +402,11 @@ export class InputNumber extends Component {
}
}

this.updateValue(event, newValueStr, 'delete-single');
this.updateValue(event, newValueStr, null, 'delete-single');
}
else {
newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);
this.updateValue(event, newValueStr, 'delete-range');
this.updateValue(event, newValueStr, null, 'delete-range');
}
break;

Expand Down Expand Up @@ -439,11 +440,11 @@ export class InputNumber extends Component {
}
}

this.updateValue(event, newValueStr, 'delete-back-single');
this.updateValue(event, newValueStr, null, 'delete-back-single');
}
else {
newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);
this.updateValue(event, newValueStr, 'delete-range');
this.updateValue(event, newValueStr, null, 'delete-range');
}
break;

Expand All @@ -457,9 +458,10 @@ export class InputNumber extends Component {
let code = event.which || event.keyCode;
let char = String.fromCharCode(code);
const isDecimalSign = this.isDecimalSign(char);
const isMinusSign = this.isMinusSign(char);

if ((48 <= code && code <= 57) || this.isMinusSign(char) || isDecimalSign) {
this.insert(event, char, isDecimalSign);
if ((48 <= code && code <= 57) || isMinusSign || isDecimalSign) {
this.insert(event, char, { isDecimalSign, isMinusSign });
}
}

Expand Down Expand Up @@ -492,21 +494,33 @@ export class InputNumber extends Component {
return false;
}

insert(event, text, isDecimalSign = false) {
insert(event, text, sign = { isDecimalSign: false, isMinusSign: false }) {
const selectionStart = this.inputEl.selectionStart;
const selectionEnd = this.inputEl.selectionEnd;
let inputValue = this.inputEl.value.trim();
const decimalCharIndex = inputValue.search(this._decimal);
this._decimal.lastIndex = 0;
const minusCharIndex = inputValue.search(this._minusSign);
this._minusSign.lastIndex = 0;
let newValueStr;

if (isDecimalSign) {
if (sign.isMinusSign) {
if (selectionStart === 0) {
newValueStr = inputValue;
if (minusCharIndex === -1 || selectionEnd !== 0) {
newValueStr = this.insertText(inputValue, text, 0, selectionEnd);
}

this.updateValue(event, newValueStr, text, 'insert');
}
}
else if (sign.isDecimalSign) {
if (decimalCharIndex > 0 && selectionStart === decimalCharIndex) {
this.updateValue(event, inputValue, 'insert');
this.updateValue(event, inputValue, text, 'insert');
}
else if (decimalCharIndex > selectionStart && decimalCharIndex < selectionEnd) {
newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);
this.updateValue(event, newValueStr, 'insert');
this.updateValue(event, newValueStr, text, 'insert');
}
}
else {
Expand All @@ -515,30 +529,37 @@ export class InputNumber extends Component {
if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {
if ((selectionStart + text.length - (decimalCharIndex + 1)) <= maxFractionDigits) {
newValueStr = inputValue.slice(0, selectionStart) + text + inputValue.slice(selectionStart + text.length);
this.updateValue(event, newValueStr, 'insert');
this.updateValue(event, newValueStr, text, 'insert');
}
}
else {
newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);
const operation = selectionStart !== selectionEnd ? 'range-insert' : 'insert';
this.updateValue(event, newValueStr, operation);
this.updateValue(event, newValueStr, text, operation);
}
}
}

insertText(value, text, start, end) {
let newValueStr;

if ((end - start) === value.length)
newValueStr = text;
else if (start === 0)
newValueStr = text + value.slice(end);
else if (end === value.length)
newValueStr = value.slice(0, start) + text;
else
newValueStr = value.slice(0, start) + text + value.slice(end);
let textSplit = text.split('.');

return newValueStr;
if (textSplit.length === 2) {
const decimalCharIndex = value.slice(start, end).search(this._decimal);
this._decimal.lastIndex = 0;
return (decimalCharIndex > 0) ? value.slice(0, start) + this.formatValue(text) + value.slice(end) : value;
}
else if ((end - start) === value.length) {
return this.formatValue(text);
}
else if (start === 0) {
return text + value.slice(end);
}
else if (end === value.length) {
return value.slice(0, start) + text;
}
else {
return value.slice(0, start) + text + value.slice(end);
}
}

deleteRange(value, start, end) {
Expand Down Expand Up @@ -623,13 +644,13 @@ export class InputNumber extends Component {
this._minusSign.lastIndex = 0;
}

updateValue(event, valueStr, operation) {
updateValue(event, valueStr, insertedValueStr, operation) {
let currentValue = this.inputEl.value;
let newValue = null;

if (valueStr != null) {
newValue = this.parseValue(valueStr);
this.updateInput(newValue, operation);
this.updateInput(newValue, insertedValueStr, operation);
}

this.handleOnChange(event, currentValue, newValue);
Expand Down Expand Up @@ -666,10 +687,14 @@ export class InputNumber extends Component {
return this.props.max;
}

if (value === '-') { // Minus sign
return null;
}

return value;
}

updateInput(value, operation) {
updateInput(value, insertedValueStr, operation) {
let inputValue = this.inputEl.value;
let newValue = this.formatValue(value);
let currentLength = inputValue.length;
Expand All @@ -678,29 +703,41 @@ export class InputNumber extends Component {
this.inputEl.value = newValue;
this.inputEl.setSelectionRange(0, 0);
this.initCursor();
this.inputEl.setSelectionRange(this.inputEl.selectionStart + 1, this.inputEl.selectionStart + 1);
const prefixLength = (this.prefix || '').length;
const selectionEnd = prefixLength + insertedValueStr.length;
this.inputEl.setSelectionRange(selectionEnd, selectionEnd);
}
else {
let selectionStart = this.inputEl.selectionEnd;
let selectionStart = this.inputEl.selectionStart;
let selectionEnd = this.inputEl.selectionEnd;
this.inputEl.value = newValue;
let newLength = newValue.length;

if (newLength === currentLength) {
if (operation === 'range-insert') {
const startValue = this.parseValue((inputValue || '').slice(0, selectionStart));
const startValueStr = startValue !== null ? startValue.toString() : '';
const startExpr = startValueStr.split('').join(`(${this.groupChar})?`);
const sRegex = new RegExp(startExpr, 'g');
sRegex.test(newValue);

const tExpr = insertedValueStr.split('').join(`(${this.groupChar})?`);
const tRegex = new RegExp(tExpr, 'g');
tRegex.test(newValue.slice(sRegex.lastIndex));

selectionEnd = sRegex.lastIndex + tRegex.lastIndex;
this.inputEl.setSelectionRange(selectionEnd, selectionEnd);
}
else if (newLength === currentLength) {
if (operation === 'insert' || operation === 'delete-back-single')
this.inputEl.setSelectionRange(selectionEnd + 1, selectionEnd + 1);
else if (operation === 'range-insert')
this.inputEl.setSelectionRange(selectionEnd, selectionEnd);
else if (operation === 'delete-single')
this.inputEl.setSelectionRange(selectionEnd - 1, selectionEnd - 1);
else if (operation === 'delete-range')
this.inputEl.setSelectionRange(selectionStart, selectionStart);
else if (operation === 'spin')
this.inputEl.setSelectionRange(selectionStart, selectionEnd);
else if (operation === 'delete-range' || operation === 'spin')
this.inputEl.setSelectionRange(selectionEnd, selectionEnd);
}
else if (operation === 'delete-back-single') {
let prevChar = inputValue.charAt(selectionStart - 1);
let nextChar = inputValue.charAt(selectionStart);
let prevChar = inputValue.charAt(selectionEnd - 1);
let nextChar = inputValue.charAt(selectionEnd);
let diff = currentLength - newLength;
let isGroupChar = this._group.test(nextChar);

Expand Down

0 comments on commit 04937f4

Please sign in to comment.