Reputation: 109
I have a form that is split into individual input boxes that visitors type letters into that form a complete word. Each input has a max length attribute of 1 that is caught by keyup()
, then if the input length equals 1 it goes to the next input using next().
This system works fine, BUT people are complaining that when they type fast it will miss letters. I am curious to know if this is simply a delay in the next()
function that cannot be overcome, or if this is just bad coding on my part?
Here is a JSFiddle, and here is a runnable Stack Snippet:
$('#psw input').keyup(function(e) {
if ($(this).val().length > 1) {
$(this).val($(this).val().substring(0, 1));
}
if ($(this).val().length == $(this).attr("maxlength")) {
if ($(this).next('[type="text"]').length > 0) {
$(this).next('[type="text"]')[0].focus();
}
}
});
$('#psw input').keydown(function(e) {
if ((e.which == 8 || e.which == 46) && $(this).val() == '') {
if ($(this).prev('[type="text"]').length > 0) {
$(this).prev('[type="text"]')[0].focus();
}
}
});
input {
width: 30px;
height: 30px;
margin: 20px;
text-align: center;
font-size: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="psw">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
</div>
Upvotes: 1
Views: 669
Reputation: 20368
The issue is that users typing quickly will usually have multiple keys pressed at the same time, so when you rely on keyup
, you get inconsistent results, because the user will have pressed a second key by the time they have released the first.
Here is a modified version of your function that uses keydown
only, along with setTimeout
to let the character in the current field be deleted when the user presses backspace, before jumping to the previous field. This works because setTimeout
queues the field movement command after the user's backspace key is executed in the browser execution queue. No key buffer or anything else complex is needed.
This eliminates all of the issues with keys being pressed soon after one another. Try it while typing fast!
Live Demo:
$('#psw input').keydown(function(e) {
if ((e.which == 8 || e.which == 46)) {
if ($(this).prev('[type="text"]').length > 0) {
var self = this;
setTimeout(function() {
$(self).prev('[type="text"]')[0].focus();
}, 0);
}
return;
}
if ($(this).val().length > 1) {
$(this).val($(this).val().substring(0, 1));
}
if ($(this).val().length == $(this).attr("maxlength")) {
if ($(this).next('[type="text"]').length > 0) {
$(this).next('[type="text"]')[0].focus();
}
}
});
input {
width: 30px;
height: 30px;
margin: 20px;
text-align: center;
font-size: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="psw">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
<input type="text" maxlength="1">
</div>
JSFiddle Version: https://jsfiddle.net/873f4Lo0/2/
Upvotes: 1