I have an input field that I would like to validate on when the user either presses enter or clicks away from it, for this I use the events keypress
and blur
. If the input fails validation, an alert box is called.
I noticed that in IE (all versions), if I press enter with invalid input, for some reason both the keypress and blur events are fired (I suspect it's the alert box, but it doesn't do this on FF/Chrome) and it shows two of the same alert box. How can I have it so only one is shown?
EDIT: In FF/Chrome, I now noticed that a second alert box appears when I click anywhere after I try to validate with enter.
Simplified code:
$("#input-field").keypress(function(event) {
if (event.keycode == 13) {
event.stopPropagation();
validate();
return false;
}
});
$("#input-field").blur(function() {
validate();
});
function validate() {
if ($("#input-field").val() == '') {
alert("Invalid input");
}
}
EDIT: Ah-ha. Not really a fix but a separate detail I forgot - I need to restore the invalid input to its previously valid value, so when the validate function checks the value again it doesn't fail twice.
I ended up just checking for an IE UserAgent and skipping the keypress event for IE (binding keypress and blur to the same function, as below). Not a direct or terrific solution, tragically, but I've been looking to solve the same problem to no avail. Some minor notes that might be helpful: jQuery normalizes which, so you can confidently use e.which == 13 with keypress. I'd also combine the functions into one bind, e.g.
$("#input-field").bind('blur keypress', function(e) {
if(e.which == 13) {
// keypress code (e.g. check for IE and return if so)
}
validate();
});
I've tried setting globals and using jQuery's data() to assign arbitrary flags to indicate whether (in your case) validation has already been triggered for the element, but the events trigger simultaneously or at least, if sequentially, rapidly enough that even with an opening line setting some flag to true did not do the trick. I'd read that putting in a tiny callback delay might help, but that is hella dirty and I wouldn't do it even as a workaround so I've not tested it. stopPropagation() and preventDefault() also did not help.