<div class="container">
<h1 class="h3 text-center font-weight-light mb-4">Enter your one time password:</h1>
<form>
<fieldset>
<div class="d-flex align-items-center justify-content-center">
<div class="input-group justify-content-end flex-nowrap">
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" required>
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" required>
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" required>
</div>
<div class="input-group-seperator"></div>
<div class="input-group flex-nowrap">
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" required>
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" required>
<input type="text" class="form-control form-control--otp js-otp-input" inputmode="numeric" pattern="[0-9]*" required>
</div>
</div>
</fieldset>
</form>
</div>
/* Codepen style
_________________________________________ */
html, body {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.container {
max-width: 600px;
padding: 2rem;
}
/* Bootstrap Add-On (BEM-syntax)
_________________________________________ */
.form-control--otp {
line-height: 2.5;
height: 3.5rem;
font-size: 1.5rem;
font-weight: bold;
text-align: center;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
@media ( min-width: 375px ) {
.form-control--otp {
line-height: 3;
height: 4.5rem;
font-size: 2rem;
font-weight: bold;
text-align: center;
max-width: 3.5rem;
}
}
.input-group-seperator {
width: 2rem;
margin-left: 0.75rem;
margin-right: 0.75rem;
height: 0.3rem;
background: #ced4da;
border-radius: 0.1rem;
}
var BACKSPACE_KEY = 8;
var ENTER_KEY = 13;
var TAB_KEY = 9;
var LEFT_KEY = 37;
var RIGHT_KEY = 39;
var ZERO_KEY = 48;
var NINE_KEY = 57;
function otp(elementId) {
var inputs = document.querySelectorAll('.js-otp-input');
var callback = null;
function init(completeCallback) {
callback = completeCallback;
for (i = 0; i < inputs.length; i++) {
registerEvents(i, inputs[i]);
}
}
function destroy() {
for (i = 0; i < inputs.length; i++) {
registerEvents(i, inputs[i]);
}
}
function registerEvents(index, element) {
element.addEventListener("input", function(ev) {
onInput(index, ev);
});
element.addEventListener("paste", function(ev) {
onPaste(index, ev);
});
element.addEventListener("keydown", function(ev) {
onKeyDown(index, ev);
});
}
function onPaste(index, ev) {
ev.preventDefault();
var curIndex = index;
var clipboardData = ev.clipboardData || window.clipboardData;
var pastedData = clipboardData.getData("Text");
for (i = 0; i < pastedData.length; i++) {
if (i < inputs.length) {
if (!isDigit(pastedData[i])) break;
inputs[curIndex].value = pastedData[i];
curIndex++;
}
}
if (curIndex == inputs.length) {
inputs[curIndex - 1].focus();
callback(retrieveOTP());
} else {
inputs[curIndex].focus();
}
}
function onKeyDown(index, ev) {
var key = ev.keyCode || ev.which;
if (key == LEFT_KEY && index > 0) {
ev.preventDefault(); // prevent cursor to move before digit in input
inputs[index - 1].focus();
}
if (key == RIGHT_KEY && index + 1 < inputs.length) {
ev.preventDefault();
inputs[index + 1].focus();
}
if (key == BACKSPACE_KEY && index > 0) {
if (inputs[index].value == "") {
// Empty and focus previous input and current input is empty
inputs[index - 1].value = "";
inputs[index - 1].focus();
} else {
inputs[index].value = "";
}
}
if (key == ENTER_KEY) {
// force submit if enter is pressed
ev.preventDefault();
if (isOTPComplete()) {
callback(retrieveOTP());
}
}
if (key == TAB_KEY && index == inputs.length - 1) {
// force submit if tab pressed on last input
ev.preventDefault();
if (isOTPComplete()) {
callback(retrieveOTP());
}
}
}
function onInput(index, ev) {
var value = ev.data || ev.target.value;
var curIndex = index;
for (i = 0; i < value.length; i++) {
if (i < inputs.length) {
if (!isDigit(value[i])) {
inputs[curIndex].value = "";
break;
}
inputs[curIndex++].value = value[i];
if (curIndex == inputs.length) {
if(isOTPComplete()) {
callback(retrieveOTP());
}
} else {
inputs[curIndex].focus();
}
}
}
}
function retrieveOTP() {
var otp = "";
for (i = 0; i < inputs.length; i++) {
otp += inputs[i].value;
}
return otp;
}
function isDigit(d) {
return d >= "0" && d <= "9";
}
function isOTPComplete() {
var isComplete = true;
var i = 0;
while (i < inputs.length && isComplete) {
if (inputs[i].value == "") {
isComplete = false;
}
i++;
}
return isComplete;
}
return {
init: init
};
}
var otpModule = otp("otp-inputs");
otpModule.init(function(passcode) {});
This Pen doesn't use any external JavaScript resources.