Form validation with keydown, keypress, and keyup
There is quite a bit of confusion in the beginner JavaScript world as to what the difference is between the keydown, keypress, and keyup events. So I hope that the following can help clear up some of the common questions as well as provide some solutions to make your life easier when dealing with cross browser key events.
As with all DOM events there is a generally accepted order to which they fire and key events are no different. When the user hits a key, the events are fired in the following sequence; keydown, keypress, keyup.
- Keydown: fired when the key is pressed but before any values have been passed to the DOM. This means that you can prevent the key from being pressed to disable user inputs.
- Keypress: fired when the key which is being pressed results in a character being sent. So this excludes modifier keys, directional keys, and keys which remove text.
- Keyup: fired after the user has released the key, telling you what key was pressed but because its being fired after the fact you are unable to prevent this event. The best way to understand these events is an example. Lets say we have a currency input in a form which we want to validate as the user types.
First we need some rules:
- Maximum value $99999.99
- Cents are not required but available Note: I am intentionally ignoring the possibility of a user pasting into the field as that’s out of scope of this post.
Click here to view this simple example on jsbin: Simple form validation on user input
var input = document.getElementsByName('currency-field')[0],
currencyRegex = /^[0-9]{0,5}(\.[0-9]{0,2})?$/;
function handleKeypress(e) {
// Get the string value of the charCode.
var char = String.fromCharCode(e.charCode),
target = e.target,
inputVal = target.value,
// Construct what the value will be if the event is not prevented.
value = inputVal.substr(0, target.selectionStart) + char + inputVal.substr(target.selectionEnd);
// Test to make sure the user is inputting only valid characters
// and that the resulting input is valid.
if (!char.match(/[0-9.]/) || !value.match(currencyRegex)) {
toggleUI(false, target);
} else {
toggleUI(true, target);
}
}
function handleKeyup(e) {
var target = e.target,
keyCode = e.keyCode;
// If the user deletes anything, test the value in the input
// again to check for validity.
if (keyCode === 8 || keyCode === 46) {
if(!target.value.match(currencyRegex)) {
toggleUI(false, target);
} else {
toggleUI(true, target);
}
}
}
function toggleUI(valid, target) {
if (valid === true) {
target.className = "valid";
} else {
target.className = "warning";
}
}
// On keypress or keyup, call their callback
input.onkeypress = handleKeypress;
input.onkeyup = handleKeyup;
This example should be fairly straight forward to follow along with but there are a few points of interest that relate to key events.
- First, notice that I am listening on not only keypress but also keyup. This is because keypress does not fire when the user deletes a character but we still need to check the input value to be sure that it’s valid.
- Second, you’ll see that I’m using e.charCode in the keypress handler but using e.keyCode in the keyup handler. This is because I don’t care what key was pressed on keypress, I only care what is being inserted into the input field; however on the keyup, I only care that a delete/backspace key was released but am not concerned about what was entered into the text box. Ok so now what about keydown? Another example is in order; we’ll take the previous example, but instead of notifying the user that something is wrong, we will prevent them from inputting invalid characters
Click here to view this simple example on jsbin: Prevent invalid input on form
var input = document.getElementsByName('currency-field')[0],
currencyRegex = /^[0-9]{0,5}(\.[0-9]{0,2})?$/;
function handleKeypress(e) {
// Get the string value of the charCode.
var char = String.fromCharCode(e.charCode),
target = e.target,
inputVal = target.value,
// Construct what the value will be if the event is not prevented.
value = inputVal.substr(0, target.selectionStart) + char + inputVal.substr(target.selectionEnd);
// Test to make sure the user is inputting only valid characters
// and that the resulting input is valid.
if (!char.match(/[0-9.]/) || !value.match(currencyRegex)) {
e.preventDefault();
}
}
function handleKeydown(e) {
var target = e.target,
keyCode = e.keyCode,
inputVal = target.value,
value;
// If the user deletes anything, construct the resulting
// value to determine validity.
if (keyCode === 8) {
value = inputVal.substr(0, target.selectionStart - 1) + inputVal.substr(target.selectionEnd);
}
if (keyCode === 46) {
value = inputVal.substr(0, target.selectionStart) + inputVal.substr(target.selectionEnd + 1);
}
if (value) {
if(!value.match(currencyRegex)) {
e.preventDefault();
}
}
}
// On keypress or keyup, call their callback
input.onkeypress = handleKeypress;
input.onkeydown = handleKeydown;
You can see by this last example that by using keydown we can listen for the delete or backspace key, check the resulting input value, and if it’s invalid, prevent the user action.
As with anything front end related there are going to be cross browser differences so I highly recommend using one of the quality javascript libraries and frameworks available to normalize these differences for you. If you have read any of my other posts you have probably guessed that I’m partial to the YUI framework.
I hope that these examples not only show you how keyup, keydown, and keypress function; but also give you some ideas on the best situations to use them. If you have any questions feel free to comment below or mention me @fromanegg