How can I focus the next input once the previous input has reached its maxlength value?
a:
b:
You can use plain JavaScript:
See DEMO.
Check the character length with el.value.length
. If it is equal to the maximum value, move to the next field by using focus()
. Bind this function to the keyup event with onkeyup
so that the function fires every time after the user keys in a character.
var a = document.getElementById("a"),
b = document.getElementById("b"),
c = document.getElementById("c");
a.onkeyup = function() {
if (this.value.length === parseInt(this.attributes["maxlength"].value)) {
b.focus();
}
}
b.onkeyup = function() {
if (this.value.length === parseInt(this.attributes["maxlength"].value)) {
c.focus();
}
}
No jQuery used and is a very clean implementation:
http://jsfiddle.net/4m5fg/5/
<div class="container">
a: <input type="text" maxlength="5" />
b: <input type="text" maxlength="5" />
c: <input type="text" maxlength="5" />
</div>
..
var container = document.getElementsByClassName("container")[0];
container.onkeyup = function(e) {
var target = e.srcElement || e.target;
var maxLength = parseInt(target.attributes["maxlength"].value, 10);
var myLength = target.value.length;
if (myLength >= maxLength) {
var next = target;
while (next = next.nextElementSibling) {
if (next == null)
break;
if (next.tagName.toLowerCase() === "input") {
next.focus();
break;
}
}
}
// Move to previous field if empty (user pressed backspace)
else if (myLength === 0) {
var previous = target;
while (previous = previous.previousElementSibling) {
if (previous == null)
break;
if (previous.tagName.toLowerCase() === "input") {
previous.focus();
break;
}
}
}
}
If you're focused on creating card(debit/credit) number input type. Then clean an easily manageable jQuery version as follows:
/*..............................................................................................
* jQuery function for Credit card number input group
......................................................................................................*/
// make container label of input groups, responsible
$('.card-box').on('focus', function(e){
$(this).parent().addClass('focus-form-control');
});
$('.card-box').on('blur', function(e){
$(this).parent().removeClass('focus-form-control');
});
$('.card-box-1').on('keyup', function(e){
e.preventDefault();
var max_length = parseInt($(this).attr('maxLength'));
var _length = parseInt($(this).val().length);
if(_length >= max_length) {
$('.card-box-2').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
if(_length <= 0){
return;
}
});
$('.card-box-2').on('keyup', function(e){
e.preventDefault();
var max_length = parseInt($(this).attr('maxLength'));
var _length = parseInt($(this).val().length);
if(_length >= max_length) {
$('.card-box-3').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
if(_length <= 0){
$('.card-box-1').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
});
$('.card-box-3').on('keyup', function(e){
e.preventDefault();
var max_length = parseInt($(this).attr('maxLength'));
var _length = parseInt($(this).val().length);
if(_length >= max_length) {
$('.card-box-4').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
if(_length <= 0){
$('.card-box-2').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
});
$('.card-box-4').on('keyup', function(e){
e.preventDefault();
var max_length = parseInt($(this).attr('maxLength'));
var _length = parseInt($(this).val().length);
if(_length >= max_length) {
return;
}
if(_length <= 0){
$('.card-box-3').focus().removeAttr('readonly');
$(this).attr('readonly', 'readonly');
}
});
/*..............................................................................................
* End jQuery function for Credit card number input group
......................................................................................................*/
/* Hide HTML5 Up and Down arrows. */
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none; margin: 0;
}
input[type="number"] { -moz-appearance: textfield; }
.card-box {
width: 20%; display: inline-block; height: 100%; border: none;
}
.focus-form-control {
border-color: #66afe9; outline: 0;-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="form-control" style="padding: 0; max-width: 300px; ">
<input class="card-box card-box-1" type="number" id="CreditCard_CardNumber1" required step="1" minlength="4" maxlength="4" pattern="[0-9]{4}" value="" placeholder="0000"
onClick="this.setSelectionRange(0, this.value.length)" oninput="this.value=this.value.slice(0,this.maxLength||'');this.value=(this.value < 1) ? ('') : this.value;"/>
<input class="card-box card-box-2" type="number" id="CreditCard_CardNumber2" readonly required step="1" minlength="4" maxlength="4" pattern="[0-9]{4}" value="" placeholder="0000"
onClick="this.setSelectionRange(0, this.value.length)" oninput="this.value=this.value.slice(0,this.maxLength||'');this.value=(this.value < 1) ? ('') : this.value;" />
<input class="card-box card-box-3" type="number" id="CreditCard_CardNumber3" readonly required step="1" minlength="4" maxlength="4" pattern="[0-9]{4}" value="" placeholder="0000"
onClick="this.setSelectionRange(0, this.value.length)" oninput="this.value=this.value.slice(0,this.maxLength||'');this.value=(this.value < 1) ? ('') : this.value;" />
<input class="card-box card-box-4" type="number" id="CreditCard_CardNumber4" readonly required step="1" minlength="4" maxlength="4" pattern="[0-9]{4}" value="" placeholder="0000"
onClick="this.setSelectionRange(0, this.value.length)" oninput="this.value=this.value.slice(0,this.maxLength||'');this.value=(this.value < 1) ? ('') : this.value;" />
</div>
Updated btevfik code, Onkeyup or onkeydown will create issue as you won't be able to delete the previous input on tab navigation. It will be tough to edit or change the text inside the input box as it will be limited to maxlength. So we can use oninput event to achieve the task.
DEMO
HTML
<ul>
<li>a: <input type="text" maxlength="5" /></li>
<li>b: <input type="text" maxlength="3" /></li>
<li>c: <input type="text" maxlength="5" /></li>
<li>d: <input type="text" maxlength="3" /></li>
<li>e: <input type="text" maxlength="6" /></li>
<li>f: <input type="text" maxlength="10" /></li>
<li>g: <input type="text" maxlength="7" /></li>
</ul>
Javascript
$(document).ready(function(){
$('input').on("input", function(){
if($(this).val().length==$(this).attr("maxlength")){
$(this).next().focus();
}
});
});
CSS
ul {list-style-type:none;}
li {padding:5px 5px;}
You can watch for input in the fields and test its value:
$("input").bind("input", function() {
var $this = $(this);
setTimeout(function() {
if ( $this.val().length >= parseInt($this.attr("maxlength"),10) )
$this.next("input").focus();
},0);
});
Working demo.
The setTimeout
is there to ensure the code will only run after the input is completed and the value updated. Binding input
ensures most types of input will trigger the event, including key presses, copy/paste (even from mouse) and drag & drop (though in this case, the latter won't work, since the focus was on the draggable, not the droppable).
Note: on some older browsers, you might also need to bind propertychange
.
If a user pastes text that is greater than the maxlength, ideally it should spill into the next input.
To do that, you might need to remove the maxlength
attribute using JavaScript (to be able to capture the full input), and implement that functionality yourself. I made a small example, relevant parts below:
$("input").each(function() {
var $this = $(this);
$(this).data("maxlength", $this.prop("maxlength"));
$(this).removeAttr("maxlength");
})
This removes the attribute, but saves it in data, so you can access it later.
function spill($this, val) {
var maxlength = $this.data("maxlength");
if ( val.length >= maxlength ) {
$this.val(val.substring(0, maxlength));
var next = $this.next("input").focus();
spill(next, val.substring(maxlength));
}
else
$this.val(val);
}
Here the max length logic is reintroduced in JavaScript, as well as getting the "discarded" part and using it in a recursive call to spill
. If there's no next element, the call to data
will return undefined
and the loop will stop, so the input will be truncated in the last field.
let otp = document.querySelector('#otp-screen');
for(let pin of otp.children) {
pin.onkeyup = function() {
if(pin.nextElementSibling) {
pin.nextElementSibling.focus();
}
}
}
<div class="otp-screen" id="otp-screen">
<input type="text" placeholder="0" maxlength="1"/>
<input type="text" placeholder="0" maxlength="1"/>
<input type="text" placeholder="0" maxlength="1"/>
<input type="text" placeholder="0" maxlength="1"/>
</div>