Validate html text input as it's typed
What's the best way of validating an HTML text input as it's typed? All ways I know of doing it has some drawbacks:
Using
$.keypress
you only have access to the input's old value, not the new one. Also, some events (like cutting/pasting using the mouse) won't be detected.Using
$.change
only works when the input loses focus.This question proposes a solution, where you use polling to watch for property changes. In principle, it's possible to validate the new value in the callback, then revert to the old one if invalid. However, besides requiring polling, I'm not sure it's free from race conditions.
This article suggests using browser specific features when present, falling back to polling if none is available. Looks like the best approach so far.
[Update] as pointed in the answers,
$.keyup
give access to the value after update. However, not only it doesn't work for mouse cut/paste, but also fails if you press and hold a key, only releasing after a lot has been entered. Or, if combiningkeydown
andkeyup
to save/restore the old value, it breaks if the user types too fast.
None of the solutions above are error free or really safe cross-browsers. Are there better solutions out there, either ready-to-use or in-the-making? Seems to be a common problem, I've attempted to answer similar questions recently, with no success, and I'm interested in an answer as well.
(A good argument against this practice is also welcome, in case there are new problems that would rise if this validation were implemented; however, that seems a common thing in other languages, so I doubt it is a bad thing to want)
You can use the input
(FF) and propertychange
(all others) events to catch all forms of input including keyboard and rmb cut paste.
http://jsfiddle.net/dFBzW/
$('input').bind('input propertychange', function() {
$('#output').html($(this).val());
});
A good argument against this practice is also welcome, in case there are new problems that would rise if this validation were implemented; however, that seems a common thing in other languages, so I doubt it is a bad thing to want.
If by "validate" you mean "prevent invalid characters from being entered at all", I think this is a bad practice. It's confusing for users, who may not be paying close attention and who perhaps aren't even looking at the field while they type (e.g., if they're entering account or phone numbers that they're reading from a piece of paper). The value that actually gets saved/used may be slightly different to the value they thought they'd entered.
If by "validate" you mean "test the current value and draw the user's attention to any problems" by e.g., displaying an error next to the field or changing the background colour, then there is no problem using a combination of several events including keyup, change, blur, paste, click:
$("field selector").on("keyup change blur paste cut click", function() { ... });
This will catch most normal cases as the user types, and for the clipboard or drag'n'drop cases you at least know that at worst the field will still be validated when the user leaves it. (Obviously you don't allow submit until all errors have been corrected.)
If you process keyup and keydown that covers cases where the user held a key down, because most browsers will send repeated keydown events for that.
In the jQuery world, it's common to leverage plug-ins for these validation tasks. Plug-ins can be relatively easy to use, and their popularity usually reflects in less bugs than code written from scratch.
Input validation is usually split into categories, including:
1) Correct input format / Input mask. for example, only A-Z, or say, 10 digit numbers.
2) Content existence in a domain. For example, airport code or postal codes.
For (1) you can use these relatively popular plug-ins:
Digital Bush's Masked Input Plugin for Jquery. It has many options for customisation including spaces, eg:
from Digital Bush website:
$("#phone").mask("(999) 999-9999");
The autoNumeric from decorplanit.com . They have a nice support for numeric, as well as currency, rounding, etc.
adapted from autoNumeric website:
$('#amountPaid').autoNumeric({aSep: '.', aDec: ','}); // eg, 9.000,00
For (2), you can use, for example, jQuery UI's autocomplete, combined with server resource data, in a format like JSON. These are likely to require custom code to lock input, but you can still leverage plug-ins for the basic functionality, and focus on the specific business logic you are creating.
Some text above adapted from two answers in other posts here and here.