UNPKG

react-simple-currency

Version:

A react input wrapper to mask and handle currency values

160 lines (132 loc) 3.93 kB
var React = require('react') var PropTypes = require('prop-types') class SimpleCurrencyInput extends React.Component { constructor(props) { super(props) this.onInputType = this.onInputType.bind(this) this.formattedRawValue = this.formattedRawValue.bind(this) this.getRawValue = this.getRawValue.bind(this) this.state = { rawValue: this.props.value, tabIndex: this.props.tabIndex, readOnly: this.props.readOnly } } componentWillMount() { this.notifyParentWithRawValue(this.state.rawValue) } componentWillReceiveProps (nextProps) { if (nextProps.value || nextProps.value === 0) { this.setState({ rawValue: nextProps.value }) } } onInputType (event) { const input = event.target.value let rawValue = this.getRawValue(input) if (!rawValue) { rawValue = 0 } this.notifyParentWithRawValue(rawValue) this.setState({ rawValue }) } notifyParentWithRawValue (rawValue) { let display = this.formattedRawValue(rawValue) this.props.onInputChange(rawValue, display) } getRawValue (displayedValue) { let result = displayedValue result = removeOccurrences(result, this.props.delimiter) result = removeOccurrences(result, this.props.separator) result = removeOccurrences(result, this.props.unit) let intValue = parseInt(result) return intValue } formattedRawValue (rawValue) { const minChars = '0'.length + this.props.precision let result = '' result = `${rawValue}` if (result.length < minChars) { const leftZeroesToAdd = minChars - result.length result = `${repeatZeroes(leftZeroesToAdd)}${result}` } let beforeSeparator = result.slice(0, result.length - this.props.precision) let afterSeparator = result.slice(result.length - this.props.precision) if (beforeSeparator.length > 3) { var chars = beforeSeparator.split('').reverse() let withDots = '' for (var i = chars.length -1; i >= 0; i--) { let char = chars[i] let dot = i % 3 === 0 ? this.props.delimiter : '' withDots = `${withDots}${char}${dot}` } withDots = withDots.substring(0, withDots.length - 1) beforeSeparator = withDots } result = beforeSeparator + this.props.separator + afterSeparator if (this.props.unit) { result = `${this.props.unit} ${result}` } return result } render() { return ( <input id={this.props.id} className={this.props.className} onBlur={this.props.onInputBlur} onFocus={this.props.onInputFocus} onChange={this.onInputType} value={this.formattedRawValue(this.state.rawValue)} disabled={this.props.disabled} autoFocus={this.props.autoFocus} tabIndex={this.state.tabIndex} readOnly={this.state.readOnly} /> ) } } const repeatZeroes = (times) => { let result = '' let i = 0 for (i = 0; i < times; i++) { result += '0' } return result } const removeOccurrences = (from, toRemove) => { toRemove = toRemove.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') var re = new RegExp(toRemove, 'g') return from.replace(re, '') } SimpleCurrencyInput.propTypes = { id: PropTypes.string, autoFocus: PropTypes.bool, delimiter: PropTypes.string, disabled: PropTypes.bool, onInputChange: PropTypes.func, onInputBlur: PropTypes.func, onInputFocus: PropTypes.func, precision: PropTypes.number, readOnly: PropTypes.bool, separator: PropTypes.string, tabIndex: PropTypes.number, unit: PropTypes.string, value: PropTypes.number.isRequired } SimpleCurrencyInput.defaultProps = { value: 0, precision: 2, separator: '.', delimiter: ',', unit: '', disabled: false, autoFocus: false, onInputChange: () => {}, onInputBlur: () => {}, onInputFocus: () => {} } export default SimpleCurrencyInput