validate input with decimal precision and scale

4.8k views Asked by At

I am trying to create a javascript function which is called on keypress event on a input which does the following:

  • Input should be a valid decimal with format (5,2) => (XXXXX.YY) which are variable to the function. Input is restricted if user adds any value which does not conform to the format above.
  • If existing input starts with . append 0 to the starting automatically

HTML

<input type="text" onkeypress="return checkDecimal(event, this, 5, 2);"  id="price2" value="27.15">

Javascript

function checkDecimal(evt, item, lenBeforeDecimal, lenAfterDecimal) {
    var charCode = evt.which;

    var trimmed = $(item).val().replace(/\b^0+/g, "");
    if(checkStartsWith(trimmed, '.') == true){
        trimmed = '0' + trimmed;
    }

    //Allow following keys
    //8 = Backspace, 9 = Tab
    if(charCode == 8 || charCode == 9){
        return true;
    }

    //Only a single '.' is to be allowed
    if(charCode == 46){
        var dotOccurrences = (trimmed.match(/\./g) || []).length;

        if(dotOccurrences != undefined && dotOccurrences == 1){
            return false;
        }else{
            return true;
        }
    }

    if (charCode > 31 && ((charCode < 48) || (charCode > 57))) {
        return false;
    }
    if ($(item).val() != trimmed){
        $(item).val(trimmed);}


    //Check the start and end length
    if(trimmed.indexOf('.') == -1){
        if(trimmed.length >= parseInt(lenBeforeDecimal)){
            return false;
        }
    }else{
        var inputArr = trimmed.split(".");
        if(inputArr[0].length > parseInt(lenBeforeDecimal) || inputArr[1].length >= parseInt(lenAfterDecimal)){
            return false;
        }
    }

    return true;
}
function checkStartsWith(str, prefix){
    return str.indexOf(prefix) === 0;
}

Issues

  • If user inputs 12345.9 and then moves the caret position after 5, user is able to add another digit before the decimal 123456.9 which should not be allowed.
  • If user inputs 1.9 and then remove 1 and add 5, 5 is added at the end and the entered value becomes 0.95 and not 5.9

JS Fiddle

1

There are 1 answers

1
RobG On BEST ANSWER

Consider using a regular expression like:

/^(\d{0,5}\.\d{0,2}|\d{0,5}|\.\d{0,2})$/;

that allows everything up to and including your required format, but returns false if the number part is more than 5 digits or if the fraction is more than 2 digits, e.g.:

<input type="text" onkeyup="check(this.value)"><span id="er"></span>

<script>

function check(v) {
  var re = /^(\d{0,5}\.\d{0,2}|\d{0,5}|\.\d{0,2})$/;
  document.getElementById('er').innerHTML = re.test(v);
}

</script>

You'll need separate validation for the final value, e.g.

/^\d{5}\.\d{2}$/.test(value);

to make sure it's the required format.

I don't understand the requirement to add a leading zero to "." since the user must enter 5 leading digits anyway (unless I misunderstand the question).