Skip to content

Commit b055a79

Browse files
authored
Merge pull request #54 from satyam-seth-learnings/otp-input-field
Otp input field
2 parents 01bde3f + 9949158 commit b055a79

File tree

10 files changed

+330
-39
lines changed

10 files changed

+330
-39
lines changed

OTP Input Field/demo1/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- [Medium Blog Link](https://sqkhor.medium.com/create-an-otp-input-with-javascript-c0c9f7c610fe)

OTP Input Field/demo1/demo.html

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>OTP Input Field - Using JS</title>
7+
<link rel="stylesheet" href="style.css" />
8+
</head>
9+
<body>
10+
<div id="otp-input">
11+
<input
12+
type="number"
13+
step="1"
14+
min="0"
15+
max="9"
16+
autocomplete="no"
17+
pattern="\d*"
18+
/>
19+
<input
20+
type="number"
21+
step="1"
22+
min="0"
23+
max="9"
24+
autocomplete="no"
25+
pattern="\d*"
26+
/>
27+
<input
28+
type="number"
29+
step="1"
30+
min="0"
31+
max="9"
32+
autocomplete="no"
33+
pattern="\d*"
34+
/>
35+
<input
36+
type="number"
37+
step="1"
38+
min="0"
39+
max="9"
40+
autocomplete="no"
41+
pattern="\d*"
42+
/>
43+
<input
44+
type="number"
45+
step="1"
46+
min="0"
47+
max="9"
48+
autocomplete="no"
49+
pattern="\d*"
50+
/>
51+
<input
52+
type="number"
53+
step="1"
54+
min="0"
55+
max="9"
56+
autocomplete="no"
57+
pattern="\d*"
58+
/>
59+
</div>
60+
<input type="hidden" name="otp" />
61+
62+
<script src="script.js"></script>
63+
</body>
64+
</html>

OTP Input Field/demo1/script.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
function updateInput() {
2+
let inputValue = Array.from(inputs).reduce(function (otp, input) {
3+
otp += (input.value.length) ? input.value : ' ';
4+
return otp;
5+
}, "");
6+
document.querySelector("input[name=otp]").value = inputValue;
7+
}
8+
9+
window.onload = () => {
10+
const inputs = document.querySelectorAll("#otp-input input");
11+
12+
for (let i = 0; i < inputs.length; i++) {
13+
const input = inputs[i];
14+
15+
input.addEventListener("input", function () {
16+
// handling normal input
17+
if (input.value.length == 1 && i + 1 < inputs.length) {
18+
inputs[i + 1].focus();
19+
}
20+
21+
// if a value is pasted, put each character to each of the next input
22+
if (input.value.length > 1) {
23+
// sanities input
24+
if (isNaN(input.value)) {
25+
input.value = "";
26+
updateInput();
27+
return;
28+
}
29+
30+
// split characters to array
31+
const chars = input.value.split('');
32+
33+
for (let pos = 0; pos < chars.length; pos++) {
34+
// if length exceeded the number of inputs, stop
35+
if (pos + i >= inputs.length) break;
36+
37+
// paste value
38+
let targetInput = inputs[pos + i];
39+
targetInput.value = chars[pos];
40+
}
41+
42+
// focus the input next to the last pasted character
43+
let focus_index = Math.min(inputs.length - 1, i + chars.length);
44+
inputs[focus_index].focus();
45+
}
46+
updateInput();
47+
});
48+
49+
input.addEventListener("keydown", function (e) {
50+
// backspace button
51+
if (e.keyCode == 8 && input.value == '' && i != 0) {
52+
// shift next values towards the left
53+
for (let pos = i; pos < inputs.length - 1; pos++) {
54+
inputs[pos].value = inputs[pos + 1].value;
55+
}
56+
57+
// clear previous box and focus on it
58+
inputs[i - 1].value = '';
59+
inputs[i - 1].focus();
60+
updateInput();
61+
return;
62+
}
63+
64+
// delete button
65+
if (e.keyCode == 46 && i != inputs.length - 1) {
66+
// shift next values towards the left
67+
for (let pos = i; pos < inputs.length - 1; pos++) {
68+
inputs[pos].value = inputs[pos + 1].value;
69+
}
70+
71+
// clear the last box
72+
inputs[inputs.length - 1].value = '';
73+
input.select();
74+
e.preventDefault();
75+
updateInput();
76+
return;
77+
}
78+
79+
// left button
80+
if (e.keyCode == 37) {
81+
if (i > 0) {
82+
e.preventDefault();
83+
inputs[i - 1].focus();
84+
inputs[i - 1].select();
85+
}
86+
return;
87+
}
88+
89+
// right button
90+
if (e.keyCode == 39) {
91+
if (i + 1 < inputs.length) {
92+
e.preventDefault();
93+
inputs[i + 1].focus();
94+
inputs[i + 1].select();
95+
}
96+
return;
97+
}
98+
});
99+
}
100+
};

OTP Input Field/demo1/style.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
* {
2+
margin: 0;
3+
padding: 0;
4+
box-size: border-box;
5+
}
6+
7+
#otp-input {
8+
display: flex;
9+
gap: 0.5em;
10+
}
11+
12+
#otp-input input {
13+
width: 2em;
14+
padding: 0.5em 0;
15+
font-family: monospace;
16+
font-size: 1em;
17+
text-align: center;
18+
}
19+
20+
/* hide spinner */
21+
#otp-input input::-webkit-outer-spin-button,
22+
#otp-input input::-webkit-inner-spin-button {
23+
-webkit-appearance: none;
24+
margin: 0;
25+
}
26+
27+
#otp-input input[type="number"] {
28+
-moz-appearance: textfield; /* Firefox */
29+
}

