Look at the image:
I want design something like in the image, where a 4 digit one time password (OTP) is to be entered by user. Right now I have achieved th
Hope this solution helps you. You can remove onfocus event from input elements if you want.
<body>
<head>
<style>
input[type=number] {
height: 45px;
width: 45px;
font-size: 25px;
text-align: center;
border: 1px solid #000000;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
</style>
<script>
function getCodeBoxElement(index) {
return document.getElementById('codeBox' + index);
}
function onKeyUpEvent(index, event) {
const eventCode = event.which || event.keyCode;
if (getCodeBoxElement(index).value.length === 1) {
if (index !== 4) {
getCodeBoxElement(index+ 1).focus();
} else {
getCodeBoxElement(index).blur();
// Submit code
console.log('submit code ');
}
}
if (eventCode === 8 && index !== 1) {
getCodeBoxElement(index - 1).focus();
}
}
function onFocusEvent(index) {
for (item = 1; item < index; item++) {
const currentElement = getCodeBoxElement(item);
if (!currentElement.value) {
currentElement.focus();
break;
}
}
}
</script>
</head>
<body>
<form>
<input id="codeBox1" type="number" maxlength="1" onkeyup="onKeyUpEvent(1, event)" onfocus="onFocusEvent(1)"/>
<input id="codeBox2" type="number" maxlength="1" onkeyup="onKeyUpEvent(2, event)" onfocus="onFocusEvent(2)"/>
<input id="codeBox3" type="number" maxlength="1" onkeyup="onKeyUpEvent(3, event)" onfocus="onFocusEvent(3)"/>
<input id="codeBox4" type="number" maxlength="1" onkeyup="onKeyUpEvent(4, event)" onfocus="onFocusEvent(4)"/>
</form>
</body>
</body>
You can use the below directive if using AngularJS
In your HTML add
<div otp-input-directive options="otpInput"></div>
In your controller add
$scope.otpInput={
size:6,
type:"text",
onDone: function(value){
console.log(value);
},
onChange: function(value){
console.log(value);
}
};
Plunker link
UI component look and feel
https://github.com/amstel91/otp-input-directive
This works for me without any extra javascript code.
#partitioned {
padding-left: 15px;
letter-spacing: 42px;
border: 0;
background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
background-position: bottom;
background-size: 50px 1px;
background-repeat: repeat-x;
background-position-x: 35px;
width: 220px;
min-width: 220px;
}
#divInner{
left: 0;
position: sticky;
}
#divOuter{
width: 190px;
overflow: hidden;
}
<div id="divOuter">
<div id="divInner">
<input id="partitioned" type="text" maxlength="4" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');" onKeyPress="if(this.value.length==4) return false;"/>
</div>
</div>
I would just keep this 4 separate fields approach, and add the same event handler to all of them, which will:
You can even write a little separate JS for that, and re-use it.
You dont have to keep 4 separate fields;
First you should adjust the character spacing, and than adjust border style of bottom...
#partitioned {
padding-left: 15px;
letter-spacing: 42px;
border: 0;
background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
background-position: bottom;
background-size: 50px 1px;
background-repeat: repeat-x;
background-position-x: 35px;
width: 220px;
}
<input id="partitioned" type="text" maxlength="4" />
--EDIT to fix 5 underlines for 4 character ugliness--
var obj = document.getElementById('partitioned');
obj.addEventListener('keydown', stopCarret);
obj.addEventListener('keyup', stopCarret);
function stopCarret() {
if (obj.value.length > 3){
setCaretPosition(obj, 3);
}
}
function setCaretPosition(elem, caretPos) {
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
}
}
#partitioned {
padding-left: 15px;
letter-spacing: 42px;
border: 0;
background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
background-position: bottom;
background-size: 50px 1px;
background-repeat: repeat-x;
background-position-x: 35px;
width: 220px;
min-width: 220px;
}
#divInner{
left: 0;
position: sticky;
}
#divOuter{
width: 190px;
overflow: hidden;
}
<div id="divOuter">
<div id="divInner">
<input id="partitioned" type="text" maxlength="4" />
</div>
</div>
I think this can be a starting point... hope this will help...
I know this question is old. I stumbled upon this when I was trying to achieve the same for my project.
I couldn't find what I needed. So I made one myself with the ideas from here
You can use this with any number of characters and needs no change in javascript as long as all the input fields are inside a div
with id="otp"
.
Here is a preview:
Take a look at the code here
function OTPInput() {
const inputs = document.querySelectorAll('#otp > *[id]');
for (let i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('keydown', function(event) {
if (event.key === "Backspace") {
inputs[i].value = '';
if (i !== 0)
inputs[i - 1].focus();
} else {
if (i === inputs.length - 1 && inputs[i].value !== '') {
return true;
} else if (event.keyCode > 47 && event.keyCode < 58) {
inputs[i].value = event.key;
if (i !== inputs.length - 1)
inputs[i + 1].focus();
event.preventDefault();
} else if (event.keyCode > 64 && event.keyCode < 91) {
inputs[i].value = String.fromCharCode(event.keyCode);
if (i !== inputs.length - 1)
inputs[i + 1].focus();
event.preventDefault();
}
}
});
}
}
OTPInput();
@import url('https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css');
.form-control {
-webkit-transition: none;
transition: none;
width: 32px;
height: 32px;
text-align: center
}
.form-control:focus {
color: #3F4254;
background-color: #ffffff;
border-color: #884377;
outline: 0;
}
.form-control.form-control-solid {
background-color: #F3F6F9;
border-color: #F3F6F9;
color: #3F4254;
transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.form-control.form-control-solid:active,
.form-control.form-control-solid.active,
.form-control.form-control-solid:focus,
.form-control.form-control-solid.focus {
background-color: #EBEDF3;
border-color: #EBEDF3;
color: #3F4254;
transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
<div class="mb-6 text-center">
<div id="otp" class="flex justify-center">
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="first" maxlength="1" />
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="second" maxlength="1" />
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="third" maxlength="1" />
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="fourth" maxlength="1" />
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="fifth" maxlength="1" />
<input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="sixth" maxlength="1" />
</div>
</div>