4

I have a JavaScript function that validates an input field and prevents the user from typing anything that doesn't match the condition. This function is based on event.keyCode.

I'm trying to modify the function to use a RegExp and validates not "per character" but "per whole input" so that it does the same, but with different conditions:

  1. numeric only
  2. allowed decimal "." or ","

Here is the function in its current form, using event.keyCode:

function isNumeric(evt, alertDIVid, alertMsg) {
    var charCode = (evt.which) ? evt.which : event.keyCode
    if (charCode >= 48 && charCode <= 57) {
        document.getElementById(alertDIVid).innerHTML = '';
        return true;
    }
    else {
        document.getElementById(alertDIVid).innerHTML = alertMsg;
        return false;
    }
}

document.getElementById('AMNT').onkeypress = function(event) {
    event = event || window.event;
    return isNumeric(event, 'numericalert', 'Numeric values only!')
};
8
  • This is an almost exact duplicate of your previous question, apart from the added , as decimal separator. Or am I missing something? Commented Jan 11, 2012 at 19:51
  • 1
    it's similar but I don't know how to deny typing if condition does not match... Commented Jan 11, 2012 at 19:51
  • Why would you use RegEx for that? It seems perfectly simple and logical to just create an array of allowed characters and test every new character against it. Using RegEx for this task would be swatting a fly with a wrecking ball Commented Jan 11, 2012 at 19:54
  • @Codemonkey: with RegEx I can control and deny an input like "38.9.2", but not with allowed characters... Commented Jan 11, 2012 at 19:56
  • 1
    Hint in the right direction: The keypress event is fired before the field is populated. If you want to validate the value of an input field, the keyup event has to be used. A downside (or advantage?) of the keyup event is that it is only fired once (when the key is released), while the keypress event is fired also for each keypress. Commented Jan 11, 2012 at 20:15

3 Answers 3

10

In order to do the kind of validation you want, you need to listen to the keyup event instead. This event fires after the field is changed, so that you know the new value of the field. You also need to know the previous value of the field so you can "reset" it if what the user typed turns out to be invalid.

For example:

(function() {
    var previousValue = document.getElementById('myInput').value;
    var pattern = /^\d*((\.|,)\d*)?$/;

    function validateInput(event) {
        event = event || window.event;
        var newValue = event.target.value || '';

        if (newValue.match(pattern)) {
            // Valid input; update previousValue:
            previousValue = newValue;
        } else {
            // Invalid input; reset field value:
            event.target.value = previousValue;
        }
    }

    document.getElementById('myInput').onkeyup = validateInput;
}());

Working demo: http://jsfiddle.net/8kUdG/

It's worth noting that this will also validate empty strings, as well as unfinished numbers, like 5, or 42. (otherwise the user would have to insert the decimal sign after typing the decimals, which would be... weird).

And finally, keep in mind that this might not be a cross-browser safe solution. If you need a pure-JavaScript solution, you will need to refine it (i.e., this might not work in IE).


Edit: of course, showing an error message instead of resetting the input field to the previous value is also perfectly possible (updated JSFiddle):

(function() {
    var pattern = /^(?=.)\d*(?:[.,]\d+)?$/;
    var error = document.getElementById('error');

    document.getElementById('myInput').onkeyup = function(event) {
        event = event || window.event;
        var newValue = event.target.value || '';

        if (newValue.match(pattern)) {
            error.innerHTML = '';
        } else {
            error.innerHTML = 'Not a valid number!';
        }
    };
}());

I leave it up to you to replace the alert with something more user-friendly.

Sign up to request clarification or add additional context in comments.

7 Comments

You might want to replace ^ with ^(?=\.?\d|$) to ensure that the input field contains a digit. Your test will allow nothing (seems OK), or just a dot (not OK). My suggestion will allow: .5, 5., 5, etc. And empty strings. If the string should not be empty, remove |$.
Also, it's better to not modify the input's field. The OP has done a good job by notifying the user instead of updating the value: Using your current code, the user won't be able to easily correct any invalid input, because your code reverts the input's value.
@Rob: this is a tricky matter, because the user will still have to input a single . while typing (e.g.) .5. I think extra validation is needed onsubmit...
Your updated code is still having an issue: The alert dialog will prevent the user from updating the input field. This is a big annoyance, as illustrated here: jsfiddle.net/ANRPy.
+1 for efforts and processing tips. Final tip, your secondary RegExp can be optimized to: /^(?=.)\d*(?:[.,]\d+)?$/
|
0

The easiest solution would be something like this

// Returns true on valid, false on invalid
function myInputFilter(input)
{
    var value = input.value;
    var regex = /^[\d\,\.]*$/;

    if(!regex.test(value))
        return false;

    return true;
}

You could edit the function to just take a string argument, but I've chosen to have it accept the text input element instead. The RegEx can be replaced by anything, I've made a simple one for this example. I would refine it a bit if I were you (You can use the excellent online tool RegExr)

Here is an example of the filter implemented

http://jsfiddle.net/kVV77/

1 Comment

Please don't (just) refer to an external site. Make sure your answer can be read separately. Also; the OP did not specify the use of jQuery anywhere.
0

You can use following regular expression:

/^[+-]?(?=.)(?:\d+,)*\d*(?:\.\d+)?$/

to allow only any number of comma and only one dot . with the condition that number cannot start with a comma. Number can have optional + or - at the start.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.