OTP Input Field/demo2/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- [Blog Link](https://chriscoyier.net/2023/12/04/html-css-for-a-one-time-password-input/)

OTP Input Field/demo2/demo.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>OTP Input Field - Without using JS</title>
7+
<link rel="stylesheet" href="style.css" />
8+
</head>
9+
<body>
10+
<input
11+
required
12+
type="text"
13+
autocomplete="one-time-code"
14+
inputmode="numeric"
15+
maxlength="4"
16+
pattern="\d{4}"
17+
/>
18+
</body>
19+
</html>

OTP Input Field/demo2/style.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[autocomplete="one-time-code"] {
2+
--magic-number: 100px;
3+
4+
background-image: linear-gradient(#fff, #fff),
5+
url("https://assets.codepen.io/3/rounded-rectangle.svg");
6+
background-size: var(--magic-number);
7+
background-position-x: right, left;
8+
background-repeat: no-repeat, repeat-x;
9+
border: 0;
10+
height: var(--magic-number);
11+
width: calc(5 * var(--magic-number));
12+
font-size: calc(0.6 * var(--magic-number));
13+
font-family: monospace;
14+
letter-spacing: calc(0.64 * var(--magic-number));
15+
padding-inline-start: calc(0.3 * var(--magic-number));
16+
box-sizing: border-box;
17+
overflow: hidden;
18+
transform: translatex(calc(0.5 * var(--magic-number)));
19+
}
20+
[autocomplete="one-time-code"]:focus {
21+
outline: none;
22+
background-image: linear-gradient(#fff, #fff),
23+
url("https://assets.codepen.io/729148/blue-rounded-rectangle.svg");
24+
background-size: var(--magic-number);
25+
background-position-x: right, left;
26+
background-repeat: no-repeat, repeat-x;
27+
}
28+
29+
body {
30+
height: 100vh;
31+
margin: 0;
32+
display: grid;
33+
place-items: center;
34+
}

OTP Input Field/index.html

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>OTP Input Field</title>
8+
<style>
9+
* {
10+
padding: 0;
11+
margin: 0;
12+
box-sizing: border-box;
13+
}
14+
15+
body {
16+
height: 100vh;
17+
padding: 1rem;
18+
display: grid;
19+
gap: 1.2rem;
20+
place-items: center;
21+
background-color: black;
22+
}
23+
24+
a {
25+
color: white;
26+
padding: 1.2rem;
27+
font-size: 1.2rem;
28+
border-radius: 10px;
29+
text-decoration: none;
30+
border: 2px solid gray;
31+
background-color: rgba(123, 255, 0, 0.3);
32+
}
33+
34+
a:hover {
35+
border-color: white;
36+
background-color: rgba(123, 255, 0, 0.6);
37+
}
38+
</style>
39+
</head>
40+
41+
<body></body>
42+
<a href="./demo1/demo.html">Demo 1(Using JS)</a>
43+
<a href="./demo2/demo.html">Demo 2(Without using JS)</a>
44+
</html>
Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,45 @@
11
<!DOCTYPE html>
22
<html lang="en">
3-
4-
<head>
5-
<meta charset="UTF-8">
6-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8-
<title>JavaScript Experiments</title>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Scroll Triggered Animations</title>
98
<style>
10-
* {
11-
padding: 0;
12-
margin: 0;
13-
box-sizing: border-box;
14-
}
9+
* {
10+
padding: 0;
11+
margin: 0;
12+
box-sizing: border-box;
13+
}
1514

16-
body {
17-
height: 100vh;
18-
padding: 1rem;
19-
display: grid;
20-
gap: 1.2rem;
21-
place-items: center;
22-
background-color: black;
23-
}
15+
body {
16+
height: 100vh;
17+
padding: 1rem;
18+
display: grid;
19+
gap: 1.2rem;
20+
place-items: center;
21+
background-color: black;
22+
}
2423

25-
a {
26-
color: white;
27-
padding: 1.2rem;
28-
font-size: 1.2rem;
29-
border-radius: 10px;
30-
text-decoration: none;
31-
border: 2px solid gray;
32-
background-color: rgba(123, 255, 0, 0.3);
33-
}
24+
a {
25+
color: white;
26+
padding: 1.2rem;
27+
font-size: 1.2rem;
28+
border-radius: 10px;
29+
text-decoration: none;
30+
border: 2px solid gray;
31+
background-color: rgba(123, 255, 0, 0.3);
32+
}
3433

35-
a:hover {
36-
border-color: white;
37-
background-color: rgba(123, 255, 0, 0.6);
38-
}
34+
a:hover {
35+
border-color: white;
36+
background-color: rgba(123, 255, 0, 0.6);
37+
}
3938
</style>
40-
</head>
39+
</head>
4140

42-
<body>
43-
</body>
44-
<a href="./demo1/demo.html">Demo 1</a>
45-
<a href="./demo2/demo.html">Demo 2</a>
46-
<a href="./demo3/demo.html">Demo 3</a>
47-
</html>
41+
<body></body>
42+
<a href="./demo1/demo.html">Demo 1</a>
43+
<a href="./demo2/demo.html">Demo 2</a>
44+
<a href="./demo3/demo.html">Demo 3</a>
45+
</html>

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,6 @@
9696
<a href="./Custom Dropdown/demo.html">Custom Dropdown</a>
9797
<a href="./Markdown to HTML/demo.html">Markdown to HTML</a>
9898
<a href="./Audio Visualizer/demo.html">Audio Visualizer</a>
99+
<a href="./OTP Input Field/index.html">OTP Input Field</a>
99100
</body>
100101
</html>

0 commit comments

Comments
 (0)