Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decimalPrecision option and supporting tests #15

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 30 additions & 24 deletions lib/number_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function escapeRegExp(str) {
var propTypes = {
thousandSeparator: _react.PropTypes.oneOf([',', '.', true, false]),
decimalSeparator: _react.PropTypes.oneOf([',', '.', true, false]),
decimalPrecision: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.bool]),
displayType: _react.PropTypes.oneOf(['input', 'text']),
prefix: _react.PropTypes.string,
suffix: _react.PropTypes.string,
Expand All @@ -34,7 +35,8 @@ var propTypes = {

var defaultProps = {
displayType: 'input',
decimalSeparator: '.'
decimalSeparator: '.',
decimalPrecision: false
};

var NumberFormat = function (_React$Component) {
Expand Down Expand Up @@ -63,9 +65,9 @@ var NumberFormat = function (_React$Component) {
}, {
key: 'getSeparators',
value: function getSeparators() {
var _props = this.props;
var thousandSeparator = _props.thousandSeparator;
var decimalSeparator = _props.decimalSeparator;
var _props = this.props,
thousandSeparator = _props.thousandSeparator,
decimalSeparator = _props.decimalSeparator;

if (thousandSeparator === true) {
thousandSeparator = ',';
Expand All @@ -87,9 +89,8 @@ var NumberFormat = function (_React$Component) {
}, {
key: 'getNumberRegex',
value: function getNumberRegex(g) {
var _getSeparators = this.getSeparators();

var decimalSeparator = _getSeparators.decimalSeparator;
var _getSeparators = this.getSeparators(),
decimalSeparator = _getSeparators.decimalSeparator;

return new RegExp('\\d' + (decimalSeparator ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined);
}
Expand Down Expand Up @@ -123,9 +124,9 @@ var NumberFormat = function (_React$Component) {
}, {
key: 'formatWithPattern',
value: function formatWithPattern(str) {
var _props2 = this.props;
var format = _props2.format;
var mask = _props2.mask;
var _props2 = this.props,
format = _props2.format,
mask = _props2.mask;

if (!format) return str;
var hashCount = format.split('#').length - 1;
Expand All @@ -149,16 +150,17 @@ var NumberFormat = function (_React$Component) {
}, {
key: 'formatInput',
value: function formatInput(val) {
var _props3 = this.props;
var prefix = _props3.prefix;
var suffix = _props3.suffix;
var mask = _props3.mask;
var format = _props3.format;
var _props3 = this.props,
prefix = _props3.prefix,
suffix = _props3.suffix,
mask = _props3.mask,
format = _props3.format;

var _getSeparators2 = this.getSeparators();
var _getSeparators2 = this.getSeparators(),
thousandSeparator = _getSeparators2.thousandSeparator,
decimalSeparator = _getSeparators2.decimalSeparator;

var thousandSeparator = _getSeparators2.thousandSeparator;
var decimalSeparator = _getSeparators2.decimalSeparator;
var decimalPrecision = this.props.decimalPrecision;

var maskPattern = format && typeof format == 'string' && !!mask;

Expand All @@ -178,9 +180,14 @@ var NumberFormat = function (_React$Component) {
} else {
var beforeDecimal = formattedValue,
afterDecimal = '';
var hasDecimals = formattedValue.indexOf(decimalSeparator) !== -1;
var hasDecimals = formattedValue.indexOf(decimalSeparator) !== -1 || decimalPrecision !== false;
if (decimalSeparator && hasDecimals) {
var parts = formattedValue.split(decimalSeparator);
if (decimalPrecision !== false) {
var precision = decimalPrecision === true ? 2 : decimalPrecision;
var parts = parseFloat(formattedValue).toFixed(precision).split(decimalSeparator);
} else {
var parts = formattedValue.split(decimalSeparator);
}
beforeDecimal = parts[0];
afterDecimal = parts[1];
}
Expand Down Expand Up @@ -226,10 +233,9 @@ var NumberFormat = function (_React$Component) {
e.persist();
var inputValue = e.target.value + '';

var _formatInput = this.formatInput(inputValue);

var formattedValue = _formatInput.formattedValue;
var value = _formatInput.value;
var _formatInput = this.formatInput(inputValue),
formattedValue = _formatInput.formattedValue,
value = _formatInput.value;

var cursorPos = this.refs.input.selectionStart;

Expand Down
18 changes: 13 additions & 5 deletions src/number_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function escapeRegExp(str) {
const propTypes = {
thousandSeparator: PropTypes.oneOf([',', '.', true, false]),
decimalSeparator: PropTypes.oneOf([',', '.', true, false]),
decimalPrecision: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
displayType: PropTypes.oneOf(['input', 'text']),
prefix: PropTypes.string,
suffix: PropTypes.string,
Expand All @@ -24,7 +25,8 @@ const propTypes = {

const defaultProps = {
displayType: 'input',
decimalSeparator: '.'
decimalSeparator: '.',
decimalPrecision: false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep then default value of decimal precision as unlimited

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand your comment. If they pass false to the decimalPrecision, it would be unlimited number of decimal places. Could you explain this a little more?

};

class NumberFormat extends React.Component {
Expand Down Expand Up @@ -119,7 +121,8 @@ class NumberFormat extends React.Component {

formatInput(val) {
const {prefix, suffix, mask, format} = this.props;
const {thousandSeparator, decimalSeparator} = this.getSeparators()
const {thousandSeparator, decimalSeparator} = this.getSeparators();
const {decimalPrecision} = this.props;
const maskPattern = format && typeof format == 'string' && !!mask;

const numRegex = this.getNumberRegex(true);
Expand All @@ -139,9 +142,14 @@ class NumberFormat extends React.Component {
}
else{
let beforeDecimal = formattedValue, afterDecimal = '';
const hasDecimals = formattedValue.indexOf(decimalSeparator) !== -1;
const hasDecimals = formattedValue.indexOf(decimalSeparator) !== -1 || decimalPrecision !== false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on current default value of decimalPrecision, user always have to define decimalPrecision otherwise he will not be able to add it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not be able to add what? If they don't define decimalPrecision, it would bypass my change altogether and function as it normally would. Am I missing something?

if(decimalSeparator && hasDecimals) {
const parts = formattedValue.split(decimalSeparator)
if(decimalPrecision !== false) {
const precision = decimalPrecision === true ? 2 : decimalPrecision;
var parts = parseFloat(formattedValue).toFixed(precision).split(decimalSeparator);
}else {
var parts = formattedValue.split(decimalSeparator);
}
beforeDecimal = parts[0];
afterDecimal = parts[1];
}
Expand All @@ -152,7 +160,7 @@ class NumberFormat extends React.Component {
if(prefix) beforeDecimal = prefix + beforeDecimal;
if(suffix) afterDecimal = afterDecimal + suffix;

formattedValue = beforeDecimal + (hasDecimals && decimalSeparator || '') + afterDecimal;
formattedValue = beforeDecimal + (hasDecimals && decimalSeparator || '') + afterDecimal;
}

return {
Expand Down
92 changes: 92 additions & 0 deletions test/input_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,74 @@ describe('FormatNumberInput as input', () => {
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111 2111 1211 1111");
});

it('should round to passed decimal precision', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput decimalPrecision={4}/>);
const input = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'input'
);

//case 1st - already exactly precision 4 should stay that way
input.value = "4111.1111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.1111");

//case 2nd - longer precision should round
input.value = "4111.11111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.1111");

//case 3rd - shorter precision adds 0
input.value = "4111.111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.1110");

//case 4th - no decimal should round with 4 zeros
input.value = "4111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.0000");

});


it('should not round by default', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput />);
const input = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'input'
);

//case 1st - no rounding with long decimal
input.value = "4111.111111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.111111");

//case 2nd - no rounding with whole numbers
input.value = "4111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111");

//case 3rd - no rounding on single place decimals
input.value = "4111.1";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.1");
});

it('should round default 2 places', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput decimalPrecision={true} />);
const input = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'input'
);

//case 1st - auto round to 2 places
input.value = "4111.1111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.11");

//case 2nd - auto round whole integers
input.value = "4111";
ReactTestUtils.Simulate.change(input);
expect(input.value).toEqual("4111.00");
});
});

/*** format_number input as text ****/
Expand Down Expand Up @@ -184,4 +252,28 @@ describe('FormatNumberInput as text', () => {
);
expect(span.textContent).toEqual("4111 1111 1111 11__");
});

it('should not round decimals by defualt', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput value="4111" displayType={'text'} />);
const span = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'span'
);
expect(span.textContent).toEqual("4111");
});

it('should round to 2 decimals if passed true', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput value="4111" displayType={'text'} decimalPrecision={true} />);
const span = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'span'
);
expect(span.textContent).toEqual("4111.00");
});

it('should round to 4 decimals if passed 4', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput value="4111.11" displayType={'text'} decimalPrecision={4} />);
const span = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'span'
);
expect(span.textContent).toEqual("4111.1100");
});
});