How to split an input field into separate input fields on the screen?

Look at the image:

enter image description here

I want to create something like an image where a user password enters a 4-digit one-time password (OTP). Right now, I achieved this with four separate inputs, and then combining the values ​​in javascript:

<input type="text" class="form-control" placeholder="0" maxlength="1" /> <input type="text" class="form-control" placeholder="0" maxlength="1" /> <input type="text" class="form-control" placeholder="0" maxlength="1" /> <input type="text" class="form-control" placeholder="0" maxlength="1" /> 

I am not sure if this is the right approach. I think that there should be some style parameters by which one text input field will be displayed as divided into an image. Is bootstrap possible? How to create one input control that will appear as a split input field?

+17
source share
6 answers

You do not need to store 4 separate fields;

First you need to adjust the spacing between characters, and then adjust the border style from the 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 fix 5 underscores for 4 ugliness characters--

 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 may be the starting point ... hope this helps ...

+18
source

I would just use this 4 separate fields and add the same event handler for all of them:

  • Check if the input is valid (in a character class that you are ready to accept)
  • Check which field you are in, and then move the focus to the next field or ok button.

You can even write a little separate JS for this and reuse it.

+3
source

Hope this solution helps you. You can remove the 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> 
+3
source

I don't know how to split the input in html5, maybe in css you can use the same class to control your input, and you can enter a style, for example:

 div{ text-align:center; background:#eee; } input{ border: 0; outline: 0; background: transparent; border-bottom: 2px solid black; width: 100px; text-align:center; padding : 5px; margin-left:10px; } button{ margin-top:20px !important; margin: 0 auto; color: white; border-radius: 4px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); } 
 <div> <input class="form-control" placeholder="0" maxlength="1" /> <input class="form-control" placeholder="0" maxlength="1" /> <input class="form-control" placeholder="0" maxlength="1" /> <input class="form-control" placeholder="0" maxlength="1" /> <br><button type="button" onclick="myFunction()">Submit</button> <p id="optRes"></p> </div> 

Define myFunction (), and you can get your array according to your class: form-control, convert to a string, then to int if you need to check it. Does it help?

0
source

You can use the directive below if using AngularJS

In your HTML add

 <div otp-input-directive options="otpInput"></div> 

In the controller add

 $scope.otpInput={ size:6, type:"text", onDone: function(value){ console.log(value); }, onChange: function(value){ console.log(value); } }; 

Link to the plunger

User Interface Appearance

https://github.com/amstel91/otp-input-directive

0
source

this solution is with me, I use the brezze template,

0
source

Source: https://habr.com/ru/post/1014151/


All Articles